diff --git a/src/App.js b/src/App.js index 729e3f2..48ddfb0 100644 --- a/src/App.js +++ b/src/App.js @@ -1,7 +1,7 @@ import React, { useState, useEffect, useCallback, useMemo } from 'react'; import { BrowserRouter as Router, Routes, Route, Navigate, Link, useLocation, useNavigate } from 'react-router-dom'; import { DateRange } from 'react-date-range'; -import { format, parseISO, isValid } from 'date-fns'; +import { format, parseISO, isValid, startOfDay } from 'date-fns'; import { de } from 'date-fns/locale'; import './App.css'; import 'react-date-range/dist/styles.css'; @@ -40,9 +40,16 @@ const formatRangeLabel = (start, end) => { return 'Zeitraum auswählen'; }; -const buildSelectionRange = (start, end) => { - const startDate = parseDateValue(start) || parseDateValue(end) || new Date(); - const endDate = parseDateValue(end) || parseDateValue(start) || startDate; +const buildSelectionRange = (start, end, minDate) => { + const minimum = minDate || startOfDay(new Date()); + let startDate = parseDateValue(start) || parseDateValue(end) || minimum; + let endDate = parseDateValue(end) || parseDateValue(start) || startDate; + if (startDate < minimum) { + startDate = minimum; + } + if (endDate < minimum) { + endDate = startDate; + } return { startDate, endDate, @@ -76,6 +83,7 @@ function App() { const [dirtyDialogSaving, setDirtyDialogSaving] = useState(false); const [confirmDialog, setConfirmDialog] = useState({ open: false, resolve: null }); const [activeRangePicker, setActiveRangePicker] = useState(null); + const minSelectableDate = useMemo(() => startOfDay(new Date()), []); const weekdays = ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag']; @@ -866,7 +874,7 @@ function App() { return updated; }) ); - }, [setConfig, setIsDirty]); + }, [setConfig]); const configMap = useMemo(() => { const map = new Map(); @@ -880,15 +888,21 @@ function App() { const visibleConfig = useMemo(() => config.filter((item) => !item.hidden), [config]); + const activeRangeEntry = useMemo(() => { + if (!activeRangePicker) { + return null; + } + return config.find((item) => item.id === activeRangePicker) || null; + }, [activeRangePicker, config]); + useEffect(() => { if (!activeRangePicker) { return; } - const stillExists = config.some((item) => item.id === activeRangePicker); - if (!stillExists) { + if (!activeRangeEntry || activeRangeEntry.desiredWeekday) { setActiveRangePicker(null); } - }, [activeRangePicker, config]); + }, [activeRangePicker, activeRangeEntry]); const handleStoreSelection = async (store) => { const storeId = String(store.id); @@ -1343,62 +1357,24 @@ function App() { -
- - {activeRangePicker === item.id && !item.desiredWeekday && ( -
- { - const { startDate, endDate } = ranges.selection; - handleDateRangeSelection(item.id, startDate, endDate); - }} - moveRangeOnFirstSelection={false} - ranges={[buildSelectionRange(rangeStart, rangeEnd)]} - rangeColors={['#2563EB']} - months={1} - direction="horizontal" - showDateDisplay={false} - locale={de} - /> -
- - -
-
- )} -
+
@@ -1437,6 +1413,75 @@ function App() { Konfiguration speichern
+ + {activeRangeEntry && !activeRangeEntry.desiredWeekday && ( +
setActiveRangePicker(null)} + > +
event.stopPropagation()} + > +
+

Zeitraum auswählen für

+

+ {activeRangeEntry.label || `Store ${activeRangeEntry.id}`} +

+
+
+ { + const { startDate, endDate } = ranges.selection; + handleDateRangeSelection(activeRangeEntry.id, startDate, endDate); + }} + moveRangeOnFirstSelection={false} + ranges={[ + buildSelectionRange( + activeRangeEntry.desiredDateRange?.start, + activeRangeEntry.desiredDateRange?.end, + minSelectableDate + ) + ]} + rangeColors={['#2563EB']} + months={1} + direction="horizontal" + showDateDisplay={false} + locale={de} + minDate={minSelectableDate} + /> +
+
+ +
+ + +
+
+
+
+ )} ); diff --git a/src/PickupConfigEditor.js b/src/PickupConfigEditor.js index 4d1826c..4c3130a 100644 --- a/src/PickupConfigEditor.js +++ b/src/PickupConfigEditor.js @@ -1,6 +1,6 @@ import { useState, useEffect } from 'react'; import { DateRange } from 'react-date-range'; -import { format, parseISO, isValid } from 'date-fns'; +import { format, parseISO, isValid, startOfDay } from 'date-fns'; import { de } from 'date-fns/locale'; import 'react-date-range/dist/styles.css'; import 'react-date-range/dist/theme/default.css'; @@ -37,9 +37,16 @@ const formatRangeLabel = (start, end) => { return 'Zeitraum auswählen'; }; -const buildSelectionRange = (start, end) => { - const startDate = parseDateValue(start) || parseDateValue(end) || new Date(); - const endDate = parseDateValue(end) || parseDateValue(start) || startDate; +const buildSelectionRange = (start, end, minDate) => { + const minimum = minDate || startOfDay(new Date()); + let startDate = parseDateValue(start) || parseDateValue(end) || minimum; + let endDate = parseDateValue(end) || parseDateValue(start) || startDate; + if (startDate < minimum) { + startDate = minimum; + } + if (endDate < minimum) { + endDate = startDate; + } return { startDate, endDate, @@ -53,6 +60,7 @@ const PickupConfigEditor = () => { const [status, setStatus] = useState(''); const [error, setError] = useState(''); const [activeRangePicker, setActiveRangePicker] = useState(null); + const minSelectableDate = startOfDay(new Date()); // Simulierte API-Endpunkte - diese müssen in Ihrer tatsächlichen Implementierung angepasst werden const API_URL = '/api/iobroker/pickup-config'; @@ -62,6 +70,16 @@ const PickupConfigEditor = () => { fetchConfig(); }, []); + useEffect(() => { + if (!activeRangePicker) { + return; + } + const entry = config.find((item) => item.id === activeRangePicker); + if (!entry || entry.desiredWeekday) { + setActiveRangePicker(null); + } + }, [activeRangePicker, config]); + const fetchConfig = async () => { setLoading(true); setError(''); @@ -155,27 +173,38 @@ const PickupConfigEditor = () => { } }; - const handleDateRangeSelection = (index, startDate, endDate) => { - const newConfig = [...config]; + const handleDateRangeSelection = (entryId, startDate, endDate) => { const startValue = formatDateValue(startDate); const endValue = formatDateValue(endDate); - if (startValue || endValue) { - newConfig[index].desiredDateRange = { - start: startValue || endValue, - end: endValue || startValue - }; - if (newConfig[index].desiredWeekday) { - delete newConfig[index].desiredWeekday; - } - } else if (newConfig[index].desiredDateRange) { - delete newConfig[index].desiredDateRange; - } - if (newConfig[index].desiredDate) { - delete newConfig[index].desiredDate; - } - setConfig(newConfig); + setConfig((prev) => + prev.map((item) => { + if (item.id !== entryId) { + return item; + } + const updated = { ...item }; + if (startValue || endValue) { + updated.desiredDateRange = { + start: startValue || endValue, + end: endValue || startValue + }; + if (updated.desiredWeekday) { + delete updated.desiredWeekday; + } + } else if (updated.desiredDateRange) { + delete updated.desiredDateRange; + } + if (updated.desiredDate) { + delete updated.desiredDate; + } + return updated; + }) + ); }; + const activeRangeEntry = activeRangePicker + ? config.find((item) => item.id === activeRangePicker) || null + : null; + if (loading) { return
Lade Konfiguration...
; } @@ -265,62 +294,24 @@ const PickupConfigEditor = () => { -
- - {activeRangePicker === item.id && !item.desiredWeekday && ( -
- { - const { startDate, endDate } = ranges.selection; - handleDateRangeSelection(index, startDate, endDate); - }} - moveRangeOnFirstSelection={false} - ranges={[buildSelectionRange(rangeStart, rangeEnd)]} - rangeColors={['#2563EB']} - months={1} - direction="horizontal" - showDateDisplay={false} - locale={de} - /> -
- - -
-
- )} -
+ ); @@ -350,6 +341,75 @@ const PickupConfigEditor = () => { {JSON.stringify(config, null, 2)} + + {activeRangeEntry && !activeRangeEntry.desiredWeekday && ( +
setActiveRangePicker(null)} + > +
event.stopPropagation()} + > +
+

Zeitraum auswählen für

+

+ {activeRangeEntry.label || `Store ${activeRangeEntry.id}`} +

+
+
+ { + const { startDate, endDate } = ranges.selection; + handleDateRangeSelection(activeRangeEntry.id, startDate, endDate); + }} + moveRangeOnFirstSelection={false} + ranges={[ + buildSelectionRange( + activeRangeEntry.desiredDateRange?.start, + activeRangeEntry.desiredDateRange?.end, + minSelectableDate + ) + ]} + rangeColors={['#2563EB']} + months={1} + direction="horizontal" + showDateDisplay={false} + locale={de} + minDate={minSelectableDate} + /> +
+
+ +
+ + +
+
+
+
+ )} ); };