"use client"; import { useState } from "react"; import { useRouter } from "next/navigation"; import { useQueryClient } from "@tanstack/react-query"; import { toast } from "sonner"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Logo } from "@/components/ui/logo"; import { Loader2, ChevronRight } from "lucide-react"; import { useTranslations } from "@/lib/i18n/context"; import { cn } from "@/lib/utils"; const TOTAL_STEPS = 4; export default function OnboardingPage() { const router = useRouter(); const queryClient = useQueryClient(); const { t } = useTranslations(); const [step, setStep] = useState(1); const [saving, setSaving] = useState(false); // Step 1: Profile const [heightCm, setHeightCm] = useState(""); const [dateOfBirth, setDateOfBirth] = useState(""); const [gender, setGender] = useState(""); // Step 2: Medications const [medName, setMedName] = useState(""); const [medDose, setMedDose] = useState(""); const [meds, setMeds] = useState>([]); // Step 3: Targets const [targetSys, setTargetSys] = useState(""); const [targetDia, setTargetDia] = useState(""); const [targetWeight, setTargetWeight] = useState(""); async function finishOnboarding() { setSaving(true); try { const body: Record = {}; if (heightCm) body.heightCm = parseFloat(heightCm); if (dateOfBirth) body.dateOfBirth = dateOfBirth; if (gender) body.gender = gender; const profileRes = await fetch("/api/onboarding/complete", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body), }); if (!profileRes.ok) { throw new Error(t("onboarding.errorProfile")); } // Create medications. Server validation requires at least one schedule, // so we attach a sensible default — the user is informed via medScheduleHint // and can refine it in Medications later. Phase 3.5 of the audit replaces // this entire wizard with an empty-state-driven flow. for (const med of meds) { const medRes = await fetch("/api/medications", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ name: med.name, dose: med.dose, schedules: [{ windowStart: "08:00", windowEnd: "09:00" }], }), }); if (!medRes.ok) { throw new Error(t("onboarding.errorMedication", { name: med.name })); } } if (targetSys || targetDia || targetWeight) { const targets: Record = {}; if (targetSys) targets.bpSysTarget = parseInt(targetSys); if (targetDia) targets.bpDiaTarget = parseInt(targetDia); if (targetWeight) targets.weightTarget = parseFloat(targetWeight); const targetsRes = await fetch("/api/insights/targets", { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify(targets), }); if (!targetsRes.ok) { throw new Error(t("onboarding.errorTargets")); } } await queryClient.invalidateQueries({ queryKey: ["auth"] }); router.replace("/"); } catch (err) { const message = err instanceof Error ? err.message : t("onboarding.errorGeneric"); toast.error(message); setSaving(false); } } function addMedication() { if (!medName.trim()) return; setMeds([...meds, { name: medName.trim(), dose: medDose.trim() }]); setMedName(""); setMedDose(""); } function nextStep() { if (step < TOTAL_STEPS) { setStep(step + 1); } else { finishOnboarding(); } } return (

{t("onboarding.welcome")}

{t("onboarding.setupDescription")}

{/* Progress indicator */}
{Array.from({ length: TOTAL_STEPS }, (_, i) => (
))}
{/* Step 1: Profile */} {step === 1 && (

{t("settings.profile")}

setHeightCm(e.target.value)} placeholder="175" min={50} max={300} step={0.1} />

{t("settings.genderHint")}

setDateOfBirth(e.target.value)} max={new Date().toISOString().slice(0, 10)} />

{t("settings.dateOfBirthHint")}

)} {/* Step 2: Medications */} {step === 2 && (

{t("onboarding.medicationsTitle")}

{t("onboarding.medicationsDescription")}

setMedName(e.target.value)} placeholder={t("onboarding.medNamePlaceholder")} className="flex-1" /> setMedDose(e.target.value)} placeholder={t("onboarding.medDosePlaceholder")} className="w-24" />
{meds.length > 0 && ( <>
    {meds.map((m, i) => (
  • {m.name} {m.dose && `(${m.dose})`}
  • ))}

{t("onboarding.medScheduleHint")}

)}
)} {/* Step 3: Notifications teaser */} {step === 3 && (

{t("onboarding.notificationsTitle")}

{t("onboarding.notificationsDescription")}

📱 Telegram — {t("onboarding.telegramHint")}

🔔 Web Push — {t("onboarding.webPushHint")}

{t("onboarding.notificationsLater")}

)} {/* Step 4: Targets */} {step === 4 && (

{t("onboarding.targetsTitle")}

{t("onboarding.targetsDescription")}

setTargetSys(e.target.value)} placeholder="130" />
setTargetDia(e.target.value)} placeholder="85" />
setTargetWeight(e.target.value)} placeholder="75" step={0.1} />
)} {/* Navigation buttons */}
{step < TOTAL_STEPS ? ( ) : ( )}
); }