Fix mobile date picker + auto-update end date from start date (v2.3.4)

- 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)
This commit is contained in:
Maurice
2026-03-19 18:01:41 +01:00
parent 22f5623adb
commit fd6fc9e71f
3 changed files with 37 additions and 4 deletions

View File

@@ -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"

View File

@@ -73,11 +73,26 @@ export function CustomDatePicker({ value, onChange, placeholder, style = {} }) {
{open && ReactDOM.createPortal(
<div ref={dropRef} style={{
position: 'fixed',
top: (() => { 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)',
}}>