feat: blacklist, guest lookup, bank transfer payment page

- Add is_blacklisted column to guests (migration 068)
- POST /widget/bookings: block blacklisted guests (403, generic message)
- GET /widget/:slug/guests/lookup: find existing guest by email/phone for auto-fill
- Widget form: debounce guest lookup on email/phone input, show "Заполнить" suggestion
- Widget payment screen: replace fake card form with proper YooKassa redirect screen or bank transfer details page
- Add bank transfer details field to widget settings (saved as widget_bank_details)
- GuestsPage: blacklist toggle button in edit modal + 🚫 ЧС badge in table

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-08 01:31:10 +03:00
parent 08d6629ae8
commit 2b20fc18b3
7 changed files with 277 additions and 90 deletions

View File

@@ -869,9 +869,22 @@ export const api = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
}).then(r => r.json()) as Promise<{ bookingId: string; status: string; confirmationUrl: string | null }>,
}).then(async r => {
const json = await r.json()
if (!r.ok) throw { status: r.status, ...json }
return json as { bookingId: string; status: string; confirmationUrl: string | null }
}),
getBookingStatus: (slug: string, bookingId: string) =>
fetch(`${BASE}/api/widget/${slug}/bookings/${bookingId}/status`).then(r => r.json()),
lookupGuest: (slug: string, params: { email?: string; phone?: string }) => {
const qs = new URLSearchParams()
if (params.email) qs.set('email', params.email)
if (params.phone) qs.set('phone', params.phone)
return fetch(`${BASE}/api/widget/${slug}/guests/lookup?${qs}`).then(async r => {
if (!r.ok) return null
return r.json() as Promise<{ first_name: string; last_name: string; middle_name?: string; email?: string; phone?: string; is_blacklisted: boolean }>
})
},
},
}
@@ -1043,6 +1056,7 @@ export interface GuestApiType {
loyaltyTier: string
loyaltyPoints: number
rating: number
isBlacklisted: boolean
totalStays: number
totalSpent: number
lastVisit: string | null
@@ -1076,6 +1090,7 @@ export interface GuestPayload {
notes?: string
tags?: string[]
rating?: number
is_blacklisted?: boolean
}
export interface RentalObjectApi {
@@ -1665,6 +1680,7 @@ export interface WidgetConfig {
allowExtraBeds: boolean
allowChildren: boolean
hotelName: string
bankDetails: string
}
}