fix: maintenance overlay + context menu UX improvements
- Calendar overlay: normalize date strings (slice 0-10) to handle full ISO timestamps from Postgres; fix off-by-one (to = exclusive); stronger stripe visibility; guard against vFrom >= vTo - Context menu: dateFrom defaults to today, indefinite defaults to false (both date inputs shown immediately) - DateRangeForm: extracted DateInput component with CalendarDays icon that triggers native date picker - HK status order: clean → inspect → cleaning → dirty Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -215,12 +215,14 @@ export function BookingCalendar({ rooms, bookings, slug, onBookingCreate, onBook
|
||||
if (draftRoom && (draftRoom.status === 'maintenance' || draftRoom.status === 'blocked')) {
|
||||
const bookIn = new Date(checkIn + 'T00:00:00')
|
||||
const bookOut = new Date(checkOut + 'T00:00:00')
|
||||
const mFrom = draftRoom.maintenanceFrom ? new Date(draftRoom.maintenanceFrom + 'T00:00:00') : null
|
||||
const mTo = draftRoom.maintenanceTo ? new Date(draftRoom.maintenanceTo + 'T00:00:00') : null
|
||||
const mFrom = draftRoom.maintenanceFrom ? new Date(draftRoom.maintenanceFrom.slice(0, 10) + 'T00:00:00') : null
|
||||
const mTo = draftRoom.maintenanceTo ? new Date(draftRoom.maintenanceTo.slice(0, 10) + 'T00:00:00') : null
|
||||
const overlaps = (!mFrom || bookOut > mFrom) && (!mTo || bookIn < mTo)
|
||||
if (overlaps) {
|
||||
const period = mFrom
|
||||
? ` (${draftRoom.maintenanceFrom}${mTo ? ` — ${draftRoom.maintenanceTo}` : ' — без срока'})`
|
||||
const fromStr = draftRoom.maintenanceFrom?.slice(0, 10)
|
||||
const toStr = draftRoom.maintenanceTo?.slice(0, 10)
|
||||
const period = fromStr
|
||||
? ` (${fromStr}${toStr ? ` — ${toStr}` : ' — без срока'})`
|
||||
: ' (без срока)'
|
||||
setMaintenanceWarningDraft({ draft, roomStatus: draftRoom.status, period })
|
||||
setDragStart(null); setDragEnd(null); setDraft(null)
|
||||
@@ -522,16 +524,16 @@ export function BookingCalendar({ rooms, bookings, slug, onBookingCreate, onBook
|
||||
<div className="relative flex-1">
|
||||
{/* Maintenance / blocked overlay — with optional date range */}
|
||||
{(room.status === 'maintenance' || room.status === 'blocked') && (() => {
|
||||
const from = room.maintenanceFrom ? new Date(room.maintenanceFrom + 'T00:00:00') : null
|
||||
const to = room.maintenanceTo ? new Date(room.maintenanceTo + 'T00:00:00') : null
|
||||
// Calculate left offset and width if dates are set
|
||||
let left = 0, width = '100%'
|
||||
// slice(0,10) normalises both 'YYYY-MM-DD' and full ISO timestamps from Postgres
|
||||
const from = room.maintenanceFrom ? new Date(room.maintenanceFrom.slice(0, 10) + 'T00:00:00') : null
|
||||
const to = room.maintenanceTo ? new Date(room.maintenanceTo.slice(0, 10) + 'T00:00:00') : null
|
||||
let left = 0, width: string | number = '100%'
|
||||
if (from || to) {
|
||||
const visibleFrom = from ? Math.max(0, differenceInDays(from, startDate)) : 0
|
||||
const visibleTo = to ? Math.min(dates.length - 1, differenceInDays(to, startDate)) : dates.length - 1
|
||||
if (visibleTo < 0 || visibleFrom >= dates.length) return null
|
||||
left = visibleFrom * CELL_WIDTH
|
||||
width = `${(visibleTo - visibleFrom + 1) * CELL_WIDTH}px`
|
||||
const vFrom = from ? Math.max(0, differenceInDays(from, startDate)) : 0
|
||||
const vTo = to ? Math.min(dates.length, differenceInDays(to, startDate)) : dates.length
|
||||
if (vTo <= 0 || vFrom >= dates.length || vFrom >= vTo) return null
|
||||
left = vFrom * CELL_WIDTH
|
||||
width = (vTo - vFrom) * CELL_WIDTH
|
||||
}
|
||||
return (
|
||||
<div
|
||||
@@ -539,11 +541,11 @@ export function BookingCalendar({ rooms, bookings, slug, onBookingCreate, onBook
|
||||
style={{
|
||||
left, width,
|
||||
background: room.status === 'maintenance'
|
||||
? 'repeating-linear-gradient(45deg, transparent, transparent 6px, rgba(251,146,60,0.12) 6px, rgba(251,146,60,0.12) 12px)'
|
||||
: 'repeating-linear-gradient(45deg, transparent, transparent 6px, rgba(148,163,184,0.15) 6px, rgba(148,163,184,0.15) 12px)',
|
||||
? 'repeating-linear-gradient(45deg, transparent, transparent 5px, rgba(251,146,60,0.22) 5px, rgba(251,146,60,0.22) 10px)'
|
||||
: 'repeating-linear-gradient(45deg, transparent, transparent 5px, rgba(148,163,184,0.25) 5px, rgba(148,163,184,0.25) 10px)',
|
||||
backgroundColor: room.status === 'maintenance'
|
||||
? 'rgba(251,146,60,0.05)'
|
||||
: 'rgba(148,163,184,0.08)',
|
||||
? 'rgba(251,146,60,0.08)'
|
||||
: 'rgba(148,163,184,0.12)',
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user