diff --git a/src/components/bookings/BookingModal.tsx b/src/components/bookings/BookingModal.tsx index d416930..17ec01a 100644 --- a/src/components/bookings/BookingModal.tsx +++ b/src/components/bookings/BookingModal.tsx @@ -1,4 +1,4 @@ -import { useState, useLayoutEffect } from 'react' +import { useState, useLayoutEffect, useRef, useEffect } from 'react' import { format, addDays } from 'date-fns' import { Star, Banknote, CreditCard, AlertCircle, Map, Plus, Trash2, Tag, Minus, BedDouble, Tv2, Send, Loader2, CheckCircle2, Clock, CalendarDays, User, Phone } from 'lucide-react' import { MOCK_DISCOUNTS } from '../../pages/DiscountsPage' @@ -103,6 +103,11 @@ export function BookingModal({ open, draft, rooms, bookings = [], onClose, onSav const [rentalPhone, setRentalPhone] = useState('') const [rentalNotes, setRentalNotes] = useState('') const [rentalSaving, setRentalSaving] = useState(false) + // Rental guest autocomplete + const [rentalShowSugg, setRentalShowSugg] = useState(false) + const [rentalDbResults, setRentalDbResults] = useState<{ id: string; firstName: string; lastName: string; phone: string | null }[]>([]) + const rentalSearchTimer = useRef | null>(null) + const rentalNameRef = useRef(null) const rentalObj = rentalObjects?.find(o => o.id === rentalObjId) ?? rentalObjects?.[0] const rentalDayBookings = rentalBookings.filter(b => @@ -130,6 +135,27 @@ export function BookingModal({ open, draft, rooms, bookings = [], onClose, onSav setRentalEndM(rentalEffStart + 60) } }, [rentalEffStart]) + + // Close rental guest suggestions on outside click + useEffect(() => { + const handler = (e: MouseEvent) => { + if (rentalNameRef.current && !rentalNameRef.current.contains(e.target as Node)) { + setRentalShowSugg(false) + } + } + document.addEventListener('mousedown', handler) + return () => document.removeEventListener('mousedown', handler) + }, []) + + // Rental guest suggestions from current bookings + const rentalGuestSugg = [ + ...(bookings ?? []).filter(b => b.status === 'checked_in'), + ...(bookings ?? []).filter(b => b.status === 'confirmed'), + ] + const rentalFiltered = rentalGuest.trim().length > 0 + ? rentalGuestSugg.filter(b => b.guestName.toLowerCase().includes(rentalGuest.toLowerCase())) + : rentalGuestSugg + const rentalHasFullDay = rentalDayBookings.some(b => b.isFullDay) const rentalHasTimed = rentalDayBookings.some(b => !b.isFullDay) const rentalNoSlots = !rentalHasFullDay && rentalAvailStarts.length === 0 @@ -470,11 +496,12 @@ export function BookingModal({ open, draft, rooms, bookings = [], onClose, onSav Весь день {rentalHasTimed && Есть частичные брони} {!rentalIsFullDay && ( @@ -524,8 +551,58 @@ export function BookingModal({ open, draft, rooms, bookings = [], onClose, onSav - setRentalGuest(e.target.value)} /> +
+ setRentalShowSugg(true)} + onChange={e => { + const val = e.target.value + setRentalGuest(val) + setRentalShowSugg(true) + if (rentalSearchTimer.current) clearTimeout(rentalSearchTimer.current) + if (val.trim().length >= 2 && slug) { + rentalSearchTimer.current = setTimeout(async () => { + try { + const results = await api.guests.list(slug, val.trim()) + setRentalDbResults(results.slice(0, 8)) + } catch { setRentalDbResults([]) } + }, 300) + } else { + setRentalDbResults([]) + } + }} + /> + {rentalShowSugg && (rentalFiltered.length > 0 || rentalDbResults.length > 0) && ( +
+ {rentalFiltered.slice(0, 5).map(b => ( + + ))} + {rentalDbResults + .filter(g => !rentalFiltered.some(b => b.guestName === `${g.lastName} ${g.firstName}`)) + .map(g => ( + + ))} +
+ )} +