diff --git a/frontend/src/components/SectionMutationDrawer.tsx b/frontend/src/components/SectionMutationDrawer.tsx index 90c4cc1..b370841 100644 --- a/frontend/src/components/SectionMutationDrawer.tsx +++ b/frontend/src/components/SectionMutationDrawer.tsx @@ -119,37 +119,67 @@ function generateBlockGroup(): string { /** * Compound AM/PM time selector — three linked selects for hour, minute, period. - * Reports the chosen time as a "HH:MM" 24-hour string via `onChange`. + * Reports the chosen time as a "HH:MM" 24-hour string via `onChange`, but only + * once hour and minute are both set. Local state retains partial selections so + * each dropdown "sticks" as the user works through them. */ +function parseTimeValue(value: string): { hour: string; minute: string; period: 'AM' | 'PM' } { + if (!value) return { hour: '', minute: '', period: 'AM' }; + const [h24, m] = value.split(':'); + const hNum = Number(h24); + return { + hour: Number.isFinite(hNum) ? String(hNum % 12 || 12) : '', + minute: m ?? '', + period: Number.isFinite(hNum) && hNum >= 12 ? 'PM' : 'AM', + }; +} + function TimeSelect({ value, onChange }: { value: string; onChange: (v: string) => void }) { - const [h24, m] = value ? value.split(':') : ['', '']; - const hNum = h24 ? Number(h24) : null; - const hour = hNum !== null ? String(hNum % 12 || 12) : ''; - const minute = m ?? ''; - const period: 'AM' | 'PM' = hNum !== null && hNum >= 12 ? 'PM' : 'AM'; - - function emit(newHour: string, newMinute: string, newPeriod: 'AM' | 'PM') { - if (newHour && newMinute) onChange(to24Hour(newHour, newMinute, newPeriod)); + const [draft, setDraft] = useState(() => parseTimeValue(value)); + + // Re-sync local draft when the parent changes `value` externally. + useEffect(() => { + setDraft(parseTimeValue(value)); + }, [value]); + + function update(next: { hour: string; minute: string; period: 'AM' | 'PM' }) { + setDraft(next); + if (next.hour && next.minute) onChange(to24Hour(next.hour, next.minute, next.period)); } - const sel = 'text-xs border border-gray-200 rounded px-1.5 py-1 focus:outline-none focus:ring-1 focus:ring-burgundy-500 bg-white'; + const sel = 'text-xs border border-gray-200 rounded px-1.5 py-1 hover:border-gray-300 focus:outline-none focus:ring-1 focus:ring-burgundy-500 bg-white'; return (