40227-vm/frontend/docs/zone-checkin-integration.md

2.8 KiB

Daily Zone Check-in Integration

Purpose

Campus staff log a daily self-regulation "Emotional Zone" (blue/green/yellow/red). The same state drives three surfaces: the dashboard check-in card, the /zones-of-regulation page (reminder banner + card), and a notification-dropdown nudge when an eligible user has not checked in today.

Backend contract

/api/zone_checkins requires explicit ZONE_CHECKIN. This personal workflow permission is not implied by globalAccess. The client never computes the date; "today" is the campus-local date computed server-side from campuses.timezone.

  • 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 }

Frontend Structure

  • API/types: shared/api/zoneCheckins.ts, shared/types/zoneCheckins.ts
  • Business: business/zone-checkin/hooks.ts (useTodayZoneCheckIn, useZoneCheckInHistory), business/zone-checkin/selectors.ts (canZoneCheckIn, shouldNudgeZoneCheckIn)
  • Components: components/zone-checkin/ZoneCheckInCard.tsx (shared card), ZoneCheckInReminder.tsx (banner), ZoneCheckInSection.tsx (page section)

Behavior

  • Eligibility/nudge gating requires the effective ZONE_CHECKIN permission. Seed data grants it only to the campus staff workflow audience (director, office_manager, teacher, support_staff), but custom permissions can extend or remove it per user. Global/full-access leadership users do not see self-state nudges unless they receive explicit ZONE_CHECKIN.
  • Dashboard: the card is wired through useDashboardPage (which exposes showZoneCheckIn + needsZoneCheckIn) with an optimistic shell value for snappy selection.
  • Zones page: ZoneCheckInSection is self-contained (useTodayZoneCheckIn) and renders above the regulation content.
  • 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. Its error surfaces only save/clear failures; non-eligible users should not trigger the /today request.

Tests

  • business/zone-checkin/selectors.test.ts (eligibility + nudge), business/top-bar/selectors.test.ts (notification builder + zones href).
  • 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.