From fd6fc9e71faf55f7a1a231dece85091c039de58a Mon Sep 17 00:00:00 2001 From: Maurice Date: Thu, 19 Mar 2026 18:01:41 +0100 Subject: [PATCH] Fix mobile date picker + auto-update end date from start date (v2.3.4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Date picker dropdown stays within viewport on mobile (no more overflow) - Opens above if not enough space below - Centers on very small screens (<360px) - End date auto-adjusts when start date changes: - If no end date or end < start → end = start - If both set → preserves trip duration (shifts end by same delta) --- client/src/components/Trips/TripFormModal.jsx | 20 ++++++++++++++++++- .../shared/CustomDateTimePicker.jsx | 19 ++++++++++++++++-- server/package.json | 2 +- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/client/src/components/Trips/TripFormModal.jsx b/client/src/components/Trips/TripFormModal.jsx index a3f3cff..280ca67 100644 --- a/client/src/components/Trips/TripFormModal.jsx +++ b/client/src/components/Trips/TripFormModal.jsx @@ -92,7 +92,25 @@ export default function TripFormModal({ isOpen, onClose, onSave, trip, onCoverUp } } - const update = (field, value) => setFormData(prev => ({ ...prev, [field]: value })) + const update = (field, value) => setFormData(prev => { + const next = { ...prev, [field]: value } + // Auto-adjust end date when start date changes + if (field === 'start_date' && value) { + if (!prev.end_date || prev.end_date < value) { + // If no end date or end date is before new start, set end = start + next.end_date = value + } else if (prev.start_date) { + // Preserve trip duration: shift end date by same delta + const oldStart = new Date(prev.start_date + 'T00:00:00') + const oldEnd = new Date(prev.end_date + 'T00:00:00') + const duration = Math.round((oldEnd - oldStart) / 86400000) + const newEnd = new Date(value + 'T00:00:00') + newEnd.setDate(newEnd.getDate() + duration) + next.end_date = newEnd.toISOString().split('T')[0] + } + } + return next + }) const inputCls = "w-full px-3 py-2.5 border border-slate-200 rounded-lg text-slate-900 placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-slate-300 focus:border-transparent text-sm" diff --git a/client/src/components/shared/CustomDateTimePicker.jsx b/client/src/components/shared/CustomDateTimePicker.jsx index 26bd333..8020d46 100644 --- a/client/src/components/shared/CustomDateTimePicker.jsx +++ b/client/src/components/shared/CustomDateTimePicker.jsx @@ -73,11 +73,26 @@ export function CustomDatePicker({ value, onChange, placeholder, style = {} }) { {open && ReactDOM.createPortal(
{ const r = ref.current?.getBoundingClientRect(); return r ? r.bottom + 4 : 0 })(), - left: (() => { const r = ref.current?.getBoundingClientRect(); return r ? r.left : 0 })(), + ...(() => { + const r = ref.current?.getBoundingClientRect() + if (!r) return { top: 0, left: 0 } + const w = 268, pad = 8 + const vw = window.innerWidth + const vh = window.innerHeight + let left = r.left + let top = r.bottom + 4 + // Keep within viewport horizontally + if (left + w > vw - pad) left = Math.max(pad, vw - w - pad) + // If not enough space below, open above + if (top + 320 > vh) top = Math.max(pad, r.top - 320) + // On very small screens, center horizontally + if (vw < 360) left = Math.max(pad, (vw - w) / 2) + return { top, left } + })(), zIndex: 99999, background: 'var(--bg-card)', border: '1px solid var(--border-primary)', borderRadius: 14, boxShadow: '0 8px 32px rgba(0,0,0,0.12)', padding: 12, width: 268, + maxWidth: 'calc(100vw - 16px)', animation: 'selectIn 0.15s ease-out', backdropFilter: 'blur(24px)', WebkitBackdropFilter: 'blur(24px)', }}> diff --git a/server/package.json b/server/package.json index 117d5b1..377cc5c 100644 --- a/server/package.json +++ b/server/package.json @@ -1,6 +1,6 @@ { "name": "nomad-server", - "version": "2.3.3", + "version": "2.3.4", "main": "src/index.js", "scripts": { "start": "node --experimental-sqlite src/index.js",