fix(robustheit+ux): atomares Speichern, Offline-Härtung, Einsatz-Beenden, Audit raus
Robustheit / Datensicherheit: - Features-PUT in prisma.$transaction (delete+create atomar) — verhindert Totalverlust bei Abbruch zwischen Löschen und Neuanlegen - localStorage-Features pro Projekt (lageplan-features-<id>) statt globalem Key — verhindert Datenübertrag zwischen Projekten - Sync-Queue verwirft dauerhafte 4xx-Fehler statt Endlos-Retry - beforeunload persistiert auch leere Feature-Listen (Löschungen gehen nicht verloren) UX: - Leitungsrechner-Dropdown: Popover z-[2000] (lag hinter dem Panel), Label gekürzt - Neuer "Einsatz beenden"-Button (speichert, löst Lock, schliesst Einsatz) - Audit-Trail-Einstiege entfernt (Toolbar-Button + Menü-Eintrag) Version 1.4.10 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -21,10 +21,12 @@ export function useAutoSave({
|
||||
isEditingByMe,
|
||||
setSyncQueueCount,
|
||||
}: UseAutoSaveOptions) {
|
||||
// Persist features to localStorage on change (including empty array to reflect deletions)
|
||||
// Persist features to localStorage on change (per project — verhindert, dass Features
|
||||
// eines Projekts in ein anderes "bluten"). Inkl. leerem Array (spiegelt Löschungen).
|
||||
useEffect(() => {
|
||||
localStorage.setItem('lageplan-features', JSON.stringify(features))
|
||||
}, [features])
|
||||
if (!currentProject?.id) return
|
||||
localStorage.setItem(`lageplan-features-${currentProject.id}`, JSON.stringify(features))
|
||||
}, [features, currentProject?.id])
|
||||
|
||||
// Auto-save to API — debounced 2s after every feature change + fallback interval
|
||||
const saveTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
||||
@@ -81,7 +83,9 @@ export function useAutoSave({
|
||||
// Also save on page unload / tab switch
|
||||
useEffect(() => {
|
||||
const handleBeforeUnload = () => {
|
||||
if (currentProject?.id && featuresRef.current.length > 0) {
|
||||
// Nur der aktive Bearbeiter persistiert beim Schliessen — auch eine leere Liste,
|
||||
// damit "alles gelöscht + Tab zu" nicht die alten Elemente in der DB stehen lässt.
|
||||
if (currentProject?.id && isEditingByMe) {
|
||||
const payload = JSON.stringify({ features: featuresRef.current })
|
||||
navigator.sendBeacon(`/api/projects/${currentProject.id}/features`, new Blob([payload], { type: 'application/json' }))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user