mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 06:32:03 +00:00
The done screen moves focus to its heading like every other screen; the confirm screen's preference list holds only dt/dd pairs and the settings link stands beside it; Back from Q1 is not offered once the flow has been entered, because the front door would resume past the welcome and bounce straight back; the medication task records no target on the ledger, as the contract says, and keeps the id on the screen; and the two success affordances go through the outcome module rather than a hand-rolled tick. The error-code catalogue lists the answers and restart codes and no longer the retired step ones, and the session-surface guard learns the one new deriving helper the onboarding pages read through.
92 lines
3.1 KiB
TypeScript
92 lines
3.1 KiB
TypeScript
"use client";
|
|
|
|
import { useRouter } from "next/navigation";
|
|
import { toast } from "sonner";
|
|
import { ListChecks, Loader2 } from "lucide-react";
|
|
|
|
import { toastWrittenOutcome } from "@/components/outcome/outcome-toast";
|
|
|
|
import { Button } from "@/components/ui/button";
|
|
import { SettingsCard } from "@/components/settings/settings-card";
|
|
import { SettingsCardActions } from "@/components/settings/_card-actions";
|
|
import { SettingsCardHeader } from "@/components/settings/_card-header";
|
|
import { useOnboardingRestart } from "@/components/onboarding/use-onboarding-flow";
|
|
import { localizedApiError } from "@/lib/api/localized-error";
|
|
import { useTranslations } from "@/lib/i18n/context";
|
|
import { resetChecklistDismissals } from "@/lib/onboarding/checklist-storage";
|
|
|
|
/**
|
|
* v1.39 (C2) — Settings → Account → Setup.
|
|
*
|
|
* The two ways back into the first-run experience (design spec §Principles 4
|
|
* and §After the flow). "Set up again" asks the questions once more through
|
|
* the restart route, which resets the ledger and keeps the answers as
|
|
* prefill — and writes no module state, so a module switched on by hand is
|
|
* never switched off by a re-run. "Show the checklist again" forgets what
|
|
* this browser hid; the checklist's dismissals live in the browser, so the
|
|
* button lives on the same origin.
|
|
*/
|
|
export function SetupCard() {
|
|
const { t } = useTranslations();
|
|
const router = useRouter();
|
|
const restart = useOnboardingRestart();
|
|
|
|
async function setUpAgain() {
|
|
if (restart.isPending) return;
|
|
try {
|
|
await restart.mutateAsync();
|
|
router.push("/onboarding/who");
|
|
} catch (err) {
|
|
toast.error(localizedApiError(err, t, "onboarding.errorGeneric"));
|
|
}
|
|
}
|
|
|
|
function showChecklist() {
|
|
// Something was hidden and is back: a written outcome. Nothing was
|
|
// hidden: an empty one — there was nothing to bring back.
|
|
if (resetChecklistDismissals()) {
|
|
toastWrittenOutcome("success", t("settings.setup.checklistShown"));
|
|
} else {
|
|
toastWrittenOutcome("empty", t("settings.setup.checklistNothingHidden"));
|
|
}
|
|
}
|
|
|
|
return (
|
|
<SettingsCard data-slot="settings-setup-card">
|
|
<SettingsCardHeader
|
|
icon={ListChecks}
|
|
title={t("settings.setup.title")}
|
|
description={t("settings.setup.description")}
|
|
/>
|
|
<SettingsCardActions>
|
|
<Button
|
|
type="button"
|
|
variant="outline"
|
|
size="sm"
|
|
className="min-h-11"
|
|
onClick={showChecklist}
|
|
data-slot="settings-show-checklist"
|
|
>
|
|
{t("settings.setup.showChecklist")}
|
|
</Button>
|
|
<Button
|
|
type="button"
|
|
size="sm"
|
|
className="min-h-11"
|
|
onClick={setUpAgain}
|
|
disabled={restart.isPending}
|
|
data-slot="settings-set-up-again"
|
|
>
|
|
{restart.isPending ? (
|
|
<Loader2
|
|
aria-hidden="true"
|
|
className="size-4 animate-spin motion-reduce:animate-none"
|
|
/>
|
|
) : null}
|
|
{t("settings.setup.setUpAgain")}
|
|
</Button>
|
|
</SettingsCardActions>
|
|
</SettingsCard>
|
|
);
|
|
}
|