"use client"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { Printer, RotateCcw } from "lucide-react"; import { useEffectOnChange } from "@/hooks/useEffectOnChange"; import { type DivingFigures } from "@/lib/checkin"; import { unitLabel, type UnitSystem } from "@/lib/units"; import { dialogFormSubmit } from "@/lib/dialog-form"; import { divingFiguresFromForm, divingFiguresSchema, divingFiguresToForm, type DivingFiguresInput, } from "@/lib/validations/checkin"; import { UnitNumberInput } from "@/components/unit-number-input"; import { Button } from "@/components/ui/button"; import { DatePicker } from "@/components/ui/date-picker"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; export interface DivingFiguresDialogProps { open: boolean; onOpenChange: (open: boolean) => void; /** The system the depth box shows and takes, the diver's own. */ units: UnitSystem; /** What the log itself says - where a fresh dialog opens, and what "Use logged figures" returns to. */ logged: DivingFigures; /** The diver's correction, or null while the summary is printing the log's own figures. */ corrected: DivingFigures | null; /** Emits a correction, or null to go back to the log's figures. */ onChange: (figures: DivingFigures | null) => void; } /** * Corrects the three diving figures for the summary about to be printed, and for a * check-in link made from it while the correction stands - which keeps the figures it * was made with for its day - and for nothing else. * * Deliberately not a save. A diver's logged dives are the ones they entered here, and * a career predating the app - or a fortnight logged on paper - makes the honest * number one this app cannot know. Storing the correction would then need it * reconciled against every dive logged afterwards, a running offset nobody can keep * true; a figure typed once, for one desk, needs no reconciliation at all. Reloading * the page brings the log's own figures back, which is the right default for the next * check-in. */ export function DivingFiguresDialog({ open, onOpenChange, units, logged, corrected, onChange, }: DivingFiguresDialogProps) { const form = useForm({ resolver: zodResolver(divingFiguresSchema), defaultValues: divingFiguresToForm(corrected ?? logged), }); // Reload on open, so the dialog shows what the summary is printing rather than // whatever the previous invocation left behind - the same reset-on-open as every // create/edit dialog in the app, and on the same hook, so a route kept mounted // under `Activity` cannot blank a dialog the diver left open. const { reset } = form; useEffectOnChange(() => { if (open) reset(divingFiguresToForm(corrected ?? logged)); }, [open, corrected, logged, reset]); const onSubmit = (data: DivingFiguresInput) => { onChange(divingFiguresFromForm(data)); onOpenChange(false); }; return ( Diving What your log holds, which may not be everything you have dived. Corrections here print on this summary and go with a link you share from it — nothing is saved to your log, and reloading the page brings the logged figures back.
( Dives logged { const typed = parseInt(event.target.value, 10); field.onChange(Number.isNaN(typed) ? null : typed); }} /> } /> )} /> ( {/* The unit in the label, as every other depth box in the app writes it: the number is the diver's own system and nothing else on the row says which. */} Max depth ({unitLabel("depth", units)}) {/* Shows and takes the diver's own units while the value behind it stays metric, like every other depth box. */} } /> )} /> ( Last dive } /> )} /> {/* Only once there is something to undo, and it closes the dialog the way a save does: both answer the same question. */} {corrected && ( )} {/* Not "Save changes": nothing is saved, and a diver who read the line above and then pressed Save would be right to expect it waiting at the next desk. */}
); }