# Health Care Admin Page Design ## Summary Add a dedicated management route under `/settings/health` for persisted elder health data. This keeps operational navigation (`/health`) separate from backend data administration, matching the user's direction to split the management surface into its own page. ## Route Boundary - Unscoped route: `app/(app)/app/settings/health/page.tsx` - Scoped route: `app/(app)/app/[organizationSlug]/settings/health/page.tsx` - Optional redirect source: none in MVP. `/app/health` stays independent. - Navigation: add a management item under `管理系统`. - Breadcrumbs: add `"/settings/health": "健康数据管理"`. The page should follow existing settings pages: 1. Server Component loads `getCurrentAuthContext()`. 2. Redirect unauthenticated users to `/login`. 3. Redirect users without `health:read` back to a safe workspace route. 4. Load persisted initial data through server helpers. 5. Render a focused Client Component for filtering and mutation UI. ## Data Model All tables use `organizationId` for tenant scope and `createdAt` / `updatedAt` timestamps. ### `health_profiles` - `id` - `organizationId` - `elderId` - `allergyNotes` - `medicalHistory` - `medicationNotes` - `careRestrictions` - `emergencyNotes` - `createdAt` - `updatedAt` Constraint: unique `(organizationId, elderId)` so each elder has one admin health profile. ### `vital_records` - `id` - `organizationId` - `elderId` - `recordedAt` - `source`: `manual | device | import` - `systolicBp` - `diastolicBp` - `heartRate` - `temperatureTenths` - `spo2` - `bloodGlucoseTenths` - `weightTenths` - `notes` - `createdByAccountId` - `createdAt` - `updatedAt` Integer tenths avoid PostgreSQL numeric string handling for MVP decimal values. ### `chronic_conditions` - `id` - `organizationId` - `elderId` - `name` - `status`: `active | controlled | resolved` - `diagnosedAt` - `treatmentNotes` - `followUpNotes` - `createdAt` - `updatedAt` ### `health_anomaly_reviews` - `id` - `organizationId` - `elderId` - `vitalRecordId` - `severity`: `info | warning | critical` - `status`: `pending | reviewed | resolved` - `title` - `description` - `reviewedByAccountId` - `reviewedAt` - `resolutionNotes` - `createdAt` - `updatedAt` `vitalRecordId` is nullable so reviews can also be created directly against an elder health concern. ## Server Helpers Create `modules/health/`: - `modules/health/types.ts` - shared enum values, labels, API DTO types, and validators. - `modules/health/server/operations.ts` - `listHealthAdminData(organizationId: string)` - `upsertHealthProfile(...)` - `createVitalRecord(...)` - `createChronicCondition(...)` - `updateHealthReview(...)` - `modules/health/components/HealthAdminClient.tsx` - client-side tabs, filters, dialogs/forms, optimistic-free refresh. Server reads should batch queries by organization and join elders once. Avoid per-elder database calls. ## API Design MVP route handlers: - `GET /api/health/admin` - permission: `health:read` - returns metrics, elders, profiles, recent vitals, chronic conditions, reviews. - `PUT /api/health/profiles/[elderId]` - permission: `health:manage` - validates elder belongs to active organization. - upserts one profile. - `POST /api/health/vitals` - permission: `health:manage` - validates elder belongs to active organization. - creates vital record. - may create a pending review if values exceed MVP thresholds. - `POST /api/health/chronic-conditions` - permission: `health:manage` - validates elder belongs to active organization. - creates chronic condition. - `PATCH /api/health/reviews/[id]` - permission: `health:manage` - validates review belongs to active organization. - updates status and review metadata. All responses use `ApiResult`. ## Permission Design Update `modules/core/types.ts` and `modules/core/server/permissions.ts`: - Add `health:read` - Add `health:manage` - Add permission definitions in category `健康` - Grant defaults: - `org_admin`: read/manage - `manager`: read/manage - `caregiver`: read/manage unless user chooses stricter admin-only behavior - `viewer`: read This avoids overloading `elder:update` for a separate health management page. ## UI Design The page should look like an internal management console: - Header: `健康数据管理`, short description, manage badge if allowed. - Metrics: elders with profiles, vitals today, active chronic conditions, pending reviews. - Tabs: - `健康档案`: elder list with profile completeness and edit dialog. - `生命体征`: recent vitals table and add-vital dialog. - `慢病记录`: condition table and add-condition dialog. - `异常复核`: pending/reviewed/resolved queue with review action. - Filters: elder search, status/severity select, source select where useful. Keep tables and cards dense; no landing-page composition. ## Compatibility And Rollback - Existing `/app/health` remains unchanged in MVP, limiting frontend blast radius. - New tables are additive; rollback is dropping the generated health tables/enums and removing nav/API/page files. - Existing seed file has uncommitted work. Implementation must read and preserve user changes in `modules/core/server/default-workspace-data.ts` before adding health seed rows. ## Validation Required: - `pnpm db:generate` - Review generated SQL in `drizzle/` - `pnpm lint` - `pnpm type-check` - `pnpm build` Manual checks: - login as authorized user and open `/app/{slug}/settings/health` - create/update a health profile - create a vital record - create or review an abnormal item - verify reload persists records - verify mutation with insufficient permission returns `403`