Files
HealthLog/src/hooks/use-coach-checkin.ts
T
Marc-André Bombeck ba5a17a54e fix(daily): keep the coach check-in constants out of the client bundle
The Today hero and the check-in hook imported the check-in intent constants
from digest.ts, which — since the milestone slice — transitively reaches the
database through the streak baseline engine. That pulled the Postgres driver
into the client bundle (a Turbopack 'Can't resolve net/tls/dns' build failure
the worktree build couldn't surface). Move the four constants to a tiny,
dependency-free coach-checkin-intents module; the client imports them from
there, and digest.ts (the server builder) stays server-only.
2026-07-17 09:37:39 +02:00

60 lines
2.1 KiB
TypeScript

"use client";
/**
* S3 — the coach check-in card's keep / let-go actions (§2.3).
*
* The Today rail surfaces a `coach_checkin` `PriorityItem` whose two mutating
* one-tap actions close the coach loop through the EXISTING plan-lifecycle
* route (`PATCH /api/coach/plans/[id]`) — no new backend surface:
* - keep → re-arm: status `active` + `reviewDate` pushed out one more cycle,
* so the check-in comes back in a week rather than the same day;
* - letGo → guilt-free retirement: status `abandoned`, a terminal, respected
* outcome (the calm inversion of a streak). The card never nags.
*
* "Adjust" is navigation (an `href` into the coach) handled by `PriorityCard`
* as a `<Link>` — it never reaches this hook.
*
* Both invalidate the daily digest (so the acted-on card leaves the rail) and
* every plans-list slot (so the /coach/plans ledger stays in step). Keys route
* through the centralised factory — no bare arrays.
*/
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { apiPatch } from "@/lib/api/api-fetch";
import { queryKeys } from "@/lib/query-keys";
import { COACH_CHECKIN_REVIEW_DAYS } from "@/lib/daily/coach-checkin-intents";
export function useCoachCheckinAction() {
const queryClient = useQueryClient();
const invalidate = () => {
void queryClient.invalidateQueries({ queryKey: queryKeys.dailyDigest() });
void queryClient.invalidateQueries({ queryKey: queryKeys.coachPlansAll() });
};
const keep = useMutation({
mutationFn: async (planId: string) => {
const reviewDate = new Date(
Date.now() + COACH_CHECKIN_REVIEW_DAYS * 86_400_000,
).toISOString();
await apiPatch(`/api/coach/plans/${encodeURIComponent(planId)}`, {
status: "active",
reviewDate,
});
return planId;
},
onSuccess: invalidate,
});
const letGo = useMutation({
mutationFn: async (planId: string) => {
await apiPatch(`/api/coach/plans/${encodeURIComponent(planId)}`, {
status: "abandoned",
});
return planId;
},
onSuccess: invalidate,
});
return { keep, letGo };
}