fix: buttons not working

This commit is contained in:
2025-11-10 12:00:15 +01:00
parent f1d5d6bfee
commit 4c3c4afe27
3 changed files with 68 additions and 46 deletions

View File

@@ -117,3 +117,22 @@ pre {
width: 100%; width: 100%;
} }
} }
@keyframes dashboard-row-glow {
0% {
background-color: rgba(59, 130, 246, 0.25);
box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.45);
}
60% {
background-color: rgba(59, 130, 246, 0.15);
box-shadow: 0 0 0 6px rgba(59, 130, 246, 0.15);
}
100% {
background-color: transparent;
box-shadow: 0 0 0 0 transparent;
}
}
.dashboard-row-highlight {
animation: dashboard-row-glow 2.5s ease forwards;
}

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect, useCallback, useMemo } from 'react'; import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react';
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom'; import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
import { startOfDay } from 'date-fns'; import { startOfDay } from 'date-fns';
import './App.css'; import './App.css';
@@ -40,6 +40,10 @@ function App() {
const [activeRangePicker, setActiveRangePicker] = useState(null); const [activeRangePicker, setActiveRangePicker] = useState(null);
const [notificationPanelOpen, setNotificationPanelOpen] = useState(false); const [notificationPanelOpen, setNotificationPanelOpen] = useState(false);
const [focusedStoreId, setFocusedStoreId] = useState(null); const [focusedStoreId, setFocusedStoreId] = useState(null);
const configRef = useRef(config);
useEffect(() => {
configRef.current = config;
}, [config]);
const minSelectableDate = useMemo(() => startOfDay(new Date()), []); const minSelectableDate = useMemo(() => startOfDay(new Date()), []);
const weekdays = ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag']; const weekdays = ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag'];
@@ -681,47 +685,49 @@ function App() {
}; };
}, [isDirty]); }, [isDirty]);
const persistConfigUpdate = async (updater, successMessage, { autoCommit = false } = {}) => { const persistConfigUpdate = useCallback(
if (!session?.token) { async (updater, successMessage, { autoCommit = false } = {}) => {
return; const baseConfig = configRef.current;
} const nextConfigState = typeof updater === 'function' ? updater(baseConfig) : updater;
let nextConfigState; if (!nextConfigState) {
setConfig((prev) => { return;
nextConfigState = typeof updater === 'function' ? updater(prev) : updater;
return nextConfigState;
});
if (!nextConfigState) {
return;
}
if (!autoCommit) {
setIsDirty(true);
}
setStatus('Speichere...');
setError('');
try {
const response = await authorizedFetch('/api/config', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(nextConfigState)
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
} }
const result = await response.json(); setConfig(nextConfigState);
if (!result.success) { if (!session?.token) {
throw new Error(result.error || 'Unbekannter Fehler beim Speichern'); setIsDirty(true);
return;
} }
const message = successMessage || 'Konfiguration gespeichert.'; if (!autoCommit) {
setStatus(message);
setTimeout(() => setStatus(''), 3000);
setIsDirty(false);
} catch (err) {
setError(`Fehler beim Speichern: ${err.message}`);
if (autoCommit) {
setIsDirty(true); setIsDirty(true);
} }
} setStatus('Speichere...');
}; setError('');
try {
const response = await authorizedFetch('/api/config', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(nextConfigState)
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const result = await response.json();
if (!result.success) {
throw new Error(result.error || 'Unbekannter Fehler beim Speichern');
}
const message = successMessage || 'Konfiguration gespeichert.';
setStatus(message);
setTimeout(() => setStatus(''), 3000);
setIsDirty(false);
} catch (err) {
setError(`Fehler beim Speichern: ${err.message}`);
if (autoCommit) {
setIsDirty(true);
}
}
},
[authorizedFetch, session?.token]
);
const deleteEntry = async (entryId) => { const deleteEntry = async (entryId) => {
const confirmed = await askConfirmation({ const confirmed = await askConfirmation({

View File

@@ -43,17 +43,14 @@ const DashboardView = ({
return; return;
} }
row.scrollIntoView({ behavior: 'smooth', block: 'center' }); row.scrollIntoView({ behavior: 'smooth', block: 'center' });
row.classList.add('ring-4', 'ring-blue-400', 'bg-blue-50', 'transition'); row.classList.add('dashboard-row-highlight', 'ring-4', 'ring-blue-400');
row.style.transition = 'background-color 0.8s ease, box-shadow 0.8s ease';
const timeout = setTimeout(() => { const timeout = setTimeout(() => {
row.classList.remove('ring-4', 'ring-blue-400'); row.classList.remove('dashboard-row-highlight', 'ring-4', 'ring-blue-400');
row.style.backgroundColor = 'transparent'; onClearFocus();
setTimeout(onClearFocus, 600); }, 2500);
}, 2200);
return () => { return () => {
clearTimeout(timeout); clearTimeout(timeout);
row.classList.remove('ring-4', 'ring-blue-400'); row.classList.remove('dashboard-row-highlight', 'ring-4', 'ring-blue-400');
row.style.backgroundColor = 'transparent';
}; };
}, [focusedStoreId, onClearFocus]); }, [focusedStoreId, onClearFocus]);
const { const {