feat: Implement routines feature with CRUD operations and child assignment
All checks were successful
Chore App Build, Test, and Push Docker Images / build-and-push (push) Successful in 3m0s

- Add backend routines management with add, get, update, delete, and list functionalities.
- Create models for Routine, RoutineItem, RoutineSchedule, and RoutineExtension.
- Develop event types for routine confirmation and modification.
- Implement frontend components for routine assignment, confirmation dialog, and routine management views.
- Add unit tests for routine API and integration tests for routine CRUD flow.
- Create end-to-end test plan for routines feature covering parent and child interactions.
This commit is contained in:
2026-05-05 09:08:19 -04:00
parent 082097b4f9
commit eb775ba7d8
41 changed files with 2847 additions and 29 deletions

View File

@@ -168,7 +168,7 @@ export async function getTrackingEventsForChild(params: {
export async function setChildOverride(
childId: string,
entityId: string,
entityType: 'task' | 'reward',
entityType: 'task' | 'reward' | 'routine',
customValue: number,
): Promise<Response> {
return fetch(`/api/child/${childId}/override`, {
@@ -182,6 +182,14 @@ export async function setChildOverride(
})
}
export async function setChildRoutineOverride(
childId: string,
routineId: string,
customValue: number,
): Promise<Response> {
return setChildOverride(childId, routineId, 'routine', customValue)
}
/**
* Get all overrides for a specific child.
*/
@@ -231,6 +239,37 @@ export async function deleteChoreSchedule(childId: string, taskId: string): Prom
})
}
/**
* Get the schedule for a specific child + routine pair.
*/
export async function getRoutineSchedule(childId: string, routineId: string): Promise<Response> {
return fetch(`/api/child/${childId}/routine/${routineId}/schedule`)
}
/**
* Create or replace the schedule for a specific child + routine pair.
*/
export async function setRoutineSchedule(
childId: string,
routineId: string,
schedule: object,
): Promise<Response> {
return fetch(`/api/child/${childId}/routine/${routineId}/schedule`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(schedule),
})
}
/**
* Delete the schedule for a specific child + routine pair.
*/
export async function deleteRoutineSchedule(childId: string, routineId: string): Promise<Response> {
return fetch(`/api/child/${childId}/routine/${routineId}/schedule`, {
method: 'DELETE',
})
}
/**
* Extend a timed-out chore for the remainder of today only.
* `localDate` is the client's local ISO date (e.g. '2026-02-22').
@@ -247,6 +286,22 @@ export async function extendChoreTime(
})
}
/**
* Extend a timed-out routine for the remainder of today only.
* `localDate` is the client's local ISO date (e.g. '2026-02-22').
*/
export async function extendRoutineTime(
childId: string,
routineId: string,
localDate: string,
): Promise<Response> {
return fetch(`/api/child/${childId}/routine/${routineId}/extend`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ date: localDate }),
})
}
// ── Chore Confirmation API ──────────────────────────────────────────────────
/**
@@ -310,3 +365,28 @@ export async function resetChore(childId: string, taskId: string): Promise<Respo
export async function fetchPendingConfirmations(): Promise<Response> {
return fetch('/api/pending-confirmations')
}
/**
* Child confirms they completed a routine.
*/
export async function confirmRoutine(childId: string, routineId: string): Promise<Response> {
return fetch(`/api/child/${childId}/confirm-routine`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ routine_id: routineId }),
})
}
/**
* Child cancels a pending routine confirmation.
*/
export async function cancelRoutineConfirmation(
childId: string,
routineId: string,
): Promise<Response> {
return fetch(`/api/child/${childId}/cancel-routine-confirmation`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ routine_id: routineId }),
})
}