All checks were successful
Chore App Build, Test, and Push Docker Images / build-and-push (push) Successful in 2m25s
- Updated BASE_VERSION in version.py to 1.0.15. - Added ROUTINES-IMPLEMENTATION-SUMMARY.md detailing the implementation status, phases, and test coverage for the new routines feature. - Created e2e-routines-test-plan.md outlining the end-to-end test strategy for the routines feature. - Introduced plan-routinesFeature.prompt.md to summarize the design and implementation plan for the routines feature.
232 lines
14 KiB
Markdown
232 lines
14 KiB
Markdown
# 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/<id>` — fetch single
|
|
- `GET /routine/list` — list by user
|
|
- `PUT /routine/<id>/edit` — update
|
|
- `DELETE /routine/<id>` — delete (cascade: remove from all children, delete items, schedules, overrides)
|
|
12. Create `backend/api/routine_item_api.py`:
|
|
- `PUT /routine/<routine_id>/item/add` — add item
|
|
- `PUT /routine/<routine_id>/item/<item_id>/edit` — edit item name/image
|
|
- `DELETE /routine/<routine_id>/item/<item_id>` — remove item
|
|
- `GET /routine/<routine_id>/items` — list items
|
|
13. Create `backend/api/child_routine_api.py`:
|
|
- `POST /child/<id>/assign-routine` — add routine to child
|
|
- `POST /child/<id>/remove-routine` — remove from child
|
|
- `PUT /child/<id>/set-routines` — replace all assigned routines
|
|
- `GET /child/<id>/list-routines` — list assigned routines with schedule, pending_status, extension_date, image_url, custom_value, and embedded items
|
|
- `GET /child/<id>/list-assignable-routines` — routines not yet assigned
|
|
- `POST /child/<id>/confirm-routine` — child submits routine as pending (creates PendingConfirmation entity_type='routine')
|
|
- `POST /child/<id>/cancel-routine-confirmation` — cancel pending
|
|
14. Create `backend/api/routine_schedule_api.py`:
|
|
- `GET /child/<child_id>/routine/<routine_id>/schedule` — fetch
|
|
- `PUT /child/<child_id>/routine/<routine_id>/schedule` — create/update
|
|
- `DELETE /child/<child_id>/routine/<routine_id>/schedule` — delete
|
|
- `POST /child/<child_id>/routine/<routine_id>/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/<id>/approve-routine/<confirmation_id>` — approve (award points via override or routine.points)
|
|
- Add `POST /child/<id>/reject-routine/<confirmation_id>` — reject
|
|
- Add `POST /child/<id>/reset-routine/<confirmation_id>` — 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/<id>/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<string[]>` 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/<childId>/task/<entityId>/...` or `/child/<childId>/routine/<entityId>/...`.
|
|
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
|