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.
14 KiB
14 KiB
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
- Create
backend/models/routine.py— fields: name, points, image_id, user_id (inherits BaseModel). Mirror Task model. - Create
backend/models/routine_item.py— fields: routine_id, name, image_id, order (int). No points. - Create
backend/models/routine_schedule.py— copy of ChoreSchedule replacing task_id→routine_id. Same DayConfig, modes, deadline fields. - Create
backend/models/routine_extension.py— fields: child_id, routine_id, date (ISO). Mirror TaskExtension. - Extend
backend/models/pending_confirmation.py— add 'routine' to entity_type Literal. - Extend
backend/models/child.py— addroutines: list[str]field (default=[]). - Create DB layers (mirror existing patterns):
backend/db/routines.py— get/add/update/delete/list by userbackend/db/routine_items.py— get_items_for_routine/add/update/delete/delete_for_routinebackend/db/routine_schedules.py— get/upsert/delete/delete_for_child/delete_for_routinebackend/db/routine_extensions.py— get/add/delete_for_child_routine
- Extend
backend/db/child_overrides.pyentity_type to allow 'routine'.
Phase 2: Backend SSE Events
- 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_idsbackend/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_idbackend/events/types/child_routine_confirmation.py— payload: child_id, routine_id, operation (PENDING|APPROVED|REJECTED|RESET)
- 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
- Create
backend/api/routine_api.py:PUT /routine/add— create routineGET /routine/<id>— fetch singleGET /routine/list— list by userPUT /routine/<id>/edit— updateDELETE /routine/<id>— delete (cascade: remove from all children, delete items, schedules, overrides)
- Create
backend/api/routine_item_api.py:PUT /routine/<routine_id>/item/add— add itemPUT /routine/<routine_id>/item/<item_id>/edit— edit item name/imageDELETE /routine/<routine_id>/item/<item_id>— remove itemGET /routine/<routine_id>/items— list items
- Create
backend/api/child_routine_api.py:POST /child/<id>/assign-routine— add routine to childPOST /child/<id>/remove-routine— remove from childPUT /child/<id>/set-routines— replace all assigned routinesGET /child/<id>/list-routines— list assigned routines with schedule, pending_status, extension_date, image_url, custom_value, and embedded itemsGET /child/<id>/list-assignable-routines— routines not yet assignedPOST /child/<id>/confirm-routine— child submits routine as pending (creates PendingConfirmation entity_type='routine')POST /child/<id>/cancel-routine-confirmation— cancel pending
- Create
backend/api/routine_schedule_api.py:GET /child/<child_id>/routine/<routine_id>/schedule— fetchPUT /child/<child_id>/routine/<routine_id>/schedule— create/updateDELETE /child/<child_id>/routine/<routine_id>/schedule— deletePOST /child/<child_id>/routine/<routine_id>/extend— extend deadline
- Extend
backend/api/pending_confirmation.py:- Add
GET /pending-confirmations?type=routinesupport (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
- Add
- Update
backend/api/child_api.py— cascade delete routines/schedules/extensions when child deleted. - Update
backend/main.py— register all new blueprints.
Phase 4: TypeScript Models & API Helpers
- 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
- Add
- Update
frontend/src/common/backendEvents.ts— add new event type string constants. - Update
frontend/src/common/api.ts— add helpers: confirmRoutine(), cancelRoutineConfirmation(), setChildRoutineOverride().
Phase 5: Frontend — Child Mode
- 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_confirmationto update status reactively
- Update
frontend/src/components/child/ChildView.vue:- Add
routines: ref<string[]>andchildRoutineListRef - Add Routines
ScrollingListbetween 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
- fetchBaseUrl:
- 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)
- Add
- Add routes:
/child/:id/routine/:routineId→ RoutineDetailView
Phase 6: Frontend — Parent Mode (Routine Library)
- 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
- Create
frontend/src/views/parent/RoutinesView.vue:- ItemList of all routines with add/edit/delete
- Add → RoutineEditor (create mode)
- Edit → RoutineEditor (edit mode)
- 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)
- 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)
- 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
- "Edit Routine" → navigate to
- Register SSE events to refresh list: routine_modified, child_routines_set, routine_schedule_modified, routine_time_extended, child_routine_confirmation, child_override_set
- Create
frontend/src/components/routine/RoutineAssignView.vue— selectable ItemList of unassigned routines (parallel to ChoreAssignView). - 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
- In
backend/api/child_routine_api.py— after creating the PendingConfirmation for a routine, callsend_push_to_user(user_id, payload)(mirrorchild_api.pychore 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
- Refactor
ScheduleModal.vue— replace hard-codedtask_idwithentityType: 'task' | 'routine'+entityIdprops. All API calls to.../scheduleand.../extendswitch onentityTypeto route to either/child/<childId>/task/<entityId>/...or/child/<childId>/routine/<entityId>/.... - Update all current ScheduleModal usages to explicitly pass
entityType='task'so existing behavior is preserved. - Routine kebab "Set Schedule" passes
entityType='routine'.
Relevant Files
New backend:
backend/models/routine.py,routine_item.py,routine_schedule.py,routine_extension.pybackend/db/routines.py,routine_items.py,routine_schedules.py,routine_extensions.pybackend/api/routine_api.py,routine_item_api.py,child_routine_api.py,routine_schedule_api.pybackend/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 fieldbackend/models/pending_confirmation.py— extend entity_type Literalbackend/db/child_overrides.py— allow 'routine' entity_typebackend/api/child_api.py— cascade deletesbackend/api/pending_confirmation.py— routine approval endpointsbackend/events/types/event_types.py— new constantsbackend/main.py— register blueprints
New frontend:
frontend/src/components/routine/RoutineEditor.vuefrontend/src/components/routine/RoutineDetailView.vuefrontend/src/components/routine/RoutineAssignView.vuefrontend/src/views/parent/RoutinesView.vue
Modified frontend:
frontend/src/common/models.ts— new interfaces + SSE payload typesfrontend/src/common/backendEvents.ts— new event constantsfrontend/src/common/api.ts— new helpersfrontend/src/components/child/ChildView.vue— add routines list + navigationfrontend/src/components/task/TaskSubNav.vue— add Routines tabfrontend/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 equivalentsbackend/models/chore_schedule.py— copy for RoutineSchedulebackend/models/task_extension.py— copy for routine_extension.pyfrontend/src/components/shared/ScrollingList.vue— reuse for routines in child viewfrontend/src/components/shared/EntityEditForm.vue— reuse in RoutineEditor top sectionbackend/utils/push_sender.py+child_api.pychore confirm (~L1186) — push notification pattern
Verification
- Create a routine with 2+ items via Tasks → Routines tab, assign to a child, verify it appears in child view
- Child submits "Done" → push notification fires → pending confirmation appears in parent view → approve → points credited
- Reject flow → no points awarded
- Schedule a routine for specific days → verify it only appears on those days
- Set a deadline → verify "TOO LATE" stamp after deadline passes
- Extend deadline via kebab → verify stamp removed for that day
- Set per-child point override → verify override value shown and applied on approval
- Delete routine → cascades (removed from children, items/schedules/extensions/overrides deleted)
- SSE: parent sees routine confirmation in notifications without page refresh
- 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