update the codebase poc ver1
This commit is contained in:
184
workspace/sprint_1_2/CODEBASE/frontend/spec/DESIGN.md
Normal file
184
workspace/sprint_1_2/CODEBASE/frontend/spec/DESIGN.md
Normal file
@@ -0,0 +1,184 @@
|
||||
---
|
||||
name: Lumina MSK
|
||||
colors:
|
||||
surface: '#f5faf9'
|
||||
surface-dim: '#d6dbda'
|
||||
surface-bright: '#f5faf9'
|
||||
surface-container-lowest: '#ffffff'
|
||||
surface-container-low: '#f0f5f4'
|
||||
surface-container: '#eaefee'
|
||||
surface-container-high: '#e4e9e8'
|
||||
surface-container-highest: '#dee3e3'
|
||||
on-surface: '#171d1c'
|
||||
on-surface-variant: '#3e4945'
|
||||
inverse-surface: '#2c3131'
|
||||
inverse-on-surface: '#edf2f1'
|
||||
outline: '#6f7975'
|
||||
outline-variant: '#bec9c4'
|
||||
surface-tint: '#056b58'
|
||||
primary: '#056b58'
|
||||
on-primary: '#ffffff'
|
||||
primary-container: '#76c8b1'
|
||||
on-primary-container: '#005344'
|
||||
inverse-primary: '#84d6be'
|
||||
secondary: '#23686c'
|
||||
on-secondary: '#ffffff'
|
||||
secondary-container: '#adeef2'
|
||||
on-secondary-container: '#2b6e72'
|
||||
tertiary: '#5f5983'
|
||||
on-tertiary: '#ffffff'
|
||||
tertiary-container: '#bab3e2'
|
||||
on-tertiary-container: '#49446c'
|
||||
error: '#ba1a1a'
|
||||
on-error: '#ffffff'
|
||||
error-container: '#ffdad6'
|
||||
on-error-container: '#93000a'
|
||||
primary-fixed: '#a0f3da'
|
||||
primary-fixed-dim: '#84d6be'
|
||||
on-primary-fixed: '#002019'
|
||||
on-primary-fixed-variant: '#005142'
|
||||
secondary-fixed: '#adeef2'
|
||||
secondary-fixed-dim: '#91d1d6'
|
||||
on-secondary-fixed: '#002021'
|
||||
on-secondary-fixed-variant: '#004f53'
|
||||
tertiary-fixed: '#e5deff'
|
||||
tertiary-fixed-dim: '#c8c1f1'
|
||||
on-tertiary-fixed: '#1b163c'
|
||||
on-tertiary-fixed-variant: '#47426a'
|
||||
background: '#f5faf9'
|
||||
on-background: '#171d1c'
|
||||
surface-variant: '#dee3e3'
|
||||
typography:
|
||||
headline-lg:
|
||||
fontFamily: Manrope
|
||||
fontSize: 32px
|
||||
fontWeight: '700'
|
||||
lineHeight: 40px
|
||||
letterSpacing: -0.02em
|
||||
headline-lg-mobile:
|
||||
fontFamily: Manrope
|
||||
fontSize: 24px
|
||||
fontWeight: '700'
|
||||
lineHeight: 32px
|
||||
headline-md:
|
||||
fontFamily: Manrope
|
||||
fontSize: 20px
|
||||
fontWeight: '600'
|
||||
lineHeight: 28px
|
||||
body-lg:
|
||||
fontFamily: Work Sans
|
||||
fontSize: 18px
|
||||
fontWeight: '400'
|
||||
lineHeight: 28px
|
||||
body-md:
|
||||
fontFamily: Work Sans
|
||||
fontSize: 16px
|
||||
fontWeight: '400'
|
||||
lineHeight: 24px
|
||||
label-sm:
|
||||
fontFamily: Work Sans
|
||||
fontSize: 12px
|
||||
fontWeight: '600'
|
||||
lineHeight: 16px
|
||||
letterSpacing: 0.05em
|
||||
data-display:
|
||||
fontFamily: Work Sans
|
||||
fontSize: 14px
|
||||
fontWeight: '500'
|
||||
lineHeight: 20px
|
||||
rounded:
|
||||
sm: 0.25rem
|
||||
DEFAULT: 0.5rem
|
||||
md: 0.75rem
|
||||
lg: 1rem
|
||||
xl: 1.5rem
|
||||
full: 9999px
|
||||
spacing:
|
||||
unit: 8px
|
||||
container-margin: 20px
|
||||
gutter: 16px
|
||||
stack-sm: 8px
|
||||
stack-md: 16px
|
||||
stack-lg: 24px
|
||||
---
|
||||
|
||||
## Brand & Style
|
||||
|
||||
The design system is built for the MSK (musculoskeletal) healthcare sector, where clarity, empathy, and professional trust are paramount. The personality is "Clinical yet Compassionate"—moving away from sterile, intimidating medical interfaces toward a supportive, collaborative environment.
|
||||
|
||||
### Design Style: Soft Glassmorphism
|
||||
This system utilizes a refined **Glassmorphism** aesthetic. By using translucent layers, background blurs, and soft-spectrum gradients, the UI feels lightweight and accessible. This approach reduces cognitive load for patients managing pain while maintaining a high-tech, modern clinical feel for practitioners.
|
||||
|
||||
**Key Attributes:**
|
||||
- **Accessible & Trustworthy:** High legibility and clear hit targets.
|
||||
- **Supportive:** Soft rounded corners and a calming palette to lower patient anxiety.
|
||||
- **Collaborative:** Distinctive visual styles for shared data between patient and provider.
|
||||
|
||||
## Colors
|
||||
|
||||
The palette is derived from healing minerals and soft daylight.
|
||||
|
||||
- **Primary (Soft Mint):** Used for primary actions, success states, and key navigational elements. It evokes health and freshness.
|
||||
- **Secondary (Teal):** A deeper, grounding tone for typography, active icons, and emphasis. It provides the "clinical" anchor to the design.
|
||||
- **Tertiary (Lavender):** Used for supplemental information, secondary categories, and patient-specific metrics. It adds a layer of softness and warmth.
|
||||
- **Neutral (Arctic White):** The base background is a very slight cool-tinted white to reduce screen glare.
|
||||
|
||||
**Glassmorphism Specs:**
|
||||
Surfaces should use `glass_surface` with a `backdrop-filter: blur(12px)`. Borders on these elements should use the `glass_border` to create a "shimmer" effect that defines the edge without adding heavy visual weight.
|
||||
|
||||
## Typography
|
||||
|
||||
Typography is focused on high-speed readability and precision.
|
||||
|
||||
**Manrope** is used for headlines to provide a modern, balanced, and trustworthy appearance. Its geometric roots feel precise, while its open apertures remain friendly.
|
||||
|
||||
**Work Sans** is used for body text and medical data. It is a highly legible "workhorse" font that performs exceptionally well in data-heavy contexts (like exercise logs or medication lists).
|
||||
|
||||
**Medical Data Note:** For metrics and time-stamps, always enable tabular figures (`tnum`) to ensure numbers align vertically in lists and tables, allowing patients to easily track progress.
|
||||
|
||||
## Layout & Spacing
|
||||
|
||||
This design system utilizes a **Fluid Grid** model with a soft 8px baseline rhythm.
|
||||
|
||||
- **Mobile:** 4-column grid with 20px side margins. Elements reflow into a single-column vertical stack for primary medical info.
|
||||
- **Desktop/Tablet:** 12-column grid. Information is organized into "Dashboard Tiles" using the glassmorphism surface tokens.
|
||||
- **Safe Zones:** High-priority buttons (like "Start Session" or "Emergency") are always placed within the "natural thumb zone" on mobile, with a minimum 48px hit target.
|
||||
|
||||
Spacing between related medical data points should be tight (`stack-sm`), while sections of the app should be clearly separated by larger gaps (`stack-lg`) to prevent "visual clutter" which can be overwhelming for users in pain.
|
||||
|
||||
## Elevation & Depth
|
||||
|
||||
Hierarchy is established through **Tonal Layers** and **Ambient Shadows** rather than stark borders.
|
||||
|
||||
1. **Level 0 (Background):** The Neutral Arctic base.
|
||||
2. **Level 1 (Cards/Tiles):** Translucent glass surfaces. They feature a very soft, diffused shadow (`0px 10px 30px rgba(77, 141, 145, 0.08)`) to give them a "floating" appearance.
|
||||
3. **Level 2 (Modals/Popovers):** Higher opacity glass with a more pronounced blur and shadow. These should feel physically closer to the user.
|
||||
4. **Interactive Elements:** Buttons utilize a slight inner-glow (white, 20% opacity) on their top edge to suggest a tactile, "pressable" quality without resorting to full skeuomorphism.
|
||||
|
||||
## Shapes
|
||||
|
||||
The shape language is consistently **Rounded**. Sharp corners are avoided to maintain the "friendly healthcare" persona.
|
||||
|
||||
- **Standard Containers:** 0.5rem (8px) radius.
|
||||
- **Large Cards/Dashboard Tiles:** 1rem (16px) radius.
|
||||
- **Patient Avatars:** Always circular to feel human and approachable.
|
||||
- **Active States:** When an item is selected, use a thicker 3px border in the Primary color rather than changing the shape.
|
||||
|
||||
## Components
|
||||
|
||||
### Buttons
|
||||
- **Primary:** Solid Teal background with White text. Pill-shaped or 8px rounded corners.
|
||||
- **Secondary:** Glass-style (translucent white) with Teal border and text.
|
||||
- **Icon Buttons:** Circular glass containers with centered icons.
|
||||
|
||||
### Tiles (Dashboard)
|
||||
Each tile is a glass container. Metrics (e.g., "Pain Level: 4") are displayed in the center with large Manrope typography. Use Lavender for "Progress" indicators and Mint for "Completed" tasks.
|
||||
|
||||
### Progress Bars
|
||||
Avoid harsh, squared-off ends. Use rounded caps for all bar charts and progress trackers. Use a gradient from Teal to Mint to signify positive progress.
|
||||
|
||||
### Inputs
|
||||
Text fields should be "Ghost Style"—a light neutral background with a 1px soft teal border that glows slightly when focused.
|
||||
|
||||
### Status Chips
|
||||
Small, high-radius (pill) labels used for categorizing medical notes (e.g., "Physical Therapy," "Consultation"). Use Lavender backgrounds with slightly darker text for maximum legibility.
|
||||
@@ -0,0 +1,135 @@
|
||||
# Component Inventory
|
||||
|
||||
Derived from 35 Figma designs in `MSK_Workspace_UIX-Design` (https://www.figma.com/design/uakk3T4efS1AIckfTEFSZO/MSK_Workspace_UIX-Design). Atoms, molecules, organisms, and templates are listed below with the Figma designs that map to each reusable module.
|
||||
|
||||
## Atoms
|
||||
|
||||
### Button
|
||||
Usage: Primary actions across the workspace (login, sign, submit, navigate).
|
||||
Figma mappings: 8-Login, 14-Create Account, 13-Success, 32-Sign Container, 10-About
|
||||
|
||||
### Input
|
||||
Usage: Text entry for login, registration, password reset, profile editing, chat.
|
||||
Figma mappings: 8-Login, 14-Create Account, 7-Reset Password, 3-Edit Profile, 28-Chat-Collab
|
||||
|
||||
### Icon
|
||||
Usage: Navigation, status, tool palette, actions (25+ icon names implemented).
|
||||
Figma mappings: All screens.
|
||||
|
||||
### Badge
|
||||
Usage: Role badge, severity grade, phase indicator, status chips.
|
||||
Figma mappings: 4-Profile, 33-MSK Home, 25-Ultrasound-View, 11-Raw-Ultrasound
|
||||
|
||||
### Label
|
||||
Usage: Form field labels, section headers, annotation tool labels.
|
||||
Figma mappings: 3-Edit Profile, 4-Profile, 21-Settings, 1-Diagnostic Form
|
||||
|
||||
### Toggle
|
||||
Usage: GradCAM/segmentation visibility, feature flags, settings preferences.
|
||||
Figma mappings: 25-Ultrasound-View, 31-Ultrasound-View, 21-Settings
|
||||
|
||||
### Tooltip
|
||||
Usage: Confidence details, measurement tooltips, severity explanations.
|
||||
Figma mappings: 25-Ultrasound-View, 31-Ultrasound-View, 18-Patient-MSK-Patient-Profile
|
||||
|
||||
## Molecules
|
||||
|
||||
### PatientHeader
|
||||
Usage: Displays patientId, patient name, and role badge in TopBar.
|
||||
Figma mappings: 4-Profile, 18-Patient-MSK-Patient-Profile, 23-Danh Sách Bệnh Nhân (Main List)
|
||||
|
||||
### ActionCluster
|
||||
Usage: Sign button + circuit breaker + more menu grouped for Quick Actions.
|
||||
Figma mappings: 25-Ultrasound-View, 31-Ultrasound-View, 32-Sign Container
|
||||
|
||||
### SeverityBadge
|
||||
Usage: Grade 0-3 with color-coded label (Rất nhẹ/Nhẹ/Trung bình/Nặng).
|
||||
Figma mappings: 25-Ultrasound-View, 31-Ultrasound-View, 1-Diagnostic Form
|
||||
|
||||
### ConfidenceBar
|
||||
Usage: Severity score as a progress bar with numeric confidence.
|
||||
Figma mappings: 25-Ultrasound-View, 31-Ultrasound-View, 27-AI-View
|
||||
|
||||
### NFRIcon
|
||||
Usage: NFR status dot + label + value (bundle size, latency, offline).
|
||||
Figma mappings: 33-MSK Home, 40-Drawer, 24-Đang xử lý
|
||||
|
||||
## Organisms
|
||||
|
||||
### TopBar
|
||||
Usage: Back button, patient info, phase display, more options, sign button.
|
||||
Figma mappings: 25-Ultrasound-View, 31-Ultrasound-View, 27-AI-View, 18-Patient-MSK-Patient-Profile
|
||||
|
||||
### BottomBar
|
||||
Usage: NFR metrics (bundle size, inference latency), EMR sync status, audit log, version.
|
||||
Figma mappings: 25-Ultrasound-View, 31-Ultrasound-View, 33-MSK Home
|
||||
|
||||
### DiagnosticCanvas
|
||||
Usage: 5-layer canvas stack (DICOM background, GradCAM, segmentation mask, SVG annotations, HUD).
|
||||
Figma mappings: 11-Raw-Ultrasound, 25-Ultrasound-View, 31-Ultrasound-View, 27-AI-View, 30-MSK Home: Upload File Success
|
||||
|
||||
### ReasoningPanel
|
||||
Usage: Phase indicator, classification card, explanation panel, chat panel, override card, quick actions.
|
||||
Figma mappings: 25-Ultrasound-View, 31-Ultrasound-View, 27-AI-View, 24-Đang xử lý
|
||||
|
||||
### ChatPanel
|
||||
Usage: Virtualized message list, SSE streaming input, message actions.
|
||||
Figma mappings: 28-Chat-Collab, 25-Ultrasound-View, 31-Ultrasound-View
|
||||
|
||||
## Templates
|
||||
|
||||
### WorkspaceShell
|
||||
Usage: TopBar + ZoneA/ZoneB (65/35 split) + BottomBar composition.
|
||||
Figma mappings: 25-Ultrasound-View, 31-Ultrasound-View, 27-AI-View, 18-Patient-MSK-Patient-Profile, 40-Drawer
|
||||
|
||||
### AuthShell
|
||||
Usage: Shared layout for login, register, forgot password, reset password screens.
|
||||
Figma mappings: 8-Login, 9-Login Password Error, 14-Create Account, 12-Create Account Exists Error, 22-Forgot Password, 7-Reset Password, 6-Reset Password Security Error
|
||||
|
||||
### PatientListShell
|
||||
Usage: Search, filters, stats, and card grid for patient list views.
|
||||
Figma mappings: 23-Danh Sách Bệnh Nhân (Main List), 29-Danh Sách Bệnh Nhân (Filtered View), 34-Danh Sách Bệnh Nhân (Main List alternate), 16-Patient Card 4, 17-Patient Card 3, 19-Patient Card 2, 20-Patient Card 1
|
||||
|
||||
### Drawer
|
||||
Usage: Side navigation drawer (open/close states).
|
||||
Figma mappings: 45-350 drawer-350, 33-MSK Home
|
||||
|
||||
## Figma-to-Component Mapping Summary
|
||||
|
||||
| Figma Node | Figma Name | Deepest Reusable Module | Route / View |
|
||||
|---|---|---|---|
|
||||
| 151-5152 | THE DIAGNOSTIC FORM | SeverityBadge + ConfidenceBar | Diagnostic Form |
|
||||
| 129-2443 | Swipe-up-card | Template (BottomSheetCard) | Bottom sheet card |
|
||||
| 105-3307 | Edit_profile | AuthShell + Input + Label | Edit Profile |
|
||||
| 99-2463 | Profile | PatientHeader + NFRIcon + Bento | Profile |
|
||||
| 99-2351 | Notifications | Organism (NotificationList) | Notifications |
|
||||
| 93-1587 | Reset Password Error | AuthShell | Reset Password Error |
|
||||
| 93-1650 | Reset Password | AuthShell + Input | Reset Password |
|
||||
| 93-1287 | Login | AuthShell + Input | Login |
|
||||
| 93-1509 | Login Password Error | AuthShell + Input | Login Error |
|
||||
| 93-1037 | About | Template (AboutPage) | About |
|
||||
| 128-1225 | Raw-Ultrasound | DiagnosticCanvas | Raw Ultrasound Viewport |
|
||||
| 97-2270 | Create Account Exists Error | AuthShell | Create Account Error |
|
||||
| 109-3698 | Success | Template (SuccessScreen) | Success |
|
||||
| 97-2180 | Create Account | AuthShell + Input | Create Account |
|
||||
| 93-1007 | Confirm Logout | Molecule (ConfirmDialog) | Logout Confirmation |
|
||||
| 82-2496 | Patient Card 4 | PatientListShell + Card | Patient List |
|
||||
| 82-2443 | Patient Card 3 | PatientListShell + Card | Patient List |
|
||||
| 78-2081 | Patient-MSK-Patient-Profile | PatientHeader + Bento + Timeline | Patient Profile |
|
||||
| 82-2390 | Patient Card 2 | PatientListShell + Card | Patient List |
|
||||
| 82-2334 | Patient Card 1 | PatientListShell + Card | Patient List |
|
||||
| 93-1165 | Settings | Molecule (SectionField) | Settings |
|
||||
| 93-1361 | Forgot Password | AuthShell | Forgot Password |
|
||||
| 82-3155 | Patient List Main View | PatientListShell + Search + Filters | Patient List |
|
||||
| 109-3657 | Processing | NFRIcon + ProgressIndicator | Processing |
|
||||
| 124-2787 | Ultrasound-View | WorkspaceShell + DiagnosticCanvas + ReasoningPanel | Ultrasound View |
|
||||
| 72-1611 | History-Ingestion | Molecule (HistoryList) + PatientHeader | History |
|
||||
| 129-2016 | AI-View | DiagnosticCanvas + ToolPalette | AI View |
|
||||
| 66-1160 | Chat-Collab | ChatPanel + Input | Chat Collaboration |
|
||||
| 82-2690 | Patient List Filtered View | PatientListShell + Search + Filters | Patient List Filtered |
|
||||
| 33-143 | Upload File Success | NFRIcon + DiagnosticCanvas | Upload Success |
|
||||
| 93-1713 | Ultrasound-View | WorkspaceShell + DiagnosticCanvas + ReasoningPanel | Ultrasound View |
|
||||
| 109-3743 | Sign Container | ActionCluster + Modal | Signature Modal |
|
||||
| 33-242 | MSK Home | WorkspaceShell + Drawer + NFRIcon | Home |
|
||||
| 78-1763 | Patient List Main (alt) | PatientListShell | Patient List |
|
||||
| 45-349 | Drawer-350 | Drawer | Drawer |
|
||||
@@ -0,0 +1,70 @@
|
||||
# Figma Component Specs
|
||||
|
||||
Source: `MSK_Workspace_UIX-Design` (file key: `uakk3T4efS1AIckfTEFSZO`)
|
||||
|
||||
## Node Map
|
||||
|
||||
| # | Node ID | Name | Route | Page Component |
|
||||
|---|---------|-------------------------------|-----------------------|-------------------------------|
|
||||
| 1 | 151-5152 | THE DIAGNOSTIC FORM | /diagnostic-form | src/pages/the-diagnostic-form.tsx |
|
||||
| 2 | 129-2443 | Swipe-up-card | /swipe-up-card | src/pages/swipe-up-card.tsx |
|
||||
| 3 | 105-3307 | Edit_profile | /edit-profile | src/pages/edit-profile.tsx |
|
||||
| 4 | 99-2463 | Profile | /profile | src/pages/Profile.tsx |
|
||||
| 5 | 99-2351 | Notifications | /notifications | src/pages/notifications.tsx |
|
||||
| 6 | 93-1587 | Reset Password - Error | /reset-password-error | src/pages/reset-password-error.tsx |
|
||||
| 7 | 93-1650 | Reset Password | /reset-password | src/pages/reset-password.tsx |
|
||||
| 8 | 93-1287 | Login | /login | src/pages/Login.tsx |
|
||||
| 9 | 93-1509 | Login - Password Error | /login-error | src/pages/login-password-error.tsx |
|
||||
| 10 | 93-1037 | About | /about | src/pages/about.tsx |
|
||||
| 11 | 128-1225 | Raw-Ultrasound | /raw-ultrasound | src/pages/raw-ultrasound.tsx |
|
||||
| 12 | 97-2270 | Create Account - Exists | /create-account-exists | src/pages/create-account-exists.tsx |
|
||||
| 13 | 109-3698 | Success | /success | src/pages/success.tsx |
|
||||
| 14 | 97-2180 | Create Account | /create-account | src/pages/create-account.tsx |
|
||||
| 15 | 93-1007 | Logout Confirm | /logout-confirm | src/pages/logout-confirm.tsx |
|
||||
| 16 | 82-2496 | Patient Card 4 | /patient-card-4 | src/pages/patient-card-4.tsx |
|
||||
| 17 | 82-2443 | Patient Card 3 | /patient-card-3 | src/pages/patient-card-3.tsx |
|
||||
| 18 | 78-2081 | Patient-MSK-Patient-Profile | /patient-profile-msk | src/pages/patient-msk-profile.tsx |
|
||||
| 19 | 82-2390 | Patient Card 2 | /patient-card-2 | src/pages/patient-card-2.tsx |
|
||||
| 20 | 82-2334 | Patient Card 1 | /patient-card-1 | src/pages/patient-card-1.tsx |
|
||||
| 21 | 93-1165 | Settings | /settings | src/pages/settings.tsx |
|
||||
| 22 | 93-1361 | Forgot Password | /forgot-password | src/pages/forgot-password.tsx |
|
||||
| 23 | 82-3155 | Patient List Main | /patients | src/pages/patient-list-main.tsx |
|
||||
| 24 | 109-3657 | Processing | /processing | src/pages/processing.tsx |
|
||||
| 25 | 124-2787 | Ultrasound-View | /ultrasound-view | src/pages/ultrasound-view.tsx |
|
||||
| 26 | 72-1611 | History-Ingestion | /history-ingestion | src/pages/history-ingestion.tsx |
|
||||
| 27 | 129-2016 | AI-View | /ai-view | src/pages/ai-view.tsx |
|
||||
| 28 | 66-1160 | Chat-Collab | /chat | src/pages/chat.tsx |
|
||||
| 29 | 82-2690 | Patient List Filtered | /patients/filtered | src/pages/patient-list-filtered.tsx |
|
||||
| 30 | 33-143 | Upload File Success | /upload-success | src/pages/upload-success.tsx |
|
||||
| 31 | 93-1713 | Ultrasound-View (Diag) | /ultrasound-view-diagnostic | src/pages/ultrasound-view-diagnostic.tsx |
|
||||
| 32 | 109-3743 | Sign Container | /sign | src/pages/sign-container.tsx |
|
||||
| 33 | 33-242 | MSK Home | /home | src/pages/home.tsx |
|
||||
| 34 | 78-1763 | Patient List Main (alt) | /patients-alt | src/pages/patient-list-main-alt.tsx |
|
||||
| 35 | 45-349 | Drawer | /drawer | src/pages/drawer.tsx |
|
||||
|
||||
|
||||
|
||||
## Design Tokens
|
||||
|
||||
See `src/styles/design-tokens.ts` for canonical tokens. Update this file after Figma Inspect extraction.
|
||||
|
||||
## Implementation Status
|
||||
|
||||
- [x] Routes wired (stub pages)
|
||||
- [ ] Pixel-perfect screens implemented
|
||||
- [ ] Component specs extracted from Figma
|
||||
- [ ] Error boundaries added
|
||||
- [ ] Image optimization (WebP/AVIF, srcset)
|
||||
- [ ] Accessibility pass
|
||||
- [ ] i18n keys externalized
|
||||
|
||||
## Priorities
|
||||
|
||||
1. Home, Login, Create Account
|
||||
2. Patient List + Cards
|
||||
3. Workspace shell + Zone A/B
|
||||
4. Auth flows (forgot/reset)
|
||||
5. AI View, Chat, Ultrasound
|
||||
6. Remaining screens
|
||||
|
||||
|
||||
@@ -39,3 +39,11 @@ See `bento/frontend/spec/interface-contract.md`.
|
||||
- SOFTWARE_SYSTEM_DESIGN_FR_25.md (Sections 2.4, 3.1, 3.2, 3.3)
|
||||
- SOLUTION_ARCHITECTURE_SPEC.md (Section 2.4)
|
||||
- PROJECT_VIS.md (Section 3.1, 3.2)
|
||||
|
||||
## PoC baseline (Sprint 1–2)
|
||||
|
||||
The interactive mock-up in `CODEBASE/frontend/implementation/` implements a subset of this specification. For what is **actually built** vs target architecture, see:
|
||||
|
||||
- `frontend/spec/uix_prototype_coverage.md` — routes, FR/UC matrix, demo flows
|
||||
- `frontend/spec/session_recording_frame_switch_spec.md` — multi-frame session recording & UIX replay
|
||||
- `frontend/spec/DESIGN.md` — visual tokens used in the prototype
|
||||
|
||||
@@ -29,6 +29,20 @@ Web Experience Team
|
||||
- Deprecation notices issued in release notes.
|
||||
- Breaking changes require major version bump.
|
||||
|
||||
## PoC implementation notes (Sprint 1–2)
|
||||
|
||||
The runnable prototype under `CODEBASE/frontend/implementation/` diverges from the target architecture above in several areas (no Zustand, Service Worker, or WebCrypto yet). Session recording and replay are specified separately:
|
||||
|
||||
| Topic | Document |
|
||||
|-------|----------|
|
||||
| Feature coverage & demo flows | `frontend/spec/uix_prototype_coverage.md` |
|
||||
| Multi-frame UIX log, WAL, replay contract | `frontend/spec/session_recording_frame_switch_spec.md` |
|
||||
| ML inference cache (IndexedDB) | `CODEBASE/docs/ml-inference-cache.md` |
|
||||
|
||||
**Session replay provides (PoC):** `UIXSessionEvent[]` vector timeline for **Nhiều khung** mode — `MOUSE_MOVE`, `FRAME_SWITCH`, `OVERLAY_CREATE` / `MUTATE` / `DELETE` with normalized coordinates; chronological replay via `UixSessionReplayEngine`; saved bundles in IndexedDB `lumina-session-recording`.
|
||||
|
||||
**Consumes (live in PoC):** `POST /api/test/analyze/batch` via Vite dev proxy → backend `:8001`.
|
||||
|
||||
## References
|
||||
- NFR-1 (Collaborative Rendering Speed ≤3s)
|
||||
- NFR-4 (Client Memory Footprint ≤150MB)
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
# UIX Specification — Frame Switching & Session Recording Association
|
||||
|
||||
Document type: UIX / interaction + data contract
|
||||
Sprint: `workspace/sprint_1_2`
|
||||
Scope: WS-25 Diagnostic Workspace — Xem lại phiên chẩn đoán + Zone A canvas
|
||||
Related FR: FR-25 (clinical workspace), FR-02 analogue (async viewport + annotation replay)
|
||||
Status: **Implemented in PoC** (Một khung / Nhiều khung, per-frame overlays, UIX chronological replay, IndexedDB WAL + saved bundles)
|
||||
|
||||
**Implementation map**
|
||||
|
||||
| Spec area | Files |
|
||||
|-----------|--------|
|
||||
| Types & segments | `implementation/src/lib/sessionRecordingTypes.ts`, `frameSegment.ts` |
|
||||
| UIX event schema + timeline | `implementation/src/lib/uixSessionEvents.ts` |
|
||||
| IndexedDB (`lumina-session-recording`) | `implementation/src/lib/sessionRecordingIndexedDb.ts` |
|
||||
| UIX WAL (multi-frame) | `uixSessionRecorder.ts`, `uixSessionWalClient.ts`, `uixSessionWalTypes.ts`, `workers/uixSessionRecorder.worker.ts` |
|
||||
| Lifecycle + scope | `implementation/src/lib/sessionLifecycle.tsx`, `sessionLifecycleStore.ts` |
|
||||
| Scope selector | `implementation/src/components/molecules/RecordingModeSelector.tsx` |
|
||||
| Toolbar actions | `SessionLifecycleToolbar.tsx`, `SessionCancelRecordDialog.tsx`, `SessionNewSessionDialog.tsx` |
|
||||
| Overlay capture + per-frame maps | `canvasOverlayRegistry.ts`, `uixOverlayRecorderRegistry.ts`, `hooks/useImageCanvasTools.ts` |
|
||||
| Pointer trace `frameId` | `hooks/usePointerTraceRecording.ts`, `data/diagnosticSessionReplay.ts` |
|
||||
| Replay engine + hook | `uixSessionReplayEngine.ts`, `hooks/useDiagnosticSessionReplay.ts`, `ReplaySandboxOverlay.tsx` |
|
||||
| Replay frame restore | `ClinicalWorkspacePage.tsx`, `DiagnosticCanvas.tsx` |
|
||||
| Saved session list + groups | `components/molecules/SavedSessionsDialog.tsx` |
|
||||
|
||||
---
|
||||
|
||||
## 1. Problem statement
|
||||
|
||||
Clinicians review multiple ultrasound frames in one encounter. Session recording must preserve which frame was active, what tools/overlays/viewport/pointer path were used, support faithful replay, and allow multiple saved records per patient.
|
||||
|
||||
## 2. Recording scope (two modes)
|
||||
|
||||
| Mode | Vietnamese | Behavior |
|
||||
|------|------------|----------|
|
||||
| Single frame | **Một khung** | Record on the current frame only; frame navigation **blocked only while `status === 'recording'`** (not when paused or ended) |
|
||||
| Multi-frame | **Nhiều khung** | Event-driven UIX session log (`UIXSessionEvent[]`) + segment timeline; frame navigation **allowed** during recording and pause; see §3 |
|
||||
|
||||
**Mode selector:** `RecordingModeSelector.tsx` — disabled while recording or paused. Preference persisted per patient in IndexedDB `settings` store.
|
||||
|
||||
**Debounce:** frame revert within 1500 ms is ignored (no segment).
|
||||
|
||||
Legacy modes (`encounter`, `per_frame`, `prompt`) map to **Nhiều khung** when loaded from storage.
|
||||
|
||||
## 2.1 Frame navigation lock
|
||||
|
||||
| Condition | Frame prev/next |
|
||||
|-----------|-----------------|
|
||||
| `single_frame` + `recording` | Locked to frame at record start |
|
||||
| `single_frame` + paused / ended / idle | Unlocked |
|
||||
| `multi_frame` (any status) | Unlocked |
|
||||
| UIX replay (`status === 'ended'` + continuous play) | Driven by replay engine (`handleReplayFrameRestore`) |
|
||||
| Manual nav during replay | Clears injected replay overlay; does not hijack live capture index |
|
||||
|
||||
Implementation: `ClinicalWorkspacePage.tsx` (`isSingleFrameNavLocked`), `DiagnosticCanvas.tsx` (patient / frame-count reset only — no spurious index snap).
|
||||
|
||||
## 3. Multi-frame: event-driven UIX log (Nhiều khung)
|
||||
|
||||
Structured vector events (not pixels), normalized coordinates `[0,1]`:
|
||||
|
||||
| Type | When recorded |
|
||||
|------|----------------|
|
||||
| `MOUSE_MOVE` | 30 Hz throttled pointer samples |
|
||||
| `FRAME_SWITCH` | Immediate on frame change (+ buffer flush) |
|
||||
| `OVERLAY_CREATE` | Stroke/mask committed |
|
||||
| `OVERLAY_MUTATE` | 30 Hz while drawing; final on pointer up; includes `color`, `strokeWidth` |
|
||||
| `OVERLAY_DELETE` | Eraser hit or clear annotations |
|
||||
|
||||
**Normalized coordinates:** all overlay and mouse samples use `[0,1]` relative to canvas content box. Replay denormalizes with default content size `1024×768` (configurable on engine).
|
||||
|
||||
**Chronological timeline:** `uixEventsToTimeline()` produces `UixReplayTimelineEntry[]` — each entry is a tuple of `{ frameId, kind, mouse?, overlay?, overlayMutate?, overlayDelete?, frameSwitch? }` at `relTime`.
|
||||
|
||||
**Recorder:** `lib/uixSessionRecorder.ts` — in-memory buffer (2s flush), Web Worker WAL → IndexedDB (`UIX_Agent_Recorder` / `pending_chunks`), then backend sync stub; merged into `capture.uixEvents` on local commit.
|
||||
|
||||
**WAL persistence (multi-frame only)**
|
||||
|
||||
| Step | Behavior |
|
||||
|------|----------|
|
||||
| Buffer | Main thread accumulates events; flush every **2s** or on `FRAME_SWITCH` |
|
||||
| Local commit | Worker writes `IndexedDBSessionChunk` to IDB **before** network |
|
||||
| Network | Transmit after IDB success; delete chunk on ACK (PoC: immediate ACK stub) |
|
||||
| Crash recovery | On patient load: purge chunks >24h, replay pending chunks into capture silently |
|
||||
| Dedupe | `uixWalAppliedChunkIds` prevents double-merge after recovery |
|
||||
|
||||
All IndexedDB I/O runs in `workers/uixSessionRecorder.worker.ts` (zero main-thread IDB).
|
||||
|
||||
**Offline (PoC):** chunks queue in IndexedDB until ACK; no manual sync UI yet — see §3.1 for production recommendation.
|
||||
|
||||
### 3.1 Extended offline (future)
|
||||
|
||||
If the clinician is offline for an extended period: keep the full session in IndexedDB WAL + `localStorage` capture, show a non-blocking **Đồng bộ phiên** action when `pending_chunks` exist for the patient, and retry background sync on reconnect. Purge or export chunks older than 24h that never ACK.
|
||||
|
||||
**Replay:** `lib/uixSessionReplayEngine.ts` — chronological UIX timeline replay:
|
||||
|
||||
| Capability | Behavior |
|
||||
|------------|----------|
|
||||
| Timeline tuples | `UixReplayTimelineEntry` — frame + mouse / overlay create / mutate / delete per instant (`uixEventsToTimeline`) |
|
||||
| Frame transition | `FRAME_SWITCH` restores correct frame index, DICOM URL, and per-frame overlay cache |
|
||||
| Overlay chronology | `OVERLAY_MUTATE` grows strokes progressively; `OVERLAY_CREATE` commits; `OVERLAY_DELETE` removes |
|
||||
| Pen simulation | Mutate events carry `color` + `strokeWidth`; ghost cursor uses pen ink during replay (`ReplayViewportState.penColor`) |
|
||||
| Editing indicator | `editingOverlay` flag pulses ghost cursor while stroke in progress |
|
||||
| Canvas refresh | ~30 Hz overlay restore key during UIX continuous playback (`useDiagnosticSessionReplay`) |
|
||||
| Fallback | Bundles without `uixEvents` use legacy segment + `pointerTrace` replay path |
|
||||
|
||||
**Implementation map**
|
||||
|
||||
| Area | Files |
|
||||
|------|--------|
|
||||
| UIX types + timeline | `lib/uixSessionEvents.ts` |
|
||||
| Replay engine | `lib/uixSessionReplayEngine.ts` |
|
||||
| Canvas bridge | `lib/uixOverlayRecorderRegistry.ts`, `hooks/useImageCanvasTools.ts` |
|
||||
| Pointer (multi-frame) | `hooks/usePointerTraceRecording.ts` |
|
||||
| Lifecycle wiring | `lib/sessionLifecycle.tsx` |
|
||||
| Replay integration | `hooks/useDiagnosticSessionReplay.ts`, `ReplaySandboxOverlay.tsx` |
|
||||
|
||||
Single-frame mode keeps the legacy `pointerTrace` + checkpoint snapshot path unchanged.
|
||||
|
||||
## 4. Per-frame overlay isolation
|
||||
|
||||
Live canvas annotations are stored in a **per-`frameId` overlay map** (`useImageCanvasTools.ts`):
|
||||
|
||||
1. On frame switch: persist outgoing frame strokes → load incoming frame strokes → redraw canvas.
|
||||
2. During multi-frame recording: overlay mutations emit UIX events tagged with active `frameId`.
|
||||
3. On segment end / frame switch while recording: overlay checkpoint frozen on segment; live canvas cleared for transit (clinical workflow).
|
||||
4. On replay: engine maintains per-frame overlay cache; `frameRestore.overlay` injected via `segmentOverlayReplay` on `DiagnosticCanvas`.
|
||||
|
||||
**Bug class prevented:** syncing strokes to a new `frameId` before loading that frame's data (cross-frame bleed). Fixed by explicit persist/load on `frameId` change only.
|
||||
|
||||
## 5. Session toolbar & lifecycle actions
|
||||
|
||||
| Action | Vietnamese | When visible | Effect |
|
||||
|--------|----------|--------------|--------|
|
||||
| Record | **Ghi** | idle / paused | Start or resume capture; opens first segment |
|
||||
| Pause | **Tạm dừng** | recording | Pause clock; multi-frame UIX buffer flushed |
|
||||
| End | **Kết thúc ghi** | recording / paused | `status → ended`; enables save |
|
||||
| Cancel record | **Hủy ghi** | recording / paused (unsaved) | Confirm → discard capture, events, overlays, WAL session id |
|
||||
| New session | **Phiên mới** | idle / ended | Confirm → empty idle session; clears canvas annotations; keeps DICOM stack |
|
||||
| Save | **Lưu phiên** | ended | Write `SavedRecordingBundle` to IndexedDB |
|
||||
| Session list | **Danh sách phiên** | always | Load / delete saved bundles |
|
||||
| Reset | **Làm mới từ đầu** | ended | Legacy full reset with confirm |
|
||||
|
||||
Component: `SessionLifecycleToolbar.tsx` in `ReviewDiagnosticSessionPanel.tsx`.
|
||||
|
||||
## 6. Data model
|
||||
|
||||
### 6.1 In-progress capture (`localStorage`)
|
||||
|
||||
`SessionCaptureState` (`sessionLifecycleStore.ts`):
|
||||
|
||||
| Field | Purpose |
|
||||
|-------|---------|
|
||||
| `status` | `idle` \| `recording` \| `paused` \| `ended` |
|
||||
| `recordingMode` | `single_frame` \| `multi_frame` |
|
||||
| `events[]` | Legacy DICOM / tool structured events |
|
||||
| `pointerTrace[]` | Single-frame comet samples (with `frameId`) |
|
||||
| `uixEvents[]` | Multi-frame vector log (merged from WAL on flush) |
|
||||
| `segments[]` | `FrameSegment` timeline with viewport + optional `overlayCheckpoint` |
|
||||
| `overlaysByFrameId` | Live per-frame overlay snapshots |
|
||||
| `uixWalSessionId` | Active WAL session key (multi-frame) |
|
||||
| `uixWalAppliedChunkIds` | Dedupe set for crash recovery |
|
||||
|
||||
### 6.2 Saved bundle (IndexedDB)
|
||||
|
||||
Store: `saved-bundles`
|
||||
|
||||
- `SavedRecordingBundle`: events, `pointerTrace` (with `frameId`), `uixEvents`, `segments[]` (each may carry `overlayCheckpoint`), `overlaysByFrameId`, `recordingMode`, `primaryFrameId`, notes/edits
|
||||
- **Overlay checkpoints:** when a segment ends (frame switch or Kết thúc ghi), strokes/masks for that frame are frozen on the segment and cleared from the live canvas so transit matches clinical workflow
|
||||
- `EncounterGroup`: `childRecordIds[]` for per-frame splits
|
||||
- Recording mode preference in `settings` store
|
||||
|
||||
Active in-progress capture remains in `localStorage` (`sessionLifecycleStore.ts`) for fast resume.
|
||||
|
||||
## 7. User flows (summary)
|
||||
|
||||
1. **Ghi** — starts segment with current `frameId`, viewport, structured `FrameRef` on events
|
||||
2. **Frame switch while recording (Nhiều khung)** — `FRAME_SWITCH` UIX event + segment boundary; overlay checkpoint on outgoing frame
|
||||
3. **Tạm dừng / tiếp tục** — pause clock; multi-frame buffer flushed on pause
|
||||
4. **Hủy ghi** — discard unsaved capture (confirm)
|
||||
5. **Phiên mới** — empty idle session without save (confirm)
|
||||
6. **Kết thúc ghi** — enables **Lưu phiên**
|
||||
7. **Lưu phiên** — writes bundle + overlay snapshots to IndexedDB
|
||||
8. **Replay** — UIX engine or legacy segment resolver at time *t*; restores frame index + progressive overlays; filters pointer comet by `frameId`
|
||||
9. **Danh sách phiên** — flat rows + expandable encounter groups
|
||||
|
||||
## 8. Acceptance criteria (PoC)
|
||||
|
||||
- AC-1 Multi-frame: ≥2 frames in one saved bundle; replay mid-timeline shows correct frame image
|
||||
- AC-2 Overlay chronology: strokes grow during replay; pen color matches recorded ink
|
||||
- AC-3 Frame switch: comet / ghost cursor never spans frames without image switch
|
||||
- AC-4 Per-frame isolation: annotations on frame A do not appear on frame B after switch
|
||||
- AC-5 Save: `overlaysByFrameId` + `uixEvents` included; load restores frame + notes
|
||||
- AC-6 Cancel: **Hủy ghi** clears in-progress state without writing bundle
|
||||
- AC-7 WAL recovery: pending chunks <24h merged on patient reload without duplicate events
|
||||
- AC-8 Single-frame: nav locked only during active recording; replay uses legacy path
|
||||
|
||||
## 9. References
|
||||
|
||||
- [uix_prototype_coverage.md](./uix_prototype_coverage.md)
|
||||
- `docs/ml-inference-cache.md` — `contentHash` / `frameId` identity (future alignment)
|
||||
- `Design_Material/FR_25_UC_DESIGN/Insight_note.md` — FR-02 metadata recorder vision
|
||||
@@ -0,0 +1,341 @@
|
||||
# UIX Prototype Coverage — Sprint 1–2 (FR-25)
|
||||
|
||||
> **Document type:** UIX / functional coverage map for the interactive mock-up
|
||||
> **Sprint:** `workspace/sprint_1_2`
|
||||
> **Implementation root:** `CODEBASE/frontend/implementation/`
|
||||
> **Design authority:** `Design_Material/FR_25_UC_DESIGN/`
|
||||
> **Status:** Living document (PoC baseline, not production-complete)
|
||||
|
||||
---
|
||||
|
||||
## 1. Purpose & scope
|
||||
|
||||
This file documents what the **Lumina MSK front-end prototype** currently demonstrates in the browser: which screens exist, which functional requirements (FRs) and use cases (UCs) they address, which source files implement each capability, and how a reviewer should walk through the demo.
|
||||
|
||||
The prototype is a **Vietnamese-language React SPA** focused on **FR-25 — Synovitis Grading Engine** (ULTS workspace). It implements the **WS-25 Diagnostic Workspace** layout described in:
|
||||
|
||||
- `Design_Material/FR_25_UC_DESIGN/UI_Screen_Spec/Screen_Analysis_WS-25.md`
|
||||
- `Design_Material/FR_25_UC_DESIGN/CONTEXT_FR_25_UC_ELIT.md`
|
||||
- `Design_Material/FR_25_UC_DESIGN/Use_Case/FR_25_UC_SPEC.md`
|
||||
|
||||
**Out of scope for this build:** auth shells, EMR live sync, PWA service worker, WebCrypto encryption, Zustand global store (specified in `frontend_spec.md` target architecture but not yet adopted in code).
|
||||
|
||||
---
|
||||
|
||||
## 2. Prototype maturity (mock vs live)
|
||||
|
||||
| Layer | In this prototype | Notes |
|
||||
|--------|-------------------|--------|
|
||||
| **Patient worklist** | Mock seed data + local add/edit | `data/mockData.ts`, `lib/patientStore.tsx` |
|
||||
| **Ultrasound frames** | PNG test images per patient profile | `data/scanFrames.ts`, `data/patientScanProfiles.generated.ts` |
|
||||
| **CV / segmentation / grading** | **Live** via FastAPI test proxy | `POST /api/test/analyze/batch` → Vite proxy → backend `:8001` |
|
||||
| **Inference cache** | **Live** IndexedDB + cross-tab dedupe | `lib/mlInferenceCacheStore.ts`, `docs/ml-inference-cache.md` |
|
||||
| **Clinical chat (Socratic)** | Mock replies | `data/clinicalChatMock.ts`, `ClinicalChatPanel.tsx` |
|
||||
| **Session replay** | Local capture + **multi-frame UIX timeline** replay; saved bundles in **IndexedDB**; in-progress capture in `localStorage` | [session_recording_frame_switch_spec.md](./session_recording_frame_switch_spec.md) — `sessionLifecycle.tsx`, `uixSessionRecorder.ts`, `uixSessionReplayEngine.ts`, `useDiagnosticSessionReplay.ts` |
|
||||
| **Sign-off / EMR** | UI only; no cryptographic seal or EMR POST | `DiagnosisSignOffOverlay.tsx` |
|
||||
| **Safety escalation overlay** | Component exists, **not routed** | `SafetyEscalationOverlay.tsx` (see §7) |
|
||||
|
||||
---
|
||||
|
||||
## 3. Routes & primary screens
|
||||
|
||||
| Route | Screen (VI) | Entry file | Shell / layout |
|
||||
|-------|-------------|------------|----------------|
|
||||
| `/` | Danh sách công việc | `pages/PatientWorklistPage.tsx` | `AppShell` + `PatientListShell` |
|
||||
| `/workspace/:patientId` | Không gian chẩn đoán | `pages/ClinicalWorkspacePage.tsx` | `AppShell` + `WorkspaceShell` (65/35) |
|
||||
|
||||
Routing is defined in `src/App.tsx`. Global providers: `PatientStoreProvider` (worklist state).
|
||||
|
||||
### 3.1 WS-25 zone layout (clinical workspace)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ TopBar — patient name, MRN, joint, review + sign actions │
|
||||
├──────────────────────────────┬──────────────────────────────┤
|
||||
│ Zone A (~65%) │ Zone B (~35%) │
|
||||
│ DiagnosticCanvas │ SidebarLayerCarousel │
|
||||
│ + ReplaySandboxOverlay │ • Diagnosis: SideNavBar │
|
||||
│ (review playback only) │ • Review: ReviewDiagnostic │
|
||||
│ │ SessionPanel │
|
||||
└──────────────────────────────┴──────────────────────────────┘
|
||||
```
|
||||
|
||||
- **Resizable split:** `components/shells/WorkspaceShell.tsx` (persisted ratio in `localStorage`).
|
||||
- **Layer carousel:** `components/organisms/SidebarLayerCarousel.tsx` — rotates **Thông tin chẩn đoán** ↔ **Xem lại phiên chẩn đoán**.
|
||||
|
||||
---
|
||||
|
||||
## 4. Feature coverage (what the mock-up can do)
|
||||
|
||||
### 4.1 Patient worklist (UC-48376 entry)
|
||||
|
||||
| Capability | How to use | Primary files |
|
||||
|------------|------------|---------------|
|
||||
| Search & filter patients | Search box + status chips (Khẩn cấp / Đang xử lý / Theo dõi) | `PatientListShell.tsx`, `PatientWorklistPage.tsx` |
|
||||
| Status summary cards | Top of worklist grid | `StatusSummaryCard.tsx` |
|
||||
| Open diagnostic session | **Mở phiên chẩn đoán** on card | `PatientCard.tsx` → navigate `/workspace/:id` |
|
||||
| Add / edit patient profile | **Thêm bệnh nhân**, card edit | `AddPatientProfileModal.tsx`, `PatientProfileModal.tsx`, `patientStore.tsx` |
|
||||
| Cached AI grade on card | Shown after workspace inference warms cache | `useWorklistCachedAiGrades.ts`, `PatientCard.tsx` |
|
||||
|
||||
### 4.2 Load & review scan session (UC-48376, UC-47988)
|
||||
|
||||
| Capability | How to use | Primary files |
|
||||
|------------|------------|---------------|
|
||||
| Load patient frames | Auto on workspace open | `DiagnosticCanvas.tsx`, `getScanFramesForPatient()` |
|
||||
| Frame carousel | Prev/next or ribbon controls | `DiagnosticCanvas.tsx`, `AnnotationRibbon.tsx` |
|
||||
| Pan / zoom / draw / erase | Floating annotation ribbon on canvas | `useImageCanvasTools.ts`, `AnnotationRibbon.tsx` |
|
||||
| Toggle segmentation mask | Ribbon or parent mask toggle | `SegmentationOverlay.tsx`, `useSegmentationOverlay.ts` |
|
||||
| ML pipeline (angle → inflammation → seg → severity) | Automatic per frame via API | `segmentationApi.ts`, `cvAnalyzeApi.ts`, `interpretSegmentationResult.ts` |
|
||||
| Synovitis grade display | Zone B severity badge + metrics | `SeverityBadge.tsx`, `SideNavBar.tsx`, `synovitisSeverity.ts` |
|
||||
| Angle classification chip | Zone B blob + legend | `AngleClassificationBlob.tsx`, `angleClassification.ts` |
|
||||
| Calibration / tier tuning | Zone B calibration controls | `CalibrationControls.tsx`, `calibrationEngine.ts` |
|
||||
| ML error & retry | Inline panel on canvas | `MlServiceErrorPanel.tsx`, `mlServiceError.ts` |
|
||||
| Closed-loop draw prompt | Confirm region mask after closed stroke | `ClosedLoopPrompt.tsx` |
|
||||
|
||||
### 4.3 Human–AI dialogue & form (UC-25776 partial, UC-55146 partial)
|
||||
|
||||
| Capability | How to use | Primary files |
|
||||
|------------|------------|---------------|
|
||||
| Clinical chat panel | Type in Zone B chat; mock Socratic replies | `ClinicalChatPanel.tsx`, `clinicalChatMock.ts` |
|
||||
| Diagnostic form drawer | Open form from Zone B; auto-save draft | `DiagnosticFormDrawer.tsx`, `diagnosticFormDraftStore.ts` |
|
||||
| Diagnosis snapshot for chat | Captures canvas viewport image | `captureViewportSnapshot.ts`, `ClinicalWorkspacePage.tsx` |
|
||||
|
||||
### 4.4 Session record & replay (FR-02 analogue — partial)
|
||||
|
||||
Full interaction contract: [session_recording_frame_switch_spec.md](./session_recording_frame_switch_spec.md).
|
||||
|
||||
#### Recording scope
|
||||
|
||||
| Mode | Vietnamese UI | Behavior |
|
||||
|------|---------------|----------|
|
||||
| Single frame | **Một khung** | Pointer trace + DICOM event log on one frame; frame nav **locked only while `recording`** |
|
||||
| Multi-frame | **Nhiều khung** | Vector UIX event log (`UIXSessionEvent[]`) + segment timeline; frame nav allowed while recording/paused |
|
||||
|
||||
Mode selector: `RecordingModeSelector.tsx` (disabled during **Ghi** / **Tạm dừng**).
|
||||
|
||||
#### Toolbar & lifecycle
|
||||
|
||||
| Capability | How to use | Primary files |
|
||||
|------------|------------|---------------|
|
||||
| Start / pause / end recording | **Ghi** / **Tạm dừng** / **Kết thúc ghi** | `SessionLifecycleToolbar.tsx`, `sessionLifecycle.tsx` |
|
||||
| Recording mode | **Một khung** / **Nhiều khung** | `RecordingModeSelector.tsx`, `sessionRecordingIndexedDb.ts` |
|
||||
| Discard in-progress capture | **Hủy ghi** (confirm) — clears events, overlays, WAL session | `SessionCancelRecordDialog.tsx`, `confirmCancelRecording` |
|
||||
| New empty session | **Phiên mới** (confirm) — idle state, clears canvas log, keeps DICOM | `SessionNewSessionDialog.tsx`, `startNewRecordingSession` |
|
||||
| Save named bundle | **Lưu phiên** after **Kết thúc ghi** | `sessionRecordingIndexedDb.ts`, `SavedSessionsDialog.tsx` |
|
||||
| Load saved sessions | **Danh sách phiên** | `SavedSessionsDialog.tsx` |
|
||||
| Reset (legacy) | **Làm mới từ đầu** | `SessionResetConfirmDialog.tsx` |
|
||||
|
||||
#### Capture layers
|
||||
|
||||
| Layer | Single-frame | Multi-frame |
|
||||
|-------|--------------|-------------|
|
||||
| DICOM / viewport events | `useDicomFrameRecording.ts` | Same |
|
||||
| Pointer comet samples | `usePointerTraceRecording.ts` (`pointerTrace[]`) | UIX `MOUSE_MOVE` @ 30 Hz |
|
||||
| Overlay strokes | Segment checkpoint on end/switch | `OVERLAY_CREATE` / `MUTATE` / `DELETE` via `uixOverlayRecorderRegistry.ts` |
|
||||
| Crash-safe WAL | — | `uixSessionRecorder.worker.ts` → IndexedDB `pending_chunks` (24h TTL) |
|
||||
|
||||
#### Per-frame overlays (canvas)
|
||||
|
||||
Annotations are **isolated per `frameId`**: switching frames persists outgoing strokes and loads the target frame's overlay map. Replay restores progressive overlay state per frame. See `useImageCanvasTools.ts`, `DiagnosticCanvas.tsx`.
|
||||
|
||||
#### Replay
|
||||
|
||||
| Capability | How to use | Primary files |
|
||||
|------------|------------|---------------|
|
||||
| Continuous replay + timeline | Tab **Phát liên tục**, play/scrub/speed | `ReviewDiagnosticSessionPanel.tsx`, `useDiagnosticSessionReplay.ts` |
|
||||
| Step-by-step replay | Tab **Từng bước hành động** | Same panel + carousel mode |
|
||||
| Multi-frame chronological replay | Auto when saved bundle has `uixEvents` | `uixSessionReplayEngine.ts`, `uixSessionEvents.ts` |
|
||||
| Frame switch on replay | Engine applies `FRAME_SWITCH` → canvas index + DICOM | `ClinicalWorkspacePage.tsx` (`handleReplayFrameRestore`) |
|
||||
| Progressive overlay draw | `OVERLAY_MUTATE` grows strokes; pen color on ghost cursor | `ReplaySandboxOverlay.tsx`, `ReplayViewportState.penColor` |
|
||||
| Optional mouse comet | Checkbox **Hiển thị vết chuột (comet)** | `ReplaySandboxOverlay.tsx`, `sessionReplayNotesStore.ts` |
|
||||
| Session notes & edits | Per-step notes, session description, event title/detail edits | `sessionReplayNotesStore.ts` |
|
||||
|
||||
**Persistence:** in-progress capture in **`localStorage`** per `patientId`; committed bundles in **IndexedDB** (`lumina-session-recording`). Not EMR, not server (WAL backend transmit is PoC stub).
|
||||
|
||||
### 4.5 Finalize & sign (UC-92006 — UI shell only)
|
||||
|
||||
| Capability | How to use | Primary files |
|
||||
|------------|------------|---------------|
|
||||
| Open sign-off overlay | Top bar **Ký & Hoàn tất** | `DiagnosisSignOffOverlay.tsx`, `ClinicalWorkspacePage.tsx` |
|
||||
| Edit structured diagnostic draft | Fields in overlay | `data/diagnosticForm.ts` |
|
||||
| Confirm (local) | Clears draft in `localStorage` only | `diagnosticFormDraftStore.ts` |
|
||||
|
||||
No JWT signing, hash sealing, or EMR transmission is implemented in the front-end PoC.
|
||||
|
||||
---
|
||||
|
||||
## 5. FR-25 use-case traceability matrix
|
||||
|
||||
Legend: **✓** implemented (demo-ready) · **~** partial / mock · **—** not in prototype
|
||||
|
||||
| UC ID | Use case (short) | Quadrant | Coverage | Primary UI / code |
|
||||
|-------|------------------|----------|----------|-------------------|
|
||||
| UC-48376 | Load patient scan session | Intake | **✓** | `PatientWorklistPage`, `DiagnosticCanvas`, `useSegmentationOverlay` |
|
||||
| UC-47988 | Review suggested synovitis grade | Intake | **✓** | `SideNavBar`, `SeverityBadge`, `SegmentationOverlay` |
|
||||
| UC-92006 | Finalize & sign electronic record | Intake | **~** | `DiagnosisSignOffOverlay` (UI only) |
|
||||
| UC-25776 | GradCAM & CoT explanation panel | Q1 | **~** | Chat mock + severity copy; no real GradCAM tensor UI |
|
||||
| UC-02423 | Log high-trust concur block | Q1 | **—** | — |
|
||||
| UC-22159 | Conversational circuit breaker | Q2 | **—** | `SafetyEscalationOverlay` not mounted |
|
||||
| UC-55146 | Socratic reasoning dialogue | Q2 | **~** | `ClinicalChatPanel` (mock LLM) |
|
||||
| UC-74821 | BERT drift monitor | Q2 | **—** | — |
|
||||
| UC-65473 | RAG referee arbitration | Q2 | **—** | — |
|
||||
| UC-25637 | Expose pixel-level activation logic | Q3 | **~** | Segmentation overlay + legend; no GradCAM heatmap layer |
|
||||
| UC-60739 | Isolate visual noise / artifacts | Q3 | **~** | Draw/erase tools on canvas |
|
||||
| UC-62864 | Commit validated ground-truth | Q3 | **—** | — |
|
||||
| UC-35956 | Clinical investigation mode | Q4 | **—** | Overlay exists, not wired |
|
||||
| UC-47796 | Structured morphology annotation | Q4 | **—** | — |
|
||||
| UC-01580 | Serialize session to telemetry queue | Q4 | **—** | — |
|
||||
|
||||
### 5.1 Related product FRs (outside FR-25 UC pack)
|
||||
|
||||
| FR | Title (from user research) | Prototype relation |
|
||||
|----|----------------------------|--------------------|
|
||||
| FR-02 | Async voice-over annotation & timeline canvas | **Partial** — multi-frame UIX vector replay (pointer + overlay chronology + frame switch); no audio, no multi-user thread |
|
||||
| FR-01, FR-03–05 | Mobile haptics, sheets, 3D, patient portal | **Not implemented** in this desktop web PoC |
|
||||
|
||||
---
|
||||
|
||||
## 6. NFR touchpoints (UI-relevant)
|
||||
|
||||
| NFR | Requirement (summary) | How the prototype addresses it | Spec / code reference |
|
||||
|-----|----------------------|--------------------------------|------------------------|
|
||||
| NFR-1 | Collaborative rendering ≤ 3s | Batch analyze API + IndexedDB cache; worklist pre-warm | `ml-inference-cache.md`, `useSegmentationOverlay.ts` |
|
||||
| NFR-4 | Client memory ≤ 150 MB | Single-frame pipeline, PNG assets, no video replay | `Screen_Analysis_WS-25.md` §5.2 |
|
||||
| NFR-14 | Legacy hardware compatibility | CPU canvas + static PNG fallback path (no WebGL requirement) | `useImageCanvasTools.ts` |
|
||||
| NFR-16 | Air-gapped / governed egress | Front-end calls same-origin `/api/test` only; cloud LLM not wired in UI | `vite.config.ts`, `segmentationApi.ts` |
|
||||
|
||||
Other NFRs (availability, audit immutability, explanation factuality) are **backend / knowledge-layer** concerns; see `CODEBASE/backend/spec/` and `CODEBASE/knowledge/spec/`.
|
||||
|
||||
---
|
||||
|
||||
## 7. Sprint 1–2 mapping to design materials
|
||||
|
||||
| Design artifact | Role | Implemented in prototype |
|
||||
|-----------------|------|---------------------------|
|
||||
| `FR_25_UC_DESIGN/CONTEXT_FR_25_UC_ELIT.md` | FR-25 boundary, actors, quadrants | WS-25 layout + UC table above |
|
||||
| `FR_25_UC_DESIGN/Use_Case/FR_25_UC_SPEC.md` | Deep-dive UC flows | Intake UCs + partial Q1/Q2/Q3 |
|
||||
| `FR_25_UC_DESIGN/UI_Screen_Spec/Screen_Analysis_WS-25.md` | WS-25 rationale (65/35, no modal over image) | `WorkspaceShell`, carousel sidebar |
|
||||
| `FR_25_UC_DESIGN/Insight_note.md` | User research → FR-01…05 | Informs roadmap; FR-02 partial via replay |
|
||||
| `frontend/spec/DESIGN.md` | Tokens (mint glassmorphism) | `styles/global.css`, component inline tokens |
|
||||
| `frontend/spec/component-inventory.md` | Figma → component map | Atoms/molecules/organisms under `src/components/` |
|
||||
| `frontend/spec/figma-component-specs.md` | Figma node detail | Reference for future parity |
|
||||
| `CODEBASE/docs/ml-inference-cache.md` | PoC inference architecture | Live in workspace |
|
||||
|
||||
**Sprint folder:** `workspace/sprint_1_2/` — code under `CODEBASE/`, design under `Design_Material/`.
|
||||
|
||||
---
|
||||
|
||||
## 8. Recommended demo flows
|
||||
|
||||
### Flow A — Full FR-25 happy path (~5 min)
|
||||
|
||||
1. Open `/` → filter **Đang xử lý** → **Mở phiên chẩn đoán** (e.g. patient with low confidence).
|
||||
2. Wait for segmentation / grade in Zone B (backend proxy required — see `frontend_startup_and_build.md`).
|
||||
3. Toggle mask, pan/zoom, draw annotation on canvas.
|
||||
4. Open diagnostic form drawer → fill fields → close (draft auto-saved).
|
||||
5. Use clinical chat with a short question (mock reply).
|
||||
6. **Ký & Hoàn tất** → review draft → confirm (local only).
|
||||
|
||||
### Flow B — Multi-frame session record & replay (~5 min)
|
||||
|
||||
1. In workspace, open sidebar **Xem lại phiên chẩn đoán**.
|
||||
2. Select **Nhiều khung** → **Ghi**.
|
||||
3. Draw on frame 1 → switch frame (prev/next) → draw on frame 2 → toggle mask → **Kết thúc ghi**.
|
||||
4. **Lưu phiên** with a name → verify in **Danh sách phiên**.
|
||||
5. Load saved session → enable **Hiển thị vết chuột (comet)** → **Phát liên tục** → scrub across a frame switch and mid-stroke overlay.
|
||||
6. Confirm: correct frame image, strokes appear progressively in pen color, ghost cursor matches ink.
|
||||
7. Optional: **Hủy ghi** during capture or **Phiên mới** for a clean idle session without saving.
|
||||
|
||||
### Flow B2 — Single-frame record (~2 min)
|
||||
|
||||
1. Select **Một khung** → **Ghi** → interact (frame nav blocked) → **Kết thúc ghi** → replay with comet trail filtered to that frame.
|
||||
|
||||
### Flow C — Worklist & profiles (~2 min)
|
||||
|
||||
1. **Thêm bệnh nhân** → save → open new workspace.
|
||||
2. Return to worklist → edit patient card → verify search.
|
||||
|
||||
---
|
||||
|
||||
## 9. Source tree (implementation highlights)
|
||||
|
||||
```
|
||||
implementation/src/
|
||||
├── pages/
|
||||
│ ├── PatientWorklistPage.tsx # UC-48376 entry
|
||||
│ └── ClinicalWorkspacePage.tsx # WS-25 orchestration
|
||||
├── components/
|
||||
│ ├── organisms/
|
||||
│ │ ├── DiagnosticCanvas.tsx # Zone A canvas stack
|
||||
│ │ ├── SideNavBar.tsx # Zone B diagnosis layer
|
||||
│ │ ├── ReviewDiagnosticSessionPanel.tsx # Replay UI
|
||||
│ │ ├── ReplaySandboxOverlay.tsx # Ghost cursor + comet
|
||||
│ │ ├── DiagnosisSignOffOverlay.tsx
|
||||
│ │ └── DiagnosticFormDrawer.tsx
|
||||
│ ├── shells/
|
||||
│ │ ├── WorkspaceShell.tsx # 65/35 split
|
||||
│ │ └── PatientListShell.tsx
|
||||
│ └── molecules/
|
||||
│ ├── SessionLifecycleToolbar.tsx
|
||||
│ ├── RecordingModeSelector.tsx
|
||||
│ ├── SessionCancelRecordDialog.tsx
|
||||
│ ├── SessionNewSessionDialog.tsx
|
||||
│ ├── SavedSessionsDialog.tsx
|
||||
│ ├── ClinicalChatPanel.tsx
|
||||
│ └── …
|
||||
├── hooks/
|
||||
│ ├── useDiagnosticSessionReplay.ts # UIX + legacy segment replay
|
||||
│ ├── useDicomFrameRecording.ts
|
||||
│ ├── useImageCanvasTools.ts # Per-frame overlay maps
|
||||
│ ├── usePointerTraceRecording.ts
|
||||
│ └── useSegmentationOverlay.ts
|
||||
├── lib/
|
||||
│ ├── sessionLifecycle.tsx # Recording state machine
|
||||
│ ├── sessionLifecycleStore.ts # localStorage capture
|
||||
│ ├── sessionRecordingIndexedDb.ts # Saved bundles + mode pref
|
||||
│ ├── uixSessionEvents.ts # UIX event types + timeline
|
||||
│ ├── uixSessionRecorder.ts # Buffer + WAL bridge
|
||||
│ ├── uixSessionReplayEngine.ts # Chronological replay
|
||||
│ ├── uixSessionWalClient.ts # Main-thread WAL API
|
||||
│ ├── frameSegment.ts # Segment boundaries
|
||||
│ ├── segmentationApi.ts # /api/test client
|
||||
│ └── mlInferenceCacheStore.ts
|
||||
├── workers/
|
||||
│ └── uixSessionRecorder.worker.ts # IndexedDB WAL I/O
|
||||
└── data/
|
||||
├── mockData.ts # Seed patients
|
||||
├── diagnosticSessionReplay.ts # Event schema + mock timeline
|
||||
└── scanFrames.ts # Frame catalogue
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Known gaps & follow-ups
|
||||
|
||||
1. **SafetyEscalationOverlay** — built for UC-22159 / UC-35956 but not mounted in `App.tsx` or `ClinicalWorkspacePage.tsx`.
|
||||
2. **Target `frontend_spec.md` stack** — Zustand, Service Worker, WebCrypto, WebGL adapter not integrated.
|
||||
3. **Auth screens** — Figma inventory includes login/register; no routes in `App.tsx`.
|
||||
4. **EMR & audit** — Sign-off does not call backend; no immutable audit log UI.
|
||||
5. **Replay** — No audio; legacy single-frame uses short-window comet; multi-frame uses vector UIX timeline (not rrweb DOM replay). WAL backend sync is stubbed.
|
||||
6. **Extended offline** — WAL chunks persist locally; no **Đồng bộ phiên** UI yet.
|
||||
7. **Mobile** — WS-25 stacked layout spec exists; prototype is desktop-first (split collapses at 1024px).
|
||||
|
||||
---
|
||||
|
||||
## 11. Related documents
|
||||
|
||||
| Document | Path |
|
||||
|----------|------|
|
||||
| Front-end target architecture | `frontend/spec/frontend_spec.md` |
|
||||
| **Session recording & multi-frame replay** | `frontend/spec/session_recording_frame_switch_spec.md` |
|
||||
| Interface contract | `frontend/spec/interface_contract.md` |
|
||||
| Design tokens | `frontend/spec/DESIGN.md` |
|
||||
| Component inventory (Figma) | `frontend/spec/component-inventory.md` |
|
||||
| FR-25 UC context | `Design_Material/FR_25_UC_DESIGN/CONTEXT_FR_25_UC_ELIT.md` |
|
||||
| WS-25 screen analysis | `Design_Material/FR_25_UC_DESIGN/UI_Screen_Spec/Screen_Analysis_WS-25.md` |
|
||||
| ML cache PoC | `CODEBASE/docs/ml-inference-cache.md` |
|
||||
| Local run instructions | `frontend/spec/frontend_startup_and_build.md` |
|
||||
|
||||
---
|
||||
|
||||
*Maintainer: Web Experience / sprint_1_2 team. Update this file when new routes, UCs, or replay capabilities land in `implementation/`.*
|
||||
Reference in New Issue
Block a user