From f5542429b0e5ab22ed688a478dd8f29bd2bc7a58 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 9 Nov 2025 18:46:38 +0100 Subject: [PATCH] feat: streamline dashboard actions by removing inline add-entry form and manual refresh --- src/App.js | 104 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 95 insertions(+), 9 deletions(-) diff --git a/src/App.js b/src/App.js index 0ab24fd..fcc1cdb 100644 --- a/src/App.js +++ b/src/App.js @@ -28,6 +28,7 @@ function App() { const [dirtyDialogMessage, setDirtyDialogMessage] = useState(''); const [pendingNavigation, setPendingNavigation] = useState(null); const [dirtyDialogSaving, setDirtyDialogSaving] = useState(false); + const [confirmDialog, setConfirmDialog] = useState({ open: false }); const weekdays = ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag']; const delay = useCallback((ms) => new Promise((resolve) => setTimeout(resolve, ms)), []); @@ -543,6 +544,31 @@ function App() { setPendingNavigation(null); }, []); + const askConfirmation = useCallback( + (options = {}) => + new Promise((resolve) => { + setConfirmDialog({ + open: true, + title: options.title || 'Bitte bestätigen', + message: options.message || 'Bist du sicher?', + confirmLabel: options.confirmLabel || 'Ja', + cancelLabel: options.cancelLabel || 'Abbrechen', + confirmTone: options.confirmTone || 'primary', + resolve + }); + }), + [] + ); + + const handleConfirmDialog = useCallback((result) => { + setConfirmDialog((prev) => { + if (prev?.resolve) { + prev.resolve(result); + } + return { open: false }; + }); + }, []); + useEffect(() => { let ticker; let cancelled = false; @@ -651,18 +677,30 @@ function App() { } }; - const deleteEntry = (entryId) => { - setIsDirty(true); - if (window.confirm('Soll dieser Eintrag dauerhaft gelöscht werden?')) { - const updatedConfig = config.filter((item) => item.id !== entryId); - setConfig(updatedConfig); - setStatus('Eintrag gelöscht!'); - setTimeout(() => setStatus(''), 3000); + const deleteEntry = async (entryId) => { + const confirmed = await askConfirmation({ + title: 'Eintrag löschen', + message: 'Soll dieser Eintrag dauerhaft gelöscht werden?', + confirmLabel: 'Löschen', + confirmTone: 'danger' + }); + if (!confirmed) { + return; } + setIsDirty(true); + const updatedConfig = config.filter((item) => item.id !== entryId); + setConfig(updatedConfig); + setStatus('Eintrag gelöscht!'); + setTimeout(() => setStatus(''), 3000); }; const hideEntry = async (entryId) => { - if (!window.confirm('Soll dieser Betrieb ausgeblendet werden?')) { + const confirmed = await askConfirmation({ + title: 'Betrieb ausblenden', + message: 'Soll dieser Betrieb ausgeblendet werden?', + confirmLabel: 'Ausblenden' + }); + if (!confirmed) { return; } setIsDirty(true); @@ -749,9 +787,15 @@ function App() { if (existing && !existing.hidden) { return; } - if (!window.confirm(`Soll der Betrieb "${store.name}" zur Liste hinzugefügt werden?`)) { + const confirmed = await askConfirmation({ + title: 'Betrieb hinzufügen', + message: `Soll der Betrieb "${store.name}" zur Liste hinzugefügt werden?`, + confirmLabel: 'Hinzufügen' + }); + if (!confirmed) { return; } + setIsDirty(true); const message = existing ? 'Betrieb wieder eingeblendet.' : 'Betrieb zur Liste hinzugefügt.'; setIsDirty(true); await persistConfigUpdate( @@ -1409,6 +1453,16 @@ function App() { onCancel={handleDirtyCancel} saving={dirtyDialogSaving} /> + handleConfirmDialog(true)} + onCancel={() => handleConfirmDialog(false)} + /> ); @@ -1508,6 +1562,38 @@ function DirtyNavigationDialog({ open, message, onSave, onDiscard, onCancel, sav ); } +function ConfirmationDialog({ open, title, message, confirmLabel, cancelLabel, confirmTone = 'primary', onConfirm, onCancel }) { + if (!open) { + return null; + } + const confirmClasses = + confirmTone === 'danger' + ? 'bg-red-600 hover:bg-red-700 focus:ring-red-500' + : 'bg-blue-600 hover:bg-blue-700 focus:ring-blue-500'; + return ( +
+
+

{title || 'Bitte bestätigen'}

+

{message || 'Bist du sicher?'}

+
+ + +
+
+
+ ); +} + function formatEta(seconds) { if (seconds == null || seconds === Infinity) { return null;