feat(ux): Sprint 3 mobile nav, sync conflicts, and resilience
Improve mobile bottom navigation, accessible dialogs and cards, explicit sync conflict resolution, i18n error messages, encrypted draft autosave, and persistent storage hints for offline data safety. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -5,6 +5,8 @@ import { getActiveMasterKey } from '../services/auth.js'
|
||||
import { getLogbookKey } from '../services/logbookKeys.js'
|
||||
import { encryptJson, decryptJson } from '../services/crypto.js'
|
||||
import { syncLogbook } from '../services/sync.js'
|
||||
import { saveEntryDraft, clearEntryDraft } from '../services/entryDraft.js'
|
||||
import { getErrorMessage } from '../utils/errors.js'
|
||||
import { downloadLogbookPagePdf } from '../services/pdfExport.js'
|
||||
import { FileText, Save, ChevronLeft, Check, Compass, Plus, Trash2, MapPin, CloudSun, Clock, Download, Upload, Pencil, X, ChevronDown, ChevronUp } from 'lucide-react'
|
||||
import PhotoCapture from './PhotoCapture.tsx'
|
||||
@@ -288,6 +290,14 @@ export default function LogEntryEditor({
|
||||
events
|
||||
])
|
||||
|
||||
useEffect(() => {
|
||||
if (readOnly || loading || !date) return
|
||||
const timer = window.setTimeout(() => {
|
||||
void saveEntryDraft(logbookId, entryId, buildPayloadForSigning())
|
||||
}, 4000)
|
||||
return () => window.clearTimeout(timer)
|
||||
}, [readOnly, loading, logbookId, entryId, buildPayloadForSigning, date])
|
||||
|
||||
const fuelPerMotorHour = useMemo(
|
||||
() => computeFuelPerMotorHour(parseFloat(fuelConsumption) || 0, parseFloat(motorHours) || 0),
|
||||
[fuelConsumption, motorHours]
|
||||
@@ -1208,15 +1218,17 @@ export default function LogEntryEditor({
|
||||
...signaturesForSave
|
||||
})
|
||||
|
||||
await clearEntryDraft(logbookId, entryId)
|
||||
|
||||
setSuccess(true)
|
||||
trackPlausibleEvent(PlausibleEvents.TRAVEL_DAY_SAVED)
|
||||
setTimeout(() => {
|
||||
setSuccess(false)
|
||||
onBack()
|
||||
}, 1500)
|
||||
} catch (err: any) {
|
||||
} catch (err: unknown) {
|
||||
console.error('Failed to save entry details:', err)
|
||||
setError(err.message || 'Failed to save entry details.')
|
||||
setError(getErrorMessage(err, t('errors.save_failed')))
|
||||
} finally {
|
||||
setSaving(false)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user