diff --git a/src/components/calendar/BookingCalendar.tsx b/src/components/calendar/BookingCalendar.tsx index f2ef444..c1c6c0e 100644 --- a/src/components/calendar/BookingCalendar.tsx +++ b/src/components/calendar/BookingCalendar.tsx @@ -669,7 +669,7 @@ export function BookingCalendar({ rooms, bookings, slug, onBookingCreate, onBook const isWe = date.getDay() === 0 || date.getDay() === 6 const isTod = isToday(date) const dayBookings = (rentalBookings ?? []).filter( - b => b.objectId === obj.id && b.date === dateStr && b.status !== 'cancelled', + b => b.objectId === obj.id && (b.date as string).slice(0, 10) === dateStr && b.status !== 'cancelled', ) const hasFullDay = dayBookings.some(b => b.isFullDay) @@ -791,10 +791,11 @@ export function BookingCalendar({ rooms, bookings, slug, onBookingCreate, onBook obj={rentalModal.obj} date={rentalModal.date} existingBookings={(rentalBookings ?? []).filter( - b => b.objectId === rentalModal.obj.id && b.date === rentalModal.date, + b => b.objectId === rentalModal.obj.id && (b.date as string).slice(0, 10) === rentalModal.date, )} bookings={bookings} rooms={rooms} + slug={slug} onClose={() => setRentalModal(null)} onSave={(b) => { onRentalBookingCreate?.(b) diff --git a/src/components/rental/RentalBookingModal.tsx b/src/components/rental/RentalBookingModal.tsx index fefd14e..eb383b8 100644 --- a/src/components/rental/RentalBookingModal.tsx +++ b/src/components/rental/RentalBookingModal.tsx @@ -1,6 +1,7 @@ import { useState, useRef, useEffect } from 'react' import { X, Clock, CalendarDays, User, Phone, AlertCircle, Banknote, CreditCard, Building2, Link2 } from 'lucide-react' import { cn } from '../../lib/utils' +import { api } from '../../lib/api' import type { RentalObject, RentalBooking } from '../../data/rentalData' import type { Booking, Room } from '../../types' @@ -11,6 +12,7 @@ interface RentalBookingModalProps { editBooking?: RentalBooking bookings?: Booking[] // all room bookings (for guest search + link) rooms?: Room[] // room list (for displaying room numbers) + slug?: string onClose: () => void onSave: (b: RentalBooking) => void } @@ -24,7 +26,7 @@ function formatHour(h: number): string { } export function RentalBookingModal({ - obj, date, existingBookings, editBooking, bookings = [], rooms = [], onClose, onSave, + obj, date, existingBookings, editBooking, bookings = [], rooms = [], slug, onClose, onSave, }: RentalBookingModalProps) { const isEdit = !!editBooking const [isFullDay, setIsFullDay] = useState(editBooking?.isFullDay ?? false) @@ -41,6 +43,10 @@ export function RentalBookingModal({ const [showSuggestions, setShowSuggestions] = useState(false) const nameRef = useRef(null) + // DB guest search + const [dbResults, setDbResults] = useState<{ id: string; firstName: string; lastName: string; phone: string | null }[]>([]) + const searchTimerRef = useRef | null>(null) + // Bookings with guest info — checked_in first, then confirmed const checkedIn = bookings.filter(b => b.status === 'checked_in') const confirmed = bookings.filter(b => b.status === 'confirmed') @@ -234,14 +240,30 @@ export function RentalBookingModal({ className="input pl-8 text-sm" placeholder="Имя гостя" value={guestName} - onChange={e => { setGuestName(e.target.value); setShowSuggestions(true) }} + onChange={e => { + const val = e.target.value + setGuestName(val) + setShowSuggestions(true) + if (searchTimerRef.current) clearTimeout(searchTimerRef.current) + if (val.trim().length >= 2 && slug) { + searchTimerRef.current = setTimeout(async () => { + try { + const results = await api.guests.list(slug, val.trim()) + setDbResults(results.slice(0, 8)) + } catch { setDbResults([]) } + }, 300) + } else { + setDbResults([]) + } + }} onFocus={() => setShowSuggestions(true)} autoComplete="off" /> {/* Suggestions dropdown */} - {showSuggestions && filtered.length > 0 && ( -
- {filtered.slice(0, 10).map(b => { + {showSuggestions && (filtered.length > 0 || dbResults.length > 0) && ( +
+ {/* Current/upcoming guests from bookings */} + {filtered.slice(0, 5).map(b => { const rLabel = roomLabel(b) const isCheckedIn = b.status === 'checked_in' return ( @@ -251,20 +273,41 @@ export function RentalBookingModal({ onMouseDown={() => selectGuest(b)} className="w-full flex items-center gap-2.5 px-3 py-2.5 hover:bg-slate-50 dark:hover:bg-slate-700 transition-colors text-left" > -
+

{b.guestName}

- {isCheckedIn ? '🏠 Проживает' : '📅 Бронь'}{rLabel ? ` · ${rLabel}` : ''} - {b.guestPhone ? ` · ${b.guestPhone}` : ''} + {isCheckedIn ? '🏠 Проживает' : '📅 Бронь'}{rLabel ? ` · ${rLabel}` : ''}{b.guestPhone ? ` · ${b.guestPhone}` : ''}

) })} + {/* DB guest search results */} + {dbResults + .filter(g => !filtered.some(b => b.guestName === `${g.lastName} ${g.firstName}`)) + .map(g => ( + + )) + }
)}
diff --git a/src/pages/CalendarPage.tsx b/src/pages/CalendarPage.tsx index d48d1eb..3d4a177 100644 --- a/src/pages/CalendarPage.tsx +++ b/src/pages/CalendarPage.tsx @@ -159,6 +159,8 @@ export function CalendarPage() { setRentalBookings(prev => [...prev, created]) } catch (err) { console.error('Failed to create rental booking:', err) + const msg = err instanceof Error ? err.message : 'Ошибка сохранения аренды' + alert(msg) } }, [slug])