# Plan: Routines Feature ## Summary A "Routines" system lets parents define a named checklist of simple items (e.g., "Morning Routine": Make Bed, Get Dressed, Eat Breakfast) worth X points. Children see routines in a scrollable list between Chores and Rewards in child mode. Tapping a routine opens a detail view showing the item list; a "Done" button submits it for parent approval. Points are awarded on parent approval. Supports scheduling (days/interval), deadlines, time extension, and per-child point overrides — all parallel to the existing chore system. --- ## Key Design Decisions - **Routine items** are their own minimal entity (name + optional image, no points). Points belong to the routine. - **No per-item completion tracking** — detail screen is informational only. "Done" button submits the whole routine. - **Assignment**: per-child, same pattern as tasks (child.routines: list[str]). - **Parent approval**: approve/reject the whole routine (no item-level detail). - **Scheduling**: new RoutineSchedule model parallel to ChoreSchedule (same structure, routine_id instead of task_id). - **Point overrides**: reuse ChildOverride with entity_type='routine'. - **Pending confirmations**: extend PendingConfirmation entity_type to include 'routine'. - **Routine editor**: single-page with details section (name, points, image) + items sub-panel below. --- ## Phase 1: Backend Models & DB 1. Create `backend/models/routine.py` — fields: name, points, image_id, user_id (inherits BaseModel). Mirror Task model. 2. Create `backend/models/routine_item.py` — fields: routine_id, name, image_id, order (int). No points. 3. Create `backend/models/routine_schedule.py` — copy of ChoreSchedule replacing task_id→routine_id. Same DayConfig, modes, deadline fields. 4. Create `backend/models/routine_extension.py` — fields: child_id, routine_id, date (ISO). Mirror TaskExtension. 5. Extend `backend/models/pending_confirmation.py` — add 'routine' to entity_type Literal. 6. Extend `backend/models/child.py` — add `routines: list[str]` field (default=[]). 7. Create DB layers (mirror existing patterns): - `backend/db/routines.py` — get/add/update/delete/list by user - `backend/db/routine_items.py` — get_items_for_routine/add/update/delete/delete_for_routine - `backend/db/routine_schedules.py` — get/upsert/delete/delete_for_child/delete_for_routine - `backend/db/routine_extensions.py` — get/add/delete_for_child_routine 8. Extend `backend/db/child_overrides.py` entity_type to allow 'routine'. ## Phase 2: Backend SSE Events 9. Create event type files (mirror existing pattern): - `backend/events/types/routine_modified.py` — payload: routine_id, operation (ADD|EDIT|DELETE) - `backend/events/types/child_routines_set.py` — payload: child_id, routine_ids - `backend/events/types/routine_schedule_modified.py` — payload: child_id, routine_id, operation (SET|DELETED) - `backend/events/types/routine_time_extended.py` — payload: child_id, routine_id - `backend/events/types/child_routine_confirmation.py` — payload: child_id, routine_id, operation (PENDING|APPROVED|REJECTED|RESET) 10. Update `backend/events/types/event_types.py` — add: ROUTINE_MODIFIED, CHILD_ROUTINES_SET, ROUTINE_SCHEDULE_MODIFIED, ROUTINE_TIME_EXTENDED, CHILD_ROUTINE_CONFIRMATION ## Phase 3: Backend API 11. Create `backend/api/routine_api.py`: - `PUT /routine/add` — create routine - `GET /routine/` — fetch single - `GET /routine/list` — list by user - `PUT /routine//edit` — update - `DELETE /routine/` — delete (cascade: remove from all children, delete items, schedules, overrides) 12. Create `backend/api/routine_item_api.py`: - `PUT /routine//item/add` — add item - `PUT /routine//item//edit` — edit item name/image - `DELETE /routine//item/` — remove item - `GET /routine//items` — list items 13. Create `backend/api/child_routine_api.py`: - `POST /child//assign-routine` — add routine to child - `POST /child//remove-routine` — remove from child - `PUT /child//set-routines` — replace all assigned routines - `GET /child//list-routines` — list assigned routines with schedule, pending_status, extension_date, image_url, custom_value, and embedded items - `GET /child//list-assignable-routines` — routines not yet assigned - `POST /child//confirm-routine` — child submits routine as pending (creates PendingConfirmation entity_type='routine') - `POST /child//cancel-routine-confirmation` — cancel pending 14. Create `backend/api/routine_schedule_api.py`: - `GET /child//routine//schedule` — fetch - `PUT /child//routine//schedule` — create/update - `DELETE /child//routine//schedule` — delete - `POST /child//routine//extend` — extend deadline 15. Extend `backend/api/pending_confirmation.py`: - Add `GET /pending-confirmations?type=routine` support (or ensure existing endpoint includes routines) - Add `POST /child//approve-routine/` — approve (award points via override or routine.points) - Add `POST /child//reject-routine/` — reject - Add `POST /child//reset-routine/` — reset 16. Update `backend/api/child_api.py` — cascade delete routines/schedules/extensions when child deleted. 17. Update `backend/main.py` — register all new blueprints. ## Phase 4: TypeScript Models & API Helpers 18. Update `frontend/src/common/models.ts`: - Add `Routine` (id, name, points, image_id) - Add `RoutineItem` (id, routine_id, name, image_id, order) - Add `ChildRoutine` (extends Routine + custom_value, schedule, extension_date, pending_status, approved_at, items: RoutineItem[]) - Add `RoutineSchedule` (mirror ChoreSchedule with routine_id) - Add new SSE payload types: RoutineModifiedEventPayload, ChildRoutinesSetEventPayload, RoutineScheduleModifiedPayload, RoutineTimeExtendedPayload, ChildRoutineConfirmationPayload 19. Update `frontend/src/common/backendEvents.ts` — add new event type string constants. 20. Update `frontend/src/common/api.ts` — add helpers: confirmRoutine(), cancelRoutineConfirmation(), setChildRoutineOverride(). ## Phase 5: Frontend — Child Mode 21. Create `frontend/src/components/routine/RoutineDetailView.vue`: - Receives childId + routineId as route params - Fetches routine data (name, points, image, items list) via `GET /child//list-routines` (or dedicated detail endpoint) - Displays routine header (name, image, points) - Vertical card list of items (name + image, non-interactive) - "Done" button → RoutineConfirmDialog → calls confirmRoutine() → routine becomes 'pending' - If pending_status='pending': "Done" shows cancel dialog instead - If approved today: shows "COMPLETED" stamp (read-only) - If expired: shows "TOO LATE" (no action) - Back navigation to ChildView - Register SSE `child_routine_confirmation` to update status reactively 22. Update `frontend/src/components/child/ChildView.vue`: - Add `routines: ref` and `childRoutineListRef` - Add Routines `ScrollingList` between Chores list and Rewards list - fetchBaseUrl: `/api/child/${child.id}/list-routines` - itemKey: `'routines'` - filter-fn: filter by schedule (isScheduledToday equivalent for routines) - sort-fn: completed → pending → scheduled → general - getItemClass: similar chore-inactive logic for expired/completed - On routine click → navigate to RoutineDetailView route instead of triggering inline - Register new SSE handlers: routine_modified, child_routines_set, routine_schedule_modified, routine_time_extended, child_routine_confirmation - Expiry timer logic for routine deadlines (parallel to existing chore timer logic) 23. Add routes: - `/child/:id/routine/:routineId` → RoutineDetailView ## Phase 6: Frontend — Parent Mode (Routine Library) 24. Create `frontend/src/components/routine/RoutineEditor.vue`: - Top section: EntityEditForm-style fields — name (text), points (number), image picker - Bottom section: Items sub-panel - List of existing items (name + image thumbnail + delete button) - "Add item" row: inline input for name + optional image picker + confirm button - Each item has edit-in-place or edit button - Save button submits both routine details and item changes - On edit mode: pre-populate all fields and items 25. Create `frontend/src/views/parent/RoutinesView.vue`: - ItemList of all routines with add/edit/delete - Add → RoutineEditor (create mode) - Edit → RoutineEditor (edit mode) 26. Add parent routes under TaskSubNav (4th tab — "Routines"): - `/parent/tasks/routines` — library list (RoutinesView) - `/parent/tasks/routines/add` — create (RoutineEditor) - `/parent/tasks/routines/:id/edit` — edit (RoutineEditor) 27. Add tab to `frontend/src/components/task/TaskSubNav.vue` — "Routines" tab pointing to `/parent/tasks/routines` ## Phase 7: Frontend — Parent Mode (Per-Child Routine Management) 28. Extend ParentView (or child management component) to include a "Routines" section per child: - ItemList showing child's assigned routines - Assign button → RoutineAssignView (parallel to ChoreAssignView) - Kebab menu per routine item: - "Edit Routine" → navigate to `/parent/tasks/routines/:id/edit` - "Set Schedule" → open ScheduleModal with entityType='routine' - "Edit Points" → set ChildOverride with entity_type='routine' - "Extend Deadline" → call extend endpoint - Register SSE events to refresh list: routine_modified, child_routines_set, routine_schedule_modified, routine_time_extended, child_routine_confirmation, child_override_set 29. Create `frontend/src/components/routine/RoutineAssignView.vue` — selectable ItemList of unassigned routines (parallel to ChoreAssignView). 30. Extend pending confirmation approval UI — if entity_type='routine', fetch routine name and show in approval card. Approve → POST approve-routine endpoint. Reject → POST reject-routine. ## Phase 8: Push Notifications for Routine Pending 31. In `backend/api/child_routine_api.py` — after creating the PendingConfirmation for a routine, call `send_push_to_user(user_id, payload)` (mirror `child_api.py` chore confirmation pattern). Payload: `type='routine_confirmed'`, title = "Routine Pending", body = "{child_name} completed {routine_name}", include approve/reject action tokens. ## Phase 9: ScheduleModal entityType Refactor 32. Refactor `ScheduleModal.vue` — replace hard-coded `task_id` with `entityType: 'task' | 'routine'` + `entityId` props. All API calls to `.../schedule` and `.../extend` switch on `entityType` to route to either `/child//task//...` or `/child//routine//...`. 33. Update all current ScheduleModal usages to explicitly pass `entityType='task'` so existing behavior is preserved. 34. Routine kebab "Set Schedule" passes `entityType='routine'`. --- ## Relevant Files **New backend:** - `backend/models/routine.py`, `routine_item.py`, `routine_schedule.py`, `routine_extension.py` - `backend/db/routines.py`, `routine_items.py`, `routine_schedules.py`, `routine_extensions.py` - `backend/api/routine_api.py`, `routine_item_api.py`, `child_routine_api.py`, `routine_schedule_api.py` - `backend/events/types/routine_modified.py`, `child_routines_set.py`, `routine_schedule_modified.py`, `routine_time_extended.py`, `child_routine_confirmation.py` **Modified backend:** - `backend/models/child.py` — add routines field - `backend/models/pending_confirmation.py` — extend entity_type Literal - `backend/db/child_overrides.py` — allow 'routine' entity_type - `backend/api/child_api.py` — cascade deletes - `backend/api/pending_confirmation.py` — routine approval endpoints - `backend/events/types/event_types.py` — new constants - `backend/main.py` — register blueprints **New frontend:** - `frontend/src/components/routine/RoutineEditor.vue` - `frontend/src/components/routine/RoutineDetailView.vue` - `frontend/src/components/routine/RoutineAssignView.vue` - `frontend/src/views/parent/RoutinesView.vue` **Modified frontend:** - `frontend/src/common/models.ts` — new interfaces + SSE payload types - `frontend/src/common/backendEvents.ts` — new event constants - `frontend/src/common/api.ts` — new helpers - `frontend/src/components/child/ChildView.vue` — add routines list + navigation - `frontend/src/components/task/TaskSubNav.vue` — add Routines tab - `frontend/src/components/shared/ScheduleModal.vue` — entityType refactor - ParentView component — add routines section - Router — new routes **Reference patterns:** - `backend/api/chore_api.py` + `chore_schedule_api.py` — mirror for routine equivalents - `backend/models/chore_schedule.py` — copy for RoutineSchedule - `backend/models/task_extension.py` — copy for routine_extension.py - `frontend/src/components/shared/ScrollingList.vue` — reuse for routines in child view - `frontend/src/components/shared/EntityEditForm.vue` — reuse in RoutineEditor top section - `backend/utils/push_sender.py` + `child_api.py` chore confirm (~L1186) — push notification pattern --- ## Verification 1. Create a routine with 2+ items via Tasks → Routines tab, assign to a child, verify it appears in child view 2. Child submits "Done" → push notification fires → pending confirmation appears in parent view → approve → points credited 3. Reject flow → no points awarded 4. Schedule a routine for specific days → verify it only appears on those days 5. Set a deadline → verify "TOO LATE" stamp after deadline passes 6. Extend deadline via kebab → verify stamp removed for that day 7. Set per-child point override → verify override value shown and applied on approval 8. Delete routine → cascades (removed from children, items/schedules/extensions/overrides deleted) 9. SSE: parent sees routine confirmation in notifications without page refresh 10. ScheduleModal: existing chore schedule still works after entityType refactor --- ## Out of Scope - Reordering routine items (order field exists but no drag-and-drop UI planned) - Per-item completion tracking