mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 22:32:04 +00:00
Add a "Your reminders" panel under Settings → Coach that lists the stored reminders, highlights the due ones, and gives the user view, confirm, done/dismiss, and delete control over their own memory. Light the Coach launcher dot when a reminder is due, alongside the existing nudge signal. Add the generic confirm-card component for the suggested-action frame: a plain-text preview with a localized per-action heading and a single confirm tap that posts the validated params to the build endpoint. Translate the new copy in English and German.
79 lines
2.3 KiB
TypeScript
79 lines
2.3 KiB
TypeScript
"use client";
|
|
|
|
/**
|
|
* v1.22 (B2/B6) — read + mutate the user's Coach episodic reminders.
|
|
*
|
|
* One shared hook for the in-app reminder tile/indicator and the "Your context"
|
|
* ledger. Reads unwrap `(await res.json()).data` per the envelope convention;
|
|
* every key routes through `queryKeys.coachReminders(status)` so a lifecycle
|
|
* mutation invalidates the matching list. The `status` arg keys the tile read
|
|
* (`due,surfaced`) separately from the full ledger so they never share a slot.
|
|
*/
|
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
|
|
import { queryKeys } from "@/lib/query-keys";
|
|
import { apiDelete, apiGet, apiPatch } from "@/lib/api/api-fetch";
|
|
|
|
export interface CoachReminderDTO {
|
|
id: string;
|
|
note: string;
|
|
metric: string | null;
|
|
triggerKind: string;
|
|
dueAt: string | null;
|
|
contextCue: string | null;
|
|
status: string;
|
|
source: string;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
}
|
|
|
|
async function fetchReminders(status?: string): Promise<CoachReminderDTO[]> {
|
|
const qs = status ? `?status=${encodeURIComponent(status)}` : "";
|
|
const data = await apiGet<{ reminders?: CoachReminderDTO[] } | undefined>(
|
|
`/api/coach/reminders${qs}`,
|
|
);
|
|
return data?.reminders ?? [];
|
|
}
|
|
|
|
/** List the caller's reminders, optionally filtered to a status set. */
|
|
export function useCoachReminders(opts?: {
|
|
status?: string;
|
|
enabled?: boolean;
|
|
}) {
|
|
const status = opts?.status;
|
|
return useQuery({
|
|
queryKey: queryKeys.coachReminders(status),
|
|
queryFn: () => fetchReminders(status),
|
|
enabled: opts?.enabled ?? true,
|
|
});
|
|
}
|
|
|
|
/** Lifecycle + delete mutations, invalidating every reminders list slot. */
|
|
export function useCoachReminderMutations() {
|
|
const queryClient = useQueryClient();
|
|
const invalidate = () =>
|
|
queryClient.invalidateQueries({
|
|
queryKey: queryKeys.coachRemindersAll(),
|
|
});
|
|
|
|
const setStatus = useMutation({
|
|
mutationFn: async (args: { id: string; status: string }) => {
|
|
await apiPatch(`/api/coach/reminders/${encodeURIComponent(args.id)}`, {
|
|
status: args.status,
|
|
});
|
|
return args.id;
|
|
},
|
|
onSuccess: invalidate,
|
|
});
|
|
|
|
const remove = useMutation({
|
|
mutationFn: async (id: string) => {
|
|
await apiDelete(`/api/coach/reminders/${encodeURIComponent(id)}`);
|
|
return id;
|
|
},
|
|
onSuccess: invalidate,
|
|
});
|
|
|
|
return { setStatus, remove };
|
|
}
|