--- name: dyolink-lab-cases description: Lab Cases tab — list, filters, detail panel, assignment, share QR, card UX. Use when changing CasesPage, cases API, CaseDetailPanel, or case list cards. --- # Lab Cases tab **UI:** [`frontend/src/components/ui/lab/CasesPage.tsx`](frontend/src/components/ui/lab/CasesPage.tsx) **Backend:** [`backend/src/modules/cases/`](backend/src/modules/cases/) **Shared prosthesis rows:** [`LabCaseProsthesisGroupsList.tsx`](frontend/src/components/ui/lab/LabCaseProsthesisGroupsList.tsx) (also used in Treatment lab shipments rail) ## List behavior - **Default sort:** `sentAt` desc (newest first). - **Page size:** `PAGE_SIZE = 10` in `CasesPage.tsx`. - **Auto-select:** On tab open / after filter reload, select first list item if none selected; keep selection when still in list; `?caseId=` URL wins. - **Right panel:** Always shows detail for selected case when list non-empty (loading state while fetching). - **Left rail layout:** section is `flex flex-col` + `lg:min-h-[420px]` / `h-full` with `lg:items-stretch` on the grid; case list wrapper is `flex-1 min-h-0 overflow-y-auto` (do **not** use a fixed `max-h-[55vh]` — that leaves empty space above pagination). ## Filters (`GET /cases`) | Param | Behavior | |-------|----------| | `prosthesisTypeCode` | Cases with **≥1 task** of that prosthesis type (`tasks.some`) — not treatment-type filter | | `clinicOrganizationId` | From URL (`Today` case partners chart) or dropdown | | `q`, `sentFrom`, `sentTo` | Search + date range | Filter options: `GET /cases/filter-options` → `clinics`, `prosthesisTypes` (distinct codes from sent-case tasks, catalog-ordered). ## List card UI Match Treatment shipment cards: patient name, clinic, **colored prosthesis groups + teeth** (`LabCaseProsthesisGroupsList`), sent date, progress bar, due-date badge, unread dot. **No patient mobile** on list cards. List item shape: `prosthesisGroups: { prosthesisTypeCode, teeth[] }[]` from task teeth aggregation. ## Detail panel - Task assignment: `PATCH /cases/:caseId/tasks/:taskId/assign` (`TAB_CASES_EDIT`) - Comments: shared `LabCaseCommentsPanel` + `tasksApi` comment routes (`viewerSide="LAB"`). Newest-first; sent/received use logical start/end alignment (RTL-safe). Compact `h-9` composer with primary send + visibility controls. - Mark read: `POST /notifications/mark-case-read` on select (Cases tab badge) - **Share link (sent cases):** `shareUrl` on detail; attachment preview left + QR thumb right; `LabCaseShareQrDialog` (`react-qr-code`). Full flow: `.cursor/skills/lab-case-share-link/SKILL.md`. ## Permissions `TAB_CASES_READ` / `TAB_CASES_EDIT`; owner always has Cases access. `LabOrgGuard` on routes.