diff --git a/client/src/App.css b/client/src/App.css index 99f66d7..49da2d8 100644 --- a/client/src/App.css +++ b/client/src/App.css @@ -2435,15 +2435,29 @@ html.scheme-dark .themed-select-option.is-selected { } .sails-picker-pills { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(min(100%, 128px), 1fr)); - gap: 6px; + gap: 4px; + } + + .sails-picker-container.is-collapsible .sails-picker-toggle { + display: inline-flex; } .sail-pill { - text-align: center; padding: 3px 8px; font-size: 11px; + border-radius: 12px; + line-height: 1.2; + } +} + +@media (max-width: 480px) { + .sails-picker-container.is-collapsible.is-collapsed .sails-picker-pills { + max-height: 3.25rem; + } + + .sail-pill { + padding: 2px 7px; + font-size: 10px; } } @@ -2706,12 +2720,47 @@ html.theme-cupertino .events-scroll-container { /* Event Editor Interactive Sails Picker */ .sails-picker-container { grid-column: 1 / -1; + margin-top: -4px; } .sails-picker-pills { display: flex; flex-wrap: wrap; gap: 6px; + position: relative; +} + +.sails-picker-container.is-collapsible.is-collapsed .sails-picker-pills { + max-height: 3.75rem; + overflow: hidden; +} + +.sails-picker-container.is-collapsible.is-collapsed .sails-picker-pills::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 1.25rem; + background: linear-gradient(to bottom, transparent, var(--app-surface, #0f172a)); + pointer-events: none; +} + +.sails-picker-toggle { + display: none; + align-items: center; + gap: 4px; + margin: 4px auto 0; + padding: 2px 8px; + background: none; + border: none; + color: var(--app-text-muted, #94a3b8); + font-size: 12px; + cursor: pointer; +} + +.sails-picker-toggle:hover { + color: var(--app-accent, #fbbf24); } .sail-pill { diff --git a/client/src/components/LogEntryEditor.tsx b/client/src/components/LogEntryEditor.tsx index 8fb0b1b..1bb7164 100644 --- a/client/src/components/LogEntryEditor.tsx +++ b/client/src/components/LogEntryEditor.tsx @@ -6,7 +6,7 @@ import { getLogbookKey } from '../services/logbookKeys.js' import { encryptJson, decryptJson } from '../services/crypto.js' import { syncLogbook } from '../services/sync.js' import { downloadLogbookPagePdf } from '../services/pdfExport.js' -import { FileText, Save, ChevronLeft, Check, Compass, Plus, Trash2, MapPin, CloudSun, Clock, Download, Upload, Pencil, X } from 'lucide-react' +import { FileText, Save, ChevronLeft, Check, Compass, Plus, Trash2, MapPin, CloudSun, Clock, Download, Upload, Pencil, X, ChevronDown, ChevronUp } from 'lucide-react' import PhotoCapture from './PhotoCapture.tsx' import SignatureSection from './SignatureSection.tsx' import TrackMap from './TrackMap.tsx' @@ -176,6 +176,7 @@ export default function LogEntryEditor({ const [evCurrent, setEvCurrent] = useState('') const [evHeel, setEvHeel] = useState('') const [evSailsOrMotor, setEvSailsOrMotor] = useState('') + const [sailsPickerExpanded, setSailsPickerExpanded] = useState(false) const [evLogReading, setEvLogReading] = useState('') const [evDistance, setEvDistance] = useState('') const [evGpsLat, setEvGpsLat] = useState('') @@ -842,6 +843,9 @@ export default function LogEntryEditor({ ? ['Großsegel', 'Genua', 'Fock', 'Spinnaker', 'Gennaker'] : ['Mainsail', 'Genoa', 'Jib', 'Spinnaker', 'Gennaker'] + const eventSailOptions = yachtSails.length > 0 ? yachtSails : defaultSails + const showSailsPickerToggle = eventSailOptions.length + 1 > 6 + const toggleSailOrMotor = (item: string) => { let currentItems = evSailsOrMotor .split(/\s*(?:\+|\bplus\b|,)\s*/i) @@ -865,6 +869,15 @@ export default function LogEntryEditor({ return currentItems.includes(item.toLowerCase()) } + const motorPropulsionLabel = t('logs.motor_propulsion') + const sortedEventSailOptions = [...eventSailOptions].sort((a, b) => { + const aActive = isItemActive(a) + const bActive = isItemActive(b) + if (aActive === bActive) return 0 + return aActive ? -1 : 1 + }) + const isMotorActive = isItemActive(motorPropulsionLabel) + const clearEventForm = () => { setEvTime(currentLocalTimeHHMM()) setEvMgk('') @@ -1573,9 +1586,23 @@ export default function LogEntryEditor({ /> -
+
- {(yachtSails.length > 0 ? yachtSails : defaultSails).map((sail) => ( + {isMotorActive && ( + toggleSailOrMotor(motorPropulsionLabel)} + > + {motorPropulsionLabel} + + )} + {sortedEventSailOptions.map((sail) => ( ))} - toggleSailOrMotor(t('logs.motor_propulsion'))} - > - {t('logs.motor_propulsion')} - + {!isMotorActive && ( + toggleSailOrMotor(motorPropulsionLabel)} + > + {motorPropulsionLabel} + + )}
+ {showSailsPickerToggle && ( + + )}
diff --git a/client/src/i18n/locales/de.json b/client/src/i18n/locales/de.json index 26383e5..54f6336 100644 --- a/client/src/i18n/locales/de.json +++ b/client/src/i18n/locales/de.json @@ -222,6 +222,8 @@ "event_heel": "Krängung (°)", "event_sails": "Segelführung / Motor", "motor_propulsion": "Maschinenfahrt", + "sails_picker_show_more": "Alle Segel anzeigen", + "sails_picker_show_less": "Weniger anzeigen", "motor_hours": "Maschinenstunden (gesamt)", "fuel_per_motor_hour": "Verbrauch pro Maschinenstunde", "event_distance": "Distanz (sm)", diff --git a/client/src/i18n/locales/en.json b/client/src/i18n/locales/en.json index 99e2a9a..9ff4e23 100644 --- a/client/src/i18n/locales/en.json +++ b/client/src/i18n/locales/en.json @@ -222,6 +222,8 @@ "event_heel": "Heel Angle (°)", "event_sails": "Sails / Motor Status", "motor_propulsion": "Engine Propulsion", + "sails_picker_show_more": "Show all sails", + "sails_picker_show_less": "Show less", "motor_hours": "Engine hours (total)", "fuel_per_motor_hour": "Consumption per engine hour", "event_distance": "Distance (nm)",