5.6 KiB
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/healthstays independent. - Navigation: add a management item under
管理系统. - Breadcrumbs: add
"/settings/health": "健康数据管理".
The page should follow existing settings pages:
- Server Component loads
getCurrentAuthContext(). - Redirect unauthenticated users to
/login. - Redirect users without
health:readback to a safe workspace route. - Load persisted initial data through server helpers.
- 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
idorganizationIdelderIdallergyNotesmedicalHistorymedicationNotescareRestrictionsemergencyNotescreatedAtupdatedAt
Constraint: unique (organizationId, elderId) so each elder has one admin health profile.
vital_records
idorganizationIdelderIdrecordedAtsource:manual | device | importsystolicBpdiastolicBpheartRatetemperatureTenthsspo2bloodGlucoseTenthsweightTenthsnotescreatedByAccountIdcreatedAtupdatedAt
Integer tenths avoid PostgreSQL numeric string handling for MVP decimal values.
chronic_conditions
idorganizationIdelderIdnamestatus:active | controlled | resolveddiagnosedAttreatmentNotesfollowUpNotescreatedAtupdatedAt
health_anomaly_reviews
idorganizationIdelderIdvitalRecordIdseverity:info | warning | criticalstatus:pending | reviewed | resolvedtitledescriptionreviewedByAccountIdreviewedAtresolutionNotescreatedAtupdatedAt
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.tslistHealthAdminData(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.
- permission:
PUT /api/health/profiles/[elderId]- permission:
health:manage - validates elder belongs to active organization.
- upserts one profile.
- permission:
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.
- permission:
POST /api/health/chronic-conditions- permission:
health:manage - validates elder belongs to active organization.
- creates chronic condition.
- permission:
PATCH /api/health/reviews/[id]- permission:
health:manage - validates review belongs to active organization.
- updates status and review metadata.
- permission:
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/managemanager: read/managecaregiver: read/manage unless user chooses stricter admin-only behaviorviewer: 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/healthremains 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.tsbefore adding health seed rows.
Validation
Required:
pnpm db:generate- Review generated SQL in
drizzle/ pnpm lintpnpm type-checkpnpm 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