feat(logbook): attribute log events to creator and show in exports

This commit is contained in:
2026-06-03 19:39:15 +02:00
parent 6c8aa5af4c
commit 73e7613a1b
12 changed files with 332 additions and 26 deletions
+41 -3
View File
@@ -11,6 +11,7 @@ import { downloadLogbookPagePdf } from '../services/pdfExport.js'
import { FileText, Save, ChevronLeft, Check, Compass, Plus, Trash2, MapPin, CloudSun, Clock, Download, Upload, Pencil, X, ChevronDown, ChevronUp, Sparkles } from 'lucide-react'
import PhotoCapture from './PhotoCapture.tsx'
import EventRemarksCell from './EventRemarksCell.tsx'
import CreatorAvatar from './CreatorAvatar.tsx'
import { useEntryVoiceMemos } from '../hooks/useEntryVoiceMemos.js'
import { parseLiveVoiceRemark } from '../utils/liveEventCodes.js'
import { deleteEntryVoiceMemo } from '../services/voiceAttachments.js'
@@ -173,6 +174,24 @@ function fingerprintFromStoredEntry(decrypted: Record<string, unknown>): string
})
}
function findActiveCreatorId(
activeUsername: string | null,
crewSnapshotsById: Record<string, any>,
selectedSkipperId: string | null
): string {
const username = (activeUsername || '').trim()
if (username) {
const matchEntry = Object.entries(crewSnapshotsById).find(
([_, snap]) => (snap?.name || '').trim().toLowerCase() === username.toLowerCase()
)
if (matchEntry) {
return matchEntry[0]
}
return username
}
return selectedSkipperId || 'skipper'
}
interface LogEntryEditorProps {
entryId: string
logbookId: string
@@ -418,8 +437,17 @@ export default function LogEntryEditor({
})
}, [buildPayloadForSigning, signSkipper, signCrew])
const buildEventFromForm = (): LogEvent =>
normalizeLogEvent({
const buildEventFromForm = (): LogEvent => {
let creatorId: string | undefined = undefined
if (editingEventIndex !== null && events[editingEventIndex]) {
creatorId = events[editingEventIndex].creatorId
}
if (!creatorId) {
const activeUsername = localStorage.getItem('active_username')
creatorId = findActiveCreatorId(activeUsername, entryCrew.crewSnapshotsById, entryCrew.selectedSkipperId)
}
return normalizeLogEvent({
time: evTime,
mgk: evMgk,
rwk: evRwk,
@@ -436,8 +464,10 @@ export default function LogEntryEditor({
distance: evDistance,
gpsLat: evGpsLat,
gpsLng: evGpsLng,
remarks: evRemarks
remarks: evRemarks,
creatorId
})
}
const applyEventFormToEvents = (eventData: LogEvent): LogEvent[] => {
if (editingEventIndex !== null) {
@@ -1815,6 +1845,7 @@ export default function LogEntryEditor({
<thead>
<tr>
<th>{t('logs.event_time')}</th>
<th>{t('logs.event_creator')}</th>
<th>{t('logs.event_mgk')}</th>
<th>{t('logs.event_rwk')}</th>
<th>{t('logs.event_wind_direction')}</th>
@@ -1831,6 +1862,13 @@ export default function LogEntryEditor({
{events.map((ev, idx) => (
<tr key={idx}>
<td className="font-mono">{ev.time}</td>
<td style={{ textAlign: 'center', width: '40px', verticalAlign: 'middle' }}>
<CreatorAvatar
creatorId={ev.creatorId}
crewSnapshotsById={entryCrew.crewSnapshotsById}
size={24}
/>
</td>
<td>{ev.mgk ? `${ev.mgk}°` : '—'}</td>
<td>{ev.rwk ? `${ev.rwk}°` : '—'}</td>
<td>{ev.windDirection || '—'}</td>