mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 14:32:03 +00:00
Server and first client render now agree everywhere query state used to leak into the chrome, checkboxes no longer nest inside buttons, delete confirmations admit the undo they offer, raw step counts drop their decimals, the truncated unit label wraps instead, streaks know their singular, the medication header speaks the user's date format, a failed coach turn keeps the user's message and says what went wrong, settings status notes follow a language switch, the locale only flips once its bundle actually loaded, and the last raw api fetches in hooks move onto the shared client.
63 lines
2.5 KiB
TypeScript
63 lines
2.5 KiB
TypeScript
"use client";
|
|
|
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
|
|
import { queryKeys } from "@/lib/query-keys";
|
|
import { apiFetchRaw, apiPut } from "@/lib/api/api-fetch";
|
|
import {
|
|
DEFAULT_COACH_PREFS,
|
|
type CoachPrefs,
|
|
} from "@/lib/validations/coach-prefs";
|
|
|
|
/**
|
|
* v1.4.23 W6 (S-03) — shared accessor for the per-user Coach
|
|
* preferences row. Both the Coach drawer's settings sheet and the
|
|
* message-thread evidence-disclosure default consume the same
|
|
* `/api/auth/me/coach-prefs` payload; before the extraction the two
|
|
* call sites duplicated the same `useQuery` block with subtly
|
|
* different fallback semantics (one threw on `!ok`, the other returned
|
|
* defaults). The hook centralises the cache key, the envelope unwrap,
|
|
* and the "treat fetch failure as defaults" stance so the next surface
|
|
* (insights cog, settings tab) inherits a single source of truth.
|
|
*
|
|
* The query is gated on `enabled` so the settings sheet can defer the
|
|
* fetch until the sheet actually opens. Callers that always want the
|
|
* row (message thread) leave it unset (defaults to true).
|
|
*/
|
|
export function useCoachPrefs(opts?: { enabled?: boolean }) {
|
|
return useQuery<CoachPrefs>({
|
|
queryKey: queryKeys.coachPrefs(),
|
|
queryFn: async () => {
|
|
// `apiFetchRaw` (no .ok throw) — a non-OK read soft-fails to the
|
|
// defaults instead of surfacing an error state.
|
|
const res = await apiFetchRaw("/api/auth/me/coach-prefs");
|
|
if (!res.ok) return DEFAULT_COACH_PREFS;
|
|
const env = (await res.json()) as { data: CoachPrefs };
|
|
return env.data;
|
|
},
|
|
enabled: opts?.enabled,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* v1.7.2 — shared writer for the Coach preferences row. Both the
|
|
* settings sheet and the chat-side sources rail persist the same
|
|
* `coachPrefsJson` through `PUT /api/auth/me/coach-prefs`, so the write
|
|
* path lives here next to the reader. On success the canonical defaulted
|
|
* shape the route echoes back is seeded into the `coachPrefs()` cache so
|
|
* every surface that reads the hook re-renders against one source of
|
|
* truth — the rail and the cog can never drift.
|
|
*/
|
|
export function useSaveCoachPrefs(opts?: { onSuccess?: () => void }) {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationKey: queryKeys.coachPrefs(),
|
|
mutationFn: async (next: CoachPrefs) =>
|
|
apiPut<CoachPrefs>("/api/auth/me/coach-prefs", next),
|
|
onSuccess: (data) => {
|
|
queryClient.setQueryData<CoachPrefs>(queryKeys.coachPrefs(), data);
|
|
opts?.onSuccess?.();
|
|
},
|
|
});
|
|
}
|