From 42e0fff40c0b78acb49813453c57084e8e30f6e7 Mon Sep 17 00:00:00 2001 From: Kyle Pope Date: Tue, 24 Feb 2026 01:11:31 +0800 Subject: [PATCH] Revert ReminderForm to single datetime-local input Matches EventForm pattern used across UMBRA. Remind At and Recurrence now sit side-by-side in a 2-column grid. Empty optional fields send null instead of empty string. Co-Authored-By: Claude Opus 4.6 --- .../src/components/reminders/ReminderForm.tsx | 129 +++++------------- 1 file changed, 37 insertions(+), 92 deletions(-) diff --git a/frontend/src/components/reminders/ReminderForm.tsx b/frontend/src/components/reminders/ReminderForm.tsx index c8d1dc3..435f06d 100644 --- a/frontend/src/components/reminders/ReminderForm.tsx +++ b/frontend/src/components/reminders/ReminderForm.tsx @@ -22,53 +22,28 @@ interface ReminderFormProps { onClose: () => void; } -function parseRemindAt(remindAt?: string) { - if (!remindAt) return { date: '', hour: '12', minute: '00', period: 'PM' as const }; - const d = new Date(remindAt); - const date = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`; - let hours = d.getHours(); - const period = hours >= 12 ? 'PM' as const : 'AM' as const; - hours = hours % 12 || 12; - return { - date, - hour: String(hours), - minute: String(d.getMinutes()).padStart(2, '0'), - period, - }; -} - -function buildRemindAt(date: string, hour: string, minute: string, period: 'AM' | 'PM'): string { - if (!date) return ''; - let h = parseInt(hour, 10); - if (period === 'AM' && h === 12) h = 0; - else if (period === 'PM' && h !== 12) h += 12; - return `${date}T${String(h).padStart(2, '0')}:${minute}`; -} - export default function ReminderForm({ reminder, onClose }: ReminderFormProps) { const queryClient = useQueryClient(); - const parsed = parseRemindAt(reminder?.remind_at); - const [title, setTitle] = useState(reminder?.title || ''); - const [description, setDescription] = useState(reminder?.description || ''); - const [date, setDate] = useState(parsed.date); - const [hour, setHour] = useState(parsed.hour); - const [minute, setMinute] = useState(parsed.minute); - const [period, setPeriod] = useState<'AM' | 'PM'>(parsed.period); - const [recurrenceRule, setRecurrenceRule] = useState(reminder?.recurrence_rule || ''); + const [formData, setFormData] = useState({ + title: reminder?.title || '', + description: reminder?.description || '', + remind_at: reminder?.remind_at ? reminder.remind_at.slice(0, 16) : '', + recurrence_rule: reminder?.recurrence_rule || '', + }); const mutation = useMutation({ - mutationFn: async () => { - const data = { - title, - description: description || null, - remind_at: buildRemindAt(date, hour, minute, period) || null, - recurrence_rule: recurrenceRule || null, + mutationFn: async (data: typeof formData) => { + const payload = { + ...data, + description: data.description || null, + remind_at: data.remind_at || null, + recurrence_rule: data.recurrence_rule || null, }; if (reminder) { - const response = await api.put(`/reminders/${reminder.id}`, data); + const response = await api.put(`/reminders/${reminder.id}`, payload); return response.data; } else { - const response = await api.post('/reminders', data); + const response = await api.post('/reminders', payload); return response.data; } }, @@ -86,7 +61,7 @@ export default function ReminderForm({ reminder, onClose }: ReminderFormProps) { const handleSubmit = (e: FormEvent) => { e.preventDefault(); - mutation.mutate(); + mutation.mutate(formData); }; return ( @@ -102,8 +77,8 @@ export default function ReminderForm({ reminder, onClose }: ReminderFormProps) { setTitle(e.target.value)} + value={formData.title} + onChange={(e) => setFormData({ ...formData, title: e.target.value })} required /> @@ -112,67 +87,37 @@ export default function ReminderForm({ reminder, onClose }: ReminderFormProps) {