diff --git a/frontend/src/pages/SleepPage.jsx b/frontend/src/pages/SleepPage.jsx index 9f43767..49dfa14 100644 --- a/frontend/src/pages/SleepPage.jsx +++ b/frontend/src/pages/SleepPage.jsx @@ -48,6 +48,17 @@ export default function SleepPage() { setTimeout(() => setToast(null), 4000) } + // Clean data: convert empty strings to null for optional integer fields + const cleanSleepData = (data) => ({ + ...data, + quality: data.quality === '' ? null : data.quality, + wake_count: data.wake_count === '' ? 0 : data.wake_count, + deep_minutes: data.deep_minutes === '' ? null : data.deep_minutes, + rem_minutes: data.rem_minutes === '' ? null : data.rem_minutes, + light_minutes: data.light_minutes === '' ? null : data.light_minutes, + awake_minutes: data.awake_minutes === '' ? null : data.awake_minutes, + }) + const handleImport = async (file) => { if (!file) return if (!file.name.endsWith('.csv')) { @@ -248,7 +259,7 @@ export default function SleepPage() { { try { - await api.createSleep(data) + await api.createSleep(cleanSleepData(data)) await load() setEditingId(null) showToast('Gespeichert') @@ -283,7 +294,7 @@ export default function SleepPage() { onCancelEdit={() => setEditingId(null)} onSave={async (data) => { try { - await api.updateSleep(entry.id, data) + await api.updateSleep(entry.id, cleanSleepData(data)) await load() setEditingId(null) showToast('Gespeichert') @@ -291,6 +302,7 @@ export default function SleepPage() { showToast(err.message, 'error') } }} + cleanSleepData={cleanSleepData} onDelete={() => handleDelete(entry.id, entry.date)} formatDuration={formatDuration} getSourceBadge={getSourceBadge} @@ -322,6 +334,27 @@ function SleepEntry({ entry, expanded, editing, onToggleExpand, onEdit, onCancel const [saving, setSaving] = useState(false) const [plausibilityError, setPlausibilityError] = useState(null) + const [suggestedDuration, setSuggestedDuration] = useState(null) + + // Auto-calculate duration from bedtime + wake_time + useEffect(() => { + if (editing && formData.bedtime && formData.wake_time) { + const [bedH, bedM] = formData.bedtime.split(':').map(Number) + const [wakeH, wakeM] = formData.wake_time.split(':').map(Number) + + let bedMinutes = bedH * 60 + bedM + let wakeMinutes = wakeH * 60 + wakeM + + if (wakeMinutes < bedMinutes) { + wakeMinutes += 24 * 60 + } + + const duration = wakeMinutes - bedMinutes + setSuggestedDuration(duration) + } else { + setSuggestedDuration(null) + } + }, [editing, formData.bedtime, formData.wake_time]) // Live plausibility check useEffect(() => { @@ -386,6 +419,12 @@ function SleepEntry({ entry, expanded, editing, onToggleExpand, onEdit, onCancel />
= {formatDuration(formData.duration_minutes)} + {suggestedDuration && suggestedDuration !== formData.duration_minutes && ( + setFormData({ ...formData, duration_minutes: suggestedDuration })}> + 💡 Vorschlag: {formatDuration(suggestedDuration)} (übernehmen?) + + )}
@@ -690,6 +729,28 @@ function NewEntryForm({ onSave, onCancel, formatDuration }) { const [saving, setSaving] = useState(false) const [plausibilityError, setPlausibilityError] = useState(null) const [showDetail, setShowDetail] = useState(false) + const [suggestedDuration, setSuggestedDuration] = useState(null) + + // Auto-calculate duration from bedtime + wake_time + useEffect(() => { + if (formData.bedtime && formData.wake_time) { + const [bedH, bedM] = formData.bedtime.split(':').map(Number) + const [wakeH, wakeM] = formData.wake_time.split(':').map(Number) + + let bedMinutes = bedH * 60 + bedM + let wakeMinutes = wakeH * 60 + wakeM + + // If wake time < bed time, add 24 hours (crossed midnight) + if (wakeMinutes < bedMinutes) { + wakeMinutes += 24 * 60 + } + + const duration = wakeMinutes - bedMinutes + setSuggestedDuration(duration) + } else { + setSuggestedDuration(null) + } + }, [formData.bedtime, formData.wake_time]) // Live plausibility check useEffect(() => { @@ -750,6 +811,12 @@ function NewEntryForm({ onSave, onCancel, formatDuration }) { />
= {formatDuration(formData.duration_minutes)} + {suggestedDuration && suggestedDuration !== formData.duration_minutes && ( + setFormData({ ...formData, duration_minutes: suggestedDuration })}> + 💡 Vorschlag: {formatDuration(suggestedDuration)} (übernehmen?) + + )}