fix: reservations panel mobile responsiveness

- Hide type filter pills on mobile (< md breakpoint)
- Move add button right-aligned on mobile
- Separate booking code into its own row below date/time
- Hide weekday in date on mobile for space
- Reduce padding on mobile
This commit is contained in:
Maurice
2026-04-15 23:26:49 +02:00
parent 9186b8c850
commit c8fc21b8bd
@@ -94,9 +94,10 @@ function ReservationCard({ r, tripId, onEdit, onDelete, files = [], onNavigateTo
try { await onDelete(r.id) } catch { toast.error(t('reservations.toast.deleteError')) } try { await onDelete(r.id) } catch { toast.error(t('reservations.toast.deleteError')) }
} }
const isMobile = typeof window !== 'undefined' && window.innerWidth < 768
const fmtDate = (str) => { const fmtDate = (str) => {
const dateOnly = str.includes('T') ? str.split('T')[0] : str const dateOnly = str.includes('T') ? str.split('T')[0] : str
return new Date(dateOnly + 'T00:00:00Z').toLocaleDateString(locale, { weekday: 'short', day: 'numeric', month: 'short', timeZone: 'UTC' }) return new Date(dateOnly + 'T00:00:00Z').toLocaleDateString(locale, { ...(isMobile ? {} : { weekday: 'short' }), day: 'numeric', month: 'short', timeZone: 'UTC' })
} }
const fmtTime = (str) => { const fmtTime = (str) => {
const d = new Date(str) const d = new Date(str)
@@ -174,10 +175,9 @@ function ReservationCard({ r, tripId, onEdit, onDelete, files = [], onNavigateTo
{/* Body */} {/* Body */}
<div style={{ padding: 14, display: 'flex', flexDirection: 'column', gap: 12, flex: 1 }}> <div style={{ padding: 14, display: 'flex', flexDirection: 'column', gap: 12, flex: 1 }}>
{/* Date / Time / Code row */} {/* Date / Time row */}
{(hasDate || hasCode) && (
<div style={{ display: 'grid', gap: 10, gridTemplateColumns: dateCols > 1 ? `repeat(${dateCols}, 1fr)` : '1fr' }}>
{hasDate && ( {hasDate && (
<div style={{ display: 'grid', gap: 10, gridTemplateColumns: hasTime ? '1fr 1fr' : '1fr' }}>
<div> <div>
<div style={fieldLabelStyle}>{t('reservations.date')}</div> <div style={fieldLabelStyle}>{t('reservations.date')}</div>
<div style={{ ...fieldValueStyle, textAlign: 'center' }}> <div style={{ ...fieldValueStyle, textAlign: 'center' }}>
@@ -187,7 +187,6 @@ function ReservationCard({ r, tripId, onEdit, onDelete, files = [], onNavigateTo
)} )}
</div> </div>
</div> </div>
)}
{hasTime && ( {hasTime && (
<div> <div>
<div style={fieldLabelStyle}>{t('reservations.time')}</div> <div style={fieldLabelStyle}>{t('reservations.time')}</div>
@@ -196,6 +195,9 @@ function ReservationCard({ r, tripId, onEdit, onDelete, files = [], onNavigateTo
</div> </div>
</div> </div>
)} )}
</div>
)}
{/* Booking code */}
{hasCode && ( {hasCode && (
<div> <div>
<div style={fieldLabelStyle}>{t('reservations.confirmationCode')}</div> <div style={fieldLabelStyle}>{t('reservations.confirmationCode')}</div>
@@ -215,8 +217,6 @@ function ReservationCard({ r, tripId, onEdit, onDelete, files = [], onNavigateTo
</div> </div>
</div> </div>
)} )}
</div>
)}
{/* Type-specific metadata */} {/* Type-specific metadata */}
{(() => { {(() => {
@@ -435,7 +435,7 @@ export default function ReservationsPanel({ tripId, reservations, days, assignme
return ( return (
<div style={{ height: '100%', display: 'flex', flexDirection: 'column', fontFamily: "-apple-system, BlinkMacSystemFont, 'SF Pro Text', system-ui, sans-serif" }}> <div style={{ height: '100%', display: 'flex', flexDirection: 'column', fontFamily: "-apple-system, BlinkMacSystemFont, 'SF Pro Text', system-ui, sans-serif" }}>
{/* Unified toolbar */} {/* Unified toolbar */}
<div style={{ padding: '24px 28px 0' }}> <div style={{ padding: '24px 28px 0' }} className="max-md:!px-4 max-md:!pt-4">
<div style={{ <div style={{
background: 'var(--bg-tertiary)', borderRadius: 18, background: 'var(--bg-tertiary)', borderRadius: 18,
padding: '14px 16px 14px 22px', padding: '14px 16px 14px 22px',
@@ -447,8 +447,8 @@ export default function ReservationsPanel({ tripId, reservations, days, assignme
{reservations.length > 0 && ( {reservations.length > 0 && (
<> <>
<div style={{ width: 1, height: 22, background: 'var(--border-faint)', flexShrink: 0 }} /> <div className="hidden md:block" style={{ width: 1, height: 22, background: 'var(--border-faint)', flexShrink: 0 }} />
<div style={{ display: 'inline-flex', gap: 4, flexWrap: 'wrap', flex: 1, minWidth: 0 }}> <div className="hidden md:inline-flex" style={{ gap: 4, flexWrap: 'wrap', flex: 1, minWidth: 0 }}>
<button <button
onClick={() => { setTypeFilters(new Set()); sessionStorage.removeItem(storageKey) }} onClick={() => { setTypeFilters(new Set()); sessionStorage.removeItem(storageKey) }}
style={{ style={{
@@ -509,6 +509,7 @@ export default function ReservationsPanel({ tripId, reservations, days, assignme
display: 'inline-flex', alignItems: 'center', gap: 6, display: 'inline-flex', alignItems: 'center', gap: 6,
padding: '9px 14px', borderRadius: 10, fontSize: 13, fontWeight: 500, padding: '9px 14px', borderRadius: 10, fontSize: 13, fontWeight: 500,
background: 'var(--accent)', color: 'var(--accent-text)', flexShrink: 0, background: 'var(--accent)', color: 'var(--accent-text)', flexShrink: 0,
marginLeft: 'auto',
transition: 'opacity 0.15s ease', transition: 'opacity 0.15s ease',
}} }}
onMouseEnter={e => e.currentTarget.style.opacity = '0.88'} onMouseEnter={e => e.currentTarget.style.opacity = '0.88'}
@@ -522,7 +523,7 @@ export default function ReservationsPanel({ tripId, reservations, days, assignme
</div> </div>
{/* Content */} {/* Content */}
<div style={{ flex: 1, overflowY: 'auto', padding: '24px 28px 80px' }}> <div style={{ flex: 1, overflowY: 'auto', padding: '24px 28px 80px' }} className="max-md:!px-4 max-md:!pt-4">
{total === 0 && reservations.length === 0 ? ( {total === 0 && reservations.length === 0 ? (
<div style={{ textAlign: 'center', padding: '60px 20px' }}> <div style={{ textAlign: 'center', padding: '60px 20px' }}>
<BookMarked size={36} style={{ color: 'var(--text-faint)', display: 'block', margin: '0 auto 12px' }} /> <BookMarked size={36} style={{ color: 'var(--text-faint)', display: 'block', margin: '0 auto 12px' }} />