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:
@@ -3306,6 +3306,23 @@ html.theme-cupertino .events-scroll-container {
|
|||||||
border-radius: var(--app-radius-card, 12px);
|
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 {
|
.live-log-modal h3 {
|
||||||
margin: 0 0 16px;
|
margin: 0 0 16px;
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ import {
|
|||||||
import { getCurrentPosition } from '../utils/geolocation.js'
|
import { getCurrentPosition } from '../utils/geolocation.js'
|
||||||
import { sortLogEventsByTime, type LogEventPayload } from '../utils/logEntryPayload.js'
|
import { sortLogEventsByTime, type LogEventPayload } from '../utils/logEntryPayload.js'
|
||||||
import { useDialog } from './ModalDialog.tsx'
|
import { useDialog } from './ModalDialog.tsx'
|
||||||
|
import CourseDialInput from './CourseDialInput.tsx'
|
||||||
|
|
||||||
interface LiveLogViewProps {
|
interface LiveLogViewProps {
|
||||||
logbookId: string
|
logbookId: string
|
||||||
@@ -84,6 +85,13 @@ function lastCourseFromEvents(events: LogEventPayload[]): string {
|
|||||||
return ''
|
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({
|
export default function LiveLogView({
|
||||||
logbookId,
|
logbookId,
|
||||||
onOpenEditor,
|
onOpenEditor,
|
||||||
@@ -548,7 +556,7 @@ export default function LiveLogView({
|
|||||||
</button>
|
</button>
|
||||||
{weatherExpanded && (
|
{weatherExpanded && (
|
||||||
<div className="live-log-weather-submenu">
|
<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')}
|
{t('logs.live_wind_btn')}
|
||||||
</button>
|
</button>
|
||||||
<button type="button" className="live-log-subaction-btn" onClick={() => openValueModal('temp')} disabled={busy}>
|
<button type="button" className="live-log-subaction-btn" onClick={() => openValueModal('temp')} disabled={busy}>
|
||||||
@@ -644,10 +652,30 @@ export default function LiveLogView({
|
|||||||
|
|
||||||
{modal === 'wind' && (
|
{modal === 'wind' && (
|
||||||
<div className="live-log-modal-backdrop" onClick={() => setModal('none')}>
|
<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>
|
<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 />
|
<div className="live-log-dial-field">
|
||||||
<input type="text" className="input-text" value={valueInputSecondary} onChange={(e) => setValueInputSecondary(e.target.value)} placeholder={t('logs.event_wind_strength')} />
|
<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">
|
<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 secondary" onClick={() => setModal('none')}>{t('logs.confirm_no')}</button>
|
||||||
<button type="button" className="btn primary" onClick={confirmValueModal}>{t('logs.live_sails_confirm')}</button>
|
<button type="button" className="btn primary" onClick={confirmValueModal}>{t('logs.live_sails_confirm')}</button>
|
||||||
@@ -656,7 +684,29 @@ export default function LiveLogView({
|
|||||||
</div>
|
</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-backdrop" onClick={() => setModal('none')}>
|
||||||
<div className="live-log-modal glass" onClick={(e) => e.stopPropagation()}>
|
<div className="live-log-modal glass" onClick={(e) => e.stopPropagation()}>
|
||||||
<h3>
|
<h3>
|
||||||
@@ -664,7 +714,6 @@ export default function LiveLogView({
|
|||||||
{modal === 'temp' && t('logs.live_temp_btn')}
|
{modal === 'temp' && t('logs.live_temp_btn')}
|
||||||
{modal === 'precip' && t('logs.live_precip_btn')}
|
{modal === 'precip' && t('logs.live_precip_btn')}
|
||||||
{modal === 'sea_state' && t('logs.live_sea_state_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 === 'fuel' && t('logs.live_fuel_btn')}
|
||||||
{modal === 'water' && t('logs.live_water_btn')}
|
{modal === 'water' && t('logs.live_water_btn')}
|
||||||
{modal === 'sog' && t('logs.live_sog_btn')}
|
{modal === 'sog' && t('logs.live_sog_btn')}
|
||||||
@@ -684,7 +733,6 @@ export default function LiveLogView({
|
|||||||
: modal === 'temp' ? t('logs.live_temp_placeholder')
|
: modal === 'temp' ? t('logs.live_temp_placeholder')
|
||||||
: modal === 'precip' ? t('logs.live_precip_placeholder')
|
: modal === 'precip' ? t('logs.live_precip_placeholder')
|
||||||
: modal === 'sea_state' ? t('logs.live_sea_state_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 === 'fuel' ? t('logs.live_fuel_placeholder')
|
||||||
: modal === 'water' ? t('logs.live_water_placeholder')
|
: modal === 'water' ? t('logs.live_water_placeholder')
|
||||||
: modal === 'sog' ? t('logs.live_sog_placeholder')
|
: modal === 'sog' ? t('logs.live_sog_placeholder')
|
||||||
|
|||||||
Reference in New Issue
Block a user