@clicka1/booking 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +171 -0
- package/dist/SalonBookingModal-ZIIKN2O2.js +941 -0
- package/dist/SalonBookingModal-ZIIKN2O2.js.map +1 -0
- package/dist/booking.css +2 -0
- package/dist/chunk-HA7DFBYI.js +548 -0
- package/dist/chunk-HA7DFBYI.js.map +1 -0
- package/dist/index.d.ts +192 -0
- package/dist/index.js +970 -0
- package/dist/index.js.map +1 -0
- package/package.json +37 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../lib/salon-services.ts","../../../lib/salon-opening-hours.ts","../../../lib/booking-blocks.ts","../../../lib/tracking-events.ts","../../../components/booking/useBookingFlow.ts","../../../components/booking/BookingWidget.tsx","../../../components/booking/BookingProvider.tsx","../../../components/booking/useBooking.ts","../../../components/booking/BookingButton.tsx"],"names":["id","t","BookingWidget","useMemo","useRef","useState","useEffect","useCallback","jsx","forwardRef","BookingButton"],"mappings":"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","file":"index.js","sourcesContent":["function randomHex(bytes: number): string {\n const buf = new Uint8Array(bytes);\n globalThis.crypto.getRandomValues(buf);\n return Array.from(buf, b => b.toString(16).padStart(2, '0')).join('');\n}\n\nexport type PaymentType = 'none' | 'deposit' | 'full';\nexport type CancelPolicyAction = 'full_refund' | 'keep_deposit' | 'keep_full';\n\nexport type ServiceItem = {\n id?: string;\n name: string;\n nameEn?: string;\n description?: string;\n descriptionEn?: string;\n category?: string;\n price: number;\n duration_min: number;\n images?: string[];\n variants?: { label: string; price: number; duration?: number }[];\n assignedTeamMemberIds?: string[];\n payment_type?: PaymentType;\n deposit_amount?: number; // euros (e.g. 20 = €20)\n requires_confirmation?: boolean;\n cancel_policy_hours?: number; // hours before which free cancel is allowed\n cancel_policy_action?: CancelPolicyAction; // what happens after the deadline\n};\n\nexport type ParsedSalonService = {\n id: string;\n name: string;\n nameEn?: string;\n description?: string;\n descriptionEn?: string;\n category?: string;\n price?: number;\n duration: number;\n images?: string[];\n variants?: { label: string; price: number; duration?: number }[];\n assignedTeamMemberIds?: string[];\n payment_type?: PaymentType;\n deposit_amount?: number;\n requires_confirmation?: boolean;\n cancel_policy_hours?: number;\n cancel_policy_action?: CancelPolicyAction;\n};\n\nfunction pickFirstNonEmptyString(...values: unknown[]): string {\n for (const value of values) {\n const text = String(value ?? '').trim();\n if (text) return text;\n }\n return '';\n}\n\n/** Returns true for index-based IDs that are positionally unstable (svc-0, svc-1, svc-2-3, …). */\nfunction isUnstableId(id: string): boolean {\n return /^svc-\\d/.test(id);\n}\n\nfunction assignUniqueServiceId(candidate: string, usedIds: Set<string>): string {\n const trimmed = candidate.trim();\n // Keep the candidate if it exists, is not a positional svc-N id, and is unique.\n if (trimmed && !isUnstableId(trimmed) && !usedIds.has(trimmed)) {\n usedIds.add(trimmed);\n return trimmed;\n }\n // Generate a stable random ID (8 hex chars, same pattern as onboarding_code).\n let id = randomHex(4);\n while (usedIds.has(id)) id = randomHex(4);\n usedIds.add(id);\n return id;\n}\n\n/** Parse salon services JSON for public UI and admin (skips unnamed rows, guarantees unique ids). */\nexport function parseSalonServices(raw: unknown): ParsedSalonService[] {\n if (typeof raw === 'string') {\n try {\n raw = JSON.parse(raw) as unknown;\n } catch {\n return [];\n }\n }\n let items: unknown[] = [];\n if (Array.isArray(raw)) {\n items = raw;\n } else if (raw && typeof raw === 'object') {\n items = Object.values(raw as Record<string, unknown>);\n } else {\n return [];\n }\n\n const usedIds = new Set<string>();\n const out: ParsedSalonService[] = [];\n\n items.forEach((item, index) => {\n const row = item as Record<string, unknown>;\n const name = pickFirstNonEmptyString(row.name, row.service_name, row.serviceName, row.title);\n if (!name) return;\n\n const id = assignUniqueServiceId(String(row.id ?? ''), usedIds);\n const duration = Number(row.duration ?? row.duration_min ?? row.durationMin ?? 30) || 30;\n const priceRaw = row.price ?? row.service_price ?? row.servicePrice;\n const price = priceRaw != null ? Number(priceRaw) : undefined;\n const variants = Array.isArray(row.variants)\n ? (row.variants as unknown[])\n .map((variant): { label: string; price: number; duration?: number } | null => {\n if (!variant || typeof variant !== 'object') return null;\n const v = variant as Record<string, unknown>;\n const label = String(v.label ?? '').trim();\n if (!label) return null;\n const priceNum = Number(v.price ?? NaN);\n if (!Number.isFinite(priceNum)) return null;\n const durationNum = Number(v.duration ?? NaN);\n return {\n label,\n price: Math.max(0, priceNum),\n duration: Number.isFinite(durationNum) ? Math.max(5, Math.round(durationNum)) : undefined,\n };\n })\n .filter((variant): variant is { label: string; price: number; duration?: number } => variant !== null)\n : undefined;\n const images = Array.isArray(row.images)\n ? (row.images as unknown[])\n .map((image) => String(image ?? '').trim())\n .filter(Boolean)\n : undefined;\n const assignedTeamMemberIds = Array.isArray(row.assignedTeamMemberIds)\n ? [...new Set((row.assignedTeamMemberIds as unknown[])\n .map((id) => String(id ?? '').trim())\n .filter(Boolean))]\n : undefined;\n\n const paymentTypeRaw = String(row.payment_type ?? '');\n const paymentType: PaymentType | undefined = ['none', 'deposit', 'full'].includes(paymentTypeRaw)\n ? (paymentTypeRaw as PaymentType)\n : undefined;\n const depositAmountRaw = Number(row.deposit_amount ?? NaN);\n const depositAmount = Number.isFinite(depositAmountRaw) ? Math.max(0, depositAmountRaw) : undefined;\n\n const cancelPolicyHoursRaw = Number(row.cancel_policy_hours ?? NaN);\n const cancelPolicyHours = Number.isFinite(cancelPolicyHoursRaw) && cancelPolicyHoursRaw > 0\n ? cancelPolicyHoursRaw\n : undefined;\n const cancelPolicyActionRaw = String(row.cancel_policy_action ?? '');\n const cancelPolicyAction: CancelPolicyAction | undefined = (\n ['full_refund', 'keep_deposit', 'keep_full'] as CancelPolicyAction[]\n ).includes(cancelPolicyActionRaw as CancelPolicyAction)\n ? (cancelPolicyActionRaw as CancelPolicyAction)\n : undefined;\n\n out.push({\n id,\n name,\n nameEn: String(row.nameEn ?? '').trim() || undefined,\n description: String(row.description ?? '').trim() || undefined,\n descriptionEn: String(row.descriptionEn ?? '').trim() || undefined,\n category:\n pickFirstNonEmptyString(\n row.category,\n row.category_name,\n row.categoryName,\n row.service_category,\n row.serviceCategory,\n ) || undefined,\n price: price != null && Number.isFinite(price) ? price : undefined,\n duration,\n images,\n variants: variants && variants.length > 0 ? variants : undefined,\n ...(assignedTeamMemberIds && assignedTeamMemberIds.length > 0\n ? { assignedTeamMemberIds }\n : {}),\n ...(paymentType !== undefined ? { payment_type: paymentType } : {}),\n ...(depositAmount !== undefined ? { deposit_amount: depositAmount } : {}),\n ...(row.requires_confirmation === true ? { requires_confirmation: true } : {}),\n ...(cancelPolicyHours !== undefined ? { cancel_policy_hours: cancelPolicyHours } : {}),\n ...(cancelPolicyAction !== undefined ? { cancel_policy_action: cancelPolicyAction } : {}),\n });\n });\n\n return out;\n}\n\n/** Returns a copy of the service with name/description resolved for the given locale. */\nexport function localizeService<T extends { name: string; nameEn?: string; description?: string; descriptionEn?: string }>(\n service: T,\n locale: string,\n): T {\n if (locale !== 'en') return service;\n const name = service.nameEn?.trim() || service.name;\n const description = service.descriptionEn?.trim() || service.description;\n return { ...service, name, description };\n}\n\nexport function normalizeServices(raw: unknown): ServiceItem[] {\n return parseSalonServices(raw).map((s) => {\n const normalizedVariants = Array.isArray(s.variants)\n ? s.variants\n .map((variant) => ({\n label: String(variant.label ?? '').trim(),\n price: Math.max(0, Number(variant.price) || 0),\n duration:\n variant.duration != null && Number.isFinite(Number(variant.duration))\n ? Math.max(5, Math.round(Number(variant.duration)))\n : undefined,\n }))\n .filter((variant) => variant.label.length > 0)\n : [];\n\n const basePrice =\n normalizedVariants.length > 0\n ? normalizedVariants[0]!.price\n : Math.max(0, Number(s.price ?? 0) || 0);\n const baseDuration =\n normalizedVariants.length > 0\n ? Math.max(5, Number(normalizedVariants[0]!.duration ?? s.duration ?? 30) || 30)\n : Math.max(5, s.duration);\n\n return {\n id: s.id,\n name: s.name,\n ...(s.nameEn ? { nameEn: s.nameEn } : {}),\n description: s.description,\n ...(s.descriptionEn ? { descriptionEn: s.descriptionEn } : {}),\n category: s.category,\n price: basePrice,\n duration_min: baseDuration,\n ...(Array.isArray(s.images) && s.images.length > 0 ? { images: s.images } : {}),\n ...(normalizedVariants.length > 0 ? { variants: normalizedVariants } : {}),\n ...(Array.isArray(s.assignedTeamMemberIds) && s.assignedTeamMemberIds.length > 0\n ? { assignedTeamMemberIds: s.assignedTeamMemberIds }\n : {}),\n ...(['none', 'deposit', 'full'].includes(String((s as unknown as ServiceItem).payment_type ?? ''))\n ? { payment_type: (s as unknown as ServiceItem).payment_type }\n : {}),\n ...((s as unknown as ServiceItem).deposit_amount != null && Number.isFinite(Number((s as unknown as ServiceItem).deposit_amount))\n ? { deposit_amount: Math.max(0, Number((s as unknown as ServiceItem).deposit_amount)) }\n : {}),\n ...((s as unknown as ServiceItem).requires_confirmation === true ? { requires_confirmation: true } : {}),\n ...(s.cancel_policy_hours !== undefined ? { cancel_policy_hours: s.cancel_policy_hours } : {}),\n ...(s.cancel_policy_action !== undefined ? { cancel_policy_action: s.cancel_policy_action } : {}),\n };\n });\n}\n","/** Работно време в стил BOOKA уеб: ключове Monday..Sunday, стойност null = затворено. */\n\nconst DAY_NAMES_EN = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] as const;\n\nconst CLICKA_TO_EN: Record<string, (typeof DAY_NAMES_EN)[number]> = {\n monday: 'Monday',\n tuesday: 'Tuesday',\n wednesday: 'Wednesday',\n thursday: 'Thursday',\n friday: 'Friday',\n saturday: 'Saturday',\n sunday: 'Sunday',\n};\n\nexport type OpeningDayRecord = Record<string, { open: string; close: string } | null>;\n\nconst DEFAULT_OPENING_HOURS: Record<(typeof DAY_NAMES_EN)[number], { open: string; close: string }> = {\n Monday: { open: '09:00', close: '18:00' },\n Tuesday: { open: '09:00', close: '18:00' },\n Wednesday: { open: '09:00', close: '18:00' },\n Thursday: { open: '09:00', close: '18:00' },\n Friday: { open: '09:00', close: '18:00' },\n Saturday: { open: '10:00', close: '16:00' },\n Sunday: { open: '10:00', close: '16:00' },\n};\n\n/** Clicka `working_hours` (monday..sunday) + опционален `opening_hours` JSON от Neon → Monday..Sunday. */\nexport function mergeOpeningHours(\n workingHours: Record<string, { open?: string; close?: string; closed?: boolean }> | null | undefined,\n openingHoursOverride: unknown\n): OpeningDayRecord {\n const out: OpeningDayRecord = {};\n for (const d of DAY_NAMES_EN) out[d] = null;\n\n const fromOverride = normalizeOpeningOverride(openingHoursOverride);\n if (fromOverride) {\n for (const d of DAY_NAMES_EN) {\n if (fromOverride[d] !== undefined) out[d] = fromOverride[d];\n }\n return out;\n }\n\n if (workingHours && typeof workingHours === 'object') {\n for (const [k, v] of Object.entries(workingHours)) {\n const en = CLICKA_TO_EN[k.toLowerCase()];\n if (!en) continue;\n if (!v || v.closed || !v.open || !v.close) out[en] = null;\n else out[en] = { open: v.open, close: v.close };\n }\n }\n return out;\n}\n\nfunction normalizeOpeningOverride(raw: unknown): OpeningDayRecord | null {\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return null;\n const o = raw as Record<string, unknown>;\n const out: OpeningDayRecord = {};\n let any = false;\n for (const d of DAY_NAMES_EN) {\n const v = o[d];\n if (v && typeof v === 'object' && !Array.isArray(v)) {\n const open = String((v as { open?: unknown }).open ?? '');\n const close = String((v as { close?: unknown }).close ?? '');\n if (open && close) {\n out[d] = { open, close };\n any = true;\n } else {\n out[d] = null;\n }\n }\n }\n return any ? out : null;\n}\n\nexport function getCurrentStatusString(openingHours: OpeningDayRecord): string {\n const hasAny = Object.keys(openingHours).some((k) => openingHours[k] != null);\n const now = new Date();\n const dayIndex = (now.getDay() + 6) % 7;\n const dayName = DAY_NAMES_EN[dayIndex];\n const hours = hasAny ? (openingHours[dayName] ?? null) : (DEFAULT_OPENING_HOURS[dayName] ?? null);\n if (!hours) return 'Затворено';\n const [openH, openM] = hours.open.split(':').map(Number);\n const [closeH, closeM] = hours.close.split(':').map(Number);\n const nowMins = now.getHours() * 60 + now.getMinutes();\n const openMins = openH * 60 + openM;\n const closeMins = closeH * 60 + closeM;\n const formatTime = (h: number, m: number) =>\n `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}\\u00a0ч`;\n if (nowMins < openMins) return `Затворено - отваря в ${formatTime(openH, openM)}`;\n if (nowMins >= closeMins) return `Затворено - отваря утре в ${formatTime(openH, openM)}`;\n return `Отворено - затваря в ${formatTime(closeH, closeM)}`;\n}\n\nexport function getEffectiveHours(\n openingHours: OpeningDayRecord,\n dayName: (typeof DAY_NAMES_EN)[number]\n): { open: string; close: string } | null {\n const hasAnyHours = Object.keys(openingHours).some((k) => openingHours[k] != null);\n if (hasAnyHours) {\n return openingHours[dayName] ?? null;\n }\n return DEFAULT_OPENING_HOURS[dayName] ?? null;\n}\n\nexport const DAY_LABELS_BG: Record<string, string> = {\n Monday: 'Понеделник',\n Tuesday: 'Вторник',\n Wednesday: 'Сряда',\n Thursday: 'Четвъртък',\n Friday: 'Петък',\n Saturday: 'Събота',\n Sunday: 'Неделя',\n};\n\nexport { DAY_NAMES_EN };\n","export type BookingBlock = {\n date: string; // YYYY-MM-DD\n allDay: boolean;\n start?: string; // HH:mm\n end?: string; // HH:mm\n note?: string;\n};\n\nfunction isIsoDate(value: string): boolean {\n return /^\\d{4}-\\d{2}-\\d{2}$/.test(value);\n}\n\nfunction isTime(value: string): boolean {\n return /^([01]\\d|2[0-3]):[0-5]\\d$/.test(value);\n}\n\nfunction toMinutes(value: string): number {\n const [h, m] = value.split(':').map(Number);\n return h * 60 + m;\n}\n\nexport function normalizeBookingBlocks(raw: unknown): BookingBlock[] {\n if (!Array.isArray(raw)) return [];\n const out: BookingBlock[] = [];\n for (const item of raw) {\n if (!item || typeof item !== 'object') continue;\n const row = item as Record<string, unknown>;\n const date = String(row.date ?? '').trim();\n if (!isIsoDate(date)) continue;\n const allDay = row.allDay === true;\n const start = String(row.start ?? '').trim();\n const end = String(row.end ?? '').trim();\n const note = String(row.note ?? '').trim();\n if (!allDay) {\n if (!isTime(start) || !isTime(end)) continue;\n if (toMinutes(end) <= toMinutes(start)) continue;\n out.push({ date, allDay: false, start, end, ...(note ? { note } : {}) });\n continue;\n }\n out.push({ date, allDay: true, ...(note ? { note } : {}) });\n }\n out.sort((a, b) => `${a.date}-${a.start ?? ''}`.localeCompare(`${b.date}-${b.start ?? ''}`));\n return out;\n}\n\nexport function isDateBlockedAllDay(blocks: BookingBlock[], date: string): boolean {\n return blocks.some((b) => b.date === date && b.allDay);\n}\n\nexport function isBlockedForStartTime(\n blocks: BookingBlock[],\n date: string,\n startTime: string,\n durationMin: number\n): boolean {\n if (isDateBlockedAllDay(blocks, date)) return true;\n if (!isTime(startTime)) return false;\n const start = toMinutes(startTime);\n const end = start + Math.max(1, durationMin);\n for (const block of blocks) {\n if (block.date !== date || block.allDay || !block.start || !block.end) continue;\n const blockStart = toMinutes(block.start);\n const blockEnd = toMinutes(block.end);\n const overlaps = start < blockEnd && end > blockStart;\n if (overlaps) return true;\n }\n return false;\n}\n\n","declare global {\n interface Window {\n fbq?: (...args: unknown[]) => void;\n gtag?: (...args: unknown[]) => void;\n dataLayer?: unknown[];\n }\n}\n\nexport type BookingEventData = {\n serviceName?: string;\n value?: number; // EUR\n currency?: string;\n};\n\n// Session key — resets on new browser session (tab close)\nconst BOOKING_STARTED_KEY = 'tracking_booking_started';\n\nexport function trackPageView() {\n window.fbq?.('track', 'PageView');\n window.gtag?.('event', 'page_view');\n}\n\nexport function trackViewContent() {\n window.fbq?.('track', 'ViewContent');\n}\n\nexport function trackLead() {\n window.fbq?.('track', 'Lead');\n window.gtag?.('event', 'generate_lead');\n}\n\nexport function trackSignUp() {\n window.fbq?.('track', 'CompleteRegistration');\n window.gtag?.('event', 'sign_up');\n}\n\n/**\n * Fires booking_started only once per browser session.\n * Resets after a successful booking_completed so a new attempt in the same\n * tab counts again — but 5 modal opens without booking = 1 event.\n */\nexport function trackBookingStarted() {\n if (typeof sessionStorage === 'undefined') return;\n if (sessionStorage.getItem(BOOKING_STARTED_KEY)) return;\n sessionStorage.setItem(BOOKING_STARTED_KEY, '1');\n window.gtag?.('event', 'booking_started');\n}\n\nexport function trackBookingCompleted({ serviceName, value, currency = 'EUR' }: BookingEventData = {}) {\n // Reset so a second booking in the same session fires booking_started again\n if (typeof sessionStorage !== 'undefined') {\n sessionStorage.removeItem(BOOKING_STARTED_KEY);\n }\n\n const metaParams: Record<string, unknown> = {};\n if (value != null && value > 0) {\n metaParams.value = value;\n metaParams.currency = currency;\n }\n if (serviceName) metaParams.content_name = serviceName;\n\n // Standard Meta event — агенции, оптимизиращи по стандартни Facebook события\n window.fbq?.('track', 'Schedule', metaParams);\n // Custom Meta event — агенции с custom конверсии в Events Manager\n window.fbq?.('trackCustom', 'BookingCompleted', { ...metaParams, service_name: serviceName });\n\n const ga4Params: Record<string, unknown> = {};\n if (value != null && value > 0) {\n ga4Params.value = value;\n ga4Params.currency = currency;\n }\n if (serviceName) ga4Params.service_name = serviceName;\n\n window.gtag?.('event', 'booking_completed', ga4Params);\n}\n\n/**\n * Fires a test custom event visible in Meta Events Manager.\n * Use from the admin Marketing tab to verify the pixel is loaded.\n */\nexport function trackMetaTest() {\n if (!window.fbq) return false;\n window.fbq('trackCustom', 'EngineTest', { source: 'admin_test' });\n return true;\n}\n","'use client';\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { isDateBlockedAllDay, isBlockedForStartTime } from '@/lib/booking-blocks';\nimport { trackBookingStarted, trackBookingCompleted } from '@/lib/tracking-events';\nimport { useT } from '@/lib/i18n-react';\nimport type {\n UseBookingFlowOptions,\n UseBookingFlowReturn,\n BookingServiceItem,\n BookingSuccessDetails,\n OccupiedSlot,\n PublicStaffMember,\n} from './types';\n\nconst DAY_KEYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'] as const;\n\nfunction pad(n: number): string {\n return String(n).padStart(2, '0');\n}\n\nfunction toLocalISODate(d: Date): string {\n return new Date(d.getTime() - d.getTimezoneOffset() * 60000).toISOString().split('T')[0]!;\n}\n\nexport function useBookingFlow({\n slug,\n openingHours,\n bookingBlocks,\n slotIntervalMin,\n bookingAdvanceDays,\n bookingServices,\n engineUrl = '',\n successUrl,\n cancelUrl,\n locale = 'bg-BG',\n onEvent,\n}: UseBookingFlowOptions): UseBookingFlowReturn {\n const t = useT();\n const api = engineUrl.replace(/\\/$/, '');\n const slugPath = `/api/public/v1/salons/${encodeURIComponent(slug)}`;\n\n // ── Modal visibility ─────────────────────────────────────────────────\n const [bookingOpen, setBookingOpen] = useState(false);\n\n // ── Service selection ────────────────────────────────────────────────\n const [selectedServiceIdxs, setSelectedServiceIdxs] = useState<number[]>([]);\n\n // ── Date / time ──────────────────────────────────────────────────────\n const [selectedDate, setSelectedDate] = useState('');\n const [selectedTime, setSelectedTime] = useState('');\n const [occupiedByDate, setOccupiedByDate] = useState<Record<string, OccupiedSlot[]>>({});\n const [minDate, setMinDate] = useState('');\n const [maxDate, setMaxDate] = useState('');\n\n // ── Contact fields ───────────────────────────────────────────────────\n const [clientName, setClientName] = useState('');\n const [clientPhone, setClientPhone] = useState('');\n const [clientEmail, setClientEmail] = useState('');\n const [notes, setNotes] = useState('');\n\n // ── Staff (TEAM plan) ────────────────────────────────────────────────\n const [staffMembers, setStaffMembers] = useState<PublicStaffMember[]>([]);\n const [selectedStaffMemberId, setSelectedStaffMemberIdState] = useState<string | null>(null);\n const staffFetchedRef = useRef(false);\n\n // ── Submission ───────────────────────────────────────────────────────\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [bookingError, setBookingError] = useState('');\n const [bookingSuccess, setBookingSuccess] = useState('');\n const [bookingSuccessDetails, setBookingSuccessDetails] = useState<BookingSuccessDetails | null>(null);\n\n // ── Compute min/max dates on mount ──────────────────────────────────\n useEffect(() => {\n const today = new Date();\n setMinDate(toLocalISODate(today));\n const max = new Date(today);\n max.setDate(today.getDate() + Math.max(1, bookingAdvanceDays));\n setMaxDate(toLocalISODate(max));\n }, [bookingAdvanceDays]);\n\n // ── Fetch staff members once when modal first opens ──────────────────\n useEffect(() => {\n if (!bookingOpen || staffFetchedRef.current) return;\n staffFetchedRef.current = true;\n fetch(`${api}${slugPath}/staff`, { cache: 'no-store' })\n .then((r) => r.json())\n .then((d: { staff?: PublicStaffMember[] }) => {\n if (Array.isArray(d.staff)) setStaffMembers(d.staff);\n })\n .catch(() => {});\n }, [bookingOpen, slug]);\n\n // ── Fetch occupied slots whenever date or staff changes ──────────────\n useEffect(() => {\n if (!selectedDate) return;\n let cancelled = false;\n const staffParam = selectedStaffMemberId\n ? `&staffMemberId=${encodeURIComponent(selectedStaffMemberId)}`\n : '';\n fetch(\n `${api}${slugPath}/slots?date=${encodeURIComponent(selectedDate)}${staffParam}`,\n { cache: 'no-store' },\n )\n .then((r) => r.json())\n .then((d: { occupied?: Array<{ time?: string; duration?: number }> }) => {\n if (cancelled || !Array.isArray(d.occupied)) return;\n const slots: OccupiedSlot[] = d.occupied\n .map((x) => ({\n time: String(x?.time ?? ''),\n duration: Math.max(5, Number(x?.duration ?? 30) || 30),\n }))\n .filter((x) => x.time.length >= 4);\n const cacheKey = selectedStaffMemberId\n ? `${selectedDate}:${selectedStaffMemberId}`\n : selectedDate;\n if (!cancelled) setOccupiedByDate((prev) => ({ ...prev, [cacheKey]: slots }));\n })\n .catch(() => {});\n return () => { cancelled = true; };\n }, [slug, selectedDate, selectedStaffMemberId]);\n\n // ── Derived: selected service objects ────────────────────────────────\n const selectedServices = useMemo<BookingServiceItem[]>(\n () =>\n selectedServiceIdxs\n .map((i) => bookingServices[i])\n .filter((s): s is BookingServiceItem => Boolean(s)),\n [selectedServiceIdxs, bookingServices],\n );\n\n const totalDuration = useMemo(\n () => selectedServices.reduce((sum, s) => sum + (Number(s.duration) || 0), 0),\n [selectedServices],\n );\n\n const totalPrice = useMemo(\n () => selectedServices.reduce((sum, s) => sum + (Number(s.price) || 0), 0),\n [selectedServices],\n );\n\n // ── Slot calculation ─────────────────────────────────────────────────\n const slotsForDate = useCallback(\n (date: string, durationMin: number): string[] | 'closed' | null => {\n if (!date) return null;\n const dayKey = DAY_KEYS[new Date(`${date}T12:00:00`).getDay()];\n const h = openingHours[dayKey] as { open?: string; close?: string } | null | undefined;\n if (!h?.open || !h?.close) return 'closed';\n if (isDateBlockedAllDay(bookingBlocks, date)) return 'closed';\n\n const dur = Math.max(5, durationMin || 30);\n const cacheKey = selectedStaffMemberId\n ? `${date}:${selectedStaffMemberId}`\n : date;\n const occupied = occupiedByDate[cacheKey] ?? [];\n\n const [oh = 0, om = 0] = h.open.split(':').map(Number);\n const [ch = 0, cm = 0] = h.close.split(':').map(Number);\n const start = oh * 60 + om;\n const latestStart = ch * 60 + cm - dur;\n const slots: string[] = [];\n\n for (let t = start; t <= latestStart; t += slotIntervalMin) {\n const slot = `${pad(Math.floor(t / 60))}:${pad(t % 60)}`;\n const slotEnd = t + dur;\n const overlaps = occupied.some(({ time, duration: d }) => {\n const [bh = 0, bm = 0] = time.split(':').map(Number);\n const existStart = bh * 60 + bm;\n const existEnd = existStart + Math.max(5, d);\n return existStart < slotEnd && existEnd > t;\n });\n if (!overlaps && !isBlockedForStartTime(bookingBlocks, date, slot, dur)) {\n slots.push(slot);\n }\n }\n return slots;\n },\n [openingHours, bookingBlocks, occupiedByDate, selectedStaffMemberId, slotIntervalMin],\n );\n\n const timeSlots = useMemo<string[] | 'closed' | null>(\n () =>\n selectedServiceIdxs.length === 0\n ? null\n : slotsForDate(selectedDate, totalDuration || 30),\n [selectedServiceIdxs.length, slotsForDate, selectedDate, totalDuration],\n );\n\n // ── Actions ──────────────────────────────────────────────────────────\n const open = useCallback((serviceId?: string) => {\n setBookingError('');\n setBookingSuccess('');\n setBookingSuccessDetails(null);\n if (serviceId) {\n const idx = bookingServices.findIndex((s) => s.id === serviceId);\n setSelectedServiceIdxs(idx >= 0 ? [idx] : []);\n } else {\n setSelectedServiceIdxs([]);\n }\n setSelectedDate('');\n setSelectedTime('');\n setClientName('');\n setClientPhone('');\n setClientEmail('');\n setNotes('');\n setBookingOpen(true);\n if (onEvent) onEvent('booking_started');\n else trackBookingStarted();\n }, [bookingServices, onEvent]);\n\n const close = useCallback(() => {\n setBookingOpen(false);\n setBookingSuccessDetails(null);\n setSelectedStaffMemberIdState(null);\n setSelectedDate('');\n setSelectedTime('');\n }, []);\n\n const toggleService = useCallback((idx: number) => {\n setSelectedServiceIdxs((prev) => {\n const has = prev.includes(idx);\n return has ? prev.filter((x) => x !== idx) : [...prev, idx];\n });\n setSelectedTime('');\n }, []);\n\n const setDate = useCallback((d: string) => {\n setSelectedDate(d);\n setSelectedTime('');\n }, []);\n\n const setStaffMemberId = useCallback((id: string) => {\n setSelectedStaffMemberIdState(id);\n setSelectedDate('');\n setSelectedTime('');\n }, []);\n\n const markSlotOccupied = useCallback((date: string, time: string, duration: number) => {\n if (!date || !time) return;\n const dur = Math.max(5, Number(duration) || 30);\n setOccupiedByDate((prev) => {\n const day = prev[date] ?? [];\n if (day.some((s) => s.time === time)) return prev;\n return { ...prev, [date]: [...day, { time, duration: dur }] };\n });\n }, []);\n\n const submit = useCallback(async (e: React.FormEvent) => {\n e.preventDefault();\n setBookingError('');\n setBookingSuccess('');\n\n if (selectedServices.length === 0) { setBookingError(t('booking.errors.noService')); return; }\n if (!clientName.trim()) { setBookingError(t('booking.errors.noName')); return; }\n if (!clientPhone.trim()) { setBookingError(t('booking.errors.noPhone')); return; }\n if (!clientEmail.trim()) { setBookingError(t('booking.errors.noEmail')); return; }\n if (!selectedDate) { setBookingError(t('booking.errors.noDate')); return; }\n if (!selectedTime) { setBookingError(t('booking.errors.noTime')); return; }\n\n const serviceName = selectedServices.map((s) => s.name).join(' + ');\n const duration = totalDuration || 30;\n const firstSvc = selectedServices[0];\n const paymentType = firstSvc?.payment_type ?? 'none';\n const depositAmt = firstSvc?.deposit_amount ?? 0;\n const amountEuros =\n paymentType === 'deposit' ? depositAmt :\n paymentType === 'full' ? (totalPrice ?? 0) : 0;\n const requiresPayment = paymentType !== 'none' && amountEuros > 0;\n\n setIsSubmitting(true);\n try {\n const res = await fetch(`${api}${slugPath}/bookings`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n clientName: clientName.trim(),\n clientPhone: clientPhone.trim(),\n clientEmail: clientEmail.trim().toLowerCase(),\n serviceName,\n servicePrice: totalPrice,\n serviceDuration: duration,\n date: selectedDate,\n time: selectedTime,\n notes: notes.trim() || undefined,\n requiresPayment,\n staffMemberId: selectedStaffMemberId ?? undefined,\n }),\n });\n\n const json = (await res.json().catch(() => ({}))) as {\n error?: string; bookingId?: string; id?: string;\n };\n if (!res.ok) {\n throw new Error(\n json.error ??\n (res.status === 500\n ? t('booking.errors.saveFailed')\n : t('booking.errors.httpError', { status: res.status })),\n );\n }\n\n // Stripe Checkout redirect for paid bookings\n const bookingId = json.bookingId ?? json.id;\n if (requiresPayment && bookingId) {\n const payRes = await fetch(`${api}${slugPath}/booking-checkout`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n bookingId,\n salonSlug: slug,\n serviceName,\n amountEuros,\n paymentType,\n successUrl,\n cancelUrl,\n }),\n });\n const payJson = (await payRes.json().catch(() => ({}))) as {\n checkoutUrl?: string; error?: string;\n };\n if (!payRes.ok || !payJson.checkoutUrl) {\n throw new Error(payJson.error ?? t('booking.errors.paymentFailed'));\n }\n window.location.href = payJson.checkoutUrl;\n return;\n }\n\n const dateLabel = new Date(`${selectedDate}T12:00:00`).toLocaleDateString(locale, {\n weekday: 'long', day: 'numeric', month: 'long',\n });\n markSlotOccupied(selectedDate, selectedTime, duration);\n setBookingSuccessDetails({ serviceName, dateLabel, time: selectedTime });\n setBookingSuccess(`${serviceName} — ${dateLabel} ${selectedTime}`);\n const eventPayload = {\n serviceName,\n value: totalPrice > 0 ? totalPrice : undefined,\n currency: 'EUR',\n };\n if (onEvent) onEvent('booking_completed', eventPayload);\n else trackBookingCompleted(eventPayload);\n } catch (err) {\n setBookingError(err instanceof Error ? err.message : t('booking.errors.generic'));\n } finally {\n setIsSubmitting(false);\n }\n }, [\n slug, selectedServices, clientName, clientPhone, clientEmail,\n selectedDate, selectedTime, notes,\n totalDuration, totalPrice, selectedStaffMemberId, markSlotOccupied,\n successUrl, cancelUrl, locale, onEvent,\n ]);\n\n return {\n bookingOpen, open, close,\n selectedServiceIdxs, toggleService, totalDuration, totalPrice, selectedServices,\n selectedDate, setDate,\n selectedTime, setTime: setSelectedTime,\n timeSlots, minDate, maxDate,\n clientName, setClientName,\n clientPhone, setClientPhone,\n clientEmail, setClientEmail,\n notes, setNotes,\n staffMembers, selectedStaffMemberId, setStaffMemberId,\n isSubmitting, bookingError, bookingSuccess, bookingSuccessDetails,\n submit,\n };\n}\n","'use client';\n\nimport {\n forwardRef,\n lazy,\n Suspense,\n useImperativeHandle,\n useMemo,\n} from 'react';\nimport { parseSalonServices, localizeService } from '@/lib/salon-services';\nimport {\n enrichServiceCategories,\n buildServiceCategoryTabs,\n} from '@/lib/salon-service-categories';\nimport { mergeOpeningHours } from '@/lib/salon-opening-hours';\nimport { normalizeBookingBlocks } from '@/lib/booking-blocks';\nimport type { BookingCatalogService } from '@/lib/booking-modal-catalog';\nimport { useBookingFlow } from './useBookingFlow';\nimport type { BookingServiceItem, BookingWidgetHandle, BookingWidgetProps } from './types';\nimport { I18nProvider } from '@/lib/i18n-react';\nimport { normalizeLocale } from '@/lib/i18n';\n\nconst SalonBookingModal = lazy(() =>\n import('@/components/salon/SalonBookingModal').then((m) => ({ default: m.SalonBookingModal })),\n);\n\n// ── Inner component ────────────────────────────────────────────────────────────\n// Must live *inside* I18nProvider so that useBookingFlow → useT() reads the\n// correct locale. If useBookingFlow were called in the outer BookingWidget,\n// it would be outside the provider and always get the 'bg' default.\n\ntype InnerProps = {\n forwardedRef: React.Ref<BookingWidgetHandle>;\n slug: string;\n openingHours: ReturnType<typeof mergeOpeningHours>;\n bookingBlocks: ReturnType<typeof normalizeBookingBlocks>;\n slotIntervalMin: number;\n bookingAdvanceDays: number;\n bookingServices: BookingServiceItem[];\n serviceCatalog: BookingCatalogService[];\n categoryTabs: ReturnType<typeof buildServiceCategoryTabs>;\n engineUrl: string;\n primaryColor: string;\n accentGradient?: string;\n successUrl?: string;\n cancelUrl?: string;\n locale: string;\n formatPrice?: (amount: number) => string;\n onEvent?: (\n name: 'booking_started' | 'booking_completed',\n payload?: { serviceName?: string; value?: number; currency?: string },\n ) => void;\n salonName: string;\n basePath: string;\n};\n\nfunction BookingWidgetInner({\n forwardedRef,\n slug,\n openingHours,\n bookingBlocks,\n slotIntervalMin,\n bookingAdvanceDays,\n bookingServices,\n serviceCatalog,\n categoryTabs,\n engineUrl,\n primaryColor,\n accentGradient,\n successUrl,\n cancelUrl,\n locale,\n formatPrice,\n onEvent,\n salonName,\n basePath,\n}: InnerProps) {\n const flow = useBookingFlow({\n slug,\n openingHours,\n bookingBlocks,\n slotIntervalMin,\n bookingAdvanceDays,\n bookingServices,\n engineUrl,\n successUrl,\n cancelUrl,\n locale,\n onEvent,\n });\n\n useImperativeHandle(forwardedRef, () => ({\n open: (serviceId?: string) => flow.open(serviceId),\n close: () => flow.close(),\n }), [flow.open, flow.close]);\n\n const firstSelected = flow.selectedServices[0];\n\n return (\n <Suspense fallback={null}>\n <SalonBookingModal\n open={flow.bookingOpen}\n primaryColor={primaryColor}\n accentGradient={accentGradient}\n locale={locale}\n formatPrice={formatPrice}\n serviceCatalog={serviceCatalog}\n categoryTabs={categoryTabs}\n services={bookingServices}\n selectedServiceIdxs={flow.selectedServiceIdxs}\n selectedDate={flow.selectedDate}\n selectedTime={flow.selectedTime}\n totalDuration={flow.totalDuration}\n totalPrice={flow.totalPrice}\n clientName={flow.clientName}\n clientPhone={flow.clientPhone}\n clientEmail={flow.clientEmail}\n notes={flow.notes}\n salonName={salonName}\n termsHref={`${basePath}/terms`}\n privacyHref={`${basePath}/privacy`}\n minDate={flow.minDate}\n maxDate={flow.maxDate}\n timeSlots={flow.timeSlots}\n paymentType={firstSelected?.payment_type ?? 'none'}\n depositAmount={firstSelected?.deposit_amount}\n cancelPolicyHours={firstSelected?.cancel_policy_hours}\n cancelPolicyAction={firstSelected?.cancel_policy_action}\n isSubmitting={flow.isSubmitting}\n bookingError={flow.bookingError}\n bookingSuccess={flow.bookingSuccess}\n bookingSuccessDetails={flow.bookingSuccessDetails}\n staffMembers={flow.staffMembers}\n selectedStaffMemberId={flow.selectedStaffMemberId}\n onClose={flow.close}\n onToggleService={flow.toggleService}\n onDateChange={flow.setDate}\n onTimeChange={flow.setTime}\n onClientNameChange={flow.setClientName}\n onClientPhoneChange={flow.setClientPhone}\n onClientEmailChange={flow.setClientEmail}\n onNotesChange={flow.setNotes}\n onStaffMemberChange={flow.setStaffMemberId}\n onSubmit={flow.submit}\n />\n </Suspense>\n );\n}\n\n// ── Public component ───────────────────────────────────────────────────────────\n\nexport const BookingWidget = forwardRef<BookingWidgetHandle, BookingWidgetProps>(\n function BookingWidget({ slug, salon, openingHours: openingHoursProp, bookingBlocks: blocksProp, basePath = '', engineUrl = '', accentGradient, successUrl, cancelUrl, locale: localeProp, formatPrice, onEvent }, ref) {\n\n // ── Opening hours ──────────────────────────────────────────────────\n const openingHours = useMemo(\n () => mergeOpeningHours(\n salon.working_hours as Record<string, { open?: string; close?: string; closed?: boolean }> | undefined,\n salon.opening_hours,\n ),\n [salon.working_hours, salon.opening_hours],\n );\n\n const resolvedHours = openingHoursProp ?? openingHours;\n const resolvedBlocks = blocksProp ?? normalizeBookingBlocks(\n salon.opening_hours && typeof salon.opening_hours === 'object'\n ? (salon.opening_hours as Record<string, unknown>).booking_blocks\n : null,\n );\n\n // ── Slot config from salon settings ───────────────────────────────\n const slotIntervalMin = useMemo((): number => {\n const oh = salon.opening_hours;\n if (oh && typeof oh === 'object') {\n const v = Number((oh as Record<string, unknown>).slot_interval_min);\n if ([15, 20, 30, 45, 60].includes(v)) return v;\n }\n return 30;\n }, [salon.opening_hours]);\n\n const bookingAdvanceDays = useMemo((): number => {\n const oh = salon.opening_hours;\n if (oh && typeof oh === 'object') {\n const v = Number((oh as Record<string, unknown>).booking_advance_days);\n if (Number.isFinite(v) && v >= 1) return Math.round(v);\n }\n return 60;\n }, [salon.opening_hours]);\n\n // ── Locale ────────────────────────────────────────────────────────\n const providerLocale = normalizeLocale(\n localeProp ?? (typeof salon.language === 'string' ? salon.language : 'bg'),\n );\n const resolvedLocale = localeProp ?? (providerLocale === 'en' ? 'en-US' : 'bg-BG');\n\n // ── Services processing ────────────────────────────────────────────\n const serviceCatalog = useMemo(\n () => enrichServiceCategories(\n parseSalonServices(salon.services).map((s) => localizeService(s, providerLocale))\n ) as BookingCatalogService[],\n [salon.services, providerLocale],\n );\n\n const categoryTabs = useMemo(\n () => buildServiceCategoryTabs(serviceCatalog),\n [serviceCatalog],\n );\n\n const bookingServices = useMemo<BookingServiceItem[]>(() => {\n const out: BookingServiceItem[] = [];\n for (const svc of serviceCatalog) {\n const variants = Array.isArray(svc.variants) ? svc.variants : [];\n if (variants.length === 0) {\n out.push(svc as unknown as BookingServiceItem);\n continue;\n }\n for (const v of variants) {\n out.push({\n ...(svc as unknown as BookingServiceItem),\n id: `${svc.id}::${v.label}`,\n name: `${svc.name} – ${v.label}`,\n price: Number(v.price ?? svc.price ?? 0) || 0,\n duration: Math.max(5, Number(v.duration ?? svc.duration ?? 30) || 30),\n variants: undefined,\n });\n }\n }\n return out;\n }, [serviceCatalog]);\n\n // ── Derived display props ─────────────────────────────────────────\n const primaryColor = typeof salon.primary_color === 'string' && salon.primary_color\n ? salon.primary_color\n : '#5B21B6';\n\n return (\n <I18nProvider locale={providerLocale}>\n <BookingWidgetInner\n forwardedRef={ref}\n slug={slug}\n openingHours={resolvedHours}\n bookingBlocks={resolvedBlocks}\n slotIntervalMin={slotIntervalMin}\n bookingAdvanceDays={bookingAdvanceDays}\n bookingServices={bookingServices}\n serviceCatalog={serviceCatalog}\n categoryTabs={categoryTabs}\n engineUrl={engineUrl}\n primaryColor={primaryColor}\n accentGradient={accentGradient}\n successUrl={successUrl}\n cancelUrl={cancelUrl}\n locale={resolvedLocale}\n formatPrice={formatPrice}\n onEvent={onEvent}\n salonName={String(salon.name ?? '')}\n basePath={basePath}\n />\n </I18nProvider>\n );\n },\n);\n","'use client';\n\nimport React, {\n createContext,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { BookingWidget } from './BookingWidget';\nimport type { BookingWidgetHandle } from './types';\n\nexport type BookingContextValue = {\n /**\n * Open the booking modal. Pass a service id to pre-select it. If the salon\n * record hasn't loaded yet, the call is queued and fired as soon as it does.\n */\n open: (service?: string) => void;\n /** Close the booking modal. No-op if it isn't open. */\n close: () => void;\n /** True once the salon record is loaded and the modal is mountable. */\n isReady: boolean;\n /** Non-null if the salon fetch failed (network, 404, etc.). */\n error: Error | null;\n /** The raw salon record once loaded, or null while loading / on error. */\n salon: Record<string, unknown> | null;\n};\n\nexport const BookingContext = createContext<BookingContextValue | null>(null);\n\nexport type BookingProviderProps = {\n children?: React.ReactNode;\n /**\n * Salon slug. If omitted, the provider tries (in order):\n * 1. `window.__CLICKA_SALON_SLUG`\n * 2. `<meta name=\"clicka:salon\" content=\"...\">`\n * 3. `process.env.NEXT_PUBLIC_SALON_SLUG` (Next.js / Vite-replaced)\n * 4. `process.env.NEXT_PUBLIC_CLICKA_SALON`\n */\n salonSlug?: string;\n /**\n * Engine origin. If omitted, the provider tries (in order):\n * 1. `window.__CLICKA_ENGINE_URL`\n * 2. `<meta name=\"clicka:engine\" content=\"...\">`\n * 3. `process.env.NEXT_PUBLIC_CLICKA_ENGINE`\n * 4. `process.env.NEXT_PUBLIC_CLICKA_API_URL`\n * 5. Default: `https://clicka.bg`\n */\n engineUrl?: string;\n /**\n * BCP-47 locale. If omitted, the provider derives it from\n * `<html lang>`, then `<body data-lang>`, then `navigator.language`,\n * defaulting to `bg-BG`.\n */\n locale?: string;\n /** Stripe success URL. Defaults to current page with `?booked=1`. */\n successUrl?: string;\n /** Stripe cancel URL. Defaults to current page with `?cancelled=1`. */\n cancelUrl?: string;\n /** CSS gradient for accent fills. */\n accentGradient?: string;\n /** Custom price formatter. */\n formatPrice?: (amount: number) => string;\n /** Analytics callback (replaces internal fbq/gtag). */\n onEvent?: (\n name: 'booking_started' | 'booking_completed',\n payload?: { serviceName?: string; value?: number; currency?: string },\n ) => void;\n /** Prefix for `/terms` and `/privacy` legal links. */\n basePath?: string;\n /**\n * When true (default), the provider attaches a document-level click handler\n * that opens the modal for any element matching `[data-clicka-book]`.\n * The attribute value (when non-empty) is passed as the service id.\n */\n autoTriggers?: boolean;\n /**\n * When true (default), the provider opens the modal on mount if the URL\n * contains `?service=<id>` or `?book=1`.\n */\n honorUrlParams?: boolean;\n};\n\nfunction readGlobalString(key: string): string | undefined {\n if (typeof window === 'undefined') return undefined;\n const v = (window as unknown as Record<string, unknown>)[key];\n return typeof v === 'string' && v ? v : undefined;\n}\n\nfunction readMeta(name: string): string | undefined {\n if (typeof document === 'undefined') return undefined;\n return (\n document.querySelector<HTMLMetaElement>(`meta[name=\"${name}\"]`)?.content || undefined\n );\n}\n\nfunction readEnv(key: string): string | undefined {\n try {\n const p = (typeof process !== 'undefined' ? process : undefined) as unknown as {\n env?: Record<string, string | undefined>;\n };\n const v = p?.env?.[key];\n return typeof v === 'string' && v ? v : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction resolveSlug(prop?: string): string | undefined {\n return (\n prop ||\n readGlobalString('__CLICKA_SALON_SLUG') ||\n readMeta('clicka:salon') ||\n readEnv('NEXT_PUBLIC_SALON_SLUG') ||\n readEnv('NEXT_PUBLIC_CLICKA_SALON')\n );\n}\n\nfunction resolveEngine(prop?: string): string {\n return (\n prop ||\n readGlobalString('__CLICKA_ENGINE_URL') ||\n readMeta('clicka:engine') ||\n readEnv('NEXT_PUBLIC_ENGINE_URL') ||\n readEnv('NEXT_PUBLIC_CLICKA_ENGINE') ||\n readEnv('NEXT_PUBLIC_CLICKA_API_URL') ||\n // Canonical host (with www). The bare clicka.bg returns a 308 redirect\n // which kills cross-origin fetches because the redirect response itself\n // carries no CORS headers — browsers reject the whole chain.\n 'https://www.clicka.bg'\n );\n}\n\nfunction resolveLocale(prop?: string): string {\n if (prop) return prop;\n if (typeof document !== 'undefined') {\n const htmlLang = document.documentElement.lang?.trim();\n if (htmlLang) {\n if (htmlLang === 'bg') return 'bg-BG';\n if (htmlLang === 'en') return 'en-US';\n return htmlLang;\n }\n const bodyLang = document.body?.dataset?.lang?.trim();\n if (bodyLang) return bodyLang === 'bg' ? 'bg-BG' : 'en-US';\n }\n if (typeof navigator !== 'undefined' && navigator.language) {\n return navigator.language;\n }\n return 'bg-BG';\n}\n\nfunction defaultReturnUrl(flag: 'booked' | 'cancelled'): string | undefined {\n if (typeof window === 'undefined') return undefined;\n return `${location.origin}${location.pathname}?${flag}=1`;\n}\n\nexport function BookingProvider({\n children,\n salonSlug,\n engineUrl,\n locale,\n successUrl,\n cancelUrl,\n accentGradient,\n formatPrice,\n onEvent,\n basePath,\n autoTriggers = true,\n honorUrlParams = true,\n}: BookingProviderProps) {\n const slug = useMemo(() => resolveSlug(salonSlug), [salonSlug]);\n const resolvedEngineUrl = useMemo(() => resolveEngine(engineUrl), [engineUrl]);\n const resolvedLocale = useMemo(() => resolveLocale(locale), [locale]);\n const resolvedSuccessUrl = useMemo(\n () => successUrl ?? defaultReturnUrl('booked'),\n [successUrl],\n );\n const resolvedCancelUrl = useMemo(\n () => cancelUrl ?? defaultReturnUrl('cancelled'),\n [cancelUrl],\n );\n\n const widgetRef = useRef<BookingWidgetHandle>(null);\n // pendingRef: undefined = no queued open. null = open without service.\n // string = open with that service id.\n const pendingRef = useRef<string | null | undefined>(undefined);\n const urlAutoOpenedRef = useRef(false);\n\n const [salon, setSalon] = useState<Record<string, unknown> | null>(null);\n const [error, setError] = useState<Error | null>(null);\n\n // ── Salon fetch ────────────────────────────────────────────────────────\n useEffect(() => {\n if (!slug) {\n console.error(\n '[@clicka/booking] BookingProvider has no salon slug. Pass `salonSlug` ' +\n 'or set NEXT_PUBLIC_SALON_SLUG / <meta name=\"clicka:salon\"> / ' +\n 'window.__CLICKA_SALON_SLUG.',\n );\n return;\n }\n let cancelled = false;\n const url = `${resolvedEngineUrl.replace(/\\/$/, '')}/api/public/v1/salons/${encodeURIComponent(slug)}`;\n fetch(url, { cache: 'no-store' })\n .then((r) => {\n if (!r.ok) throw new Error(`Salon fetch failed: HTTP ${r.status}`);\n return r.json();\n })\n .then((d: { salon?: Record<string, unknown> }) => {\n if (cancelled) return;\n if (!d.salon) throw new Error('Empty salon response');\n setSalon(d.salon);\n setError(null);\n })\n .catch((e: unknown) => {\n if (cancelled) return;\n const err = e instanceof Error ? e : new Error(String(e));\n console.error('[@clicka/booking] salon fetch failed:', err);\n setError(err);\n });\n return () => {\n cancelled = true;\n };\n }, [resolvedEngineUrl, slug]);\n\n // ── Public open/close ──────────────────────────────────────────────────\n const open = useCallback(\n (service?: string) => {\n if (widgetRef.current && salon) {\n widgetRef.current.open(service || undefined);\n } else {\n pendingRef.current = service ?? null;\n }\n },\n [salon],\n );\n\n const close = useCallback(() => widgetRef.current?.close(), []);\n\n // ── Flush pending open() when salon finishes loading ───────────────────\n useEffect(() => {\n if (salon && widgetRef.current && pendingRef.current !== undefined) {\n const s = pendingRef.current;\n pendingRef.current = undefined;\n widgetRef.current.open(s || undefined);\n }\n }, [salon]);\n\n // ── Document-level click delegation ────────────────────────────────────\n // Listens to multiple attribute names so existing sites can keep their\n // markup. Primary: [data-clicka-book]. Legacy: [data-book-service],\n // [data-book]. The attribute *value* (when not empty / 'true') is passed\n // as the service id; otherwise the modal opens without preselect.\n useEffect(() => {\n if (!autoTriggers || typeof document === 'undefined') return;\n const SELECTOR = '[data-clicka-book],[data-book-service],[data-book]';\n const handler = (ev: Event) => {\n const t = ev.target as Element | null;\n if (!t) return;\n const trigger = t.closest<HTMLElement>(SELECTOR);\n if (!trigger) return;\n ev.preventDefault();\n const raw =\n trigger.getAttribute('data-clicka-book') ??\n trigger.getAttribute('data-book-service') ??\n trigger.getAttribute('data-book') ??\n '';\n const service = raw && raw !== 'true' ? raw : undefined;\n open(service);\n };\n document.addEventListener('click', handler);\n return () => document.removeEventListener('click', handler);\n }, [autoTriggers, open]);\n\n // ── URL ?service=… / ?book=1 auto-open (once, on first salon load) ─────\n useEffect(() => {\n if (!honorUrlParams || !salon || urlAutoOpenedRef.current) return;\n if (typeof location === 'undefined') return;\n const params = new URLSearchParams(location.search);\n const initial = params.get('service');\n if (initial || params.has('book')) {\n urlAutoOpenedRef.current = true;\n open(initial || undefined);\n }\n }, [honorUrlParams, salon, open]);\n\n const value = useMemo<BookingContextValue>(\n () => ({ open, close, isReady: !!salon, error, salon }),\n [open, close, salon, error],\n );\n\n // Render the modal via portal into document.body so it escapes any\n // ancestor `transform`, `filter`, `perspective`, `contain`, or\n // `will-change: transform` — any of those create a containing block\n // for fixed-positioned descendants and would jail the modal inside\n // the consumer's component subtree instead of the viewport.\n const modalNode =\n salon && slug ? (\n <BookingWidget\n ref={widgetRef}\n slug={slug}\n salon={salon}\n engineUrl={resolvedEngineUrl}\n locale={resolvedLocale}\n successUrl={resolvedSuccessUrl}\n cancelUrl={resolvedCancelUrl}\n accentGradient={accentGradient}\n formatPrice={formatPrice}\n onEvent={onEvent}\n basePath={basePath}\n />\n ) : null;\n\n return (\n <BookingContext.Provider value={value}>\n {children}\n {modalNode && typeof document !== 'undefined'\n ? createPortal(modalNode, document.body)\n : modalNode}\n </BookingContext.Provider>\n );\n}\n","'use client';\n\nimport { useContext } from 'react';\nimport { BookingContext, type BookingContextValue } from './BookingProvider';\n\n/**\n * Access the booking modal from anywhere inside a `<BookingProvider>`.\n *\n * @throws if called outside a `<BookingProvider>` tree.\n */\nexport function useBooking(): BookingContextValue {\n const ctx = useContext(BookingContext);\n if (!ctx) {\n throw new Error(\n '[@clicka/booking] useBooking() must be called inside <BookingProvider>.',\n );\n }\n return ctx;\n}\n","'use client';\n\nimport React, { forwardRef } from 'react';\nimport { useBooking } from './useBooking';\n\nexport type BookingButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {\n /** Pre-select this service id when opening the modal. */\n service?: string;\n};\n\n/**\n * Drop-in button that opens the booking modal. Must be used inside a\n * `<BookingProvider>`. Accepts every native `<button>` prop so consumers\n * keep their own classes, styles, ARIA, etc.\n *\n * @example\n * <BookingButton>Reserve</BookingButton>\n * <BookingButton service=\"balayage\" className=\"btn btn_solid\">Book balayage</BookingButton>\n */\nexport const BookingButton = forwardRef<HTMLButtonElement, BookingButtonProps>(\n function BookingButton(\n { service, onClick, type = 'button', children, ...rest },\n ref,\n ) {\n const { open } = useBooking();\n return (\n <button\n ref={ref}\n type={type}\n onClick={(e) => {\n onClick?.(e);\n if (!e.defaultPrevented) open(service);\n }}\n {...rest}\n >\n {children}\n </button>\n );\n },\n);\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@clicka1/booking",
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"description": "White-label booking widget for salon sites powered by the Clicka engine API.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": [
|
|
7
|
+
"./dist/booking.css"
|
|
8
|
+
],
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"README.md"
|
|
12
|
+
],
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./styles.css": "./dist/booking.css"
|
|
19
|
+
},
|
|
20
|
+
"main": "./dist/index.js",
|
|
21
|
+
"module": "./dist/index.js",
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"scripts": {
|
|
24
|
+
"clean": "rm -rf dist",
|
|
25
|
+
"build:js": "tsup",
|
|
26
|
+
"build:css": "tailwindcss -c ./tailwind.config.cjs -i ./src/styles.css -o ./dist/booking.css --minify",
|
|
27
|
+
"build": "npm run clean && npm run build:js && npm run build:css"
|
|
28
|
+
},
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"react": "^18 || ^19",
|
|
31
|
+
"react-dom": "^18 || ^19",
|
|
32
|
+
"lucide-react": ">=0.300.0"
|
|
33
|
+
},
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
}
|
|
37
|
+
}
|