From 0a85b1725aed9cfd446ec51830d57ee500f0b693 Mon Sep 17 00:00:00 2001 From: Daniel Volz Date: Sun, 28 Dec 2025 18:41:22 +0100 Subject: [PATCH] feat: add form state management and reset functionality in medication editor --- frontend/src/App.tsx | 63 ++++++++++++++++++++++++++++++++++++----- frontend/src/styles.css | 4 +++ 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index e0365db..e394dd2 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -206,6 +206,8 @@ function AppContent() { const [plannerLoading, setPlannerLoading] = useState(false); const [loading, setLoading] = useState(false); const [saving, setSaving] = useState(false); + const [formSaved, setFormSaved] = useState(false); + const [originalForm, setOriginalForm] = useState(defaultForm()); const [editingId, setEditingId] = useState(null); const [showEditModal, setShowEditModal] = useState(false); const [form, setForm] = useState(defaultForm()); @@ -235,6 +237,18 @@ function AppContent() { return Object.values(fieldErrors).some(error => error !== undefined); }, [fieldErrors]); + // Check if form has been modified from original state + const formChanged = useMemo(() => { + return JSON.stringify(form) !== JSON.stringify(originalForm); + }, [form, originalForm]); + + // Reset formSaved when form changes + useEffect(() => { + if (formChanged) { + setFormSaved(false); + } + }, [formChanged]); + // Validate all fields when form changes useEffect(() => { const errors: FieldErrors = {}; @@ -783,7 +797,8 @@ function AppContent() { function startEdit(med: Medication) { setEditingId(med.id); setTakenByInput(""); // Clear tag input when starting edit - setForm({ + setFormSaved(false); + const editForm: FormState = { name: med.name, genericName: med.genericName ?? "", takenBy: med.takenBy || [], // Already an array from API @@ -801,7 +816,9 @@ function AppContent() { startDate: toDateValue(s.start), startTime: toTimeValue(s.start) })), - }); + }; + setForm(editForm); + setOriginalForm(editForm); // Show modal on mobile if (window.innerWidth <= 768) { setShowEditModal(true); @@ -814,7 +831,10 @@ function AppContent() { setPendingImage(null); setPendingImagePreview(null); setTakenByInput(""); - setForm(defaultForm()); + setFormSaved(false); + const newForm = defaultForm(); + setForm(newForm); + setOriginalForm(newForm); } function handleValueChange(key: K, value: string) { @@ -870,23 +890,38 @@ function AppContent() { const method = editingId ? "PUT" : "POST"; const url = editingId ? `/api/medications/${editingId}` : "/api/medications"; + const wasEditing = editingId; try { const res = await fetch(url, { method, headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) }); // If creating new medication and we have a pending image, upload it - if (!editingId && pendingImage && res.ok) { + if (!wasEditing && pendingImage && res.ok) { const newMed = await res.json(); if (newMed?.id) { await uploadMedImage(newMed.id, pendingImage); } } + + // Mark as saved and update original form to current state + if (res.ok) { + setFormSaved(true); + setOriginalForm(form); + } } catch { // ignore } setSaving(false); - resetForm(); + + // Only reset form if creating new medication, not when editing + if (!wasEditing) { + resetForm(); + } else { + // Close modal on mobile after edit + setShowEditModal(false); + } + loadMeds(); } @@ -1520,6 +1555,11 @@ function AppContent() {

{editingId ? t('form.editEntry') : t('form.newEntry')}

+ {editingId && ( + + )}
@@ -2578,6 +2620,11 @@ function AppContent() {

{editingId ? t('form.editEntry') : t('form.newEntry')}

+ {editingId && ( + + )}
{ saveMedication(e); setShowEditModal(false); }}>