feat: use availability rate overrides in calendar tooltip and booking modal

- Load rate_overrides in CalendarPage, pass as priceOverrides to BookingCalendar
- Tooltip shows override price for the hovered date (falls back to baseRate)
- BookingModal sums per-night prices from overrides for the stay period
- Room baseRate now only used as initial default for availability grid

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-23 16:35:13 +03:00
parent 70531c3a9a
commit 15936753b9
3 changed files with 57 additions and 21 deletions

View File

@@ -36,6 +36,8 @@ interface BookingCalendarProps {
onDraftStart?: (roomId: string, checkIn: string, checkOut: string) => void
onDraftCancel?: (roomId: string) => void
wsConnected?: boolean
/** categoryId → date (YYYY-MM-DD) → price */
priceOverrides?: Record<string, Record<string, number>>
}
const CATEGORY_ORDER: Record<string, number> = {
@@ -59,7 +61,7 @@ function getRoomTypeColor(type: string): string {
return map[type] ?? 'bg-slate-100 text-slate-600 dark:bg-slate-700 dark:text-slate-300'
}
export function BookingCalendar({ rooms, bookings, slug, onBookingCreate, onBookingUpdate, onBookingBulkUpdate, onRoomUpdate, fadingBookingIds, rentalObjects, rentalBookings, onRentalBookingCreate, locks = new Map(), onDraftStart, onDraftCancel, wsConnected }: BookingCalendarProps) {
export function BookingCalendar({ rooms, bookings, slug, onBookingCreate, onBookingUpdate, onBookingBulkUpdate, onRoomUpdate, fadingBookingIds, rentalObjects, rentalBookings, onRentalBookingCreate, locks = new Map(), onDraftStart, onDraftCancel, wsConnected, priceOverrides }: BookingCalendarProps) {
const [startDate, setStartDate] = useState(() => startOfDay(new Date()))
const [visibleDays, setVisibleDays] = useState(DAYS_VISIBLE)
@@ -878,6 +880,7 @@ export function BookingCalendar({ rooms, bookings, slug, onBookingCreate, onBook
open={true}
draft={bookingModalDraft}
rooms={rooms}
priceOverrides={priceOverrides}
bookings={bookings}
slug={slug}
rentalObjects={rentalObjects}
@@ -959,23 +962,31 @@ export function BookingCalendar({ rooms, bookings, slug, onBookingCreate, onBook
{/* Cell hover price tooltip */}
{hoverTooltip && createPortal(
<div
className="fixed z-[9990] pointer-events-none px-3 py-2 rounded-xl bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 shadow-xl text-xs"
style={{ left: hoverTooltip.x + 16, top: hoverTooltip.y + 16 }}
>
<p className="font-semibold text-slate-700 dark:text-slate-200 mb-0.5">
{format(hoverTooltip.date, 'd MMMM yyyy', { locale: ru })}
</p>
<p className="text-slate-400 dark:text-slate-500 mb-1">Номер {hoverTooltip.room.number}{hoverTooltip.room.name ? ` · ${hoverTooltip.room.name}` : ''}</p>
<p className="font-bold text-slate-900 dark:text-slate-100">
{formatCurrency(hoverTooltip.room.baseRate)}<span className="font-normal text-slate-400"> / ночь</span>
</p>
{hoverTooltip.room.allowHourly && hoverTooltip.room.hourlyRate ? (
<p className="text-slate-500 dark:text-slate-400 mt-0.5">
{formatCurrency(hoverTooltip.room.hourlyRate)} / час
</p>
) : null}
</div>,
(() => {
const dateKey = format(hoverTooltip.date, 'yyyy-MM-dd')
const catId = hoverTooltip.room.categoryId
const overridePrice = catId ? priceOverrides?.[catId]?.[dateKey] : undefined
const nightPrice = overridePrice ?? hoverTooltip.room.baseRate
return (
<div
className="fixed z-[9990] pointer-events-none px-3 py-2 rounded-xl bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 shadow-xl text-xs"
style={{ left: hoverTooltip.x + 16, top: hoverTooltip.y + 16 }}
>
<p className="font-semibold text-slate-700 dark:text-slate-200 mb-0.5">
{format(hoverTooltip.date, 'd MMMM yyyy', { locale: ru })}
</p>
<p className="text-slate-400 dark:text-slate-500 mb-1">Номер {hoverTooltip.room.number}{hoverTooltip.room.name ? ` · ${hoverTooltip.room.name}` : ''}</p>
<p className="font-bold text-slate-900 dark:text-slate-100">
{formatCurrency(nightPrice)}<span className="font-normal text-slate-400"> / ночь</span>
</p>
{hoverTooltip.room.allowHourly && hoverTooltip.room.hourlyRate ? (
<p className="text-slate-500 dark:text-slate-400 mt-0.5">
{formatCurrency(hoverTooltip.room.hourlyRate)} / час
</p>
) : null}
</div>
)
})(),
document.body,
)}
</div>