fix: dates timezone, guest lookup fallback to bookings, regex fix
- localDate() uses local timezone instead of UTC (prevents showing yesterday after midnight in UTC+3) - Guest lookup: fallback to bookings table by guest_email/guest_phone when no guest profile found in CRM (guests table) - Fix REGEXP_REPLACE pattern from '\D' (PCRE) to '[^0-9]' (PostgreSQL POSIX) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -115,7 +115,7 @@ const publicWidget: FastifyPluginAsync = async (fastify) => {
|
|||||||
if (phone) {
|
if (phone) {
|
||||||
const cleanPhone = phone.replace(/\D/g, '')
|
const cleanPhone = phone.replace(/\D/g, '')
|
||||||
params.push(cleanPhone)
|
params.push(cleanPhone)
|
||||||
conditions.push(`REGEXP_REPLACE(g.phone, '\\D', '', 'g') = $${params.length}`)
|
conditions.push(`REGEXP_REPLACE(g.phone, '[^0-9]', '', 'g') = $${params.length}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const { rows } = await db.query(
|
const { rows } = await db.query(
|
||||||
@@ -127,8 +127,41 @@ const publicWidget: FastifyPluginAsync = async (fastify) => {
|
|||||||
params,
|
params,
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!rows[0]) return reply.code(404).send({ error: 'Guest not found' })
|
if (rows[0]) return rows[0]
|
||||||
return rows[0]
|
|
||||||
|
// Fallback: search in past bookings by guest_email / guest_phone
|
||||||
|
const bConditions: string[] = []
|
||||||
|
const bParams: unknown[] = [hotel.id]
|
||||||
|
if (email) {
|
||||||
|
bParams.push(email.toLowerCase().trim())
|
||||||
|
bConditions.push(`LOWER(b.guest_email) = $${bParams.length}`)
|
||||||
|
}
|
||||||
|
if (phone) {
|
||||||
|
const cleanPhone = phone.replace(/\D/g, '')
|
||||||
|
bParams.push(cleanPhone)
|
||||||
|
bConditions.push(`REGEXP_REPLACE(b.guest_phone, '[^0-9]', '', 'g') = $${bParams.length}`)
|
||||||
|
}
|
||||||
|
const { rows: bRows } = await db.query(
|
||||||
|
`SELECT b.guest_name, b.guest_email, b.guest_phone
|
||||||
|
FROM bookings b
|
||||||
|
WHERE b.hotel_id = $1 AND (${bConditions.join(' OR ')})
|
||||||
|
ORDER BY b.created_at DESC
|
||||||
|
LIMIT 1`,
|
||||||
|
bParams,
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!bRows[0]) return reply.code(404).send({ error: 'Guest not found' })
|
||||||
|
|
||||||
|
// Parse guest_name into first/last name (format: "Фамилия Имя Отчество" or "Имя Фамилия")
|
||||||
|
const nameParts = (bRows[0].guest_name as string || '').trim().split(/\s+/)
|
||||||
|
return {
|
||||||
|
first_name: nameParts[1] ?? nameParts[0] ?? '',
|
||||||
|
last_name: nameParts[0] ?? '',
|
||||||
|
middle_name: nameParts[2] ?? null,
|
||||||
|
email: bRows[0].guest_email ?? null,
|
||||||
|
phone: bRows[0].guest_phone ?? null,
|
||||||
|
is_blacklisted: false,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -289,7 +322,7 @@ const publicWidget: FastifyPluginAsync = async (fastify) => {
|
|||||||
if (guestPhone) {
|
if (guestPhone) {
|
||||||
const cleanPhone = guestPhone.replace(/\D/g, '')
|
const cleanPhone = guestPhone.replace(/\D/g, '')
|
||||||
blParams.push(cleanPhone)
|
blParams.push(cleanPhone)
|
||||||
blConditions.push(`REGEXP_REPLACE(phone, '\\D', '', 'g') = $${blParams.length}`)
|
blConditions.push(`REGEXP_REPLACE(phone, '[^0-9]', '', 'g') = $${blParams.length}`)
|
||||||
}
|
}
|
||||||
const { rows: blRows } = await db.query(
|
const { rows: blRows } = await db.query(
|
||||||
`SELECT id FROM guests WHERE hotel_id = $1 AND is_blacklisted = TRUE AND (${blConditions.join(' OR ')}) LIMIT 1`,
|
`SELECT id FROM guests WHERE hotel_id = $1 AND is_blacklisted = TRUE AND (${blConditions.join(' OR ')}) LIMIT 1`,
|
||||||
|
|||||||
@@ -195,10 +195,12 @@ export function WidgetPreview({ settings, slug, realRooms, realCategories, payme
|
|||||||
paymentEnabled?: boolean
|
paymentEnabled?: boolean
|
||||||
}) {
|
}) {
|
||||||
const [previewTab, setPreviewTab] = useState<'rooms' | 'rental'>('rooms')
|
const [previewTab, setPreviewTab] = useState<'rooms' | 'rental'>('rooms')
|
||||||
const todayStr = new Date().toISOString().slice(0, 10)
|
const localDate = (offsetDays = 0) => {
|
||||||
const tomorrowStr = new Date(Date.now() + 86400000).toISOString().slice(0, 10)
|
const d = new Date(); d.setDate(d.getDate() + offsetDays)
|
||||||
const [checkIn, setCheckIn] = useState(todayStr)
|
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
|
||||||
const [checkOut, setCheckOut] = useState(tomorrowStr)
|
}
|
||||||
|
const [checkIn, setCheckIn] = useState(() => localDate(0))
|
||||||
|
const [checkOut, setCheckOut] = useState(() => localDate(1))
|
||||||
const [guests, setGuests] = useState(2)
|
const [guests, setGuests] = useState(2)
|
||||||
const [extraBeds, setExtraBeds] = useState(0)
|
const [extraBeds, setExtraBeds] = useState(0)
|
||||||
const [children, setChildren] = useState(0)
|
const [children, setChildren] = useState(0)
|
||||||
|
|||||||
Reference in New Issue
Block a user