'use client'; import { FASTING_PROTOCOLS, PROTOCOL_DEFAULT_MINUTES } from '@ketopath/shared'; import { useTranslations } from 'next-intl'; import { useEffect, useState, useTransition } from 'react'; import { Button } from '@/components/ui/button'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { endFast, startFast, updateFastSymptoms, type FastEventRow } from './actions'; type Protocol = (typeof FASTING_PROTOCOLS)[number]; const PROTOCOL_LABEL: Record = { FOURTEEN_TEN: '14:10', SIXTEEN_EIGHT: '16:8', EIGHTEEN_SIX: '18:6', TWENTY_FOUR: '20:4', ESE_24: 'ESE 24h', FIVE_TWO: '5:2', }; // PRD §5.3 — fasi metaboliche del digiuno (ore di digiuno trascorse). function metabolicPhaseKey(hoursElapsed: number): string { if (hoursElapsed < 4) return 'postprandial'; if (hoursElapsed < 12) return 'glycogenolysis'; if (hoursElapsed < 18) return 'lipolysis'; if (hoursElapsed < 24) return 'ketogenesis'; return 'autophagy'; } function pad(n: number): string { return String(n).padStart(2, '0'); } function formatElapsed(seconds: number): string { const sec = Math.max(0, Math.floor(seconds)); const h = Math.floor(sec / 3600); const m = Math.floor((sec % 3600) / 60); const s = sec % 60; return `${pad(h)}:${pad(m)}:${pad(s)}`; } export function FastTimer({ active }: { active: FastEventRow | null }) { if (active) { return ; } return ; } function ActiveTimer({ event }: { event: FastEventRow }) { const t = useTranslations('Fasting'); const startMs = new Date(event.startedAt).getTime(); const targetMs = event.targetDuration * 60 * 1000; const [now, setNow] = useState(() => Date.now()); const [pending, startTransition] = useTransition(); useEffect(() => { const id = setInterval(() => setNow(Date.now()), 1000); return () => clearInterval(id); }, []); const elapsedMs = Math.max(0, now - startMs); const remainingMs = Math.max(0, targetMs - elapsedMs); const reached = elapsedMs >= targetMs; const progress = Math.min(1, elapsedMs / targetMs); const hoursElapsed = elapsedMs / 1000 / 3600; const phase = metabolicPhaseKey(hoursElapsed); function complete() { startTransition(async () => { await endFast(event.id, false); }); } function abort() { if (typeof window !== 'undefined' && !window.confirm(t('confirmAbort'))) return; startTransition(async () => { await endFast(event.id, true); }); } return (

{t('activeBadge')} · {PROTOCOL_LABEL[event.protocol]}

{formatElapsed(elapsedMs / 1000)}

{reached ? t('reached') : t('remaining', { time: formatElapsed(remainingMs / 1000) })}

); } function ProtocolSelector() { const t = useTranslations('Fasting'); const [protocol, setProtocol] = useState('SIXTEEN_EIGHT'); const [error, setError] = useState(null); const [pending, startTransition] = useTransition(); function start() { setError(null); startTransition(async () => { const result = await startFast({ protocol }); if (!result.ok) setError(result.error); }); } return (

{t('inactiveBadge')}

{t('startCallToAction')}

{t('chooseProtocol')}

{error ? (

{error}

) : null}
); } function ProgressBar({ progress, reached }: { progress: number; reached: boolean }) { return (
); } function Row({ label, value }: { label: string; value: string }) { return (
{label}
{value}
); } const HOUR_FMT = new Intl.DateTimeFormat('it-IT', { weekday: 'short', hour: '2-digit', minute: '2-digit', }); function formatStart(iso: string): string { return HOUR_FMT.format(new Date(iso)); } function SymptomsDiary({ event }: { event: FastEventRow }) { const t = useTranslations('Fasting'); const initial = (event.symptoms as Record | null) ?? {}; const [headache, setHeadache] = useState(!!initial.headache); const [energy, setEnergy] = useState( typeof initial.energy === 'number' ? initial.energy : 5, ); const [hunger, setHunger] = useState( typeof initial.hunger === 'number' ? initial.hunger : 5, ); const [clarity, setClarity] = useState( typeof initial.clarity === 'number' ? initial.clarity : 5, ); const [other, setOther] = useState( typeof initial.other === 'string' ? initial.other : '', ); const [pending, startTransition] = useTransition(); const [saved, setSaved] = useState(false); function save(): void { startTransition(async () => { setSaved(false); const symptoms: Parameters[1] = { headache, energy, hunger, clarity, }; const trimmedOther = other.trim(); if (trimmedOther) symptoms.other = trimmedOther; const result = await updateFastSymptoms(event.id, symptoms); if (result.ok) { setSaved(true); window.setTimeout(() => setSaved(false), 2500); } }); } return (

{t('symptomsTitle')}

{t('symptomsHint')}

{t('symptomOther')}