Add multi-guest management: per-booking roster, docs, guest autocomplete

- Migration 010: booking_guests table (roster per booking with passport data)
- Backend: /bookings/:id/guests CRUD — auto-links/creates guest profiles by passport
- Backend: /hotel-settings GET/PATCH for key-value settings (require_guest_docs)
- BookingDetailPanel: Гости tab with multi-guest list, inline add/edit form,
  guest autocomplete (debounced search in guests table), child/main badges,
  passport fields for adults, scan stub, require-docs warning
- SettingsPage: toggle "Обязательное заполнение документов гостей"
- Pass slug prop through CalendarPage → BookingCalendar → BookingDetailPanel

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-19 20:53:07 +03:00
parent de4fb2126b
commit 873a9a4fc4
10 changed files with 803 additions and 11 deletions

View File

@@ -266,6 +266,30 @@ export const api = {
req<Hotel>('PATCH', `/api/hotels/${slug}`, toHotelPayload(data)),
},
// ── Booking Guests ────────────────────────────────────────────────────────
bookingGuests: {
list: (slug: string, bookingId: string) =>
req<BookingGuest[]>('GET', `/api/hotels/${slug}/bookings/${bookingId}/guests`),
add: (slug: string, bookingId: string, data: BookingGuestPayload) =>
req<BookingGuest>('POST', `/api/hotels/${slug}/bookings/${bookingId}/guests`, data),
update: (slug: string, bookingId: string, id: string, data: BookingGuestPayload) =>
req<BookingGuest>('PATCH', `/api/hotels/${slug}/bookings/${bookingId}/guests/${id}`, data),
remove: (slug: string, bookingId: string, id: string) =>
req<void>('DELETE', `/api/hotels/${slug}/bookings/${bookingId}/guests/${id}`),
},
// ── Hotel Settings ────────────────────────────────────────────────────────
hotelSettings: {
get: (slug: string) =>
req<HotelSettings>('GET', `/api/hotels/${slug}/hotel-settings`),
update: (slug: string, data: Partial<HotelSettings>) =>
req<{ ok: boolean }>('PATCH', `/api/hotels/${slug}/hotel-settings`, data),
},
// ── Guests ────────────────────────────────────────────────────────────────
guests: {
list: (slug: string, q?: string) =>
@@ -391,6 +415,45 @@ export interface HotelPayload {
checkInTime?: string; checkOutTime?: string
}
export interface BookingGuest {
id: string
bookingId: string
hotelId: string
guestId: string | null
firstName: string
lastName: string
middleName: string | null
birthDate: string | null
isChild: boolean
isMain: boolean
passportSeries: string | null
passportNumber: string | null
passportIssuedBy: string | null
passportIssueDate: string | null
nationality: string | null
createdAt: string
updatedAt: string
}
export interface BookingGuestPayload {
first_name?: string
last_name?: string
middle_name?: string
birth_date?: string
is_child?: boolean
is_main?: boolean
passport_series?: string
passport_number?: string
passport_issued_by?: string
passport_issue_date?: string
nationality?: string
}
export interface HotelSettings {
require_guest_docs?: boolean
[key: string]: unknown
}
export interface GuestApiType {
id: string
hotelId: string