82 lines
4.0 KiB
Markdown
82 lines
4.0 KiB
Markdown
# Daily Zone Check-in Integration
|
|
|
|
## Purpose
|
|
|
|
Staff log a daily self-regulation "Emotional Zone" (blue/green/yellow/red).
|
|
The same state drives the dashboard check-in card, the `/zones-of-regulation`
|
|
overview cards, the profile unified results table, leader dashboard
|
|
completion/risk sections, and a notification-dropdown nudge when an eligible
|
|
user has not checked in today.
|
|
|
|
## Backend contract
|
|
|
|
`/api/zone_checkins` requires explicit `ZONE_CHECKIN` for personal reads/writes.
|
|
This personal workflow permission is not implied by `globalAccess`. The client
|
|
never computes the date; "today" is computed server-side from the user's campus
|
|
timezone, falling back to UTC for organization/school-scope staff without a
|
|
campus.
|
|
|
|
- `GET /today` → `{ date, zone, isCheckedInToday }`
|
|
- `POST /` `{ data: { zone } }` → record today's zone (upsert)
|
|
- `DELETE /today` → clear today's zone
|
|
- `GET /?from=&to=` → history `{ rows: [{ date, zone }], count }`
|
|
- `GET /completion` → leader/report scoped staff completion `{ summary, rows }`
|
|
with `READ_ZONE_CHECKIN_REPORTS`.
|
|
|
|
## Frontend Structure
|
|
|
|
- API/types: `shared/api/zoneCheckins.ts`, `shared/types/zoneCheckins.ts`
|
|
- Business: `business/zone-checkin/hooks.ts` (`useTodayZoneCheckIn`,
|
|
`useZoneCheckInHistory`, `useZoneCheckInCompletion`),
|
|
`business/zone-checkin/selectors.ts`
|
|
(`canZoneCheckIn`, `shouldNudgeZoneCheckIn`)
|
|
- Components: `components/zone-checkin/ZoneCheckInCard.tsx` (shared dashboard
|
|
card), `ZoneCheckInReminder.tsx` (banner), `ZoneCheckInSection.tsx` (composed
|
|
section), and the `/zones-of-regulation` overview cards.
|
|
|
|
## Behavior
|
|
|
|
- **Eligibility/nudge gating** requires the effective `ZONE_CHECKIN` permission.
|
|
Seed data grants it to staff users expected to complete the daily workflow
|
|
across organization, school, campus, and class scopes; custom permissions can
|
|
extend or remove it per user.
|
|
- **Dashboard**: the card is wired through `useDashboardPage` (which exposes
|
|
`showZoneCheckIn` + `needsZoneCheckIn`) with an optimistic shell value for snappy
|
|
selection.
|
|
- **Zones page**: the main zone overview cards call `useTodayZoneCheckIn`
|
|
through `useZonesOfRegulationPage`; selecting blue/green/yellow/red both opens
|
|
the zone detail panel and saves the eligible user's daily check-in. Parent
|
|
drill-down keeps the selection local and does not persist personal state; the
|
|
backend also rejects personal zone mutations in child scopes.
|
|
- **Notifications**: `business/top-bar` derives a single unread notification from
|
|
`shouldNudgeZoneCheckIn` (`buildTopBarNotifications`) — there is no backend
|
|
notifications store. The notification carries an `href`
|
|
(`APP_ROUTE_PATHS.zones`); clicking it navigates to `/zones-of-regulation`
|
|
(a react-router `Link`) and closes the dropdown.
|
|
- `useTodayZoneCheckIn` is disabled for users without `ZONE_CHECKIN` or when the
|
|
user is drilled into a child scope. Disabled callers receive empty local state
|
|
instead of stale cached check-in data. Its `error` surfaces **only**
|
|
save/clear failures; non-eligible users should not trigger the `/today`
|
|
request.
|
|
- **Leader dashboards**: `useDirectorDashboardPage` loads `useZoneCheckInCompletion`
|
|
with the effective tenant in its query key and appends Daily Zone Check-In rows
|
|
to the unified completion table. Non-green completed zones are shown as medium
|
|
risk in Risk Areas.
|
|
- **Profile**: the unified quiz/results table includes today's Daily Zone
|
|
Check-In for eligible users.
|
|
- **Content**: zone cards and page copy are backend-owned content catalog presets
|
|
(`regulation-zones`, `zones-of-regulation-page-content`) for new organizations.
|
|
|
|
## Tests
|
|
|
|
- `business/zone-checkin/selectors.test.ts` (eligibility + nudge),
|
|
`business/top-bar/selectors.test.ts` (notification builder + zones `href`),
|
|
`business/director-dashboard/selectors.test.ts`, `business/profile/selectors.test.ts`,
|
|
and `shared/api/zoneCheckins.test.ts`.
|
|
- Seeded e2e: `frontend/tests/e2e/zone-checkins.seeded.e2e.ts` (record /
|
|
read-back / clear today, invalid-zone rejection, external-role lockout).
|
|
|
|
## Verification
|
|
|
|
- `npm run typecheck`, `npm run lint`, `npm run test` pass.
|