import { useEffect, useRef, type CSSProperties, type RefObject } from 'react'; import type { AdventureLogEntry } from '../game/types'; import { useT } from '../i18n'; function formatTime(timestamp: number): string { const d = new Date(timestamp); const hh = String(d.getHours()).padStart(2, '0'); const mm = String(d.getMinutes()).padStart(2, '0'); return `${hh}:${mm}`; } const scrollAreaStyle: CSSProperties = { flex: 1, overflowY: 'auto', padding: '4px 2px', fontSize: 12, lineHeight: 1.6, color: '#bbb', maxHeight: 'min(52vh, 420px)', }; const entryStyle: CSSProperties = { whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', }; const timestampStyle: CSSProperties = { color: 'rgba(140,160,200,0.7)', marginRight: 4, fontFamily: 'monospace', fontSize: 11, }; const battleChildStyle: CSSProperties = { paddingLeft: 14, fontSize: 11, color: '#9aa', whiteSpace: 'normal', overflow: 'visible', textOverflow: 'unset', lineHeight: 1.45, }; const detailsStyle: CSSProperties = { marginBottom: 4, }; const summaryStyle: CSSProperties = { cursor: 'pointer', }; /** Scrollable adventure log list (Hero sheet Journal tab). */ export function AdventureLogEntries({ entries, scrollRef, }: { entries: AdventureLogEntry[]; scrollRef?: RefObject; }) { const tr = useT(); const innerRef = useRef(null); const ref = scrollRef ?? innerRef; useEffect(() => { if (ref.current) { ref.current.scrollTop = ref.current.scrollHeight; } }, [entries.length, ref]); const lastBattleIdx = (() => { for (let i = entries.length - 1; i >= 0; i--) { if (entries[i]?.kind === 'battle_group') return i; } return -1; })(); return (
{entries.length === 0 && (
{tr.noEventsYet}
)} {entries.map((entry, idx) => { if (entry.kind === 'battle_group') { const isLastBattle = idx === lastBattleIdx; return (
[{formatTime(entry.timestamp)}] {entry.title}
{entry.lines.map((line) => (
{line.message}
))}
); } return (
[{formatTime(entry.timestamp)}] {entry.message}
); })}
); }