# 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`
