improvement: some new gadgets added to dashboard. some new functionality added to existed gadgets.
This commit is contained in:
@@ -28,4 +28,8 @@ Dates/times/numbers: `frontend/src/lib/i18n/format.ts` + `useLocale()`. **Form d
|
||||
|
||||
## Treatment / appointment colors
|
||||
|
||||
Treatment-type colors and labels: `components/shared/treatmentTypeDisplay.ts` + `catalog-type-colors.ts`. UI badges: `components/ui/treatment/TreatmentTypeBadge.tsx`.
|
||||
Treatment-type colors and labels: `components/shared/treatmentTypeDisplay.ts` + `catalog-type-colors.ts`. UI badges: `components/ui/treatment/TreatmentTypeBadge.tsx`. **Prosthesis** colors/labels: `components/treatment/prosthesisTypeDisplay.ts` — use on lab Cases/Tasks/Today charts.
|
||||
|
||||
## Today dashboard
|
||||
|
||||
CLINIC + LAB KPIs/charts in `modules/today/today.service.ts`. Deep links: `components/today/today-deep-links.ts`. Task KPIs need `TAB_TASKS_READ` (no owner bypass). Skill: `.cursor/skills/today-dashboard/SKILL.md`.
|
||||
|
||||
14
.cursor/rules/lab-cases.mdc
Normal file
14
.cursor/rules/lab-cases.mdc
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
description: Lab Cases tab — prosthesis filter, auto-select, list cards
|
||||
globs: frontend/src/components/ui/lab/CasesPage.tsx,frontend/src/components/ui/lab/CaseDetailPanel.tsx,frontend/src/components/ui/lab/LabCaseProsthesisGroupsList.tsx,frontend/src/components/lab/caseDetailUtils.ts,backend/src/modules/cases/**
|
||||
alwaysApply: false
|
||||
---
|
||||
|
||||
# Lab Cases
|
||||
|
||||
- **Filter by prosthesis**, not treatment type — `prosthesisTypeCode`; matches cases with **any task** of that type.
|
||||
- **Auto-select** newest case on tab open; right panel never empty when list has items; `?caseId=` deep link overrides.
|
||||
- **List cards:** `LabCaseProsthesisGroupsList` (catalog color + teeth); same component as Treatment shipments rail; no patient mobile on card.
|
||||
- **Assignment** in detail only (`TAB_CASES_EDIT`); task status changes on Tasks tab.
|
||||
|
||||
Skill: `.cursor/skills/lab-cases/SKILL.md`
|
||||
@@ -14,5 +14,6 @@ alwaysApply: false
|
||||
- **Case due dates:** clinic sets in Treatment lab dispatch; lab sees on Cases/Tasks; `overdue` filter + `sortBy=dueDate` on Tasks.
|
||||
- **Mobile UX:** `LAB_TASK_STATUS_SELECT_CLASS` (44px tap target on small screens); `TaskCaseGroupHeader` sticky while scrolling grouped tasks; filter selects use same touch sizing on Tasks.
|
||||
- **Show in case:** `GET /tasks/locate-page` finds page in full list; highlight + scroll.
|
||||
- **Today deep links:** `parseTasksSearchParams` + `prosthesisTypeCode` / `unassignedOnly` / `overdueOnly` query params on Tasks.
|
||||
|
||||
Full map: `.cursor/skills/lab-tasks/SKILL.md`
|
||||
|
||||
42
.cursor/skills/lab-cases/SKILL.md
Normal file
42
.cursor/skills/lab-cases/SKILL.md
Normal file
@@ -0,0 +1,42 @@
|
||||
---
|
||||
name: dyolink-lab-cases
|
||||
description: Lab Cases tab — list, filters, detail panel, assignment, card UX. Use when changing CasesPage, cases API, 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).
|
||||
- **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).
|
||||
|
||||
## 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
|
||||
- Mark read: `POST /notifications/mark-case-read` on select (Cases tab badge)
|
||||
|
||||
## Permissions
|
||||
|
||||
`TAB_CASES_READ` / `TAB_CASES_EDIT`; owner always has Cases access. `LabOrgGuard` on routes.
|
||||
@@ -40,6 +40,8 @@ Components: `TaskCaseGroupHeader`, `TaskProsthesisGroupHeader`, `TaskRow`.
|
||||
| `stepCompleted` | `GET /tasks` | Workflow step dropdown |
|
||||
| `pinImportant` | `GET /tasks` | Important first (sort pin) |
|
||||
| `assignedToMe` | `GET /tasks` | Only tasks assigned to current user |
|
||||
| `prosthesisTypeCode` | `GET /tasks` | From Today prosthesis chart deep link |
|
||||
| `unassignedOnly` | `GET /tasks` | Tasks with no assignee |
|
||||
| `overdue` | `GET /tasks` | Cases with due date before today and at least one in-progress task |
|
||||
| `sortBy=dueDate` | `GET /tasks` | Sort by `LabCase.dueDate` (flat list; grouping off) |
|
||||
| Clinics + steps options | `GET /tasks/filter-options` | Populates dropdowns (not from current page) |
|
||||
@@ -55,6 +57,7 @@ Components: `TaskCaseGroupHeader`, `TaskProsthesisGroupHeader`, `TaskRow`.
|
||||
- **Overdue cases:** `overdue=true` — `LabCase.dueDate` before start of UTC day **and** at least one task still `IN_PROGRESS`. Shown with error badge on Cases list/detail and task case headers.
|
||||
- **Sort by due date:** `sortBy=dueDate` — flat list (grouping off); tiebreakers match other non-date sorts.
|
||||
- **Reset view:** `resetView` restores `DEFAULT_TASKS_VIEW` from `tasksViewDefaults.ts`.
|
||||
- **URL state:** `parseTasksSearchParams` applies Today deep-link query params on mount (`importantOnly`, `overdueOnly`, `unassignedOnly`, `prosthesisTypeCode`, `status`, sort).
|
||||
- **Show in case:** flat-sort rows only; resets filters/sort, calls `GET /tasks/locate-page` to find the correct page in the full default-sorted list, then highlights + scrolls to the task.
|
||||
- **Complete animation:** when marking done under in-progress filter, row plays exit animation + success toast before refetch.
|
||||
|
||||
|
||||
50
.cursor/skills/today-dashboard/SKILL.md
Normal file
50
.cursor/skills/today-dashboard/SKILL.md
Normal file
@@ -0,0 +1,50 @@
|
||||
---
|
||||
name: dyolink-today-dashboard
|
||||
description: Today tab dashboard — KPIs, charts, deep links, gadget registry. Use when adding/changing Today widgets, chart clicks, or tab navigation from Today.
|
||||
---
|
||||
|
||||
# Today dashboard
|
||||
|
||||
**UI:** [`frontend/src/components/ui/today/TodayDashboard.tsx`](frontend/src/components/ui/today/TodayDashboard.tsx)
|
||||
**Backend:** [`backend/src/modules/today/today.service.ts`](backend/src/modules/today/today.service.ts)
|
||||
**Registry:** [`frontend/src/components/today/widget-registry.ts`](frontend/src/components/today/widget-registry.ts)
|
||||
**Deep links:** [`frontend/src/components/today/today-deep-links.ts`](frontend/src/components/today/today-deep-links.ts)
|
||||
**Gadget order:** [`frontend/src/components/today/today-gadget-order.ts`](frontend/src/components/today/today-gadget-order.ts)
|
||||
|
||||
## Adding a KPI widget
|
||||
|
||||
1. `TodayWidgetKey` in [`frontend/src/types/today.ts`](frontend/src/types/today.ts)
|
||||
2. Loader in `today.service.ts` (gate with same permission as target tab)
|
||||
3. Entry in `TODAY_KPI_DEFINITIONS` — `isVisible`, `formatValue`, `href` or `resolveHref(widgets)` for dynamic links
|
||||
4. `TODAY_KPI_GADGET_FEATURE` in `today-gadget-order.ts`
|
||||
5. i18n `today.widget*` keys in **en, fa, nl**
|
||||
|
||||
KPIs with count `0` still register; `getVisibleTodayKpis` hides when `formatValue` returns `null` (widget missing from API).
|
||||
|
||||
## Deep links & chart clicks
|
||||
|
||||
| Source | Target |
|
||||
|--------|--------|
|
||||
| Task KPIs | `/tasks?…` via `todayDeepLinks` + `parseTasksSearchParams` |
|
||||
| Tasks by prosthesis chart (LAB) | `tasksByProsthesis(code)` |
|
||||
| Case partners chart (LAB) | `casesByClinic(clinicOrgId)` |
|
||||
| Providers w/o hours (CLINIC) | `staffMissingWorkingHours(membershipIds)` — widget returns `membershipIds[]`; Staff highlights rows (`STAFF_ROW_HIGHLIGHT_CLASS`) |
|
||||
|
||||
Use `useRouter` from `@/i18n/navigation` for chart clicks. KPI cards use `Link`/`href` on `KpiCard`.
|
||||
|
||||
## Charts (LAB examples)
|
||||
|
||||
- **Tasks by prosthesis** — `TodayBarChart` + `colorForCode` from prosthesis catalog; `canViewTasks`
|
||||
- **Cases due this week** — `casesDueWeek` buckets (next 7 local days); active sent cases with due date + in-progress task; `canViewCases`; empty card still shown
|
||||
- **Lab task activity** — stacked week chart; `canViewCases \|\| canViewTasks`
|
||||
|
||||
Week day labels: `useTodayDayLabelFormatter` + `mapWeekChartBuckets`.
|
||||
|
||||
## Permissions (task KPIs)
|
||||
|
||||
`TAB_TASKS_READ` / `TAB_TASKS_EDIT` — **no owner bypass** (unlike Cases). LAB owner needs tasks participation opt-in for task gadgets.
|
||||
|
||||
## Deferred / planned
|
||||
|
||||
- **Unread lab updates** (clinic KPI) → `/treatment?labUpdates=1`, scope `updates`, highlight first unread shipment (reuse `GET /treatments/lab-cases/unread`)
|
||||
- Treatment mix bar click, lab pending send KPI, lab activity day click
|
||||
Reference in New Issue
Block a user