Use course dials for live-log wind direction and course entry.

Reuses CourseDialInput from the classic journal editor in the live modals, prefilled from the most recent wind or course values.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-31 21:20:19 +02:00
parent 74282f50d0
commit a0b8664e23
2 changed files with 76 additions and 11 deletions
+17
View File
@@ -3306,6 +3306,23 @@ html.theme-cupertino .events-scroll-container {
border-radius: var(--app-radius-card, 12px);
}
.live-log-modal--dial {
width: min(320px, 100%);
}
.live-log-dial-field {
display: flex;
flex-direction: column;
gap: 8px;
margin-bottom: 16px;
}
.live-log-dial-field label {
font-size: 13px;
font-weight: 600;
color: var(--app-text-muted);
}
.live-log-modal h3 {
margin: 0 0 16px;
font-size: 17px;
+59 -11
View File
@@ -47,6 +47,7 @@ import {
import { getCurrentPosition } from '../utils/geolocation.js'
import { sortLogEventsByTime, type LogEventPayload } from '../utils/logEntryPayload.js'
import { useDialog } from './ModalDialog.tsx'
import CourseDialInput from './CourseDialInput.tsx'
interface LiveLogViewProps {
logbookId: string
@@ -84,6 +85,13 @@ function lastCourseFromEvents(events: LogEventPayload[]): string {
return ''
}
function lastWindDirectionFromEvents(events: LogEventPayload[]): string {
for (let i = events.length - 1; i >= 0; i--) {
if (events[i].windDirection.trim()) return events[i].windDirection
}
return ''
}
export default function LiveLogView({
logbookId,
onOpenEditor,
@@ -548,7 +556,7 @@ export default function LiveLogView({
</button>
{weatherExpanded && (
<div className="live-log-weather-submenu">
<button type="button" className="live-log-subaction-btn" onClick={() => openValueModal('wind')} disabled={busy}>
<button type="button" className="live-log-subaction-btn" onClick={() => openValueModal('wind', lastWindDirectionFromEvents(events))} disabled={busy}>
{t('logs.live_wind_btn')}
</button>
<button type="button" className="live-log-subaction-btn" onClick={() => openValueModal('temp')} disabled={busy}>
@@ -644,10 +652,30 @@ export default function LiveLogView({
{modal === 'wind' && (
<div className="live-log-modal-backdrop" onClick={() => setModal('none')}>
<div className="live-log-modal glass" onClick={(e) => e.stopPropagation()}>
<div className="live-log-modal live-log-modal--dial glass" onClick={(e) => e.stopPropagation()}>
<h3>{t('logs.live_wind_btn')}</h3>
<input type="text" className="input-text mb-2" value={valueInput} onChange={(e) => setValueInput(e.target.value)} placeholder={t('logs.event_wind_direction')} autoFocus />
<input type="text" className="input-text" value={valueInputSecondary} onChange={(e) => setValueInputSecondary(e.target.value)} placeholder={t('logs.event_wind_strength')} />
<div className="live-log-dial-field">
<label>{t('logs.event_wind_direction')}</label>
<CourseDialInput
value={valueInput}
onChange={setValueInput}
disabled={busy}
allowCardinal
displayMode="auto"
size="sm"
aria-label={t('logs.event_wind_direction')}
/>
</div>
<div className="live-log-dial-field">
<label>{t('logs.event_wind_strength')}</label>
<input
type="text"
className="input-text"
value={valueInputSecondary}
onChange={(e) => setValueInputSecondary(e.target.value)}
placeholder="e.g. 4 Bft"
/>
</div>
<div className="live-log-modal-actions">
<button type="button" className="btn secondary" onClick={() => setModal('none')}>{t('logs.confirm_no')}</button>
<button type="button" className="btn primary" onClick={confirmValueModal}>{t('logs.live_sails_confirm')}</button>
@@ -656,7 +684,29 @@ export default function LiveLogView({
</div>
)}
{['pressure', 'temp', 'precip', 'sea_state', 'course', 'fuel', 'water', 'sog', 'stw'].includes(modal) && (
{modal === 'course' && (
<div className="live-log-modal-backdrop" onClick={() => setModal('none')}>
<div className="live-log-modal live-log-modal--dial glass" onClick={(e) => e.stopPropagation()}>
<h3>{t('logs.live_course_btn')}</h3>
<div className="live-log-dial-field">
<label>{t('logs.event_mgk')}</label>
<CourseDialInput
value={valueInput}
onChange={setValueInput}
disabled={busy}
size="sm"
aria-label={t('logs.event_mgk')}
/>
</div>
<div className="live-log-modal-actions">
<button type="button" className="btn secondary" onClick={() => setModal('none')}>{t('logs.confirm_no')}</button>
<button type="button" className="btn primary" onClick={confirmValueModal}>{t('logs.live_sails_confirm')}</button>
</div>
</div>
</div>
)}
{['pressure', 'temp', 'precip', 'sea_state', 'fuel', 'water', 'sog', 'stw'].includes(modal) && (
<div className="live-log-modal-backdrop" onClick={() => setModal('none')}>
<div className="live-log-modal glass" onClick={(e) => e.stopPropagation()}>
<h3>
@@ -664,7 +714,6 @@ export default function LiveLogView({
{modal === 'temp' && t('logs.live_temp_btn')}
{modal === 'precip' && t('logs.live_precip_btn')}
{modal === 'sea_state' && t('logs.live_sea_state_btn')}
{modal === 'course' && t('logs.live_course_btn')}
{modal === 'fuel' && t('logs.live_fuel_btn')}
{modal === 'water' && t('logs.live_water_btn')}
{modal === 'sog' && t('logs.live_sog_btn')}
@@ -684,11 +733,10 @@ export default function LiveLogView({
: modal === 'temp' ? t('logs.live_temp_placeholder')
: modal === 'precip' ? t('logs.live_precip_placeholder')
: modal === 'sea_state' ? t('logs.live_sea_state_placeholder')
: modal === 'course' ? t('logs.live_course_placeholder')
: modal === 'fuel' ? t('logs.live_fuel_placeholder')
: modal === 'water' ? t('logs.live_water_placeholder')
: modal === 'sog' ? t('logs.live_sog_placeholder')
: t('logs.live_stw_placeholder')
: modal === 'fuel' ? t('logs.live_fuel_placeholder')
: modal === 'water' ? t('logs.live_water_placeholder')
: modal === 'sog' ? t('logs.live_sog_placeholder')
: t('logs.live_stw_placeholder')
}
autoFocus
onKeyDown={(e) => { if (e.key === 'Enter') confirmValueModal() }}