fix(logs): Ereignisprotokoll chronologisch nach Uhrzeit sortieren
Einträge werden beim Laden, Speichern und Export älteste-oben angezeigt (sortLogEventsByTime). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -20,7 +20,7 @@ import {
|
||||
hasAnySignature
|
||||
} from '../utils/signatures.js'
|
||||
import type { SignatureValue } from '../types/signatures.js'
|
||||
import { buildLogEntryPayload, type LogEventPayload } from '../utils/logEntryPayload.js'
|
||||
import { buildLogEntryPayload, sortLogEventsByTime, type LogEventPayload } from '../utils/logEntryPayload.js'
|
||||
import { hashEntryForSigning } from '../utils/entryCanonicalHash.js'
|
||||
import { signLogEntry } from '../services/entrySigning.js'
|
||||
import { getLogbookAccess } from '../services/logbookAccess.js'
|
||||
@@ -483,7 +483,7 @@ export default function LogEntryEditor({
|
||||
setSignSkipper(normalizeSignature(preloadedEntry.signSkipper) || '')
|
||||
setSignCrew(normalizeSignature(preloadedEntry.signCrew) || '')
|
||||
loadTrackStatsFromEntry(preloadedEntry)
|
||||
setEvents(preloadedEntry.events || [])
|
||||
setEvents(sortLogEventsByTime(preloadedEntry.events || []))
|
||||
setSavedFingerprint(fingerprintFromStoredEntry(preloadedEntry))
|
||||
return
|
||||
}
|
||||
@@ -516,7 +516,7 @@ export default function LogEntryEditor({
|
||||
setSignSkipper(normalizeSignature(decrypted.signSkipper) || '')
|
||||
setSignCrew(normalizeSignature(decrypted.signCrew) || '')
|
||||
loadTrackStatsFromEntry(decrypted)
|
||||
setEvents(decrypted.events || [])
|
||||
setEvents(sortLogEventsByTime(decrypted.events || []))
|
||||
setSavedFingerprint(fingerprintFromStoredEntry(decrypted))
|
||||
}
|
||||
}
|
||||
@@ -871,7 +871,7 @@ export default function LogEntryEditor({
|
||||
if (editingEventIndex !== null) {
|
||||
const hadSkipperSignature = !!signSkipper
|
||||
markSkipperSignatureClearedForEventChange()
|
||||
nextEvents = events.map((ev, idx) => (idx === editingEventIndex ? eventData : ev))
|
||||
nextEvents = sortLogEventsByTime(events.map((ev, idx) => (idx === editingEventIndex ? eventData : ev)))
|
||||
if (hadSkipperSignature) {
|
||||
void showAlertRef.current(
|
||||
t('logs.sign_cleared_skipper_re_sign'),
|
||||
@@ -879,7 +879,7 @@ export default function LogEntryEditor({
|
||||
)
|
||||
}
|
||||
} else {
|
||||
nextEvents = [...events, eventData]
|
||||
nextEvents = sortLogEventsByTime([...events, eventData])
|
||||
}
|
||||
|
||||
setEvents(nextEvents)
|
||||
|
||||
@@ -3,6 +3,7 @@ import { getActiveMasterKey } from './auth.js'
|
||||
import { getLogbookKey } from './logbookKeys.js'
|
||||
import { decryptJson } from './crypto.js'
|
||||
import { formatSignatureForExport, normalizeSignature } from '../utils/signatures.js'
|
||||
import { sortLogEventsByTime } from '../utils/logEntryPayload.js'
|
||||
import i18n from '../i18n/index.js'
|
||||
|
||||
function escapeCsvValue(val: string | number | undefined | null): string {
|
||||
@@ -134,7 +135,7 @@ export async function exportLogbookToCsv(logbookId: string, preloadedData?: { ya
|
||||
].map(escapeCsvValue));
|
||||
} else {
|
||||
// Sort events chronologically by time
|
||||
const sortedEvents = [...eventsList].sort((a, b) => (a.time || '').localeCompare(b.time || ''));
|
||||
const sortedEvents = sortLogEventsByTime(eventsList);
|
||||
for (const ev of sortedEvents) {
|
||||
rows.push([
|
||||
dateVal, travelDay, dep, dest,
|
||||
|
||||
@@ -4,6 +4,7 @@ import { getActiveMasterKey } from './auth.js'
|
||||
import { getLogbookKey } from './logbookKeys.js'
|
||||
import { decryptJson } from './crypto.js'
|
||||
import { isSignatureImage, isPasskeySignature } from '../utils/signatures.js'
|
||||
import { sortLogEventsByTime } from '../utils/logEntryPayload.js'
|
||||
import i18n from '../i18n/index.js'
|
||||
|
||||
function formatPasskeySignDate(signedAt: string): string {
|
||||
@@ -132,7 +133,7 @@ export async function generateLogbookPagePdf(logbookId: string, entryId: string,
|
||||
// Draw Data Rows
|
||||
const events = entry.events || [];
|
||||
const maxRows = 16;
|
||||
const sortedEvents = [...events].sort((a: any, b: any) => (a.time || '').localeCompare(b.time || ''));
|
||||
const sortedEvents = sortLogEventsByTime(events);
|
||||
|
||||
doc.setFont('Helvetica', 'normal');
|
||||
|
||||
|
||||
@@ -17,6 +17,11 @@ export interface LogEventPayload {
|
||||
remarks: string
|
||||
}
|
||||
|
||||
/** Chronological order: earliest time first (HH:MM). */
|
||||
export function sortLogEventsByTime<T extends Pick<LogEventPayload, 'time'>>(events: T[]): T[] {
|
||||
return [...events].sort((a, b) => (a.time || '').localeCompare(b.time || ''))
|
||||
}
|
||||
|
||||
export interface LogEntryPayloadInput {
|
||||
date: string
|
||||
dayOfTravel: string
|
||||
@@ -38,7 +43,7 @@ export function buildLogEntryPayload(input: LogEntryPayloadInput): Record<string
|
||||
destination: input.destination.trim(),
|
||||
freshwater: { ...input.freshwater },
|
||||
fuel: { ...input.fuel },
|
||||
events: input.events.map((e) => ({ ...e }))
|
||||
events: sortLogEventsByTime(input.events.map((e) => ({ ...e })))
|
||||
}
|
||||
|
||||
if (input.trackDistanceNm !== undefined) payload.trackDistanceNm = input.trackDistanceNm
|
||||
|
||||
Reference in New Issue
Block a user