diff --git a/client/src/components/LogEntryEditor.tsx b/client/src/components/LogEntryEditor.tsx index fd113c0..112c709 100644 --- a/client/src/components/LogEntryEditor.tsx +++ b/client/src/components/LogEntryEditor.tsx @@ -76,6 +76,8 @@ export default function LogEntryEditor({ }: LogEntryEditorProps) { const { t, i18n } = useTranslation() const { showAlert, showConfirm } = useDialog() + const showAlertRef = useRef(showAlert) + showAlertRef.current = showAlert // General details state const [date, setDate] = useState('') @@ -145,6 +147,7 @@ export default function LogEntryEditor({ const fileInputRef = useRef(null) const lockedContentHashRef = useRef(null) const contentReadyRef = useRef(false) + const lastSignatureAlertHashRef = useRef(null) const applyTrackStats = (waypoints: SavedTrack['waypoints']) => { const stats = computeTrackStats(waypoints) @@ -252,12 +255,15 @@ export default function LogEntryEditor({ lockedContentHashRef.current = null setSignSkipper('') setSignCrew('') - void showAlert( - t('logs.sign_cleared_re_sign'), - t('logs.sign_cleared_re_sign_title') - ) + if (lastSignatureAlertHashRef.current !== entryHash) { + lastSignatureAlertHashRef.current = entryHash + void showAlertRef.current( + t('logs.sign_cleared_re_sign'), + t('logs.sign_cleared_re_sign_title') + ) + } } - }, [entryHash, signSkipper, signCrew, readOnly, showAlert, t]) + }, [entryHash, signSkipper, signCrew, readOnly, t]) const confirmSignWarning = useCallback(async (): Promise => { return showConfirm( @@ -355,6 +361,7 @@ export default function LogEntryEditor({ setError(null) lockedContentHashRef.current = null contentReadyRef.current = false + lastSignatureAlertHashRef.current = null try { if (readOnly && preloadedEntry) { setDate(preloadedEntry.date || '') @@ -1330,7 +1337,7 @@ export default function LogEntryEditor({ style={{ width: 'auto', padding: '10px 20px', marginLeft: 'auto', display: 'flex' }} > - Add Event Entry + {t('logs.add_event_btn')} )} diff --git a/client/src/components/ModalDialog.tsx b/client/src/components/ModalDialog.tsx index f9ae596..8594a23 100644 --- a/client/src/components/ModalDialog.tsx +++ b/client/src/components/ModalDialog.tsx @@ -1,4 +1,4 @@ -import React, { createContext, useContext, useState, useRef } from 'react' +import React, { createContext, useContext, useState, useRef, useCallback, useMemo } from 'react' interface DialogContextType { showAlert: (message: string, title?: string, confirmText?: string) => Promise @@ -25,7 +25,7 @@ export function DialogProvider({ children }: { children: React.ReactNode }) { const resolveRef = useRef<((val: any) => void) | null>(null) - const showAlert = (msg: string, headerTitle?: string, btnText?: string): Promise => { + const showAlert = useCallback((msg: string, headerTitle?: string, btnText?: string): Promise => { setMessage(msg) setTitle(headerTitle || '') setType('alert') @@ -35,9 +35,14 @@ export function DialogProvider({ children }: { children: React.ReactNode }) { return new Promise((resolve) => { resolveRef.current = resolve }) - } + }, []) - const showConfirm = (msg: string, headerTitle?: string, btnConfirm?: string, btnCancel?: string): Promise => { + const showConfirm = useCallback(( + msg: string, + headerTitle?: string, + btnConfirm?: string, + btnCancel?: string + ): Promise => { setMessage(msg) setTitle(headerTitle || '') setType('confirm') @@ -48,26 +53,31 @@ export function DialogProvider({ children }: { children: React.ReactNode }) { return new Promise((resolve) => { resolveRef.current = resolve }) - } + }, []) - const handleConfirm = () => { + const handleConfirm = useCallback(() => { setIsOpen(false) if (resolveRef.current) { resolveRef.current(type === 'confirm' ? true : undefined) resolveRef.current = null } - } + }, [type]) - const handleCancel = () => { + const handleCancel = useCallback(() => { setIsOpen(false) if (resolveRef.current) { resolveRef.current(false) resolveRef.current = null } - } + }, []) + + const contextValue = useMemo( + () => ({ showAlert, showConfirm }), + [showAlert, showConfirm] + ) return ( - + {children} {isOpen && (
diff --git a/client/src/i18n/locales/de.json b/client/src/i18n/locales/de.json index d8d61c3..7a1b741 100644 --- a/client/src/i18n/locales/de.json +++ b/client/src/i18n/locales/de.json @@ -115,6 +115,7 @@ "new_entry": "Neuer Reisetag", "travel_details": "Reisedetails", "add_event": "Neuen Logbucheintrag hinzufügen", + "add_event_btn": "Ereignis hinzufügen", "date": "Datum", "day_of_travel": "Tag der Reise / Reisetag", "departure": "Start-Hafen (Reise von)", diff --git a/client/src/i18n/locales/en.json b/client/src/i18n/locales/en.json index fc4b7ab..a5ff535 100644 --- a/client/src/i18n/locales/en.json +++ b/client/src/i18n/locales/en.json @@ -115,6 +115,7 @@ "new_entry": "New Travel Day", "travel_details": "Travel Details", "add_event": "Add Event Log Record", + "add_event_btn": "Add Event Entry", "date": "Date", "day_of_travel": "Day of Travel", "departure": "Departure Port (von)",