@getmicdrop/venue-calendar 4.0.69 → 4.0.70

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.
Files changed (67) hide show
  1. package/dist/{CarouselView.legacy-H5I8FG8q.js → CarouselView.legacy-CAtJAiSb.js} +3 -3
  2. package/dist/{CarouselView.legacy-H5I8FG8q.js.map → CarouselView.legacy-CAtJAiSb.js.map} +1 -1
  3. package/dist/{CartView-Bp50FEe3.js → CartView-CpA__vH7.js} +53 -53
  4. package/dist/{CartView-Bp50FEe3.js.map → CartView-CpA__vH7.js.map} +1 -1
  5. package/dist/{Checkout-C_7r24PK.js → Checkout-Bm3yGYYr.js} +278 -273
  6. package/dist/Checkout-Bm3yGYYr.js.map +1 -0
  7. package/dist/{Checkout-CbltFN5w.js → Checkout-CRBwRTOc.js} +114 -114
  8. package/dist/{Checkout-CbltFN5w.js.map → Checkout-CRBwRTOc.js.map} +1 -1
  9. package/dist/{Checkout.legacy-C8IT4aEk.js → Checkout.legacy-CpgxTxZl.js} +5 -5
  10. package/dist/{Checkout.legacy-C8IT4aEk.js.map → Checkout.legacy-CpgxTxZl.js.map} +1 -1
  11. package/dist/{CheckoutTimer-BDGvUG7s.js → CheckoutTimer-SMZRnL_T.js} +2 -2
  12. package/dist/{CheckoutTimer-BDGvUG7s.js.map → CheckoutTimer-SMZRnL_T.js.map} +1 -1
  13. package/dist/{CollectionView-BjcFcBDn.js → CollectionView-DgVzimMX.js} +5 -5
  14. package/dist/{CollectionView-BjcFcBDn.js.map → CollectionView-DgVzimMX.js.map} +1 -1
  15. package/dist/{CollectionView.legacy-DXRPPTGM.js → CollectionView.legacy-BTAS-mTd.js} +31 -31
  16. package/dist/{CollectionView.legacy-DXRPPTGM.js.map → CollectionView.legacy-BTAS-mTd.js.map} +1 -1
  17. package/dist/{Event-DNTpd-NG.js → Event-BNVO_E6j.js} +145 -145
  18. package/dist/{Event-DNTpd-NG.js.map → Event-BNVO_E6j.js.map} +1 -1
  19. package/dist/{EventDetailsView-DokL1zEd.js → EventDetailsView-CXvl9xwe.js} +6 -6
  20. package/dist/{EventDetailsView-DokL1zEd.js.map → EventDetailsView-CXvl9xwe.js.map} +1 -1
  21. package/dist/{EventPage-DfER-ohd.js → EventPage-Dc4CtBeS.js} +5 -5
  22. package/dist/{EventPage-DfER-ohd.js.map → EventPage-Dc4CtBeS.js.map} +1 -1
  23. package/dist/{EventPage.legacy-DKCXDcqQ.js → EventPage.legacy-D-9svuzb.js} +49 -49
  24. package/dist/{EventPage.legacy-DKCXDcqQ.js.map → EventPage.legacy-D-9svuzb.js.map} +1 -1
  25. package/dist/{FeaturedView.legacy-DkEiwirz.js → FeaturedView.legacy-BKF3u2sH.js} +19 -19
  26. package/dist/{FeaturedView.legacy-DkEiwirz.js.map → FeaturedView.legacy-BKF3u2sH.js.map} +1 -1
  27. package/dist/{GalleryCard-DBSyzYbv.js → GalleryCard-lNx3CEtB.js} +9 -9
  28. package/dist/{GalleryCard-DBSyzYbv.js.map → GalleryCard-lNx3CEtB.js.map} +1 -1
  29. package/dist/{GalleryView.legacy-CcqQNcMK.js → GalleryView.legacy-CMjIfp2b.js} +3 -3
  30. package/dist/{GalleryView.legacy-CcqQNcMK.js.map → GalleryView.legacy-CMjIfp2b.js.map} +1 -1
  31. package/dist/{GroupedListView.legacy-Bueg0Oxp.js → GroupedListView.legacy-BybmHzIV.js} +23 -23
  32. package/dist/{GroupedListView.legacy-Bueg0Oxp.js.map → GroupedListView.legacy-BybmHzIV.js.map} +1 -1
  33. package/dist/{OrderSummary-D_G9VNpM.js → OrderSummary-B1GhsUnc.js} +7 -7
  34. package/dist/{OrderSummary-D_G9VNpM.js.map → OrderSummary-B1GhsUnc.js.map} +1 -1
  35. package/dist/{PromoCodeInput-w7EGNs3a.js → PromoCodeInput-CrXBD0oq.js} +30 -30
  36. package/dist/{PromoCodeInput-w7EGNs3a.js.map → PromoCodeInput-CrXBD0oq.js.map} +1 -1
  37. package/dist/{SeriesPage-bCW_8Ewp.js → SeriesPage-DEDSbKuu.js} +5 -5
  38. package/dist/{SeriesPage-bCW_8Ewp.js.map → SeriesPage-DEDSbKuu.js.map} +1 -1
  39. package/dist/{SeriesPage.legacy-DZmmNEWc.js → SeriesPage.legacy-BlqTBr4n.js} +38 -38
  40. package/dist/{SeriesPage.legacy-DZmmNEWc.js.map → SeriesPage.legacy-BlqTBr4n.js.map} +1 -1
  41. package/dist/{Success-CKSUEqXp.js → Success-CD4K7aRv.js} +24 -24
  42. package/dist/{Success-CKSUEqXp.js.map → Success-CD4K7aRv.js.map} +1 -1
  43. package/dist/{Success.legacy-BnjWS130.js → Success.legacy-B1Jvy8N0.js} +2 -2
  44. package/dist/{Success.legacy-BnjWS130.js.map → Success.legacy-B1Jvy8N0.js.map} +1 -1
  45. package/dist/{VenueCalendar-n-T-MmLU.js → VenueCalendar-BoSdP7xI.js} +1472 -1457
  46. package/dist/{VenueCalendar-n-T-MmLU.js.map → VenueCalendar-BoSdP7xI.js.map} +1 -1
  47. package/dist/{ViewTicketsEmbed-CV6ipR3B.js → ViewTicketsEmbed-D1nD9zJY.js} +42 -42
  48. package/dist/{ViewTicketsEmbed-CV6ipR3B.js.map → ViewTicketsEmbed-D1nD9zJY.js.map} +1 -1
  49. package/dist/{WaitlistModal-BDzMplxL.js → WaitlistModal-DWcbQmfW.js} +35 -35
  50. package/dist/{WaitlistModal-BDzMplxL.js.map → WaitlistModal-DWcbQmfW.js.map} +1 -1
  51. package/dist/api/api.cjs +1 -1
  52. package/dist/api/api.cjs.map +1 -1
  53. package/dist/api/api.mjs +160 -157
  54. package/dist/api/api.mjs.map +1 -1
  55. package/dist/{api-Bj-wXy71.js → api-CCKXC9Qs.js} +2 -2
  56. package/dist/{api-Bj-wXy71.js.map → api-CCKXC9Qs.js.map} +1 -1
  57. package/dist/{data-toggle-store.svelte-DmcpAUWu.js → data-toggle-store.svelte-CB6WLZEE.js} +2 -2
  58. package/dist/{data-toggle-store.svelte-DmcpAUWu.js.map → data-toggle-store.svelte-CB6WLZEE.js.map} +1 -1
  59. package/dist/{transform-BLT4wYBC.js → transform-BrlBxayh.js} +2 -2
  60. package/dist/{transform-BLT4wYBC.js.map → transform-BrlBxayh.js.map} +1 -1
  61. package/dist/venue-calendar.es.js +1 -1
  62. package/dist/venue-calendar.iife.js +32 -32
  63. package/dist/venue-calendar.iife.js.map +1 -1
  64. package/dist/venue-calendar.umd.js +30 -30
  65. package/dist/venue-calendar.umd.js.map +1 -1
  66. package/package.json +1 -1
  67. package/dist/Checkout-C_7r24PK.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"api.mjs","sources":["../../src/lib/api/client.ts","../../src/lib/api/orders.ts","../../src/lib/api/promo.ts","../../src/lib/api/events.ts","../../src/lib/api/venues.ts","../../src/lib/api/gift-cards.ts","../../src/lib/api/waitlist.ts","../../src/lib/api/cta.ts","../../src/lib/api/transformers/order.ts","../../src/lib/api/transformers/event.ts","../../src/lib/api/transformers/venue.ts"],"sourcesContent":["/**\r\n * API Client for MicDrop Public Checkout API\r\n *\r\n * Provides a centralized HTTP client with:\r\n * - Configurable base URL\r\n * - Per-request timeout via AbortController\r\n * - Exponential-backoff retry on 5xx and network errors (idempotent methods)\r\n * - Consistent error surfacing\r\n * - Request/response typing\r\n */\r\n\r\nimport { createLogger } from '@getmicdrop/svelte-components/utils/logger';\r\nconst logger = createLogger('VC');\r\nimport type { ApiConfig, ApiResponse } from './types.js';\r\n\r\n// Default API configuration\r\nconst DEFAULT_CONFIG: Required<ApiConfig> = {\r\n baseUrl: 'https://get-micdrop.com',\r\n timeout: 30000,\r\n retries: 2,\r\n retryDelay: 500,\r\n onError: (error: Error) => logger.error('API Error:', error),\r\n};\r\n\r\nlet globalConfig: Required<ApiConfig> = { ...DEFAULT_CONFIG };\r\n\r\nexport function configureApi(config: Partial<ApiConfig>): void {\r\n globalConfig = { ...globalConfig, ...config };\r\n}\r\n\r\nexport function getApiConfig(): Required<ApiConfig> {\r\n return { ...globalConfig };\r\n}\r\n\r\nexport function getPublicBaseUrl(): string {\r\n return `${globalConfig.baseUrl}/api/v2/public`;\r\n}\r\n\r\nexport function getLegacyPublicUrl(): string {\r\n return `${globalConfig.baseUrl}/api/public`;\r\n}\r\n\r\nexport function getOrdersV2Url(): string {\r\n return `${globalConfig.baseUrl}/api/orders/v2/public`;\r\n}\r\n\r\n/** @deprecated IP is now resolved server-side via request headers. */\r\nexport async function getClientIP(): Promise<string> {\r\n return '';\r\n}\r\n\r\n/**\r\n * Sleep utility for retry backoff.\r\n */\r\nconst sleep = (ms: number): Promise<void> =>\r\n new Promise((resolve) => setTimeout(resolve, ms));\r\n\r\n/**\r\n * fetch with timeout, idempotent retry, and exponential backoff.\r\n *\r\n * - Retries on network errors and 5xx (transient) responses.\r\n * - Never retries non-idempotent methods (POST/PUT/PATCH/DELETE) — those are\r\n * left to caller-driven retries to avoid duplicate writes.\r\n * - The supplied AbortSignal (if any) is respected and short-circuits retries.\r\n */\r\nasync function fetchWithRetry(\r\n url: string,\r\n init: RequestInit,\r\n cfg: Required<ApiConfig>\r\n): Promise<Response> {\r\n const method = (init.method || 'GET').toUpperCase();\r\n const isIdempotent = method === 'GET' || method === 'HEAD';\r\n const maxAttempts = isIdempotent ? cfg.retries + 1 : 1;\r\n\r\n let lastError: unknown;\r\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\r\n const controller = new AbortController();\r\n const timeoutId = setTimeout(() => controller.abort(), cfg.timeout);\r\n\r\n // Chain the caller's signal if provided.\r\n const callerSignal = init.signal;\r\n let onCallerAbort: (() => void) | undefined;\r\n if (callerSignal) {\r\n if (callerSignal.aborted) controller.abort();\r\n else {\r\n onCallerAbort = () => controller.abort();\r\n callerSignal.addEventListener('abort', onCallerAbort, { once: true });\r\n }\r\n }\r\n\r\n try {\r\n // @api-client-escape: internal canonical client implementation — not drift\r\n const response = await fetch(url, { ...init, signal: controller.signal });\r\n\r\n // Retry transient server errors.\r\n if (response.status >= 500 && attempt < maxAttempts) {\r\n lastError = new Error(`HTTP ${response.status}`);\r\n } else {\r\n return response;\r\n }\r\n } catch (err) {\r\n lastError = err;\r\n // Caller aborted — give up.\r\n if (callerSignal?.aborted) throw err;\r\n } finally {\r\n clearTimeout(timeoutId);\r\n if (callerSignal && onCallerAbort) {\r\n callerSignal.removeEventListener('abort', onCallerAbort);\r\n }\r\n }\r\n\r\n if (attempt < maxAttempts) {\r\n await sleep(cfg.retryDelay * Math.pow(2, attempt - 1));\r\n }\r\n }\r\n\r\n throw lastError;\r\n}\r\n\r\nexport async function apiGet<T>(\r\n endpoint: string,\r\n options?: RequestInit\r\n): Promise<ApiResponse<T>> {\r\n return apiRequest<T>('GET', endpoint, undefined, options);\r\n}\r\n\r\nexport async function apiPost<T>(\r\n endpoint: string,\r\n body?: unknown,\r\n options?: RequestInit\r\n): Promise<ApiResponse<T>> {\r\n return apiRequest<T>('POST', endpoint, body, options);\r\n}\r\n\r\nexport async function apiPut<T>(\r\n endpoint: string,\r\n body?: unknown,\r\n options?: RequestInit\r\n): Promise<ApiResponse<T>> {\r\n return apiRequest<T>('PUT', endpoint, body, options);\r\n}\r\n\r\nexport async function apiDelete<T>(\r\n endpoint: string,\r\n options?: RequestInit\r\n): Promise<ApiResponse<T>> {\r\n return apiRequest<T>('DELETE', endpoint, undefined, options);\r\n}\r\n\r\nasync function apiRequest<T>(\r\n method: string,\r\n endpoint: string,\r\n body?: unknown,\r\n options?: RequestInit\r\n): Promise<ApiResponse<T>> {\r\n const url = endpoint.startsWith('http')\r\n ? endpoint\r\n : `${getPublicBaseUrl()}${endpoint}`;\r\n\r\n try {\r\n const response = await fetchWithRetry(\r\n url,\r\n {\r\n method,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...options?.headers,\r\n },\r\n body: body !== undefined ? JSON.stringify(body) : undefined,\r\n credentials: 'include',\r\n ...options,\r\n },\r\n globalConfig\r\n );\r\n\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({}));\r\n const message =\r\n errorData.error || errorData.message || `HTTP ${response.status}`;\r\n globalConfig.onError(new Error(message));\r\n return { success: false, error: message, statusCode: response.status };\r\n }\r\n\r\n const data = await response.json();\r\n return { success: true, data: data as T, statusCode: response.status };\r\n } catch (error) {\r\n const errorMessage =\r\n error instanceof Error\r\n ? error.name === 'AbortError'\r\n ? 'Request timed out'\r\n : error.message\r\n : 'Unknown error';\r\n\r\n globalConfig.onError(\r\n error instanceof Error ? error : new Error(errorMessage)\r\n );\r\n return { success: false, error: errorMessage };\r\n }\r\n}\r\n\r\n/**\r\n * Simple fetch wrapper that returns parsed JSON or null on error.\r\n * Inherits the global timeout + retry policy for GETs.\r\n */\r\nexport async function simpleFetch<T>(\r\n url: string,\r\n options?: RequestInit\r\n): Promise<T | null> {\r\n try {\r\n const response = await fetchWithRetry(\r\n url,\r\n { credentials: 'include', ...options },\r\n globalConfig\r\n );\r\n\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({}));\r\n logger.error(`API request failed: ${response.status}`, errorData);\r\n return null;\r\n }\r\n\r\n return response.json();\r\n } catch (error) {\r\n logger.error('API request error:', error);\r\n return null;\r\n }\r\n}\r\n","import { AppError } from '@getmicdrop/svelte-components';\r\n/**\r\n * Orders API\r\n *\r\n * Functions for managing orders, payments, and reservations\r\n * in the public checkout flow.\r\n */\r\n\r\nimport { createLogger } from '@getmicdrop/svelte-components/utils/logger';\r\nconst logger = createLogger('VC');\r\nimport { getPublicBaseUrl, getOrdersV2Url, simpleFetch, apiPost, apiGet } from './client.js';\r\nimport type {\r\n PaymentIntentResponse,\r\n CompleteReservationResponse,\r\n CancelReservationResponse,\r\n CreateOrderResponse,\r\n ValidatePaymentRequest,\r\n ValidatePaymentResponse,\r\n ExtendSessionResponse,\r\n SessionStatus,\r\n Order,\r\n} from './types.js';\r\n\r\n/**\r\n * Create a payment intent for the cart\r\n *\r\n * This initiates the Stripe payment flow by creating a PaymentIntent\r\n * on the backend. The response includes the client_secret needed\r\n * for Stripe Elements.\r\n *\r\n * @param cartId - The cart/order UUID\r\n * @param quantities - Map of ticketId -> quantity\r\n * @param donationAmounts - Map of ticketId -> donation amount in dollars (for type=2 tickets)\r\n * @returns Payment intent data including client_secret, or null on error\r\n */\r\nexport async function createPaymentIntent(\r\n cartId: string,\r\n quantities: Record<string | number, number>,\r\n donationAmounts?: Record<string | number, number>\r\n): Promise<PaymentIntentResponse | null> {\r\n try {\r\n const apiResult = await apiPost<PaymentIntentResponse>(\r\n `${getOrdersV2Url()}/cart/${cartId}/payment-intent`,\r\n {\r\n productQuantities: quantities,\r\n ...(donationAmounts && Object.keys(donationAmounts).length > 0\r\n ? { donationAmounts }\r\n : {}),\r\n }\r\n );\r\n\r\n if (!apiResult.success) {\r\n logger.error('Payment intent creation failed:', apiResult.error);\r\n throw new AppError(apiResult.error || 'Failed to create payment intent', 'lib/api/orders/createPaymentIntent');\r\n }\r\n\r\n logger.debug('Payment intent created:', apiResult.data);\r\n return apiResult.data!;\r\n } catch (error) {\r\n logger.error('createPaymentIntent error:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Fetch an existing cart by UUID (cross-device pre-fill — §1.3).\r\n *\r\n * Returns the server's authoritative view of a cart so a second device\r\n * visiting the tickets page can see the in-progress reservation it created\r\n * on another device. Returns `null` if:\r\n * - the cart no longer exists (404)\r\n * - the cart belongs to a different event than `expectedEventID` (when\r\n * supplied) — we don't want to mix carts across events\r\n * - the cart status is no longer `reserved` / `active` (e.g. expired,\r\n * completed, abandoned) — caller should treat the local cookie as stale\r\n * - any network/decode failure (caller falls back to localStorage only)\r\n *\r\n * Returned shape matches the orders-service `GET /v2Public/cart/{uuid}`\r\n * response: a Cart model with embedded Reservations.\r\n */\r\nexport interface CartReservationView {\r\n ticketID: number;\r\n quantity: number;\r\n priceAtReservation: number;\r\n status: string;\r\n}\r\nexport interface CartView {\r\n uuid: string;\r\n eventID: number;\r\n status: string;\r\n expiresAt: string;\r\n reservations: CartReservationView[];\r\n}\r\n\r\nexport async function getCartByUUID(\r\n cartUUID: string,\r\n expectedEventID?: string | number\r\n): Promise<CartView | null> {\r\n if (!cartUUID) return null;\r\n try {\r\n type RawCart = {\r\n UUID?: string; uuid?: string;\r\n EventID?: number; eventID?: number;\r\n Status?: string; status?: string;\r\n ExpiresAt?: string; expiresAt?: string;\r\n Reservations?: unknown[]; reservations?: unknown[];\r\n };\r\n const apiResult = await apiGet<RawCart>(\r\n `${getOrdersV2Url()}/cart/${cartUUID}`\r\n );\r\n if (!apiResult.success) {\r\n // 404 / 410 / 5xx — caller treats as stale\r\n return null;\r\n }\r\n const raw = apiResult.data!;\r\n // The orders-service Cart model uses Go-style PascalCase JSON tags\r\n // (UUID, EventID, Status, ExpiresAt, Reservations) on some routes and\r\n // camelCase on the newer v2 routes. Tolerate both.\r\n const uuid: string = raw.UUID ?? raw.uuid ?? '';\r\n const eventID = Number(raw.EventID ?? raw.eventID ?? 0);\r\n const status: string = raw.Status ?? raw.status ?? '';\r\n const expiresAt: string = raw.ExpiresAt ?? raw.expiresAt ?? '';\r\n const rawRes: unknown[] = raw.Reservations ?? raw.reservations ?? [];\r\n const reservations: CartReservationView[] = rawRes.map(r => {\r\n const rec = r as Record<string, unknown>;\r\n return {\r\n ticketID: Number(rec.TicketID ?? rec.ticketID ?? 0),\r\n quantity: Number(rec.Quantity ?? rec.quantity ?? 0),\r\n priceAtReservation: Number(\r\n rec.PriceAtReservation ?? rec.priceAtReservation ?? 0\r\n ),\r\n status: String(rec.Status ?? rec.status ?? ''),\r\n };\r\n });\r\n if (status !== 'reserved' && status !== 'active') {\r\n // stale cart row — caller clears the cookie\r\n return null;\r\n }\r\n if (expectedEventID !== undefined && eventID !== Number(expectedEventID)) {\r\n // cart belongs to a different event — don't mix\r\n return null;\r\n }\r\n return { uuid, eventID, status, expiresAt, reservations };\r\n } catch (err) {\r\n logger.error('getCartByUUID error:', err);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Update cart quantities after the cart already exists.\r\n *\r\n * Replaces all reservations on the cart with the new quantities.\r\n * The orders-service handler releases old reservations (returning\r\n * inventory) and creates new ones (decrementing inventory) atomically.\r\n *\r\n * Use this when the user changes ticket counts AFTER the initial\r\n * cart was created via initiateOrder. The cart UUID is preserved,\r\n * so the timer and extension state stay intact.\r\n *\r\n * @returns true on success, false on failure\r\n */\r\nexport async function updateCartQuantities(\r\n cartId: string,\r\n quantities: Record<string | number, number>,\r\n donationAmounts?: Record<string | number, number>\r\n): Promise<boolean> {\r\n try {\r\n // Convert string keys to numbers (the orders-service handler\r\n // unmarshals into map[uint]int).\r\n const numericQuantities: Record<number, number> = {};\r\n for (const [k, v] of Object.entries(quantities)) {\r\n const n = typeof k === 'number' ? k : parseInt(k, 10);\r\n if (!Number.isNaN(n) && v > 0) numericQuantities[n] = v;\r\n }\r\n const numericDonations: Record<number, number> = {};\r\n if (donationAmounts) {\r\n for (const [k, v] of Object.entries(donationAmounts)) {\r\n const n = typeof k === 'number' ? k : parseInt(k, 10);\r\n if (!Number.isNaN(n) && v > 0) numericDonations[n] = v;\r\n }\r\n }\r\n // @fetch-escape: status-only endpoint — PUT /cart/:id returns an empty 2xx (no JSON body)\r\n // on success; the canonical apiPut runs response.json() unconditionally on 2xx and would\r\n // throw on the empty body, mis-reporting a successful cart update as a failure. Migrate once\r\n // the client tolerates 204/empty bodies.\r\n const response = await fetch(`${getOrdersV2Url()}/cart/${cartId}`, {\r\n method: 'PUT',\r\n headers: { 'Content-Type': 'application/json' },\r\n credentials: 'include',\r\n body: JSON.stringify({\r\n quantities: numericQuantities,\r\n ...(Object.keys(numericDonations).length > 0\r\n ? { donationAmounts: numericDonations }\r\n : {}),\r\n }),\r\n });\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({}));\r\n logger.error('Cart update failed:', errorData);\r\n return false;\r\n }\r\n return true;\r\n } catch (err) {\r\n logger.error('updateCartQuantities error:', err);\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Complete reservation after successful payment\r\n *\r\n * Called after Stripe confirms the payment to finalize the order\r\n * and generate tickets.\r\n *\r\n * @param orderUuid - The order UUID\r\n * @returns Success status and message\r\n */\r\nexport async function completeReservation(\r\n orderUuid: string\r\n): Promise<CompleteReservationResponse> {\r\n try {\r\n const apiResult = await apiPost<{ message?: string }>(\r\n `${getPublicBaseUrl()}/orders/complete/${orderUuid}`\r\n );\r\n\r\n if (!apiResult.success) {\r\n return {\r\n success: false,\r\n error: apiResult.error || 'Failed to complete reservation',\r\n };\r\n }\r\n\r\n return {\r\n success: true,\r\n message: apiResult.data?.message,\r\n };\r\n } catch (error) {\r\n logger.error('Error completing reservation:', error);\r\n return { success: false, error: 'Network error completing reservation' };\r\n }\r\n}\r\n\r\n/**\r\n * Cancel reservation and release tickets back to inventory\r\n *\r\n * Called when user abandons checkout or session expires.\r\n *\r\n * @param orderUuid - The order UUID\r\n * @returns Success status and message\r\n */\r\nexport async function cancelReservation(\r\n orderUuid: string\r\n): Promise<CancelReservationResponse> {\r\n try {\r\n const apiResult = await apiPost<{ message?: string }>(\r\n `${getPublicBaseUrl()}/orders/cancel/${orderUuid}`\r\n );\r\n\r\n if (!apiResult.success) {\r\n return {\r\n success: false,\r\n error: apiResult.error || 'Failed to cancel reservation',\r\n };\r\n }\r\n\r\n return {\r\n success: true,\r\n message: apiResult.data?.message,\r\n };\r\n } catch (error) {\r\n logger.error('Error cancelling reservation:', error);\r\n return { success: false, error: 'Network error cancelling reservation' };\r\n }\r\n}\r\n\r\n/**\r\n * Create a new order/cart\r\n *\r\n * This creates an empty order that can be used for checkout.\r\n * The order UUID is used for all subsequent operations.\r\n *\r\n * @param eventId - The event ID\r\n * @param promoCode - Optional promo code to apply\r\n * @returns The order UUID, or null on error\r\n */\r\nexport async function createOrder(\r\n eventId: string | number,\r\n promoCode?: string\r\n): Promise<CreateOrderResponse | null> {\r\n try {\r\n const apiResult = await apiPost<CreateOrderResponse>(\r\n `${getPublicBaseUrl()}/orders/create`,\r\n { eventID: eventId, promoCode }\r\n );\r\n\r\n if (!apiResult.success) {\r\n logger.error('Create order failed:', apiResult.error);\r\n return null;\r\n }\r\n\r\n return apiResult.data!;\r\n } catch (error) {\r\n logger.error('createOrder error:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Get order details (public, no auth required)\r\n *\r\n * Fetches the order details for displaying on the success page.\r\n *\r\n * @param orderId - The order UUID or ID\r\n * @returns The order details, or null on error\r\n */\r\nexport async function getOrder(orderId: string): Promise<Order | null> {\r\n return simpleFetch<Order>(`${getPublicBaseUrl()}/orders/${orderId}`);\r\n}\r\n\r\n/**\r\n * Validate payment intent and complete the order\r\n *\r\n * This is an alternative to completeReservation that accepts\r\n * additional payment details. Used by micdrop-frontend.\r\n *\r\n * @param cartId - The cart/order UUID\r\n * @param payload - Payment validation payload\r\n * @returns Validation result\r\n */\r\nexport async function validatePaymentIntent(\r\n cartId: string,\r\n payload: ValidatePaymentRequest\r\n): Promise<ValidatePaymentResponse | null> {\r\n try {\r\n const apiResult = await apiPost<{ status?: string; orderUUID?: string; uuid?: string }>(\r\n `${getOrdersV2Url()}/validatePaymentIntent/${cartId}`,\r\n payload\r\n );\r\n\r\n if (!apiResult.success) {\r\n logger.error('Payment validation failed:', apiResult.error);\r\n return {\r\n success: false,\r\n status: 'failed',\r\n error: apiResult.error || 'Payment validation failed',\r\n };\r\n }\r\n\r\n const result = apiResult.data!;\r\n return {\r\n success: true,\r\n status: result.status || 'Payment succeeded',\r\n orderUUID: result.orderUUID || result.uuid,\r\n };\r\n } catch (error) {\r\n logger.error('validatePaymentIntent error:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Extend the checkout session by 15 minutes\r\n *\r\n * Users get a limited number of extensions (typically 2-3).\r\n *\r\n * @param orderUuid - The order UUID\r\n * @returns Extension result with new expiry time\r\n */\r\nexport async function extendCheckoutSession(\r\n orderUuid: string\r\n): Promise<ExtendSessionResponse> {\r\n try {\r\n const apiResult = await apiPost<{ newExpiryTime?: string; remainingExtensions?: number }>(\r\n `${getPublicBaseUrl()}/orders/extend-session`,\r\n { orderUuid }\r\n );\r\n\r\n if (!apiResult.success) {\r\n return {\r\n success: false,\r\n error: apiResult.error || 'Failed to extend session',\r\n statusCode: apiResult.statusCode,\r\n };\r\n }\r\n\r\n const result = apiResult.data!;\r\n return {\r\n success: true,\r\n newExpiryTime: result.newExpiryTime,\r\n remainingExtensions: result.remainingExtensions,\r\n };\r\n } catch (error) {\r\n logger.error('Error extending checkout session:', error);\r\n return { success: false, error: 'Network error extending session' };\r\n }\r\n}\r\n\r\n/**\r\n * Get current session status including expiry time\r\n *\r\n * Used to display countdown timer and check if extensions are available.\r\n *\r\n * @param orderUuid - The order UUID\r\n * @returns Session status including expiry time\r\n */\r\nexport async function getSessionStatus(\r\n orderUuid: string\r\n): Promise<SessionStatus> {\r\n try {\r\n const apiResult = await apiGet<SessionStatus>(\r\n `${getPublicBaseUrl()}/orders/session/${orderUuid}`\r\n );\r\n\r\n if (!apiResult.success) {\r\n return {\r\n error: apiResult.error || 'No active session found',\r\n notFound: apiResult.statusCode === 404,\r\n };\r\n }\r\n\r\n const result = apiResult.data!;\r\n return {\r\n expiresAt: result.expiresAt,\r\n extensionCount: result.extensionCount,\r\n remainingExtensions: result.remainingExtensions,\r\n canExtend: result.canExtend,\r\n reservationCount: result.reservationCount,\r\n };\r\n } catch (error) {\r\n logger.error('Error getting session status:', error);\r\n return { error: 'Network error getting session status' };\r\n }\r\n}\r\n\r\n/**\r\n * Initiate a new order (alias for createOrder)\r\n *\r\n * This function provides backwards compatibility with micdrop-frontend.\r\n * It accepts the same parameters as the legacy initiateOrder function.\r\n *\r\n * @param cartData - Object containing eventID and optional quantities/promoCode\r\n * @returns The order UUID, or null on error\r\n */\r\nexport async function initiateOrder(\r\n cartData: {\r\n eventID: string | number;\r\n promoCode?: string;\r\n quantities?: Record<string | number, number>;\r\n } = {} as any\r\n): Promise<string | null> {\r\n try {\r\n const apiResult = await apiPost<{ uuid?: string }>(\r\n `${getPublicBaseUrl()}/orders/create`,\r\n cartData\r\n );\r\n\r\n if (!apiResult.success) {\r\n logger.error('Order initiation failed:', apiResult.error);\r\n return null;\r\n }\r\n\r\n return apiResult.data?.uuid ?? null;\r\n } catch (error) {\r\n logger.error('initiateOrder error:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Track UTM source for analytics\r\n *\r\n * Records the traffic source (utm_source parameter) for marketing analytics.\r\n *\r\n * @param venueId - The venue ID\r\n * @returns Promise that resolves when tracking is complete\r\n */\r\nexport async function trackUTMSource(venueId: string | number): Promise<void> {\r\n if (typeof window === 'undefined') return;\r\n\r\n const urlParams = new URLSearchParams(window.location.search);\r\n const utmSource = urlParams.get('utm_source') || 'Direct';\r\n\r\n try {\r\n // @fetch-escape: fire-and-forget UTM beacon — GET with no response body consumed; simpleFetch would parse JSON on empty 200 and log false-positive errors\r\n await fetch(\r\n `${getPublicBaseUrl()}/utm/${venueId}/${encodeURIComponent(utmSource)}`\r\n );\r\n } catch (error) {\r\n logger.error('UTM tracking failed:', error);\r\n }\r\n}\r\n","/**\r\n * Promo Codes API\r\n *\r\n * Functions for validating and checking promo codes\r\n * in the public checkout flow.\r\n */\r\n\r\nimport { createLogger } from '@getmicdrop/svelte-components/utils/logger';\r\nconst logger = createLogger('VC');\r\nimport { apiGet, apiPost } from './client.js';\r\nimport type { PromoValidationResponse, HasPromoCodesResponse } from './types.js';\r\n\r\n/**\r\n * Validate a promo code for an event\r\n *\r\n * Checks if a promo code is valid and returns its effects:\r\n * - Discount amount and type\r\n * - Hidden ticket reveal\r\n *\r\n * @param eventId - The event ID\r\n * @param code - The promo code to validate\r\n * @returns Validation result with discount info\r\n */\r\nexport async function validatePromoCode(\r\n eventId: string | number,\r\n code: string\r\n): Promise<PromoValidationResponse> {\r\n try {\r\n if (!code || !code.trim()) {\r\n return { valid: false, error: 'Promo code is required' };\r\n }\r\n\r\n // API uses GET with code in URL path\r\n const encodedCode = encodeURIComponent(code.trim());\r\n const apiResult = await apiGet<PromoValidationResponse>(\r\n `/promo-codes/validate/${eventId}/${encodedCode}`\r\n );\r\n\r\n if (!apiResult.success) {\r\n // 404 = invalid code, other errors are server issues\r\n if (apiResult.statusCode === 404) {\r\n return { valid: false, error: 'Invalid promo code' };\r\n }\r\n return { valid: false, error: 'Failed to validate code' };\r\n }\r\n\r\n const result = apiResult.data!;\r\n return {\r\n valid: result.valid ?? true,\r\n revealHiddenTickets: result.revealHiddenTickets,\r\n revealTicketIds: result.revealTicketIds,\r\n provideDiscount: result.provideDiscount,\r\n discountType: result.discountType,\r\n amount: result.amount,\r\n code: result.code || code,\r\n };\r\n } catch (error) {\r\n logger.error('Error validating promo code:', error);\r\n return { valid: false, error: 'Network error validating code' };\r\n }\r\n}\r\n\r\n/**\r\n * Check if promo codes are available for an event\r\n *\r\n * Used to conditionally show/hide the promo code input field.\r\n *\r\n * @param eventId - The event ID\r\n * @returns Whether promo codes exist for this event\r\n */\r\nexport async function hasPromoCodes(eventId: string | number): Promise<boolean> {\r\n try {\r\n const apiResult = await apiGet<HasPromoCodesResponse>(\r\n `/promo-codes/check/${eventId}`\r\n );\r\n\r\n if (!apiResult.success) {\r\n // If endpoint doesn't exist or errors, default to showing the input\r\n return true;\r\n }\r\n\r\n return apiResult.data!.hasPromoCodes === true;\r\n } catch (error) {\r\n logger.error('Error checking promo codes availability:', error);\r\n // Default to showing promo input if we can't check\r\n return true;\r\n }\r\n}\r\n\r\n/**\r\n * Apply a promo code to a cart\r\n *\r\n * This updates the cart with the promo code discount.\r\n *\r\n * @param cartId - The cart UUID\r\n * @param code - The promo code to apply\r\n * @returns Success status\r\n */\r\nexport async function applyPromoCode(\r\n cartId: string,\r\n code: string\r\n): Promise<{ success: boolean; error?: string }> {\r\n try {\r\n const apiResult = await apiPost(`/orders/${cartId}/apply-promo`, { code });\r\n\r\n if (!apiResult.success) {\r\n return {\r\n success: false,\r\n error: apiResult.error || 'Failed to apply promo code',\r\n };\r\n }\r\n\r\n return { success: true };\r\n } catch (error) {\r\n logger.error('Error applying promo code:', error);\r\n return { success: false, error: 'Network error applying code' };\r\n }\r\n}\r\n\r\n/**\r\n * Remove a promo code from a cart\r\n *\r\n * @param cartId - The cart UUID\r\n * @returns Success status\r\n */\r\nexport async function removePromoCode(\r\n cartId: string\r\n): Promise<{ success: boolean; error?: string }> {\r\n try {\r\n const apiResult = await apiPost(`/orders/${cartId}/remove-promo`);\r\n\r\n if (!apiResult.success) {\r\n return {\r\n success: false,\r\n error: apiResult.error || 'Failed to remove promo code',\r\n };\r\n }\r\n\r\n return { success: true };\r\n } catch (error) {\r\n logger.error('Error removing promo code:', error);\r\n return { success: false, error: 'Network error removing code' };\r\n }\r\n}\r\n","import { AppError } from '@getmicdrop/svelte-components';\r\n/**\r\n * Events API\r\n *\r\n * Functions for fetching event data, tickets, and performers\r\n * in the public checkout flow.\r\n */\r\n\r\nimport { createLogger } from '@getmicdrop/svelte-components/utils/logger';\r\nconst logger = createLogger('VC');\r\nimport { getPublicBaseUrl, simpleFetch, apiPost } from './client.js';\r\nimport type {\r\n Event,\r\n AvailableTicket,\r\n EventPerformersResponse,\r\n SeriesOccurrencesResponse,\r\n SeriesPageData,\r\n PublicCollectionData,\r\n ResolvedEntity,\r\n} from './types.js';\r\n\r\n/**\r\n * In-flight `fetchEventDetails` requests keyed by event ID. Lets\r\n * concurrent callers (Checkout, CartView, EventDetailsView, +page.js\r\n * server load — all of which may run during a single navigation) share\r\n * one HTTP request rather than triggering three.\r\n *\r\n * The entry deletes as soon as the underlying promise settles, so this\r\n * is dedup not cache. For real cache-with-TTL we'd want SWR; that's a\r\n * future milestone.\r\n */\r\nconst _eventDetailsInflight = new Map<string, Promise<Event | null>>();\r\n\r\n/**\r\n * Fetch event details\r\n *\r\n * Gets full event information including venue and ticket data.\r\n *\r\n * @param eventId - The event ID\r\n * @param customFetch - Optional custom fetch function (for SSR)\r\n * @returns Event details or null on error\r\n */\r\nexport async function fetchEventDetails(\r\n eventId: string | number,\r\n customFetch: typeof fetch = fetch\r\n): Promise<Event | null> {\r\n const key = String(eventId);\r\n // Only dedup when using the default fetch — custom-fetch callers\r\n // (e.g. SvelteKit server loads) bring their own request context.\r\n if (customFetch === fetch) {\r\n const inflight = _eventDetailsInflight.get(key);\r\n if (inflight) return inflight;\r\n }\r\n\r\n const run = (async () => {\r\n try {\r\n // @fetch-escape: customFetch injection for SSR context — caller-supplied fetch instance, cannot use simpleFetch\r\n const response = await customFetch(`${getPublicBaseUrl()}/events/${eventId}`);\r\n if (!response.ok) {\r\n throw new AppError(`Failed to fetch event details: ${response.status}`, 'lib/api/events/fetchEventDetails');\r\n }\r\n return await response.json();\r\n } catch (error) {\r\n logger.error('Error fetching event details:', error);\r\n return null;\r\n }\r\n })();\r\n\r\n if (customFetch === fetch) {\r\n _eventDetailsInflight.set(key, run);\r\n run.finally(() => {\r\n // Only clear if this same promise is still the inflight one — a\r\n // later call may have set up a fresh request after the user\r\n // triggered an explicit refresh.\r\n if (_eventDetailsInflight.get(key) === run) {\r\n _eventDetailsInflight.delete(key);\r\n }\r\n });\r\n }\r\n return run;\r\n}\r\n\r\n/**\r\n * Fetch available tickets for an event\r\n *\r\n * Returns all ticket types that are currently available for sale.\r\n *\r\n * @param eventId - The event ID\r\n * @returns Array of available tickets\r\n */\r\nexport async function fetchEventTickets(\r\n eventId: string | number\r\n): Promise<AvailableTicket[]> {\r\n try {\r\n const tickets = await simpleFetch<AvailableTicket[]>(\r\n `${getPublicBaseUrl()}/tickets/event/${eventId}`\r\n );\r\n return Array.isArray(tickets) ? tickets : [];\r\n } catch (error) {\r\n logger.error('Error fetching tickets:', error);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Fetch performers for an event\r\n *\r\n * Returns the lineup with pre-resolved avatar URLs.\r\n *\r\n * @param eventId - The event ID\r\n * @returns Performers list and visibility flag\r\n */\r\nexport async function fetchEventPerformers(\r\n eventId: string | number\r\n): Promise<EventPerformersResponse> {\r\n try {\r\n if (!eventId) {\r\n logger.warn('fetchEventPerformers called without eventId');\r\n return { performers: [], showPerformers: false };\r\n }\r\n\r\n const data = await simpleFetch<EventPerformersResponse>(\r\n `${getPublicBaseUrl()}/events/${eventId}/performers`\r\n );\r\n\r\n if (!data) {\r\n logger.error('Failed to fetch performers: network or server error');\r\n return { performers: [], showPerformers: false };\r\n }\r\n\r\n return {\r\n performers: Array.isArray(data.performers) ? data.performers : [],\r\n showPerformers: data.showPerformers === true,\r\n };\r\n } catch (error) {\r\n logger.error('Error fetching event performers:', error);\r\n return { performers: [], showPerformers: false };\r\n }\r\n}\r\n\r\n/**\r\n * Fetch all venues for an organization\r\n *\r\n * @param orgId - The organization ID\r\n * @returns Array of venues\r\n */\r\nexport async function fetchAllVenues(orgId: string | number): Promise<any[]> {\r\n try {\r\n if (!orgId) {\r\n logger.warn('fetchAllVenues called without orgId');\r\n return [];\r\n }\r\n\r\n const venues = await simpleFetch<any[]>(\r\n `${getPublicBaseUrl()}/venues/organization/${orgId}`\r\n );\r\n\r\n if (!venues) {\r\n logger.error('Failed to fetch venues: network or server error');\r\n return [];\r\n }\r\n\r\n return Array.isArray(venues) ? venues : [];\r\n } catch (error) {\r\n logger.error('Error fetching venues:', error);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Fetch events for a venue\r\n *\r\n * @param venueId - The venue ID\r\n * @returns Array of events\r\n */\r\nexport async function fetchVenueEvents(venueId: string | number): Promise<Event[]> {\r\n try {\r\n if (!venueId) {\r\n logger.warn('fetchVenueEvents called without venueId');\r\n return [];\r\n }\r\n\r\n const events = await simpleFetch<Event[]>(\r\n `${getPublicBaseUrl()}/events/venue/${venueId}`\r\n );\r\n\r\n if (!events) {\r\n logger.error('Failed to fetch venue events: network or server error');\r\n return [];\r\n }\r\n\r\n return Array.isArray(events) ? events : [];\r\n } catch (error) {\r\n logger.error('Error fetching venue events:', error);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Get events for a specific month\r\n *\r\n * Used for calendar views to efficiently load events.\r\n *\r\n * @param venueId - The venue ID\r\n * @param year - The year (e.g., 2024)\r\n * @param month - The month (1-12)\r\n * @returns Array of events for the month\r\n */\r\nexport async function getMonthEvents(\r\n venueId: string | number,\r\n year: number,\r\n month: number\r\n): Promise<Event[]> {\r\n try {\r\n const data = await simpleFetch<{ events?: Event[] } | Event[]>(\r\n `${getPublicBaseUrl()}/events/venue/${venueId}/month/${year}/${month}`\r\n );\r\n\r\n if (!data) {\r\n logger.error('Failed to fetch month events: network or server error');\r\n return [];\r\n }\r\n\r\n if (Array.isArray(data)) return data;\r\n return Array.isArray((data as { events?: Event[] }).events) ? (data as { events: Event[] }).events : [];\r\n } catch (error) {\r\n logger.error('Error fetching month events:', error);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Get events for an organization for a specific month\r\n *\r\n * @param orgId - The organization ID\r\n * @param year - The year (e.g., 2024)\r\n * @param month - The month (1-12)\r\n * @returns Array of events for the month\r\n */\r\nexport async function getOrgMonthEvents(\r\n orgId: string | number,\r\n year: number,\r\n month: number\r\n): Promise<Event[]> {\r\n try {\r\n const data = await simpleFetch<{ events?: Event[] } | Event[]>(\r\n `${getPublicBaseUrl()}/events/organization/${orgId}/month/${year}/${month}`\r\n );\r\n\r\n if (!data) {\r\n logger.error('Failed to fetch org month events: network or server error');\r\n return [];\r\n }\r\n\r\n if (Array.isArray(data)) return data;\r\n return Array.isArray((data as { events?: Event[] }).events) ? (data as { events: Event[] }).events : [];\r\n } catch (error) {\r\n logger.error('Error fetching org month events:', error);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Get series occurrences for date selector\r\n *\r\n * Returns all instances of a recurring event series.\r\n *\r\n * @param eventSeriesId - The series ID\r\n * @returns Series occurrences\r\n */\r\nexport async function getSeriesOccurrences(\r\n eventSeriesId: number\r\n): Promise<SeriesOccurrencesResponse | null> {\r\n try {\r\n const data = await simpleFetch<SeriesOccurrencesResponse>(\r\n `${getPublicBaseUrl()}/series/${eventSeriesId}/occurrences`\r\n );\r\n\r\n if (!data) {\r\n logger.error('Failed to fetch series occurrences: network or server error');\r\n return null;\r\n }\r\n\r\n return data;\r\n } catch (error) {\r\n logger.error('Error fetching series occurrences:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Fetch series occurrences with CTA state\r\n *\r\n * Returns full series data including availability status.\r\n *\r\n * @param eventSeriesId - The series ID\r\n * @param venueId - The venue ID\r\n * @returns Series occurrences with CTA state\r\n */\r\nexport async function fetchSeriesOccurrences(\r\n eventSeriesId: number,\r\n venueId: string | number\r\n): Promise<SeriesOccurrencesResponse | null> {\r\n try {\r\n const data = await simpleFetch<SeriesOccurrencesResponse>(\r\n `${getPublicBaseUrl()}/series/${eventSeriesId}/occurrences?venueId=${venueId}`\r\n );\r\n\r\n if (!data) {\r\n logger.error('Failed to fetch series with CTA: network or server error');\r\n return null;\r\n }\r\n\r\n return data;\r\n } catch (error) {\r\n logger.error('Error fetching series occurrences:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Resolve an entity-agnostic public id to its concrete type + data.\r\n *\r\n * The embed deep-link (`#{id}-{slug}`) carries no type prefix, so a cold\r\n * deep link (the show isn't in the loaded calendar month) needs the backend\r\n * to say whether the id is an event, series, or collection before the widget\r\n * can render the right view. This is the same `/api/v2/public/resolve/{id}`\r\n * endpoint get-micdrop.com's `/e/{slugId}` page resolves server-side; here we\r\n * call it cross-origin from the venue's page (the public API already serves\r\n * the calendar cross-origin, so CORS is in place).\r\n *\r\n * @param id - The entity id (numeric, type-agnostic)\r\n * @param slug - Optional slug hint (lets the backend canonicalize)\r\n * @returns `{ type, id, title, data }` or null on failure\r\n */\r\nexport async function resolvePublicEntity(\r\n id: string | number,\r\n slug?: string\r\n): Promise<ResolvedEntity | null> {\r\n try {\r\n const qs = slug ? `?slug=${encodeURIComponent(slug)}` : '';\r\n const data = await simpleFetch<ResolvedEntity>(\r\n `${getPublicBaseUrl()}/resolve/${encodeURIComponent(String(id))}${qs}`\r\n );\r\n\r\n if (!data || !data.type) {\r\n throw new AppError(\r\n 'Failed to resolve entity',\r\n 'lib/api/events/resolvePublicEntity'\r\n );\r\n }\r\n\r\n return data;\r\n } catch (error) {\r\n logger.error('Error resolving public entity:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Fetch series page data\r\n *\r\n * Returns full series information including occurrences, venue, and performers.\r\n *\r\n * @param seriesId - The series ID\r\n * @returns Series page data or null on error\r\n */\r\nexport async function fetchSeriesPage(\r\n seriesId: string | number\r\n): Promise<SeriesPageData | null> {\r\n try {\r\n const data = await simpleFetch<SeriesPageData>(\r\n `${getPublicBaseUrl()}/series/${seriesId}/page`\r\n );\r\n\r\n if (!data) {\r\n throw new AppError('Failed to fetch series page', 'lib/api/events/fetchSeriesPage');\r\n }\r\n\r\n return data;\r\n } catch (error) {\r\n logger.error('Error fetching series page:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Fetch public collection data\r\n *\r\n * Returns collection info including events list.\r\n * For password-protected collections, pass the password to authenticate.\r\n *\r\n * @param collectionId - The collection ID\r\n * @param password - Optional password for protected collections\r\n * @returns Collection data or null on error\r\n */\r\nexport async function fetchPublicCollection(\r\n collectionId: string | number,\r\n password?: string\r\n): Promise<PublicCollectionData | null> {\r\n try {\r\n const url = password\r\n ? `${getPublicBaseUrl()}/collections/${collectionId}/public?password=${encodeURIComponent(password)}`\r\n : `${getPublicBaseUrl()}/collections/${collectionId}/public`;\r\n\r\n const data = await simpleFetch<PublicCollectionData>(url);\r\n\r\n if (!data) {\r\n throw new AppError('Failed to fetch collection', 'lib/api/events/fetchPublicCollection');\r\n }\r\n\r\n return data;\r\n } catch (error) {\r\n logger.error('Error fetching collection:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Check collection password\r\n *\r\n * Validates password for password-protected collections.\r\n *\r\n * @param collectionId - The collection ID\r\n * @param password - The password to check\r\n * @returns Whether the password is valid\r\n */\r\nexport async function checkCollectionPassword(\r\n collectionId: string | number,\r\n password: string\r\n): Promise<boolean> {\r\n try {\r\n const encodedPassword = encodeURIComponent(password);\r\n const result = await simpleFetch<{ valid: boolean }>(\r\n `${getPublicBaseUrl()}/collections/${collectionId}/check-password/${encodedPassword}`\r\n );\r\n\r\n return result?.valid === true;\r\n } catch (error) {\r\n logger.error('Error checking collection password:', error);\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Check event password\r\n *\r\n * Validates password for password-protected events.\r\n *\r\n * @param eventId - The event ID\r\n * @param password - The password to check\r\n * @returns Whether the password is valid\r\n */\r\nexport async function checkEventPassword(\r\n eventId: string | number,\r\n password: string\r\n): Promise<{ valid: boolean }> {\r\n try {\r\n // POST in the body — never in the URL path, which is captured by\r\n // access logs, browser history, and Referer headers.\r\n const apiResult = await apiPost<{ valid: boolean } | boolean>(\r\n `${getPublicBaseUrl()}/events/${eventId}/check-password`,\r\n { password }\r\n );\r\n\r\n if (!apiResult.success) return { valid: false };\r\n\r\n const result = apiResult.data;\r\n if (typeof result === 'boolean') return { valid: result };\r\n return { valid: (result as { valid: boolean }).valid === true };\r\n } catch (error) {\r\n logger.error('Error checking event password:', error);\r\n return { valid: false };\r\n }\r\n}\r\n\r\n/**\r\n * Test network connection\r\n *\r\n * Health check endpoint for connectivity testing.\r\n *\r\n * @param orgId - Optional org ID\r\n * @param venueId - Optional venue ID\r\n * @returns Whether the connection is working\r\n */\r\nexport async function testNetworkConnection(\r\n orgId?: string | number,\r\n venueId?: string | number\r\n): Promise<boolean> {\r\n try {\r\n // Use a simple endpoint to test connectivity\r\n const url = venueId\r\n ? `${getPublicBaseUrl()}/events/venue/${venueId}`\r\n : orgId\r\n ? `${getPublicBaseUrl()}/venues/organization/${orgId}`\r\n : `${getPublicBaseUrl()}/health`;\r\n\r\n // @fetch-escape: HEAD request for connectivity probe — simpleFetch always parses JSON body; HEAD has no body\r\n const response = await fetch(url, {\r\n method: 'HEAD',\r\n });\r\n\r\n return response.ok;\r\n } catch (error) {\r\n logger.error('Network connection test failed:', error);\r\n return false;\r\n }\r\n}\r\n","/**\r\n * Venues API\r\n *\r\n * Functions for fetching venue data including\r\n * service fees and tax configuration.\r\n */\r\n\r\nimport { createLogger } from '@getmicdrop/svelte-components/utils/logger';\r\nconst logger = createLogger('VC');\r\nimport { apiGet } from './client.js';\r\nimport type { Venue } from './types.js';\r\n\r\n/**\r\n * Get venue details (public, no auth required)\r\n *\r\n * Fetches venue information including service fees and taxes\r\n * needed for checkout calculations.\r\n *\r\n * @param venueId - The venue ID\r\n * @returns Venue details or null on error\r\n */\r\nexport async function getVenue(venueId: string | number): Promise<Venue | null> {\r\n try {\r\n if (!venueId) {\r\n logger.warn('getVenue called without venueId');\r\n return null;\r\n }\r\n\r\n const result = await apiGet<Venue>(`/venues/${venueId}`);\r\n if (!result.success) {\r\n logger.error(`Failed to fetch venue: ${result.statusCode}`);\r\n return null;\r\n }\r\n return result.data ?? null;\r\n } catch (error) {\r\n logger.error('Error fetching venue:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Get venue service fee configuration\r\n *\r\n * Returns just the fee-related fields for checkout calculations.\r\n *\r\n * @param venueId - The venue ID\r\n * @returns Fee configuration or null on error\r\n */\r\nexport async function getVenueFees(\r\n venueId: string | number\r\n): Promise<{\r\n serviceFeePercentage: number;\r\n serviceFeeCents: number;\r\n taxPercentage: number;\r\n} | null> {\r\n const venue = await getVenue(venueId);\r\n\r\n if (!venue) {\r\n return null;\r\n }\r\n\r\n return {\r\n serviceFeePercentage: venue.serviceFeePercentage ?? 0,\r\n serviceFeeCents: venue.serviceFeeCents ?? 0,\r\n taxPercentage: venue.taxPercentage ?? 0,\r\n };\r\n}\r\n\r\n/**\r\n * Get venue by slug\r\n *\r\n * Fetches venue using its URL-friendly slug.\r\n *\r\n * @param slug - The venue slug\r\n * @returns Venue details or null on error\r\n */\r\nexport async function getVenueBySlug(slug: string): Promise<Venue | null> {\r\n try {\r\n if (!slug) {\r\n logger.warn('getVenueBySlug called without slug');\r\n return null;\r\n }\r\n\r\n const encodedSlug = encodeURIComponent(slug);\r\n const result = await apiGet<Venue>(`/venues/slug/${encodedSlug}`);\r\n if (!result.success) {\r\n logger.error(`Failed to fetch venue by slug: ${result.statusCode}`);\r\n return null;\r\n }\r\n return result.data ?? null;\r\n } catch (error) {\r\n logger.error('Error fetching venue by slug:', error);\r\n return null;\r\n }\r\n}\r\n","import { AppError, asVenueId } from '@getmicdrop/svelte-components';\r\nimport type { VenueId } from '@getmicdrop/svelte-components';\r\n/**\r\n * Gift Card Purchase API Client\r\n * Handles gift card purchase creation, cart application/removal,\r\n * and gift-card-only checkout completion.\r\n */\r\n\r\nimport { createLogger } from '@getmicdrop/svelte-components/utils/logger';\r\nimport { getOrdersV2Url, apiPost, apiDelete } from './client.js';\r\nconst logger = createLogger('VC');\r\n\r\nconst API_BASE_URL = 'https://get-micdrop.com';\r\nconst ORDERS_V2_URL = `${API_BASE_URL}/api/orders/v2`;\r\nconst ORDERS_V2_PUBLIC = () => getOrdersV2Url();\r\n\r\n/**\r\n * Request payload for creating a gift card purchase\r\n */\r\nexport interface GiftCardPurchaseRequest {\r\n // Public boundary — accept plain number too so external TypeScript callers\r\n // that pass `venueId: 1` keep compiling. Runtime serializes a number either\r\n // way. Internal call sites pass branded VenueId via asVenueId().\r\n venueId: number | VenueId;\r\n amount: number; // In cents (e.g., 5000 = $50.00)\r\n recipientEmail: string;\r\n recipientName: string;\r\n personalMessage?: string;\r\n purchaserEmail: string;\r\n purchaserName: string;\r\n scheduledDeliveryAt?: string | null; // ISO date string or null for immediate\r\n}\r\n\r\n/**\r\n * Response from gift card purchase creation\r\n */\r\nexport interface GiftCardPurchaseResponse {\r\n giftCardUUID: string;\r\n clientSecret: string;\r\n amount: number;\r\n stripePublishableKey: string;\r\n}\r\n\r\n/**\r\n * Venue information needed for gift card purchase\r\n */\r\nexport interface VenueInfo {\r\n id: VenueId;\r\n name: string;\r\n slug: string;\r\n stripePublishableKey?: string;\r\n}\r\n\r\n/**\r\n * Create a gift card purchase and get Stripe client secret\r\n * @param req - Gift card purchase request details\r\n * @returns Gift card UUID and Stripe client secret, or null on failure\r\n */\r\nexport async function createGiftCardPurchase(\r\n req: GiftCardPurchaseRequest\r\n): Promise<GiftCardPurchaseResponse | null> {\r\n try {\r\n const apiResult = await apiPost<GiftCardPurchaseResponse>(\r\n `${ORDERS_V2_URL}/gift-cards`,\r\n req\r\n );\r\n\r\n if (!apiResult.success) {\r\n logger.error('Gift card purchase creation failed:', apiResult.error);\r\n throw new AppError(apiResult.error || 'Failed to create gift card purchase', 'lib/api/gift-cards/createGiftCardPurchase');\r\n }\r\n\r\n logger.debug('Gift card purchase created:', apiResult.data);\r\n return apiResult.data!;\r\n } catch (error) {\r\n logger.error('Gift card purchase creation error:', error);\r\n return null;\r\n }\r\n}\r\n\r\nexport interface ApplyGiftCardResult {\r\n valid: boolean;\r\n giftCardCode?: string;\r\n giftCardAmount?: number;\r\n giftCardBalance?: number;\r\n paymentType?: string;\r\n stripeAmount?: number;\r\n orderTotal?: number;\r\n requiresStripe?: boolean;\r\n error?: string;\r\n}\r\n\r\n/**\r\n * Apply a gift card to a cart.\r\n */\r\nexport async function applyGiftCard(\r\n cartId: string,\r\n code: string\r\n): Promise<ApplyGiftCardResult> {\r\n try {\r\n const apiResult = await apiPost<ApplyGiftCardResult>(\r\n `${ORDERS_V2_PUBLIC()}/cart/${cartId}/apply-gift-card`,\r\n { giftCardCode: code }\r\n );\r\n\r\n if (!apiResult.success) {\r\n if (apiResult.statusCode === 429) {\r\n return {\r\n valid: false,\r\n error: 'Too many attempts. Please wait a moment and try again.',\r\n };\r\n }\r\n logger.error('Apply gift card failed:', apiResult.error);\r\n return { valid: false, error: apiResult.error || 'Invalid gift card code' };\r\n }\r\n\r\n const data = apiResult.data!;\r\n return {\r\n valid: true,\r\n giftCardCode: data.giftCardCode,\r\n giftCardAmount: data.giftCardAmount,\r\n giftCardBalance: data.giftCardBalance,\r\n paymentType: data.paymentType,\r\n stripeAmount: data.stripeAmount,\r\n orderTotal: data.orderTotal,\r\n requiresStripe: data.requiresStripe,\r\n };\r\n } catch (err) {\r\n logger.error('applyGiftCard error:', err);\r\n return {\r\n valid: false,\r\n error: 'Network error. Please check your connection and try again.',\r\n };\r\n }\r\n}\r\n\r\nexport interface RemoveGiftCardResult {\r\n success: boolean;\r\n error?: string;\r\n}\r\n\r\n/**\r\n * Remove a gift card from a cart.\r\n */\r\nexport async function removeGiftCard(cartId: string): Promise<RemoveGiftCardResult> {\r\n try {\r\n const apiResult = await apiDelete(`${ORDERS_V2_PUBLIC()}/cart/${cartId}/gift-card`);\r\n\r\n if (!apiResult.success) {\r\n logger.error('Remove gift card failed:', apiResult.error);\r\n return { success: false, error: apiResult.error || 'Failed to remove gift card' };\r\n }\r\n\r\n return { success: true };\r\n } catch (err) {\r\n logger.error('removeGiftCard error:', err);\r\n return {\r\n success: false,\r\n error: 'Network error. Please check your connection and try again.',\r\n };\r\n }\r\n}\r\n\r\nexport interface CompleteGiftCardPaymentInput {\r\n firstName: string;\r\n lastName: string;\r\n email: string;\r\n phoneNumber?: string | null;\r\n mailingList?: boolean;\r\n}\r\n\r\nexport interface CompleteGiftCardPaymentResult {\r\n success: boolean;\r\n orderId?: string;\r\n confirmationNumber?: string;\r\n error?: string;\r\n}\r\n\r\n/**\r\n * Complete a gift-card-only payment (no Stripe required when balance >= total).\r\n */\r\nexport async function completeGiftCardPayment(\r\n cartId: string,\r\n customerDetails: CompleteGiftCardPaymentInput\r\n): Promise<CompleteGiftCardPaymentResult> {\r\n try {\r\n const apiResult = await apiPost<{ orderId?: string; confirmationNumber?: string }>(\r\n `${ORDERS_V2_PUBLIC()}/cart/${cartId}/complete-gift-card-payment`,\r\n {\r\n firstName: customerDetails.firstName,\r\n lastName: customerDetails.lastName,\r\n email: customerDetails.email,\r\n phoneNumber: customerDetails.phoneNumber || null,\r\n mailingList: customerDetails.mailingList || false,\r\n }\r\n );\r\n\r\n if (!apiResult.success) {\r\n logger.error('Complete gift card payment failed:', apiResult.error);\r\n return { success: false, error: apiResult.error || 'Failed to complete payment' };\r\n }\r\n\r\n return {\r\n success: true,\r\n orderId: apiResult.data?.orderId,\r\n confirmationNumber: apiResult.data?.confirmationNumber,\r\n };\r\n } catch (err) {\r\n logger.error('completeGiftCardPayment error:', err);\r\n return {\r\n success: false,\r\n error: 'Network error. Please check your connection and try again.',\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Fetch venue information by slug\r\n * @param slug - Venue slug\r\n * @returns Venue info or null on failure\r\n */\r\nexport async function getVenueBySlug(\r\n slug: string,\r\n customFetch: typeof fetch = fetch\r\n): Promise<VenueInfo | null> {\r\n try {\r\n // @fetch-escape: customFetch injection for SSR context — cannot use apiGet (caller-supplied fetch instance)\r\n const response = await customFetch(\r\n `${API_BASE_URL}/api/v2/public/venues/slug/${slug}`\r\n );\r\n\r\n if (!response.ok) {\r\n logger.error(`Failed to fetch venue by slug: ${response.status}`);\r\n return null;\r\n }\r\n\r\n const venue = await response.json();\r\n return {\r\n id: asVenueId(venue.id),\r\n name: venue.name,\r\n slug: venue.slug,\r\n stripePublishableKey: venue.stripePublishableKey,\r\n };\r\n } catch (error) {\r\n logger.error('Error fetching venue by slug:', error);\r\n return null;\r\n }\r\n}\r\n","/**\r\n * Waitlist API\r\n *\r\n * Endpoints for the sold-out-event waitlist flow.\r\n */\r\n\r\nimport { createLogger } from '@getmicdrop/svelte-components/utils/logger';\r\nimport { apiPost, apiGet } from './client.js';\r\n\r\nconst logger = createLogger('VC');\r\n\r\nexport interface JoinWaitlistResult {\r\n success: boolean;\r\n // No position — opaque to the customer (decision #2/#20).\r\n updated?: boolean;\r\n error?: string;\r\n}\r\n\r\nconst WAITLIST_ERROR_MESSAGES: Record<string, string> = {\r\n waitlist_not_enabled: 'Waitlist is not available for this event',\r\n event_not_found: 'Event not found',\r\n invalid_phone: 'Please enter a valid phone number',\r\n already_purchased: 'You have already purchased tickets for this event',\r\n phone_already_registered: 'This phone number is already on the waitlist',\r\n};\r\n\r\n/**\r\n * Join the waitlist for a sold-out event.\r\n */\r\nexport async function joinWaitlist(\r\n eventId: string | number,\r\n email: string,\r\n phone: string | null = null,\r\n smsOptIn = false\r\n): Promise<JoinWaitlistResult> {\r\n try {\r\n const body: Record<string, unknown> = { email };\r\n if (phone && smsOptIn) {\r\n body.phone = phone;\r\n body.smsOptIn = true;\r\n }\r\n\r\n const apiResult = await apiPost<{ updated?: boolean }>(\r\n `/events/${eventId}/waitlist`,\r\n body\r\n );\r\n\r\n if (!apiResult.success) {\r\n logger.error('Join waitlist failed:', apiResult.error);\r\n return {\r\n success: false,\r\n error:\r\n WAITLIST_ERROR_MESSAGES[apiResult.error ?? ''] ||\r\n 'Failed to join waitlist. Please try again.',\r\n };\r\n }\r\n\r\n return {\r\n success: true,\r\n updated: apiResult.data?.updated,\r\n };\r\n } catch (err) {\r\n logger.error('joinWaitlist error:', err);\r\n return {\r\n success: false,\r\n error: 'Network error. Please check your connection and try again.',\r\n };\r\n }\r\n}\r\n\r\nexport interface WaitlistStatusResult {\r\n waitlistEnabled: boolean;\r\n soldOut: boolean;\r\n /**\r\n * When gated, the public event page should present \"Sold Out — join the\r\n * waitlist\" to non-members even if tickets are technically available, and only\r\n * a valid tokenized link unlocks checkout (reconciled decision #3).\r\n */\r\n gated: boolean;\r\n}\r\n\r\n/**\r\n * Fetch an event's waitlist gating status. Returns a non-gated default if the\r\n * request fails so the page degrades to normal behavior.\r\n */\r\nexport async function getWaitlistStatus(\r\n eventId: string | number\r\n): Promise<WaitlistStatusResult> {\r\n const fallback: WaitlistStatusResult = {\r\n waitlistEnabled: false,\r\n soldOut: false,\r\n gated: false,\r\n };\r\n try {\r\n const apiResult = await apiGet<{ waitlistEnabled: boolean; soldOut: boolean; gated: boolean }>(\r\n `/events/${eventId}/waitlist/status`\r\n );\r\n if (!apiResult.success) return fallback;\r\n return {\r\n waitlistEnabled: !!apiResult.data?.waitlistEnabled,\r\n soldOut: !!apiResult.data?.soldOut,\r\n gated: !!apiResult.data?.gated,\r\n };\r\n } catch (err) {\r\n logger.error('getWaitlistStatus error:', err);\r\n return fallback;\r\n }\r\n}\r\n","/**\r\n * CTA state computation.\r\n *\r\n * Pure function (no I/O) — derives the buy-button state from an event and\r\n * its ticket list. Lives in `api/` because it is the canonical, single\r\n * source of truth that replaces the duplicate implementations previously\r\n * scattered across utils/api.js, core/api-client.js, and a few components.\r\n */\r\n\r\n// Import from the specific subpath (not the bare entry) so the api/\r\n// bundle doesn't pull in the entire SC component graph (Accordion etc.)\r\n// and break `npm run build:api`.\r\nimport {\r\n formatDateRaw,\r\n formatTime,\r\n} from '@getmicdrop/svelte-components/utils/formatters';\r\n\r\nexport interface CtaStateOptions {\r\n cancelled?: boolean;\r\n isRegistration?: boolean;\r\n waitlistEnabled?: boolean;\r\n}\r\n\r\nexport interface CtaState {\r\n text: string;\r\n disabled: boolean;\r\n reason:\r\n | 'cancelled'\r\n | 'event_past'\r\n | 'no_tickets'\r\n | 'available'\r\n | 'coming_soon'\r\n | 'sold_out_waitlist'\r\n | 'sold_out'\r\n | 'sales_ended'\r\n | 'hidden_only';\r\n}\r\n\r\ninterface CtaEvent {\r\n startDateTime?: string | null;\r\n endDateTime?: string | null;\r\n hasPurchasableHiddenTickets?: boolean;\r\n}\r\n\r\ninterface CtaTicket {\r\n salesChannel?: number;\r\n salesBegin?: string | null;\r\n salesStart?: string | null;\r\n saleBegin?: string | null;\r\n onSaleStart?: string | null;\r\n salesEnd?: string | null;\r\n saleEnd?: string | null;\r\n onSaleEnd?: string | null;\r\n remainingCapacity?: number | null;\r\n quantityRemaining?: number | null;\r\n quantity?: number | null;\r\n soldOut?: boolean;\r\n isHidden?: boolean;\r\n visibility?: number;\r\n}\r\n\r\n// A hidden ticket (visibility>=2 or isHidden) that's still on sale drives the\r\n// \"Sales ended\" / \"Sold out\" / \"No tickets\" → \"Get tickets\" override. The user\r\n// just needs the promo code to see it.\r\nexport function isHiddenTicketPurchasable(ticket: CtaTicket): boolean {\r\n if (!ticket) return false;\r\n const isHidden =\r\n ticket.isHidden === true ||\r\n (typeof ticket.visibility === 'number' && ticket.visibility >= 2);\r\n if (!isHidden) return false;\r\n if (ticket.salesChannel === 2) return false;\r\n\r\n const now = new Date();\r\n const salesBegin =\r\n ticket.salesBegin ||\r\n ticket.salesStart ||\r\n ticket.saleBegin ||\r\n ticket.onSaleStart;\r\n const salesEnd = ticket.salesEnd || ticket.saleEnd || ticket.onSaleEnd;\r\n if (salesBegin && new Date(salesBegin) > now) return false;\r\n if (salesEnd && new Date(salesEnd) < now) return false;\r\n\r\n const remaining =\r\n ticket.remainingCapacity ?? ticket.quantityRemaining ?? ticket.quantity;\r\n const isSoldOut =\r\n ticket.soldOut ||\r\n (remaining !== null && remaining !== undefined && remaining <= 0);\r\n if (isSoldOut) return false;\r\n\r\n return true;\r\n}\r\n\r\nexport function computeCtaState(\r\n event: CtaEvent,\r\n tickets: CtaTicket[] | undefined,\r\n options: CtaStateOptions = {}\r\n): CtaState {\r\n const {\r\n cancelled = false,\r\n isRegistration = false,\r\n waitlistEnabled = false,\r\n } = options;\r\n const now = new Date();\r\n\r\n if (cancelled)\r\n return { text: 'Cancelled', disabled: true, reason: 'cancelled' };\r\n\r\n const eventEnd = event.endDateTime || event.startDateTime;\r\n if (eventEnd && new Date(eventEnd) < now) {\r\n return { text: 'Sales ended', disabled: true, reason: 'event_past' };\r\n }\r\n\r\n const hiddenAvailable =\r\n event?.hasPurchasableHiddenTickets === true ||\r\n (Array.isArray(tickets) && tickets.some(isHiddenTicketPurchasable));\r\n\r\n const publicTickets = (tickets || []).filter(\r\n t =>\r\n t.salesChannel !== 2 &&\r\n !t.isHidden &&\r\n !(typeof t.visibility === 'number' && t.visibility >= 2)\r\n );\r\n if (publicTickets.length === 0) {\r\n if (hiddenAvailable) {\r\n return {\r\n text: isRegistration ? 'Reserve a spot' : 'Get tickets',\r\n disabled: false,\r\n reason: 'hidden_only',\r\n };\r\n }\r\n return {\r\n text: 'No tickets available',\r\n disabled: true,\r\n reason: 'no_tickets',\r\n };\r\n }\r\n\r\n let hasPurchasable = false;\r\n let allSoldOut = true;\r\n let allComingSoon = true;\r\n let earliestSalesStart: Date | null = null;\r\n\r\n for (const ticket of publicTickets) {\r\n const salesBegin =\r\n ticket.salesBegin ||\r\n ticket.salesStart ||\r\n ticket.saleBegin ||\r\n ticket.onSaleStart;\r\n const salesEnd = ticket.salesEnd || ticket.saleEnd || ticket.onSaleEnd;\r\n const remaining =\r\n ticket.remainingCapacity ?? ticket.quantityRemaining ?? ticket.quantity;\r\n const isSoldOut =\r\n ticket.soldOut ||\r\n (remaining !== null && remaining !== undefined && remaining <= 0);\r\n\r\n const isScheduled = salesBegin ? new Date(salesBegin) > now : false;\r\n const hasSalesEnded = salesEnd ? new Date(salesEnd) < now : false;\r\n const isPurchasable = !isSoldOut && !isScheduled && !hasSalesEnded;\r\n\r\n if (isPurchasable) hasPurchasable = true;\r\n if (!isSoldOut) allSoldOut = false;\r\n if (!isScheduled) allComingSoon = false;\r\n\r\n if (isScheduled && salesBegin && !isSoldOut && !hasSalesEnded) {\r\n const startDate = new Date(salesBegin);\r\n if (!earliestSalesStart || startDate < earliestSalesStart) {\r\n earliestSalesStart = startDate;\r\n }\r\n }\r\n }\r\n\r\n if (hasPurchasable) {\r\n return {\r\n text: isRegistration ? 'Reserve a spot' : 'Get tickets',\r\n disabled: false,\r\n reason: 'available',\r\n };\r\n }\r\n\r\n if (allComingSoon && earliestSalesStart) {\r\n if (hiddenAvailable) {\r\n return {\r\n text: isRegistration ? 'Reserve a spot' : 'Get tickets',\r\n disabled: false,\r\n reason: 'hidden_only',\r\n };\r\n }\r\n const diffMs = earliestSalesStart.getTime() - now.getTime();\r\n const diffHours = diffMs / (1000 * 60 * 60);\r\n const diffDays = diffMs / (1000 * 60 * 60 * 24);\r\n let dateText: string;\r\n if (diffHours < 24) {\r\n dateText = formatTime(earliestSalesStart, { hour12: true }, 'en-US');\r\n } else if (diffDays <= 7) {\r\n dateText = formatDateRaw(\r\n earliestSalesStart,\r\n { weekday: 'short', hour: 'numeric', minute: '2-digit', hour12: true },\r\n 'en-US'\r\n );\r\n } else {\r\n const d = formatDateRaw(\r\n earliestSalesStart,\r\n { month: 'short', day: 'numeric' },\r\n 'en-US'\r\n );\r\n const t = formatTime(earliestSalesStart, { hour12: true }, 'en-US');\r\n dateText = `${d} ${t}`;\r\n }\r\n return {\r\n text: `On sale ${dateText}`,\r\n disabled: true,\r\n reason: 'coming_soon',\r\n };\r\n }\r\n\r\n if (allSoldOut) {\r\n if (hiddenAvailable) {\r\n return {\r\n text: isRegistration ? 'Reserve a spot' : 'Get tickets',\r\n disabled: false,\r\n reason: 'hidden_only',\r\n };\r\n }\r\n if (waitlistEnabled) {\r\n return {\r\n text: 'Join Waitlist',\r\n disabled: false,\r\n reason: 'sold_out_waitlist',\r\n };\r\n }\r\n return { text: 'Sold out', disabled: true, reason: 'sold_out' };\r\n }\r\n\r\n if (hiddenAvailable) {\r\n return {\r\n text: isRegistration ? 'Reserve a spot' : 'Get tickets',\r\n disabled: false,\r\n reason: 'hidden_only',\r\n };\r\n }\r\n\r\n return { text: 'Sales ended', disabled: true, reason: 'sales_ended' };\r\n}\r\n","import type { USD } from '@getmicdrop/svelte-components';\r\nimport { formatCurrency } from '@getmicdrop/svelte-components';\r\n/**\r\n * Order Transformer\r\n *\r\n * Normalizes API order responses to a consistent format.\r\n * Handles variations in field names between different API versions.\r\n */\r\n\r\nimport type { Order, PurchasedTicket } from '../types.js';\r\n\r\n/**\r\n * Raw API order response (may have varying field names)\r\n */\r\ninterface ApiOrder {\r\n uuid?: string;\r\n id?: number;\r\n ID?: number;\r\n customerEmail?: string;\r\n email?: string;\r\n customer_email?: string;\r\n customerFirstName?: string;\r\n firstName?: string;\r\n first_name?: string;\r\n customerLastName?: string;\r\n lastName?: string;\r\n last_name?: string;\r\n status?: string;\r\n totalAmount?: number;\r\n total?: number;\r\n total_amount?: number;\r\n subtotal?: number;\r\n serviceFeesAmount?: number;\r\n serviceFee?: number;\r\n service_fee?: number;\r\n service_fees_amount?: number;\r\n taxAmount?: number;\r\n tax?: number;\r\n tax_amount?: number;\r\n discount?: number;\r\n paymentIntentId?: string;\r\n payment_intent_id?: string;\r\n paymentMethod?: string;\r\n payment_method?: string;\r\n purchasedTickets?: any[];\r\n tickets?: any[];\r\n purchased_tickets?: any[];\r\n createdAt?: string;\r\n created_at?: string;\r\n updatedAt?: string;\r\n updated_at?: string;\r\n}\r\n\r\n/**\r\n * Raw API ticket response\r\n */\r\ninterface ApiTicket {\r\n uuid?: string;\r\n id?: number;\r\n ID?: number;\r\n ticketNumber?: string;\r\n ticket_number?: string;\r\n orderId?: string | number;\r\n order_id?: string | number;\r\n attendeeFirstName?: string;\r\n attendee_first_name?: string;\r\n firstName?: string;\r\n attendeeLastName?: string;\r\n attendee_last_name?: string;\r\n lastName?: string;\r\n attendeeEmail?: string;\r\n attendee_email?: string;\r\n email?: string;\r\n ticketName?: string;\r\n ticket_name?: string;\r\n name?: string;\r\n ticketTypeId?: number;\r\n ticket_type_id?: number;\r\n purchasePrice?: number;\r\n purchase_price?: number;\r\n price?: number;\r\n status?: string;\r\n checkedIn?: boolean;\r\n checked_in?: boolean;\r\n checkedInAt?: string;\r\n checked_in_at?: string;\r\n}\r\n\r\n/**\r\n * Transform a raw API ticket to normalized PurchasedTicket\r\n */\r\nexport function transformTicket(apiTicket: ApiTicket): PurchasedTicket {\r\n return {\r\n uuid: apiTicket.uuid || String(apiTicket.id || apiTicket.ID || ''),\r\n id: apiTicket.id || apiTicket.ID,\r\n ticketNumber: apiTicket.ticketNumber || apiTicket.ticket_number,\r\n orderId: apiTicket.orderId || apiTicket.order_id,\r\n attendeeFirstName:\r\n apiTicket.attendeeFirstName ||\r\n apiTicket.attendee_first_name ||\r\n apiTicket.firstName,\r\n attendeeLastName:\r\n apiTicket.attendeeLastName ||\r\n apiTicket.attendee_last_name ||\r\n apiTicket.lastName,\r\n attendeeEmail:\r\n apiTicket.attendeeEmail || apiTicket.attendee_email || apiTicket.email,\r\n ticketName:\r\n apiTicket.ticketName || apiTicket.ticket_name || apiTicket.name || '',\r\n ticketTypeId: apiTicket.ticketTypeId || apiTicket.ticket_type_id,\r\n purchasePrice:\r\n apiTicket.purchasePrice ||\r\n apiTicket.purchase_price ||\r\n apiTicket.price ||\r\n 0,\r\n status: apiTicket.status,\r\n checkedIn: apiTicket.checkedIn || apiTicket.checked_in,\r\n checkedInAt: apiTicket.checkedInAt || apiTicket.checked_in_at,\r\n };\r\n}\r\n\r\n/**\r\n * Transform a raw API order to normalized Order\r\n *\r\n * Handles various field name patterns:\r\n * - camelCase (customerEmail)\r\n * - snake_case (customer_email)\r\n * - Shortened names (email)\r\n */\r\nexport function transformOrder(apiOrder: ApiOrder): Order {\r\n // Extract tickets array from various possible field names\r\n const rawTickets =\r\n apiOrder.purchasedTickets ||\r\n apiOrder.tickets ||\r\n apiOrder.purchased_tickets ||\r\n [];\r\n\r\n return {\r\n uuid: apiOrder.uuid || String(apiOrder.id || apiOrder.ID || ''),\r\n id: apiOrder.id || apiOrder.ID,\r\n customerEmail:\r\n apiOrder.customerEmail ||\r\n apiOrder.email ||\r\n apiOrder.customer_email ||\r\n '',\r\n customerFirstName:\r\n apiOrder.customerFirstName ||\r\n apiOrder.firstName ||\r\n apiOrder.first_name,\r\n customerLastName:\r\n apiOrder.customerLastName ||\r\n apiOrder.lastName ||\r\n apiOrder.last_name,\r\n status: apiOrder.status || 'unknown',\r\n totalAmount:\r\n apiOrder.totalAmount ||\r\n apiOrder.total ||\r\n apiOrder.total_amount ||\r\n 0,\r\n subtotal: apiOrder.subtotal,\r\n serviceFeesAmount:\r\n apiOrder.serviceFeesAmount ||\r\n apiOrder.serviceFee ||\r\n apiOrder.service_fee ||\r\n apiOrder.service_fees_amount ||\r\n 0,\r\n taxAmount:\r\n apiOrder.taxAmount || apiOrder.tax || apiOrder.tax_amount || 0,\r\n discount: apiOrder.discount || 0,\r\n paymentIntentId:\r\n apiOrder.paymentIntentId || apiOrder.payment_intent_id,\r\n paymentMethod: apiOrder.paymentMethod || apiOrder.payment_method,\r\n purchasedTickets: rawTickets.map(transformTicket),\r\n createdAt: apiOrder.createdAt || apiOrder.created_at,\r\n updatedAt: apiOrder.updatedAt || apiOrder.updated_at,\r\n };\r\n}\r\n\r\n/**\r\n * Transform order for display on success page\r\n *\r\n * Returns a simplified object with display-ready values.\r\n */\r\nexport function transformOrderForDisplay(apiOrder: ApiOrder): {\r\n orderId: string;\r\n displayOrderId: string;\r\n email: string;\r\n customerName: string;\r\n total: number;\r\n formattedTotal: string;\r\n ticketCount: number;\r\n status: string;\r\n} {\r\n const order = transformOrder(apiOrder);\r\n const displayId = order.uuid.split('-')[0] || order.uuid;\r\n\r\n return {\r\n orderId: order.uuid,\r\n displayOrderId: displayId,\r\n email: order.customerEmail,\r\n customerName: [order.customerFirstName, order.customerLastName]\r\n .filter(Boolean)\r\n .join(' '),\r\n total: order.totalAmount,\r\n formattedTotal: `${formatCurrency((order.totalAmount / 100) as USD /* FIXME(canonical-cleanup:toFixed): this cast bypasses the brand boundary; replace with toCents/toUSD at the API-response-transform layer. */)}`,\r\n ticketCount: order.purchasedTickets.length,\r\n status: order.status,\r\n };\r\n}\r\n","/**\r\n * Event Transformer\r\n *\r\n * Normalizes API event responses to a consistent format.\r\n * Handles image URL resolution and CTA state calculation.\r\n */\r\n\r\nimport type { Event, AvailableTicket } from '../types.js';\r\n\r\n// CDN base URL for images\r\nconst CDN_BASE_URL = 'https://micdrop-images.sfo3.digitaloceanspaces.com';\r\n\r\n/**\r\n * Raw API event response (may have varying field names)\r\n */\r\ninterface ApiEvent {\r\n eventID?: number;\r\n id?: number;\r\n ID?: number;\r\n name?: string;\r\n title?: string;\r\n slug?: string;\r\n description?: string;\r\n date?: string;\r\n startDateTime?: string;\r\n start_date_time?: string;\r\n endDateTime?: string;\r\n end_date_time?: string;\r\n doorsOpenTime?: string;\r\n doors_open_time?: string;\r\n timezone?: string;\r\n time_zone?: string;\r\n venueId?: number;\r\n venue_id?: number;\r\n venueName?: string;\r\n venue_name?: string;\r\n venueAddress?: string;\r\n venue_address?: string;\r\n location?: string;\r\n imageUrl?: string;\r\n imageURL?: string;\r\n image_url?: string;\r\n image?: string;\r\n status?: string;\r\n isPublished?: boolean;\r\n is_published?: boolean;\r\n isCancelled?: boolean;\r\n is_cancelled?: boolean;\r\n availableTickets?: any[];\r\n available_tickets?: any[];\r\n tickets?: any[];\r\n ticketsAvailable?: number;\r\n tickets_available?: number;\r\n ticketsSold?: number;\r\n tickets_sold?: number;\r\n minPrice?: number;\r\n min_price?: number;\r\n maxPrice?: number;\r\n max_price?: number;\r\n ctaText?: string;\r\n cta_text?: string;\r\n ctaState?: string;\r\n cta_state?: string;\r\n showPerformers?: boolean;\r\n show_performers?: boolean;\r\n eventSeriesId?: number;\r\n event_series_id?: number;\r\n seriesInstanceNumber?: number;\r\n series_instance_number?: number;\r\n}\r\n\r\n/**\r\n * Get CDN image URL\r\n *\r\n * Prepends the CDN base URL if the path is relative.\r\n */\r\nexport function getCDNImageUrl(path: string | undefined): string {\r\n if (!path) return '';\r\n if (path.startsWith('http')) return path;\r\n return `${CDN_BASE_URL}/${path.replace(/^\\//, '')}`;\r\n}\r\n\r\n/**\r\n * Extract image URL from event with fallbacks\r\n */\r\nexport function getEventImageUrl(apiEvent: ApiEvent): string {\r\n const rawUrl =\r\n apiEvent.imageUrl ||\r\n apiEvent.imageURL ||\r\n apiEvent.image_url ||\r\n apiEvent.image ||\r\n '';\r\n\r\n return getCDNImageUrl(rawUrl);\r\n}\r\n\r\n/**\r\n * Calculate CTA state based on ticket availability\r\n */\r\nexport function calculateCtaState(\r\n apiEvent: ApiEvent\r\n): 'available' | 'sold_out' | 'coming_soon' | 'ended' {\r\n // Check explicit CTA state first\r\n const explicitState = apiEvent.ctaState || apiEvent.cta_state;\r\n if (explicitState) {\r\n return explicitState as any;\r\n }\r\n\r\n // Check if event is cancelled or ended\r\n if (apiEvent.isCancelled || apiEvent.is_cancelled) {\r\n return 'ended';\r\n }\r\n\r\n // Check event date\r\n const eventDate = apiEvent.startDateTime || apiEvent.start_date_time || apiEvent.date;\r\n if (eventDate) {\r\n const eventTime = new Date(eventDate).getTime();\r\n const now = Date.now();\r\n\r\n if (eventTime < now) {\r\n return 'ended';\r\n }\r\n }\r\n\r\n // Check ticket availability\r\n const availableCount =\r\n apiEvent.ticketsAvailable ?? apiEvent.tickets_available;\r\n\r\n if (availableCount !== undefined) {\r\n if (availableCount <= 0) {\r\n return 'sold_out';\r\n }\r\n return 'available';\r\n }\r\n\r\n // Check tickets array\r\n const tickets =\r\n apiEvent.availableTickets ||\r\n apiEvent.available_tickets ||\r\n apiEvent.tickets ||\r\n [];\r\n\r\n if (tickets.length === 0) {\r\n return 'coming_soon';\r\n }\r\n\r\n const totalAvailable = tickets.reduce((sum: number, t: any) => {\r\n const qty =\r\n t.quantityAvailable ?? t.quantity_available ?? t.quantity ?? 0;\r\n const sold = t.quantitySold ?? t.quantity_sold ?? 0;\r\n return sum + Math.max(0, qty - sold);\r\n }, 0);\r\n\r\n if (totalAvailable <= 0) {\r\n return 'sold_out';\r\n }\r\n\r\n return 'available';\r\n}\r\n\r\n/**\r\n * Transform a raw API ticket to normalized AvailableTicket\r\n */\r\nexport function transformTicket(apiTicket: any): AvailableTicket {\r\n return {\r\n id: apiTicket.id || apiTicket.ID,\r\n name: apiTicket.name || apiTicket.ticketName || '',\r\n description: apiTicket.description,\r\n price: apiTicket.price || 0,\r\n quantity: apiTicket.quantity || apiTicket.totalQuantity || 0,\r\n quantitySold: apiTicket.quantitySold || apiTicket.quantity_sold || 0,\r\n quantityAvailable:\r\n apiTicket.quantityAvailable ||\r\n apiTicket.quantity_available ||\r\n (apiTicket.quantity || 0) - (apiTicket.quantitySold || 0),\r\n minPerOrder: apiTicket.minPerOrder || apiTicket.min_per_order || 1,\r\n maxPerOrder: apiTicket.maxPerOrder || apiTicket.max_per_order || 10,\r\n saleStartDate: apiTicket.saleStartDate || apiTicket.sale_start_date,\r\n saleEndDate: apiTicket.saleEndDate || apiTicket.sale_end_date,\r\n isHidden: apiTicket.isHidden || apiTicket.is_hidden || false,\r\n revealWithPromoCode:\r\n apiTicket.revealWithPromoCode || apiTicket.reveal_with_promo_code,\r\n ticketType: apiTicket.ticketType || apiTicket.ticket_type || 0,\r\n sectionId: apiTicket.sectionId || apiTicket.section_id,\r\n sortOrder: apiTicket.sortOrder || apiTicket.sort_order || 0,\r\n };\r\n}\r\n\r\n/**\r\n * Transform a raw API event to normalized Event\r\n */\r\nexport function transformEvent(apiEvent: ApiEvent): Event {\r\n // Extract tickets array from various possible field names\r\n const rawTickets =\r\n apiEvent.availableTickets ||\r\n apiEvent.available_tickets ||\r\n apiEvent.tickets ||\r\n [];\r\n\r\n const tickets = rawTickets.map(transformTicket);\r\n\r\n // Calculate min/max prices from tickets\r\n const prices = tickets.map((t) => t.price).filter((p) => p > 0);\r\n const minPrice = prices.length > 0 ? Math.min(...prices) : undefined;\r\n const maxPrice = prices.length > 0 ? Math.max(...prices) : undefined;\r\n\r\n return {\r\n eventID: apiEvent.eventID || apiEvent.id || apiEvent.ID || 0,\r\n id: apiEvent.id || apiEvent.ID,\r\n name: apiEvent.name || apiEvent.title || '',\r\n title: apiEvent.title || apiEvent.name,\r\n slug: apiEvent.slug,\r\n description: apiEvent.description,\r\n date: apiEvent.date || apiEvent.startDateTime || apiEvent.start_date_time || '',\r\n startDateTime: apiEvent.startDateTime || apiEvent.start_date_time,\r\n endDateTime: apiEvent.endDateTime || apiEvent.end_date_time,\r\n doorsOpenTime: apiEvent.doorsOpenTime || apiEvent.doors_open_time,\r\n timezone: apiEvent.timezone || apiEvent.time_zone,\r\n venueId: apiEvent.venueId || apiEvent.venue_id,\r\n venueName: apiEvent.venueName || apiEvent.venue_name,\r\n venueAddress: apiEvent.venueAddress || apiEvent.venue_address,\r\n location: apiEvent.location || apiEvent.venueAddress || apiEvent.venue_address,\r\n imageUrl: getEventImageUrl(apiEvent),\r\n imageURL: getEventImageUrl(apiEvent),\r\n status: apiEvent.status,\r\n isPublished: apiEvent.isPublished ?? apiEvent.is_published,\r\n isCancelled: apiEvent.isCancelled ?? apiEvent.is_cancelled,\r\n availableTickets: tickets,\r\n ticketsAvailable:\r\n apiEvent.ticketsAvailable ??\r\n apiEvent.tickets_available ??\r\n tickets.reduce((sum, t) => sum + (t.quantityAvailable || 0), 0),\r\n ticketsSold: apiEvent.ticketsSold ?? apiEvent.tickets_sold,\r\n minPrice: apiEvent.minPrice ?? apiEvent.min_price ?? minPrice,\r\n maxPrice: apiEvent.maxPrice ?? apiEvent.max_price ?? maxPrice,\r\n ctaText: apiEvent.ctaText || apiEvent.cta_text,\r\n ctaState: calculateCtaState(apiEvent),\r\n showPerformers: apiEvent.showPerformers ?? apiEvent.show_performers,\r\n eventSeriesId: apiEvent.eventSeriesId || apiEvent.event_series_id,\r\n seriesInstanceNumber:\r\n apiEvent.seriesInstanceNumber || apiEvent.series_instance_number,\r\n };\r\n}\r\n\r\n/**\r\n * Legacy transformer name for backwards compatibility\r\n */\r\nexport const transformEventData = transformEvent;\r\n","/**\r\n * Venue Transformer\r\n *\r\n * Normalizes API venue responses to a consistent format.\r\n */\r\n\r\nimport type { Venue } from '../types.js';\r\n\r\n// CDN base URL for images\r\nconst CDN_BASE_URL = 'https://micdrop-images.sfo3.digitaloceanspaces.com';\r\n\r\n/**\r\n * Raw API venue response (may have varying field names)\r\n */\r\ninterface ApiVenue {\r\n id?: number;\r\n ID?: number;\r\n name?: string;\r\n slug?: string;\r\n address?: string;\r\n googleLocationNameCache?: string;\r\n google_location_name_cache?: string;\r\n city?: string;\r\n state?: string;\r\n zipCode?: string;\r\n zip_code?: string;\r\n country?: string;\r\n timezone?: string;\r\n time_zone?: string;\r\n logoUrl?: string;\r\n logo_url?: string;\r\n logo?: string;\r\n serviceFeePercentage?: number;\r\n service_fee_percentage?: number;\r\n serviceFeeCents?: number;\r\n service_fee_cents?: number;\r\n taxPercentage?: number;\r\n tax_percentage?: number;\r\n organizationId?: number;\r\n organization_id?: number;\r\n}\r\n\r\n/**\r\n * Get CDN image URL for venue logo\r\n */\r\nfunction getLogoUrl(path: string | undefined): string {\r\n if (!path) return '';\r\n if (path.startsWith('http')) return path;\r\n return `${CDN_BASE_URL}/${path.replace(/^\\//, '')}`;\r\n}\r\n\r\n/**\r\n * Transform a raw API venue to normalized Venue\r\n */\r\nexport function transformVenue(apiVenue: ApiVenue): Venue {\r\n const logoPath =\r\n apiVenue.logoUrl || apiVenue.logo_url || apiVenue.logo;\r\n\r\n return {\r\n id: apiVenue.id || apiVenue.ID || 0,\r\n name: apiVenue.name || '',\r\n slug: apiVenue.slug,\r\n address: apiVenue.address,\r\n googleLocationNameCache:\r\n apiVenue.googleLocationNameCache ||\r\n apiVenue.google_location_name_cache,\r\n city: apiVenue.city,\r\n state: apiVenue.state,\r\n zipCode: apiVenue.zipCode || apiVenue.zip_code,\r\n country: apiVenue.country,\r\n timezone: apiVenue.timezone || apiVenue.time_zone,\r\n logoUrl: getLogoUrl(logoPath),\r\n serviceFeePercentage:\r\n apiVenue.serviceFeePercentage ??\r\n apiVenue.service_fee_percentage ??\r\n 0,\r\n serviceFeeCents:\r\n apiVenue.serviceFeeCents ?? apiVenue.service_fee_cents ?? 0,\r\n taxPercentage:\r\n apiVenue.taxPercentage ?? apiVenue.tax_percentage ?? 0,\r\n organizationId:\r\n apiVenue.organizationId || apiVenue.organization_id,\r\n };\r\n}\r\n\r\n/**\r\n * Extract fee configuration from venue\r\n */\r\nexport function extractVenueFees(apiVenue: ApiVenue): {\r\n serviceFeePercentage: number;\r\n serviceFeeCents: number;\r\n taxPercentage: number;\r\n} {\r\n return {\r\n serviceFeePercentage:\r\n apiVenue.serviceFeePercentage ??\r\n apiVenue.service_fee_percentage ??\r\n 0,\r\n serviceFeeCents:\r\n apiVenue.serviceFeeCents ?? apiVenue.service_fee_cents ?? 0,\r\n taxPercentage:\r\n apiVenue.taxPercentage ?? apiVenue.tax_percentage ?? 0,\r\n };\r\n}\r\n\r\n/**\r\n * Get formatted venue address\r\n */\r\nexport function formatVenueAddress(venue: Venue): string {\r\n const parts = [\r\n venue.address,\r\n venue.city,\r\n venue.state,\r\n venue.zipCode,\r\n ].filter(Boolean);\r\n\r\n return parts.join(', ');\r\n}\r\n"],"names":["logger","createLogger","DEFAULT_CONFIG","error","globalConfig","configureApi","config","getApiConfig","getPublicBaseUrl","getLegacyPublicUrl","getOrdersV2Url","getClientIP","sleep","ms","resolve","fetchWithRetry","url","init","cfg","method","maxAttempts","lastError","attempt","controller","timeoutId","callerSignal","onCallerAbort","response","err","apiGet","endpoint","options","apiRequest","apiPost","body","apiPut","apiDelete","errorData","message","errorMessage","simpleFetch","createPaymentIntent","cartId","quantities","donationAmounts","apiResult","AppError","getCartByUUID","cartUUID","expectedEventID","raw","uuid","eventID","status","expiresAt","reservations","r","rec","updateCartQuantities","numericQuantities","k","v","n","numericDonations","completeReservation","orderUuid","cancelReservation","createOrder","eventId","promoCode","getOrder","orderId","validatePaymentIntent","payload","result","extendCheckoutSession","getSessionStatus","initiateOrder","cartData","trackUTMSource","venueId","utmSource","validatePromoCode","code","encodedCode","hasPromoCodes","applyPromoCode","removePromoCode","_eventDetailsInflight","fetchEventDetails","customFetch","key","inflight","run","fetchEventTickets","tickets","fetchEventPerformers","data","fetchAllVenues","orgId","venues","fetchVenueEvents","events","getMonthEvents","year","month","getOrgMonthEvents","getSeriesOccurrences","eventSeriesId","fetchSeriesOccurrences","resolvePublicEntity","id","slug","qs","fetchSeriesPage","seriesId","fetchPublicCollection","collectionId","password","checkCollectionPassword","encodedPassword","checkEventPassword","testNetworkConnection","getVenue","getVenueFees","venue","getVenueBySlug","encodedSlug","API_BASE_URL","ORDERS_V2_URL","ORDERS_V2_PUBLIC","createGiftCardPurchase","req","applyGiftCard","removeGiftCard","completeGiftCardPayment","customerDetails","WAITLIST_ERROR_MESSAGES","joinWaitlist","email","phone","smsOptIn","getWaitlistStatus","fallback","isHiddenTicketPurchasable","ticket","now","salesBegin","salesEnd","remaining","computeCtaState","event","cancelled","isRegistration","waitlistEnabled","eventEnd","hiddenAvailable","publicTickets","t","hasPurchasable","allSoldOut","allComingSoon","earliestSalesStart","isSoldOut","isScheduled","hasSalesEnded","startDate","diffMs","diffHours","diffDays","dateText","formatTime","formatDateRaw","d","transformTicket","apiTicket","transformOrder","apiOrder","rawTickets","transformOrderForDisplay","order","displayId","formatCurrency","CDN_BASE_URL","getCDNImageUrl","path","getEventImageUrl","apiEvent","rawUrl","calculateCtaState","explicitState","eventDate","eventTime","availableCount","sum","qty","sold","transformEvent","prices","p","minPrice","maxPrice","transformEventData","getLogoUrl","transformVenue","apiVenue","logoPath","extractVenueFees","formatVenueAddress"],"mappings":"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"}
1
+ {"version":3,"file":"api.mjs","sources":["../../src/lib/api/client.ts","../../src/lib/api/orders.ts","../../src/lib/api/promo.ts","../../src/lib/api/events.ts","../../src/lib/api/venues.ts","../../src/lib/api/gift-cards.ts","../../src/lib/api/waitlist.ts","../../src/lib/api/cta.ts","../../src/lib/api/transformers/order.ts","../../src/lib/api/transformers/event.ts","../../src/lib/api/transformers/venue.ts"],"sourcesContent":["/**\r\n * API Client for MicDrop Public Checkout API\r\n *\r\n * Provides a centralized HTTP client with:\r\n * - Configurable base URL\r\n * - Per-request timeout via AbortController\r\n * - Exponential-backoff retry on 5xx and network errors (idempotent methods)\r\n * - Consistent error surfacing\r\n * - Request/response typing\r\n */\r\n\r\nimport { createLogger } from '@getmicdrop/svelte-components/utils/logger';\r\nconst logger = createLogger('VC');\r\nimport type { ApiConfig, ApiResponse } from './types.js';\r\n\r\n// Default API configuration\r\nconst DEFAULT_CONFIG: Required<ApiConfig> = {\r\n baseUrl: 'https://get-micdrop.com',\r\n timeout: 30000,\r\n retries: 2,\r\n retryDelay: 500,\r\n onError: (error: Error) => logger.error('API Error:', error),\r\n};\r\n\r\nlet globalConfig: Required<ApiConfig> = { ...DEFAULT_CONFIG };\r\n\r\nexport function configureApi(config: Partial<ApiConfig>): void {\r\n globalConfig = { ...globalConfig, ...config };\r\n}\r\n\r\nexport function getApiConfig(): Required<ApiConfig> {\r\n return { ...globalConfig };\r\n}\r\n\r\nexport function getPublicBaseUrl(): string {\r\n return `${globalConfig.baseUrl}/api/v2/public`;\r\n}\r\n\r\nexport function getLegacyPublicUrl(): string {\r\n return `${globalConfig.baseUrl}/api/public`;\r\n}\r\n\r\nexport function getOrdersV2Url(): string {\r\n return `${globalConfig.baseUrl}/api/orders/v2/public`;\r\n}\r\n\r\n/** @deprecated IP is now resolved server-side via request headers. */\r\nexport async function getClientIP(): Promise<string> {\r\n return '';\r\n}\r\n\r\n/**\r\n * Sleep utility for retry backoff.\r\n */\r\nconst sleep = (ms: number): Promise<void> =>\r\n new Promise((resolve) => setTimeout(resolve, ms));\r\n\r\n/**\r\n * fetch with timeout, idempotent retry, and exponential backoff.\r\n *\r\n * - Retries on network errors and 5xx (transient) responses.\r\n * - Never retries non-idempotent methods (POST/PUT/PATCH/DELETE) — those are\r\n * left to caller-driven retries to avoid duplicate writes.\r\n * - The supplied AbortSignal (if any) is respected and short-circuits retries.\r\n */\r\nasync function fetchWithRetry(\r\n url: string,\r\n init: RequestInit,\r\n cfg: Required<ApiConfig>\r\n): Promise<Response> {\r\n const method = (init.method || 'GET').toUpperCase();\r\n const isIdempotent = method === 'GET' || method === 'HEAD';\r\n const maxAttempts = isIdempotent ? cfg.retries + 1 : 1;\r\n\r\n let lastError: unknown;\r\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\r\n const controller = new AbortController();\r\n const timeoutId = setTimeout(() => controller.abort(), cfg.timeout);\r\n\r\n // Chain the caller's signal if provided.\r\n const callerSignal = init.signal;\r\n let onCallerAbort: (() => void) | undefined;\r\n if (callerSignal) {\r\n if (callerSignal.aborted) controller.abort();\r\n else {\r\n onCallerAbort = () => controller.abort();\r\n callerSignal.addEventListener('abort', onCallerAbort, { once: true });\r\n }\r\n }\r\n\r\n try {\r\n // @api-client-escape: internal canonical client implementation — not drift\r\n const response = await fetch(url, { ...init, signal: controller.signal });\r\n\r\n // Retry transient server errors.\r\n if (response.status >= 500 && attempt < maxAttempts) {\r\n lastError = new Error(`HTTP ${response.status}`);\r\n } else {\r\n return response;\r\n }\r\n } catch (err) {\r\n lastError = err;\r\n // Caller aborted — give up.\r\n if (callerSignal?.aborted) throw err;\r\n } finally {\r\n clearTimeout(timeoutId);\r\n if (callerSignal && onCallerAbort) {\r\n callerSignal.removeEventListener('abort', onCallerAbort);\r\n }\r\n }\r\n\r\n if (attempt < maxAttempts) {\r\n await sleep(cfg.retryDelay * Math.pow(2, attempt - 1));\r\n }\r\n }\r\n\r\n throw lastError;\r\n}\r\n\r\nexport async function apiGet<T>(\r\n endpoint: string,\r\n options?: RequestInit\r\n): Promise<ApiResponse<T>> {\r\n return apiRequest<T>('GET', endpoint, undefined, options);\r\n}\r\n\r\nexport async function apiPost<T>(\r\n endpoint: string,\r\n body?: unknown,\r\n options?: RequestInit\r\n): Promise<ApiResponse<T>> {\r\n return apiRequest<T>('POST', endpoint, body, options);\r\n}\r\n\r\nexport async function apiPut<T>(\r\n endpoint: string,\r\n body?: unknown,\r\n options?: RequestInit\r\n): Promise<ApiResponse<T>> {\r\n return apiRequest<T>('PUT', endpoint, body, options);\r\n}\r\n\r\nexport async function apiDelete<T>(\r\n endpoint: string,\r\n options?: RequestInit\r\n): Promise<ApiResponse<T>> {\r\n return apiRequest<T>('DELETE', endpoint, undefined, options);\r\n}\r\n\r\nasync function apiRequest<T>(\r\n method: string,\r\n endpoint: string,\r\n body?: unknown,\r\n options?: RequestInit\r\n): Promise<ApiResponse<T>> {\r\n const url = endpoint.startsWith('http')\r\n ? endpoint\r\n : `${getPublicBaseUrl()}${endpoint}`;\r\n\r\n try {\r\n const response = await fetchWithRetry(\r\n url,\r\n {\r\n method,\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...options?.headers,\r\n },\r\n body: body !== undefined ? JSON.stringify(body) : undefined,\r\n credentials: 'include',\r\n ...options,\r\n },\r\n globalConfig\r\n );\r\n\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({}));\r\n const message =\r\n errorData.error || errorData.message || `HTTP ${response.status}`;\r\n globalConfig.onError(new Error(message));\r\n return { success: false, error: message, statusCode: response.status };\r\n }\r\n\r\n const data = await response.json();\r\n return { success: true, data: data as T, statusCode: response.status };\r\n } catch (error) {\r\n const errorMessage =\r\n error instanceof Error\r\n ? error.name === 'AbortError'\r\n ? 'Request timed out'\r\n : error.message\r\n : 'Unknown error';\r\n\r\n globalConfig.onError(\r\n error instanceof Error ? error : new Error(errorMessage)\r\n );\r\n return { success: false, error: errorMessage };\r\n }\r\n}\r\n\r\n/**\r\n * Simple fetch wrapper that returns parsed JSON or null on error.\r\n * Inherits the global timeout + retry policy for GETs.\r\n */\r\nexport async function simpleFetch<T>(\r\n url: string,\r\n options?: RequestInit\r\n): Promise<T | null> {\r\n try {\r\n const response = await fetchWithRetry(\r\n url,\r\n { credentials: 'include', ...options },\r\n globalConfig\r\n );\r\n\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({}));\r\n logger.error(`API request failed: ${response.status}`, errorData);\r\n return null;\r\n }\r\n\r\n return response.json();\r\n } catch (error) {\r\n logger.error('API request error:', error);\r\n return null;\r\n }\r\n}\r\n","import { AppError } from '@getmicdrop/svelte-components';\r\n/**\r\n * Orders API\r\n *\r\n * Functions for managing orders, payments, and reservations\r\n * in the public checkout flow.\r\n */\r\n\r\nimport { createLogger } from '@getmicdrop/svelte-components/utils/logger';\r\nconst logger = createLogger('VC');\r\nimport { getPublicBaseUrl, getOrdersV2Url, simpleFetch, apiPost, apiGet } from './client.js';\r\nimport type {\r\n PaymentIntentResponse,\r\n CompleteReservationResponse,\r\n CancelReservationResponse,\r\n CreateOrderResponse,\r\n ValidatePaymentRequest,\r\n ValidatePaymentResponse,\r\n ExtendSessionResponse,\r\n SessionStatus,\r\n Order,\r\n} from './types.js';\r\n\r\n/**\r\n * Create a payment intent for the cart\r\n *\r\n * This initiates the Stripe payment flow by creating a PaymentIntent\r\n * on the backend. The response includes the client_secret needed\r\n * for Stripe Elements.\r\n *\r\n * @param cartId - The cart/order UUID\r\n * @param quantities - Map of ticketId -> quantity\r\n * @param donationAmounts - Map of ticketId -> donation amount in dollars (for type=2 tickets)\r\n * @returns Payment intent data including client_secret, or null on error\r\n */\r\nexport async function createPaymentIntent(\r\n cartId: string,\r\n quantities: Record<string | number, number>,\r\n donationAmounts?: Record<string | number, number>\r\n): Promise<PaymentIntentResponse | null> {\r\n try {\r\n const apiResult = await apiPost<PaymentIntentResponse>(\r\n `${getOrdersV2Url()}/cart/${cartId}/payment-intent`,\r\n {\r\n productQuantities: quantities,\r\n ...(donationAmounts && Object.keys(donationAmounts).length > 0\r\n ? { donationAmounts }\r\n : {}),\r\n }\r\n );\r\n\r\n if (!apiResult.success) {\r\n logger.error('Payment intent creation failed:', apiResult.error);\r\n throw new AppError(apiResult.error || 'Failed to create payment intent', 'lib/api/orders/createPaymentIntent');\r\n }\r\n\r\n logger.debug('Payment intent created:', apiResult.data);\r\n return apiResult.data!;\r\n } catch (error) {\r\n logger.error('createPaymentIntent error:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Fetch an existing cart by UUID (cross-device pre-fill — §1.3).\r\n *\r\n * Returns the server's authoritative view of a cart so a second device\r\n * visiting the tickets page can see the in-progress reservation it created\r\n * on another device. Returns `null` if:\r\n * - the cart no longer exists (404)\r\n * - the cart belongs to a different event than `expectedEventID` (when\r\n * supplied) — we don't want to mix carts across events\r\n * - the cart status is no longer `reserved` / `active` (e.g. expired,\r\n * completed, abandoned) — caller should treat the local cookie as stale\r\n * - any network/decode failure (caller falls back to localStorage only)\r\n *\r\n * Returned shape matches the orders-service `GET /v2Public/cart/{uuid}`\r\n * response: a Cart model with embedded Reservations.\r\n */\r\nexport interface CartReservationView {\r\n ticketID: number;\r\n quantity: number;\r\n priceAtReservation: number;\r\n status: string;\r\n}\r\nexport interface CartView {\r\n uuid: string;\r\n eventID: number;\r\n status: string;\r\n expiresAt: string;\r\n reservations: CartReservationView[];\r\n}\r\n\r\nexport async function getCartByUUID(\r\n cartUUID: string,\r\n expectedEventID?: string | number\r\n): Promise<CartView | null> {\r\n if (!cartUUID) return null;\r\n try {\r\n type RawCart = {\r\n UUID?: string; uuid?: string;\r\n EventID?: number; eventID?: number;\r\n Status?: string; status?: string;\r\n ExpiresAt?: string; expiresAt?: string;\r\n Reservations?: unknown[]; reservations?: unknown[];\r\n };\r\n const apiResult = await apiGet<RawCart>(\r\n `${getOrdersV2Url()}/cart/${cartUUID}`\r\n );\r\n if (!apiResult.success) {\r\n // 404 / 410 / 5xx — caller treats as stale\r\n return null;\r\n }\r\n const raw = apiResult.data!;\r\n // The orders-service Cart model uses Go-style PascalCase JSON tags\r\n // (UUID, EventID, Status, ExpiresAt, Reservations) on some routes and\r\n // camelCase on the newer v2 routes. Tolerate both.\r\n const uuid: string = raw.UUID ?? raw.uuid ?? '';\r\n const eventID = Number(raw.EventID ?? raw.eventID ?? 0);\r\n const status: string = raw.Status ?? raw.status ?? '';\r\n const expiresAt: string = raw.ExpiresAt ?? raw.expiresAt ?? '';\r\n const rawRes: unknown[] = raw.Reservations ?? raw.reservations ?? [];\r\n const reservations: CartReservationView[] = rawRes.map(r => {\r\n const rec = r as Record<string, unknown>;\r\n return {\r\n ticketID: Number(rec.TicketID ?? rec.ticketID ?? 0),\r\n quantity: Number(rec.Quantity ?? rec.quantity ?? 0),\r\n priceAtReservation: Number(\r\n rec.PriceAtReservation ?? rec.priceAtReservation ?? 0\r\n ),\r\n status: String(rec.Status ?? rec.status ?? ''),\r\n };\r\n });\r\n if (status !== 'reserved' && status !== 'active') {\r\n // stale cart row — caller clears the cookie\r\n return null;\r\n }\r\n if (expectedEventID !== undefined && eventID !== Number(expectedEventID)) {\r\n // cart belongs to a different event — don't mix\r\n return null;\r\n }\r\n return { uuid, eventID, status, expiresAt, reservations };\r\n } catch (err) {\r\n logger.error('getCartByUUID error:', err);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Update cart quantities after the cart already exists.\r\n *\r\n * Replaces all reservations on the cart with the new quantities.\r\n * The orders-service handler releases old reservations (returning\r\n * inventory) and creates new ones (decrementing inventory) atomically.\r\n *\r\n * Use this when the user changes ticket counts AFTER the initial\r\n * cart was created via initiateOrder. The cart UUID is preserved,\r\n * so the timer and extension state stay intact.\r\n *\r\n * @returns true on success, false on failure\r\n */\r\nexport async function updateCartQuantities(\r\n cartId: string,\r\n quantities: Record<string | number, number>,\r\n donationAmounts?: Record<string | number, number>\r\n): Promise<boolean> {\r\n try {\r\n // Convert string keys to numbers (the orders-service handler\r\n // unmarshals into map[uint]int).\r\n const numericQuantities: Record<number, number> = {};\r\n for (const [k, v] of Object.entries(quantities)) {\r\n const n = typeof k === 'number' ? k : parseInt(k, 10);\r\n if (!Number.isNaN(n) && v > 0) numericQuantities[n] = v;\r\n }\r\n const numericDonations: Record<number, number> = {};\r\n if (donationAmounts) {\r\n for (const [k, v] of Object.entries(donationAmounts)) {\r\n const n = typeof k === 'number' ? k : parseInt(k, 10);\r\n if (!Number.isNaN(n) && v > 0) numericDonations[n] = v;\r\n }\r\n }\r\n // @fetch-escape: status-only endpoint — PUT /cart/:id returns an empty 2xx (no JSON body)\r\n // on success; the canonical apiPut runs response.json() unconditionally on 2xx and would\r\n // throw on the empty body, mis-reporting a successful cart update as a failure. Migrate once\r\n // the client tolerates 204/empty bodies.\r\n const response = await fetch(`${getOrdersV2Url()}/cart/${cartId}`, {\r\n method: 'PUT',\r\n headers: { 'Content-Type': 'application/json' },\r\n credentials: 'include',\r\n body: JSON.stringify({\r\n quantities: numericQuantities,\r\n ...(Object.keys(numericDonations).length > 0\r\n ? { donationAmounts: numericDonations }\r\n : {}),\r\n }),\r\n });\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({}));\r\n logger.error('Cart update failed:', errorData);\r\n return false;\r\n }\r\n return true;\r\n } catch (err) {\r\n logger.error('updateCartQuantities error:', err);\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Complete reservation after successful payment\r\n *\r\n * Called after Stripe confirms the payment to finalize the order\r\n * and generate tickets.\r\n *\r\n * @param orderUuid - The order UUID\r\n * @returns Success status and message\r\n */\r\nexport async function completeReservation(\r\n orderUuid: string\r\n): Promise<CompleteReservationResponse> {\r\n try {\r\n const apiResult = await apiPost<{ message?: string }>(\r\n `${getPublicBaseUrl()}/orders/complete/${orderUuid}`\r\n );\r\n\r\n if (!apiResult.success) {\r\n return {\r\n success: false,\r\n error: apiResult.error || 'Failed to complete reservation',\r\n };\r\n }\r\n\r\n return {\r\n success: true,\r\n message: apiResult.data?.message,\r\n };\r\n } catch (error) {\r\n logger.error('Error completing reservation:', error);\r\n return { success: false, error: 'Network error completing reservation' };\r\n }\r\n}\r\n\r\n/**\r\n * Cancel reservation and release tickets back to inventory\r\n *\r\n * Called when user abandons checkout or session expires.\r\n *\r\n * @param orderUuid - The order UUID\r\n * @returns Success status and message\r\n */\r\nexport async function cancelReservation(\r\n orderUuid: string\r\n): Promise<CancelReservationResponse> {\r\n try {\r\n const apiResult = await apiPost<{ message?: string }>(\r\n `${getPublicBaseUrl()}/orders/cancel/${orderUuid}`\r\n );\r\n\r\n if (!apiResult.success) {\r\n return {\r\n success: false,\r\n error: apiResult.error || 'Failed to cancel reservation',\r\n };\r\n }\r\n\r\n return {\r\n success: true,\r\n message: apiResult.data?.message,\r\n };\r\n } catch (error) {\r\n logger.error('Error cancelling reservation:', error);\r\n return { success: false, error: 'Network error cancelling reservation' };\r\n }\r\n}\r\n\r\n/**\r\n * Create a new order/cart\r\n *\r\n * This creates an empty order that can be used for checkout.\r\n * The order UUID is used for all subsequent operations.\r\n *\r\n * @param eventId - The event ID\r\n * @param promoCode - Optional promo code to apply\r\n * @returns The order UUID, or null on error\r\n */\r\nexport async function createOrder(\r\n eventId: string | number,\r\n promoCode?: string\r\n): Promise<CreateOrderResponse | null> {\r\n try {\r\n const apiResult = await apiPost<CreateOrderResponse>(\r\n `${getPublicBaseUrl()}/orders/create`,\r\n { eventID: eventId, promoCode }\r\n );\r\n\r\n if (!apiResult.success) {\r\n logger.error('Create order failed:', apiResult.error);\r\n return null;\r\n }\r\n\r\n return apiResult.data!;\r\n } catch (error) {\r\n logger.error('createOrder error:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Get order details (public, no auth required)\r\n *\r\n * Fetches the order details for displaying on the success page.\r\n *\r\n * @param orderId - The order UUID or ID\r\n * @returns The order details, or null on error\r\n */\r\nexport async function getOrder(orderId: string): Promise<Order | null> {\r\n return simpleFetch<Order>(`${getPublicBaseUrl()}/orders/${orderId}`);\r\n}\r\n\r\n/**\r\n * Validate payment intent and complete the order\r\n *\r\n * This is an alternative to completeReservation that accepts\r\n * additional payment details. Used by micdrop-frontend.\r\n *\r\n * @param cartId - The cart/order UUID\r\n * @param payload - Payment validation payload\r\n * @returns Validation result\r\n */\r\nexport async function validatePaymentIntent(\r\n cartId: string,\r\n payload: ValidatePaymentRequest\r\n): Promise<ValidatePaymentResponse | null> {\r\n try {\r\n const apiResult = await apiPost<{ status?: string; orderUUID?: string; uuid?: string }>(\r\n `${getOrdersV2Url()}/validatePaymentIntent/${cartId}`,\r\n payload\r\n );\r\n\r\n if (!apiResult.success) {\r\n logger.error('Payment validation failed:', apiResult.error);\r\n return {\r\n success: false,\r\n status: 'failed',\r\n error: apiResult.error || 'Payment validation failed',\r\n };\r\n }\r\n\r\n const result = apiResult.data!;\r\n return {\r\n success: true,\r\n status: result.status || 'Payment succeeded',\r\n orderUUID: result.orderUUID || result.uuid,\r\n };\r\n } catch (error) {\r\n logger.error('validatePaymentIntent error:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Extend the checkout session by 15 minutes\r\n *\r\n * Users get a limited number of extensions (typically 2-3).\r\n *\r\n * @param orderUuid - The order UUID\r\n * @returns Extension result with new expiry time\r\n */\r\nexport async function extendCheckoutSession(\r\n orderUuid: string\r\n): Promise<ExtendSessionResponse> {\r\n try {\r\n const apiResult = await apiPost<{ newExpiryTime?: string; remainingExtensions?: number }>(\r\n `${getPublicBaseUrl()}/orders/extend-session`,\r\n { orderUuid }\r\n );\r\n\r\n if (!apiResult.success) {\r\n return {\r\n success: false,\r\n error: apiResult.error || 'Failed to extend session',\r\n statusCode: apiResult.statusCode,\r\n };\r\n }\r\n\r\n const result = apiResult.data!;\r\n return {\r\n success: true,\r\n newExpiryTime: result.newExpiryTime,\r\n remainingExtensions: result.remainingExtensions,\r\n };\r\n } catch (error) {\r\n logger.error('Error extending checkout session:', error);\r\n return { success: false, error: 'Network error extending session' };\r\n }\r\n}\r\n\r\n/**\r\n * Get current session status including expiry time\r\n *\r\n * Used to display countdown timer and check if extensions are available.\r\n *\r\n * @param orderUuid - The order UUID\r\n * @returns Session status including expiry time\r\n */\r\nexport async function getSessionStatus(\r\n orderUuid: string\r\n): Promise<SessionStatus> {\r\n try {\r\n const apiResult = await apiGet<SessionStatus>(\r\n `${getPublicBaseUrl()}/orders/session/${orderUuid}`\r\n );\r\n\r\n if (!apiResult.success) {\r\n return {\r\n error: apiResult.error || 'No active session found',\r\n notFound: apiResult.statusCode === 404,\r\n };\r\n }\r\n\r\n const result = apiResult.data!;\r\n return {\r\n expiresAt: result.expiresAt,\r\n extensionCount: result.extensionCount,\r\n remainingExtensions: result.remainingExtensions,\r\n canExtend: result.canExtend,\r\n reservationCount: result.reservationCount,\r\n };\r\n } catch (error) {\r\n logger.error('Error getting session status:', error);\r\n return { error: 'Network error getting session status' };\r\n }\r\n}\r\n\r\n/**\r\n * Initiate a new order (alias for createOrder)\r\n *\r\n * This function provides backwards compatibility with micdrop-frontend.\r\n * It accepts the same parameters as the legacy initiateOrder function.\r\n *\r\n * @param cartData - Object containing eventID and optional quantities/promoCode\r\n * @returns The order UUID, or null on error\r\n */\r\nexport async function initiateOrder(\r\n cartData: {\r\n eventID: string | number;\r\n promoCode?: string;\r\n quantities?: Record<string | number, number>;\r\n } = {} as any\r\n): Promise<string | null> {\r\n try {\r\n const apiResult = await apiPost<{ uuid?: string }>(\r\n `${getPublicBaseUrl()}/orders/create`,\r\n cartData\r\n );\r\n\r\n if (!apiResult.success) {\r\n logger.error('Order initiation failed:', apiResult.error);\r\n return null;\r\n }\r\n\r\n return apiResult.data?.uuid ?? null;\r\n } catch (error) {\r\n logger.error('initiateOrder error:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Track UTM source for analytics\r\n *\r\n * Records the traffic source (utm_source parameter) for marketing analytics.\r\n *\r\n * @param venueId - The venue ID\r\n * @returns Promise that resolves when tracking is complete\r\n */\r\nexport async function trackUTMSource(venueId: string | number): Promise<void> {\r\n if (typeof window === 'undefined') return;\r\n\r\n const urlParams = new URLSearchParams(window.location.search);\r\n const utmSource = urlParams.get('utm_source') || 'Direct';\r\n\r\n try {\r\n // @fetch-escape: fire-and-forget UTM beacon — GET with no response body consumed; simpleFetch would parse JSON on empty 200 and log false-positive errors\r\n await fetch(\r\n `${getPublicBaseUrl()}/utm/${venueId}/${encodeURIComponent(utmSource)}`\r\n );\r\n } catch (error) {\r\n logger.error('UTM tracking failed:', error);\r\n }\r\n}\r\n","/**\r\n * Promo Codes API\r\n *\r\n * Functions for validating and checking promo codes\r\n * in the public checkout flow.\r\n */\r\n\r\nimport { createLogger } from '@getmicdrop/svelte-components/utils/logger';\r\nconst logger = createLogger('VC');\r\nimport { apiGet, apiPost, getOrdersV2Url } from './client.js';\r\nimport type { PromoValidationResponse, HasPromoCodesResponse } from './types.js';\r\n\r\nconst ORDERS_V2_PUBLIC = () => getOrdersV2Url();\r\n\r\n/**\r\n * Validate a promo code for an event\r\n *\r\n * Checks if a promo code is valid and returns its effects:\r\n * - Discount amount and type\r\n * - Hidden ticket reveal\r\n *\r\n * @param eventId - The event ID\r\n * @param code - The promo code to validate\r\n * @returns Validation result with discount info\r\n */\r\nexport async function validatePromoCode(\r\n eventId: string | number,\r\n code: string\r\n): Promise<PromoValidationResponse> {\r\n try {\r\n if (!code || !code.trim()) {\r\n return { valid: false, error: 'Promo code is required' };\r\n }\r\n\r\n // API uses GET with code in URL path\r\n const encodedCode = encodeURIComponent(code.trim());\r\n const apiResult = await apiGet<PromoValidationResponse>(\r\n `/promo-codes/validate/${eventId}/${encodedCode}`\r\n );\r\n\r\n if (!apiResult.success) {\r\n // 404 = invalid code, other errors are server issues\r\n if (apiResult.statusCode === 404) {\r\n return { valid: false, error: 'Invalid promo code' };\r\n }\r\n return { valid: false, error: 'Failed to validate code' };\r\n }\r\n\r\n const result = apiResult.data!;\r\n return {\r\n valid: result.valid ?? true,\r\n revealHiddenTickets: result.revealHiddenTickets,\r\n revealTicketIds: result.revealTicketIds,\r\n provideDiscount: result.provideDiscount,\r\n discountType: result.discountType,\r\n amount: result.amount,\r\n code: result.code || code,\r\n };\r\n } catch (error) {\r\n logger.error('Error validating promo code:', error);\r\n return { valid: false, error: 'Network error validating code' };\r\n }\r\n}\r\n\r\n/**\r\n * Check if promo codes are available for an event\r\n *\r\n * Used to conditionally show/hide the promo code input field.\r\n *\r\n * @param eventId - The event ID\r\n * @returns Whether promo codes exist for this event\r\n */\r\nexport async function hasPromoCodes(eventId: string | number): Promise<boolean> {\r\n try {\r\n const apiResult = await apiGet<HasPromoCodesResponse>(\r\n `/promo-codes/check/${eventId}`\r\n );\r\n\r\n if (!apiResult.success) {\r\n // If endpoint doesn't exist or errors, default to showing the input\r\n return true;\r\n }\r\n\r\n return apiResult.data!.hasPromoCodes === true;\r\n } catch (error) {\r\n logger.error('Error checking promo codes availability:', error);\r\n // Default to showing promo input if we can't check\r\n return true;\r\n }\r\n}\r\n\r\n/**\r\n * Apply a promo code to a cart\r\n *\r\n * This updates the cart with the promo code discount.\r\n *\r\n * @param cartId - The cart UUID\r\n * @param code - The promo code to apply\r\n * @returns Success status\r\n */\r\nexport async function applyPromoCode(\r\n cartId: string,\r\n code: string\r\n): Promise<{ success: boolean; error?: string }> {\r\n try {\r\n // Backend route: POST /api/orders/v2/public/cart/{uuid}/apply-promo with a\r\n // `promoCode` body (mirrors apply-gift-card). The old path/body\r\n // (/orders/{id}/apply-promo + {code}) matched no route, so the cart's\r\n // DiscountAmount was never set and the buyer was charged full price despite\r\n // the UI showing a discount.\r\n const apiResult = await apiPost(\r\n `${ORDERS_V2_PUBLIC()}/cart/${cartId}/apply-promo`,\r\n { promoCode: code }\r\n );\r\n\r\n if (!apiResult.success) {\r\n return {\r\n success: false,\r\n error: apiResult.error || 'Failed to apply promo code',\r\n };\r\n }\r\n\r\n return { success: true };\r\n } catch (error) {\r\n logger.error('Error applying promo code:', error);\r\n return { success: false, error: 'Network error applying code' };\r\n }\r\n}\r\n\r\n/**\r\n * Remove a promo code from a cart\r\n *\r\n * @param cartId - The cart UUID\r\n * @returns Success status\r\n */\r\nexport async function removePromoCode(\r\n cartId: string\r\n): Promise<{ success: boolean; error?: string }> {\r\n try {\r\n const apiResult = await apiPost(`/orders/${cartId}/remove-promo`);\r\n\r\n if (!apiResult.success) {\r\n return {\r\n success: false,\r\n error: apiResult.error || 'Failed to remove promo code',\r\n };\r\n }\r\n\r\n return { success: true };\r\n } catch (error) {\r\n logger.error('Error removing promo code:', error);\r\n return { success: false, error: 'Network error removing code' };\r\n }\r\n}\r\n","import { AppError } from '@getmicdrop/svelte-components';\r\n/**\r\n * Events API\r\n *\r\n * Functions for fetching event data, tickets, and performers\r\n * in the public checkout flow.\r\n */\r\n\r\nimport { createLogger } from '@getmicdrop/svelte-components/utils/logger';\r\nconst logger = createLogger('VC');\r\nimport { getPublicBaseUrl, simpleFetch, apiPost } from './client.js';\r\nimport type {\r\n Event,\r\n AvailableTicket,\r\n EventPerformersResponse,\r\n SeriesOccurrencesResponse,\r\n SeriesPageData,\r\n PublicCollectionData,\r\n ResolvedEntity,\r\n} from './types.js';\r\n\r\n/**\r\n * In-flight `fetchEventDetails` requests keyed by event ID. Lets\r\n * concurrent callers (Checkout, CartView, EventDetailsView, +page.js\r\n * server load — all of which may run during a single navigation) share\r\n * one HTTP request rather than triggering three.\r\n *\r\n * The entry deletes as soon as the underlying promise settles, so this\r\n * is dedup not cache. For real cache-with-TTL we'd want SWR; that's a\r\n * future milestone.\r\n */\r\nconst _eventDetailsInflight = new Map<string, Promise<Event | null>>();\r\n\r\n/**\r\n * Fetch event details\r\n *\r\n * Gets full event information including venue and ticket data.\r\n *\r\n * @param eventId - The event ID\r\n * @param customFetch - Optional custom fetch function (for SSR)\r\n * @returns Event details or null on error\r\n */\r\nexport async function fetchEventDetails(\r\n eventId: string | number,\r\n customFetch: typeof fetch = fetch\r\n): Promise<Event | null> {\r\n const key = String(eventId);\r\n // Only dedup when using the default fetch — custom-fetch callers\r\n // (e.g. SvelteKit server loads) bring their own request context.\r\n if (customFetch === fetch) {\r\n const inflight = _eventDetailsInflight.get(key);\r\n if (inflight) return inflight;\r\n }\r\n\r\n const run = (async () => {\r\n try {\r\n // @fetch-escape: customFetch injection for SSR context — caller-supplied fetch instance, cannot use simpleFetch\r\n const response = await customFetch(`${getPublicBaseUrl()}/events/${eventId}`);\r\n if (!response.ok) {\r\n throw new AppError(`Failed to fetch event details: ${response.status}`, 'lib/api/events/fetchEventDetails');\r\n }\r\n return await response.json();\r\n } catch (error) {\r\n logger.error('Error fetching event details:', error);\r\n return null;\r\n }\r\n })();\r\n\r\n if (customFetch === fetch) {\r\n _eventDetailsInflight.set(key, run);\r\n run.finally(() => {\r\n // Only clear if this same promise is still the inflight one — a\r\n // later call may have set up a fresh request after the user\r\n // triggered an explicit refresh.\r\n if (_eventDetailsInflight.get(key) === run) {\r\n _eventDetailsInflight.delete(key);\r\n }\r\n });\r\n }\r\n return run;\r\n}\r\n\r\n/**\r\n * Fetch available tickets for an event\r\n *\r\n * Returns all ticket types that are currently available for sale.\r\n *\r\n * @param eventId - The event ID\r\n * @returns Array of available tickets\r\n */\r\nexport async function fetchEventTickets(\r\n eventId: string | number\r\n): Promise<AvailableTicket[]> {\r\n try {\r\n const tickets = await simpleFetch<AvailableTicket[]>(\r\n `${getPublicBaseUrl()}/tickets/event/${eventId}`\r\n );\r\n return Array.isArray(tickets) ? tickets : [];\r\n } catch (error) {\r\n logger.error('Error fetching tickets:', error);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Fetch performers for an event\r\n *\r\n * Returns the lineup with pre-resolved avatar URLs.\r\n *\r\n * @param eventId - The event ID\r\n * @returns Performers list and visibility flag\r\n */\r\nexport async function fetchEventPerformers(\r\n eventId: string | number\r\n): Promise<EventPerformersResponse> {\r\n try {\r\n if (!eventId) {\r\n logger.warn('fetchEventPerformers called without eventId');\r\n return { performers: [], showPerformers: false };\r\n }\r\n\r\n const data = await simpleFetch<EventPerformersResponse>(\r\n `${getPublicBaseUrl()}/events/${eventId}/performers`\r\n );\r\n\r\n if (!data) {\r\n logger.error('Failed to fetch performers: network or server error');\r\n return { performers: [], showPerformers: false };\r\n }\r\n\r\n return {\r\n performers: Array.isArray(data.performers) ? data.performers : [],\r\n showPerformers: data.showPerformers === true,\r\n };\r\n } catch (error) {\r\n logger.error('Error fetching event performers:', error);\r\n return { performers: [], showPerformers: false };\r\n }\r\n}\r\n\r\n/**\r\n * Fetch all venues for an organization\r\n *\r\n * @param orgId - The organization ID\r\n * @returns Array of venues\r\n */\r\nexport async function fetchAllVenues(orgId: string | number): Promise<any[]> {\r\n try {\r\n if (!orgId) {\r\n logger.warn('fetchAllVenues called without orgId');\r\n return [];\r\n }\r\n\r\n const venues = await simpleFetch<any[]>(\r\n `${getPublicBaseUrl()}/venues/organization/${orgId}`\r\n );\r\n\r\n if (!venues) {\r\n logger.error('Failed to fetch venues: network or server error');\r\n return [];\r\n }\r\n\r\n return Array.isArray(venues) ? venues : [];\r\n } catch (error) {\r\n logger.error('Error fetching venues:', error);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Fetch events for a venue\r\n *\r\n * @param venueId - The venue ID\r\n * @returns Array of events\r\n */\r\nexport async function fetchVenueEvents(venueId: string | number): Promise<Event[]> {\r\n try {\r\n if (!venueId) {\r\n logger.warn('fetchVenueEvents called without venueId');\r\n return [];\r\n }\r\n\r\n const events = await simpleFetch<Event[]>(\r\n `${getPublicBaseUrl()}/events/venue/${venueId}`\r\n );\r\n\r\n if (!events) {\r\n logger.error('Failed to fetch venue events: network or server error');\r\n return [];\r\n }\r\n\r\n return Array.isArray(events) ? events : [];\r\n } catch (error) {\r\n logger.error('Error fetching venue events:', error);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Get events for a specific month\r\n *\r\n * Used for calendar views to efficiently load events.\r\n *\r\n * @param venueId - The venue ID\r\n * @param year - The year (e.g., 2024)\r\n * @param month - The month (1-12)\r\n * @returns Array of events for the month\r\n */\r\nexport async function getMonthEvents(\r\n venueId: string | number,\r\n year: number,\r\n month: number\r\n): Promise<Event[]> {\r\n try {\r\n const data = await simpleFetch<{ events?: Event[] } | Event[]>(\r\n `${getPublicBaseUrl()}/events/venue/${venueId}/month/${year}/${month}`\r\n );\r\n\r\n if (!data) {\r\n logger.error('Failed to fetch month events: network or server error');\r\n return [];\r\n }\r\n\r\n if (Array.isArray(data)) return data;\r\n return Array.isArray((data as { events?: Event[] }).events) ? (data as { events: Event[] }).events : [];\r\n } catch (error) {\r\n logger.error('Error fetching month events:', error);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Get events for an organization for a specific month\r\n *\r\n * @param orgId - The organization ID\r\n * @param year - The year (e.g., 2024)\r\n * @param month - The month (1-12)\r\n * @returns Array of events for the month\r\n */\r\nexport async function getOrgMonthEvents(\r\n orgId: string | number,\r\n year: number,\r\n month: number\r\n): Promise<Event[]> {\r\n try {\r\n const data = await simpleFetch<{ events?: Event[] } | Event[]>(\r\n `${getPublicBaseUrl()}/events/organization/${orgId}/month/${year}/${month}`\r\n );\r\n\r\n if (!data) {\r\n logger.error('Failed to fetch org month events: network or server error');\r\n return [];\r\n }\r\n\r\n if (Array.isArray(data)) return data;\r\n return Array.isArray((data as { events?: Event[] }).events) ? (data as { events: Event[] }).events : [];\r\n } catch (error) {\r\n logger.error('Error fetching org month events:', error);\r\n return [];\r\n }\r\n}\r\n\r\n/**\r\n * Get series occurrences for date selector\r\n *\r\n * Returns all instances of a recurring event series.\r\n *\r\n * @param eventSeriesId - The series ID\r\n * @returns Series occurrences\r\n */\r\nexport async function getSeriesOccurrences(\r\n eventSeriesId: number\r\n): Promise<SeriesOccurrencesResponse | null> {\r\n try {\r\n const data = await simpleFetch<SeriesOccurrencesResponse>(\r\n `${getPublicBaseUrl()}/series/${eventSeriesId}/occurrences`\r\n );\r\n\r\n if (!data) {\r\n logger.error('Failed to fetch series occurrences: network or server error');\r\n return null;\r\n }\r\n\r\n return data;\r\n } catch (error) {\r\n logger.error('Error fetching series occurrences:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Fetch series occurrences with CTA state\r\n *\r\n * Returns full series data including availability status.\r\n *\r\n * @param eventSeriesId - The series ID\r\n * @param venueId - The venue ID\r\n * @returns Series occurrences with CTA state\r\n */\r\nexport async function fetchSeriesOccurrences(\r\n eventSeriesId: number,\r\n venueId: string | number\r\n): Promise<SeriesOccurrencesResponse | null> {\r\n try {\r\n const data = await simpleFetch<SeriesOccurrencesResponse>(\r\n `${getPublicBaseUrl()}/series/${eventSeriesId}/occurrences?venueId=${venueId}`\r\n );\r\n\r\n if (!data) {\r\n logger.error('Failed to fetch series with CTA: network or server error');\r\n return null;\r\n }\r\n\r\n return data;\r\n } catch (error) {\r\n logger.error('Error fetching series occurrences:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Resolve an entity-agnostic public id to its concrete type + data.\r\n *\r\n * The embed deep-link (`#{id}-{slug}`) carries no type prefix, so a cold\r\n * deep link (the show isn't in the loaded calendar month) needs the backend\r\n * to say whether the id is an event, series, or collection before the widget\r\n * can render the right view. This is the same `/api/v2/public/resolve/{id}`\r\n * endpoint get-micdrop.com's `/e/{slugId}` page resolves server-side; here we\r\n * call it cross-origin from the venue's page (the public API already serves\r\n * the calendar cross-origin, so CORS is in place).\r\n *\r\n * @param id - The entity id (numeric, type-agnostic)\r\n * @param slug - Optional slug hint (lets the backend canonicalize)\r\n * @returns `{ type, id, title, data }` or null on failure\r\n */\r\nexport async function resolvePublicEntity(\r\n id: string | number,\r\n slug?: string\r\n): Promise<ResolvedEntity | null> {\r\n try {\r\n const qs = slug ? `?slug=${encodeURIComponent(slug)}` : '';\r\n const data = await simpleFetch<ResolvedEntity>(\r\n `${getPublicBaseUrl()}/resolve/${encodeURIComponent(String(id))}${qs}`\r\n );\r\n\r\n if (!data || !data.type) {\r\n throw new AppError(\r\n 'Failed to resolve entity',\r\n 'lib/api/events/resolvePublicEntity'\r\n );\r\n }\r\n\r\n return data;\r\n } catch (error) {\r\n logger.error('Error resolving public entity:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Fetch series page data\r\n *\r\n * Returns full series information including occurrences, venue, and performers.\r\n *\r\n * @param seriesId - The series ID\r\n * @returns Series page data or null on error\r\n */\r\nexport async function fetchSeriesPage(\r\n seriesId: string | number\r\n): Promise<SeriesPageData | null> {\r\n try {\r\n const data = await simpleFetch<SeriesPageData>(\r\n `${getPublicBaseUrl()}/series/${seriesId}/page`\r\n );\r\n\r\n if (!data) {\r\n throw new AppError('Failed to fetch series page', 'lib/api/events/fetchSeriesPage');\r\n }\r\n\r\n return data;\r\n } catch (error) {\r\n logger.error('Error fetching series page:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Fetch public collection data\r\n *\r\n * Returns collection info including events list.\r\n * For password-protected collections, pass the password to authenticate.\r\n *\r\n * @param collectionId - The collection ID\r\n * @param password - Optional password for protected collections\r\n * @returns Collection data or null on error\r\n */\r\nexport async function fetchPublicCollection(\r\n collectionId: string | number,\r\n password?: string\r\n): Promise<PublicCollectionData | null> {\r\n try {\r\n // Backend route is GET /api/v2/public/collections/:id (password via ?password=\r\n // query, read by GetPublicCollection). The previous \"/public\" suffix matched\r\n // no route and 404'd every public collection fetch.\r\n const url = password\r\n ? `${getPublicBaseUrl()}/collections/${collectionId}?password=${encodeURIComponent(password)}`\r\n : `${getPublicBaseUrl()}/collections/${collectionId}`;\r\n\r\n const data = await simpleFetch<PublicCollectionData>(url);\r\n\r\n if (!data) {\r\n throw new AppError('Failed to fetch collection', 'lib/api/events/fetchPublicCollection');\r\n }\r\n\r\n return data;\r\n } catch (error) {\r\n logger.error('Error fetching collection:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Check collection password\r\n *\r\n * Validates password for password-protected collections.\r\n *\r\n * @param collectionId - The collection ID\r\n * @param password - The password to check\r\n * @returns Whether the password is valid\r\n */\r\nexport async function checkCollectionPassword(\r\n collectionId: string | number,\r\n password: string\r\n): Promise<boolean> {\r\n try {\r\n const encodedPassword = encodeURIComponent(password);\r\n const result = await simpleFetch<{ valid: boolean }>(\r\n `${getPublicBaseUrl()}/collections/${collectionId}/check-password/${encodedPassword}`\r\n );\r\n\r\n return result?.valid === true;\r\n } catch (error) {\r\n logger.error('Error checking collection password:', error);\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Check event password\r\n *\r\n * Validates password for password-protected events.\r\n *\r\n * @param eventId - The event ID\r\n * @param password - The password to check\r\n * @returns Whether the password is valid\r\n */\r\nexport async function checkEventPassword(\r\n eventId: string | number,\r\n password: string\r\n): Promise<{ valid: boolean }> {\r\n try {\r\n // POST in the body — never in the URL path, which is captured by\r\n // access logs, browser history, and Referer headers.\r\n const apiResult = await apiPost<{ valid: boolean } | boolean>(\r\n `${getPublicBaseUrl()}/events/${eventId}/check-password`,\r\n { password }\r\n );\r\n\r\n if (!apiResult.success) return { valid: false };\r\n\r\n const result = apiResult.data;\r\n if (typeof result === 'boolean') return { valid: result };\r\n return { valid: (result as { valid: boolean }).valid === true };\r\n } catch (error) {\r\n logger.error('Error checking event password:', error);\r\n return { valid: false };\r\n }\r\n}\r\n\r\n/**\r\n * Test network connection\r\n *\r\n * Health check endpoint for connectivity testing.\r\n *\r\n * @param orgId - Optional org ID\r\n * @param venueId - Optional venue ID\r\n * @returns Whether the connection is working\r\n */\r\nexport async function testNetworkConnection(\r\n orgId?: string | number,\r\n venueId?: string | number\r\n): Promise<boolean> {\r\n try {\r\n // Use a simple endpoint to test connectivity\r\n const url = venueId\r\n ? `${getPublicBaseUrl()}/events/venue/${venueId}`\r\n : orgId\r\n ? `${getPublicBaseUrl()}/venues/organization/${orgId}`\r\n : `${getPublicBaseUrl()}/health`;\r\n\r\n // @fetch-escape: HEAD request for connectivity probe — simpleFetch always parses JSON body; HEAD has no body\r\n const response = await fetch(url, {\r\n method: 'HEAD',\r\n });\r\n\r\n return response.ok;\r\n } catch (error) {\r\n logger.error('Network connection test failed:', error);\r\n return false;\r\n }\r\n}\r\n","/**\r\n * Venues API\r\n *\r\n * Functions for fetching venue data including\r\n * service fees and tax configuration.\r\n */\r\n\r\nimport { createLogger } from '@getmicdrop/svelte-components/utils/logger';\r\nconst logger = createLogger('VC');\r\nimport { apiGet } from './client.js';\r\nimport type { Venue } from './types.js';\r\n\r\n/**\r\n * Get venue details (public, no auth required)\r\n *\r\n * Fetches venue information including service fees and taxes\r\n * needed for checkout calculations.\r\n *\r\n * @param venueId - The venue ID\r\n * @returns Venue details or null on error\r\n */\r\nexport async function getVenue(venueId: string | number): Promise<Venue | null> {\r\n try {\r\n if (!venueId) {\r\n logger.warn('getVenue called without venueId');\r\n return null;\r\n }\r\n\r\n const result = await apiGet<Venue>(`/venues/${venueId}`);\r\n if (!result.success) {\r\n logger.error(`Failed to fetch venue: ${result.statusCode}`);\r\n return null;\r\n }\r\n return result.data ?? null;\r\n } catch (error) {\r\n logger.error('Error fetching venue:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Get venue service fee configuration\r\n *\r\n * Returns just the fee-related fields for checkout calculations.\r\n *\r\n * @param venueId - The venue ID\r\n * @returns Fee configuration or null on error\r\n */\r\nexport async function getVenueFees(\r\n venueId: string | number\r\n): Promise<{\r\n serviceFeePercentage: number;\r\n serviceFeeCents: number;\r\n taxPercentage: number;\r\n} | null> {\r\n const venue = await getVenue(venueId);\r\n\r\n if (!venue) {\r\n return null;\r\n }\r\n\r\n return {\r\n serviceFeePercentage: venue.serviceFeePercentage ?? 0,\r\n serviceFeeCents: venue.serviceFeeCents ?? 0,\r\n taxPercentage: venue.taxPercentage ?? 0,\r\n };\r\n}\r\n\r\n/**\r\n * Get venue by slug\r\n *\r\n * Fetches venue using its URL-friendly slug.\r\n *\r\n * @param slug - The venue slug\r\n * @returns Venue details or null on error\r\n */\r\nexport async function getVenueBySlug(slug: string): Promise<Venue | null> {\r\n try {\r\n if (!slug) {\r\n logger.warn('getVenueBySlug called without slug');\r\n return null;\r\n }\r\n\r\n const encodedSlug = encodeURIComponent(slug);\r\n const result = await apiGet<Venue>(`/venues/slug/${encodedSlug}`);\r\n if (!result.success) {\r\n logger.error(`Failed to fetch venue by slug: ${result.statusCode}`);\r\n return null;\r\n }\r\n return result.data ?? null;\r\n } catch (error) {\r\n logger.error('Error fetching venue by slug:', error);\r\n return null;\r\n }\r\n}\r\n","import { AppError, asVenueId } from '@getmicdrop/svelte-components';\r\nimport type { VenueId } from '@getmicdrop/svelte-components';\r\n/**\r\n * Gift Card Purchase API Client\r\n * Handles gift card purchase creation, cart application/removal,\r\n * and gift-card-only checkout completion.\r\n */\r\n\r\nimport { createLogger } from '@getmicdrop/svelte-components/utils/logger';\r\nimport { getOrdersV2Url, apiPost, apiDelete } from './client.js';\r\nconst logger = createLogger('VC');\r\n\r\nconst API_BASE_URL = 'https://get-micdrop.com';\r\nconst ORDERS_V2_URL = `${API_BASE_URL}/api/orders/v2`;\r\nconst ORDERS_V2_PUBLIC = () => getOrdersV2Url();\r\n\r\n/**\r\n * Request payload for creating a gift card purchase\r\n */\r\nexport interface GiftCardPurchaseRequest {\r\n // Public boundary — accept plain number too so external TypeScript callers\r\n // that pass `venueId: 1` keep compiling. Runtime serializes a number either\r\n // way. Internal call sites pass branded VenueId via asVenueId().\r\n venueId: number | VenueId;\r\n amount: number; // In cents (e.g., 5000 = $50.00)\r\n recipientEmail: string;\r\n recipientName: string;\r\n personalMessage?: string;\r\n purchaserEmail: string;\r\n purchaserName: string;\r\n scheduledDeliveryAt?: string | null; // ISO date string or null for immediate\r\n}\r\n\r\n/**\r\n * Response from gift card purchase creation\r\n */\r\nexport interface GiftCardPurchaseResponse {\r\n giftCardUUID: string;\r\n clientSecret: string;\r\n amount: number;\r\n stripePublishableKey: string;\r\n}\r\n\r\n/**\r\n * Venue information needed for gift card purchase\r\n */\r\nexport interface VenueInfo {\r\n id: VenueId;\r\n name: string;\r\n slug: string;\r\n stripePublishableKey?: string;\r\n}\r\n\r\n/**\r\n * Create a gift card purchase and get Stripe client secret\r\n * @param req - Gift card purchase request details\r\n * @returns Gift card UUID and Stripe client secret, or null on failure\r\n */\r\nexport async function createGiftCardPurchase(\r\n req: GiftCardPurchaseRequest\r\n): Promise<GiftCardPurchaseResponse | null> {\r\n try {\r\n const apiResult = await apiPost<GiftCardPurchaseResponse>(\r\n `${ORDERS_V2_URL}/gift-cards`,\r\n req\r\n );\r\n\r\n if (!apiResult.success) {\r\n logger.error('Gift card purchase creation failed:', apiResult.error);\r\n throw new AppError(apiResult.error || 'Failed to create gift card purchase', 'lib/api/gift-cards/createGiftCardPurchase');\r\n }\r\n\r\n logger.debug('Gift card purchase created:', apiResult.data);\r\n return apiResult.data!;\r\n } catch (error) {\r\n logger.error('Gift card purchase creation error:', error);\r\n return null;\r\n }\r\n}\r\n\r\nexport interface ApplyGiftCardResult {\r\n valid: boolean;\r\n giftCardCode?: string;\r\n giftCardAmount?: number;\r\n giftCardBalance?: number;\r\n paymentType?: string;\r\n stripeAmount?: number;\r\n orderTotal?: number;\r\n requiresStripe?: boolean;\r\n error?: string;\r\n}\r\n\r\n/**\r\n * Apply a gift card to a cart.\r\n */\r\nexport async function applyGiftCard(\r\n cartId: string,\r\n code: string\r\n): Promise<ApplyGiftCardResult> {\r\n try {\r\n const apiResult = await apiPost<ApplyGiftCardResult>(\r\n `${ORDERS_V2_PUBLIC()}/cart/${cartId}/apply-gift-card`,\r\n { giftCardCode: code }\r\n );\r\n\r\n if (!apiResult.success) {\r\n if (apiResult.statusCode === 429) {\r\n return {\r\n valid: false,\r\n error: 'Too many attempts. Please wait a moment and try again.',\r\n };\r\n }\r\n logger.error('Apply gift card failed:', apiResult.error);\r\n return { valid: false, error: apiResult.error || 'Invalid gift card code' };\r\n }\r\n\r\n const data = apiResult.data!;\r\n return {\r\n valid: true,\r\n giftCardCode: data.giftCardCode,\r\n giftCardAmount: data.giftCardAmount,\r\n giftCardBalance: data.giftCardBalance,\r\n paymentType: data.paymentType,\r\n stripeAmount: data.stripeAmount,\r\n orderTotal: data.orderTotal,\r\n requiresStripe: data.requiresStripe,\r\n };\r\n } catch (err) {\r\n logger.error('applyGiftCard error:', err);\r\n return {\r\n valid: false,\r\n error: 'Network error. Please check your connection and try again.',\r\n };\r\n }\r\n}\r\n\r\nexport interface RemoveGiftCardResult {\r\n success: boolean;\r\n error?: string;\r\n}\r\n\r\n/**\r\n * Remove a gift card from a cart.\r\n */\r\nexport async function removeGiftCard(cartId: string): Promise<RemoveGiftCardResult> {\r\n try {\r\n const apiResult = await apiDelete(`${ORDERS_V2_PUBLIC()}/cart/${cartId}/gift-card`);\r\n\r\n if (!apiResult.success) {\r\n logger.error('Remove gift card failed:', apiResult.error);\r\n return { success: false, error: apiResult.error || 'Failed to remove gift card' };\r\n }\r\n\r\n return { success: true };\r\n } catch (err) {\r\n logger.error('removeGiftCard error:', err);\r\n return {\r\n success: false,\r\n error: 'Network error. Please check your connection and try again.',\r\n };\r\n }\r\n}\r\n\r\nexport interface CompleteGiftCardPaymentInput {\r\n firstName: string;\r\n lastName: string;\r\n email: string;\r\n phoneNumber?: string | null;\r\n mailingList?: boolean;\r\n}\r\n\r\nexport interface CompleteGiftCardPaymentResult {\r\n success: boolean;\r\n orderId?: string;\r\n confirmationNumber?: string;\r\n error?: string;\r\n}\r\n\r\n/**\r\n * Complete a gift-card-only payment (no Stripe required when balance >= total).\r\n */\r\nexport async function completeGiftCardPayment(\r\n cartId: string,\r\n customerDetails: CompleteGiftCardPaymentInput\r\n): Promise<CompleteGiftCardPaymentResult> {\r\n try {\r\n const apiResult = await apiPost<{ orderId?: string; confirmationNumber?: string }>(\r\n `${ORDERS_V2_PUBLIC()}/cart/${cartId}/complete-gift-card-payment`,\r\n {\r\n firstName: customerDetails.firstName,\r\n lastName: customerDetails.lastName,\r\n email: customerDetails.email,\r\n phoneNumber: customerDetails.phoneNumber || null,\r\n mailingList: customerDetails.mailingList || false,\r\n }\r\n );\r\n\r\n if (!apiResult.success) {\r\n logger.error('Complete gift card payment failed:', apiResult.error);\r\n return { success: false, error: apiResult.error || 'Failed to complete payment' };\r\n }\r\n\r\n return {\r\n success: true,\r\n orderId: apiResult.data?.orderId,\r\n confirmationNumber: apiResult.data?.confirmationNumber,\r\n };\r\n } catch (err) {\r\n logger.error('completeGiftCardPayment error:', err);\r\n return {\r\n success: false,\r\n error: 'Network error. Please check your connection and try again.',\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Fetch venue information by slug\r\n * @param slug - Venue slug\r\n * @returns Venue info or null on failure\r\n */\r\nexport async function getVenueBySlug(\r\n slug: string,\r\n customFetch: typeof fetch = fetch\r\n): Promise<VenueInfo | null> {\r\n try {\r\n // @fetch-escape: customFetch injection for SSR context — cannot use apiGet (caller-supplied fetch instance)\r\n const response = await customFetch(\r\n `${API_BASE_URL}/api/v2/public/venues/slug/${slug}`\r\n );\r\n\r\n if (!response.ok) {\r\n logger.error(`Failed to fetch venue by slug: ${response.status}`);\r\n return null;\r\n }\r\n\r\n const venue = await response.json();\r\n return {\r\n id: asVenueId(venue.id),\r\n name: venue.name,\r\n slug: venue.slug,\r\n stripePublishableKey: venue.stripePublishableKey,\r\n };\r\n } catch (error) {\r\n logger.error('Error fetching venue by slug:', error);\r\n return null;\r\n }\r\n}\r\n","/**\r\n * Waitlist API\r\n *\r\n * Endpoints for the sold-out-event waitlist flow.\r\n */\r\n\r\nimport { createLogger } from '@getmicdrop/svelte-components/utils/logger';\r\nimport { apiPost, apiGet } from './client.js';\r\n\r\nconst logger = createLogger('VC');\r\n\r\nexport interface JoinWaitlistResult {\r\n success: boolean;\r\n // No position — opaque to the customer (decision #2/#20).\r\n updated?: boolean;\r\n error?: string;\r\n}\r\n\r\nconst WAITLIST_ERROR_MESSAGES: Record<string, string> = {\r\n waitlist_not_enabled: 'Waitlist is not available for this event',\r\n event_not_found: 'Event not found',\r\n invalid_phone: 'Please enter a valid phone number',\r\n already_purchased: 'You have already purchased tickets for this event',\r\n phone_already_registered: 'This phone number is already on the waitlist',\r\n};\r\n\r\n/**\r\n * Join the waitlist for a sold-out event.\r\n */\r\nexport async function joinWaitlist(\r\n eventId: string | number,\r\n email: string,\r\n phone: string | null = null,\r\n smsOptIn = false\r\n): Promise<JoinWaitlistResult> {\r\n try {\r\n const body: Record<string, unknown> = { email };\r\n if (phone && smsOptIn) {\r\n body.phone = phone;\r\n body.smsOptIn = true;\r\n }\r\n\r\n const apiResult = await apiPost<{ updated?: boolean }>(\r\n `/events/${eventId}/waitlist`,\r\n body\r\n );\r\n\r\n if (!apiResult.success) {\r\n logger.error('Join waitlist failed:', apiResult.error);\r\n return {\r\n success: false,\r\n error:\r\n WAITLIST_ERROR_MESSAGES[apiResult.error ?? ''] ||\r\n 'Failed to join waitlist. Please try again.',\r\n };\r\n }\r\n\r\n return {\r\n success: true,\r\n updated: apiResult.data?.updated,\r\n };\r\n } catch (err) {\r\n logger.error('joinWaitlist error:', err);\r\n return {\r\n success: false,\r\n error: 'Network error. Please check your connection and try again.',\r\n };\r\n }\r\n}\r\n\r\nexport interface WaitlistStatusResult {\r\n waitlistEnabled: boolean;\r\n soldOut: boolean;\r\n /**\r\n * When gated, the public event page should present \"Sold Out — join the\r\n * waitlist\" to non-members even if tickets are technically available, and only\r\n * a valid tokenized link unlocks checkout (reconciled decision #3).\r\n */\r\n gated: boolean;\r\n}\r\n\r\n/**\r\n * Fetch an event's waitlist gating status. Returns a non-gated default if the\r\n * request fails so the page degrades to normal behavior.\r\n */\r\nexport async function getWaitlistStatus(\r\n eventId: string | number\r\n): Promise<WaitlistStatusResult> {\r\n const fallback: WaitlistStatusResult = {\r\n waitlistEnabled: false,\r\n soldOut: false,\r\n gated: false,\r\n };\r\n try {\r\n const apiResult = await apiGet<{ waitlistEnabled: boolean; soldOut: boolean; gated: boolean }>(\r\n `/events/${eventId}/waitlist/status`\r\n );\r\n if (!apiResult.success) return fallback;\r\n return {\r\n waitlistEnabled: !!apiResult.data?.waitlistEnabled,\r\n soldOut: !!apiResult.data?.soldOut,\r\n gated: !!apiResult.data?.gated,\r\n };\r\n } catch (err) {\r\n logger.error('getWaitlistStatus error:', err);\r\n return fallback;\r\n }\r\n}\r\n","/**\r\n * CTA state computation.\r\n *\r\n * Pure function (no I/O) — derives the buy-button state from an event and\r\n * its ticket list. Lives in `api/` because it is the canonical, single\r\n * source of truth that replaces the duplicate implementations previously\r\n * scattered across utils/api.js, core/api-client.js, and a few components.\r\n */\r\n\r\n// Import from the specific subpath (not the bare entry) so the api/\r\n// bundle doesn't pull in the entire SC component graph (Accordion etc.)\r\n// and break `npm run build:api`.\r\nimport {\r\n formatDateRaw,\r\n formatTime,\r\n} from '@getmicdrop/svelte-components/utils/formatters';\r\n\r\nexport interface CtaStateOptions {\r\n cancelled?: boolean;\r\n isRegistration?: boolean;\r\n waitlistEnabled?: boolean;\r\n}\r\n\r\nexport interface CtaState {\r\n text: string;\r\n disabled: boolean;\r\n reason:\r\n | 'cancelled'\r\n | 'event_past'\r\n | 'no_tickets'\r\n | 'available'\r\n | 'coming_soon'\r\n | 'sold_out_waitlist'\r\n | 'sold_out'\r\n | 'sales_ended'\r\n | 'hidden_only';\r\n}\r\n\r\ninterface CtaEvent {\r\n startDateTime?: string | null;\r\n endDateTime?: string | null;\r\n hasPurchasableHiddenTickets?: boolean;\r\n}\r\n\r\ninterface CtaTicket {\r\n salesChannel?: number;\r\n salesBegin?: string | null;\r\n salesStart?: string | null;\r\n saleBegin?: string | null;\r\n onSaleStart?: string | null;\r\n salesEnd?: string | null;\r\n saleEnd?: string | null;\r\n onSaleEnd?: string | null;\r\n remainingCapacity?: number | null;\r\n quantityRemaining?: number | null;\r\n quantity?: number | null;\r\n soldOut?: boolean;\r\n isHidden?: boolean;\r\n visibility?: number;\r\n}\r\n\r\n// A hidden ticket (visibility>=2 or isHidden) that's still on sale drives the\r\n// \"Sales ended\" / \"Sold out\" / \"No tickets\" → \"Get tickets\" override. The user\r\n// just needs the promo code to see it.\r\nexport function isHiddenTicketPurchasable(ticket: CtaTicket): boolean {\r\n if (!ticket) return false;\r\n const isHidden =\r\n ticket.isHidden === true ||\r\n (typeof ticket.visibility === 'number' && ticket.visibility >= 2);\r\n if (!isHidden) return false;\r\n if (ticket.salesChannel === 2) return false;\r\n\r\n const now = new Date();\r\n const salesBegin =\r\n ticket.salesBegin ||\r\n ticket.salesStart ||\r\n ticket.saleBegin ||\r\n ticket.onSaleStart;\r\n const salesEnd = ticket.salesEnd || ticket.saleEnd || ticket.onSaleEnd;\r\n if (salesBegin && new Date(salesBegin) > now) return false;\r\n if (salesEnd && new Date(salesEnd) < now) return false;\r\n\r\n const remaining =\r\n ticket.remainingCapacity ?? ticket.quantityRemaining ?? ticket.quantity;\r\n const isSoldOut =\r\n ticket.soldOut ||\r\n (remaining !== null && remaining !== undefined && remaining <= 0);\r\n if (isSoldOut) return false;\r\n\r\n return true;\r\n}\r\n\r\nexport function computeCtaState(\r\n event: CtaEvent,\r\n tickets: CtaTicket[] | undefined,\r\n options: CtaStateOptions = {}\r\n): CtaState {\r\n const {\r\n cancelled = false,\r\n isRegistration = false,\r\n waitlistEnabled = false,\r\n } = options;\r\n const now = new Date();\r\n\r\n if (cancelled)\r\n return { text: 'Cancelled', disabled: true, reason: 'cancelled' };\r\n\r\n const eventEnd = event.endDateTime || event.startDateTime;\r\n if (eventEnd && new Date(eventEnd) < now) {\r\n return { text: 'Sales ended', disabled: true, reason: 'event_past' };\r\n }\r\n\r\n const hiddenAvailable =\r\n event?.hasPurchasableHiddenTickets === true ||\r\n (Array.isArray(tickets) && tickets.some(isHiddenTicketPurchasable));\r\n\r\n const publicTickets = (tickets || []).filter(\r\n t =>\r\n t.salesChannel !== 2 &&\r\n !t.isHidden &&\r\n !(typeof t.visibility === 'number' && t.visibility >= 2)\r\n );\r\n if (publicTickets.length === 0) {\r\n if (hiddenAvailable) {\r\n return {\r\n text: isRegistration ? 'Reserve a spot' : 'Get tickets',\r\n disabled: false,\r\n reason: 'hidden_only',\r\n };\r\n }\r\n return {\r\n text: 'No tickets available',\r\n disabled: true,\r\n reason: 'no_tickets',\r\n };\r\n }\r\n\r\n let hasPurchasable = false;\r\n let allSoldOut = true;\r\n let allComingSoon = true;\r\n let earliestSalesStart: Date | null = null;\r\n\r\n for (const ticket of publicTickets) {\r\n const salesBegin =\r\n ticket.salesBegin ||\r\n ticket.salesStart ||\r\n ticket.saleBegin ||\r\n ticket.onSaleStart;\r\n const salesEnd = ticket.salesEnd || ticket.saleEnd || ticket.onSaleEnd;\r\n const remaining =\r\n ticket.remainingCapacity ?? ticket.quantityRemaining ?? ticket.quantity;\r\n const isSoldOut =\r\n ticket.soldOut ||\r\n (remaining !== null && remaining !== undefined && remaining <= 0);\r\n\r\n const isScheduled = salesBegin ? new Date(salesBegin) > now : false;\r\n const hasSalesEnded = salesEnd ? new Date(salesEnd) < now : false;\r\n const isPurchasable = !isSoldOut && !isScheduled && !hasSalesEnded;\r\n\r\n if (isPurchasable) hasPurchasable = true;\r\n if (!isSoldOut) allSoldOut = false;\r\n if (!isScheduled) allComingSoon = false;\r\n\r\n if (isScheduled && salesBegin && !isSoldOut && !hasSalesEnded) {\r\n const startDate = new Date(salesBegin);\r\n if (!earliestSalesStart || startDate < earliestSalesStart) {\r\n earliestSalesStart = startDate;\r\n }\r\n }\r\n }\r\n\r\n if (hasPurchasable) {\r\n return {\r\n text: isRegistration ? 'Reserve a spot' : 'Get tickets',\r\n disabled: false,\r\n reason: 'available',\r\n };\r\n }\r\n\r\n if (allComingSoon && earliestSalesStart) {\r\n if (hiddenAvailable) {\r\n return {\r\n text: isRegistration ? 'Reserve a spot' : 'Get tickets',\r\n disabled: false,\r\n reason: 'hidden_only',\r\n };\r\n }\r\n const diffMs = earliestSalesStart.getTime() - now.getTime();\r\n const diffHours = diffMs / (1000 * 60 * 60);\r\n const diffDays = diffMs / (1000 * 60 * 60 * 24);\r\n let dateText: string;\r\n if (diffHours < 24) {\r\n dateText = formatTime(earliestSalesStart, { hour12: true }, 'en-US');\r\n } else if (diffDays <= 7) {\r\n dateText = formatDateRaw(\r\n earliestSalesStart,\r\n { weekday: 'short', hour: 'numeric', minute: '2-digit', hour12: true },\r\n 'en-US'\r\n );\r\n } else {\r\n const d = formatDateRaw(\r\n earliestSalesStart,\r\n { month: 'short', day: 'numeric' },\r\n 'en-US'\r\n );\r\n const t = formatTime(earliestSalesStart, { hour12: true }, 'en-US');\r\n dateText = `${d} ${t}`;\r\n }\r\n return {\r\n text: `On sale ${dateText}`,\r\n disabled: true,\r\n reason: 'coming_soon',\r\n };\r\n }\r\n\r\n if (allSoldOut) {\r\n if (hiddenAvailable) {\r\n return {\r\n text: isRegistration ? 'Reserve a spot' : 'Get tickets',\r\n disabled: false,\r\n reason: 'hidden_only',\r\n };\r\n }\r\n if (waitlistEnabled) {\r\n return {\r\n text: 'Join Waitlist',\r\n disabled: false,\r\n reason: 'sold_out_waitlist',\r\n };\r\n }\r\n return { text: 'Sold out', disabled: true, reason: 'sold_out' };\r\n }\r\n\r\n if (hiddenAvailable) {\r\n return {\r\n text: isRegistration ? 'Reserve a spot' : 'Get tickets',\r\n disabled: false,\r\n reason: 'hidden_only',\r\n };\r\n }\r\n\r\n return { text: 'Sales ended', disabled: true, reason: 'sales_ended' };\r\n}\r\n","import type { USD } from '@getmicdrop/svelte-components';\r\nimport { formatCurrency } from '@getmicdrop/svelte-components';\r\n/**\r\n * Order Transformer\r\n *\r\n * Normalizes API order responses to a consistent format.\r\n * Handles variations in field names between different API versions.\r\n */\r\n\r\nimport type { Order, PurchasedTicket } from '../types.js';\r\n\r\n/**\r\n * Raw API order response (may have varying field names)\r\n */\r\ninterface ApiOrder {\r\n uuid?: string;\r\n id?: number;\r\n ID?: number;\r\n customerEmail?: string;\r\n email?: string;\r\n customer_email?: string;\r\n customerFirstName?: string;\r\n firstName?: string;\r\n first_name?: string;\r\n customerLastName?: string;\r\n lastName?: string;\r\n last_name?: string;\r\n status?: string;\r\n totalAmount?: number;\r\n total?: number;\r\n total_amount?: number;\r\n subtotal?: number;\r\n serviceFeesAmount?: number;\r\n serviceFee?: number;\r\n service_fee?: number;\r\n service_fees_amount?: number;\r\n taxAmount?: number;\r\n tax?: number;\r\n tax_amount?: number;\r\n discount?: number;\r\n paymentIntentId?: string;\r\n payment_intent_id?: string;\r\n paymentMethod?: string;\r\n payment_method?: string;\r\n purchasedTickets?: any[];\r\n tickets?: any[];\r\n purchased_tickets?: any[];\r\n createdAt?: string;\r\n created_at?: string;\r\n updatedAt?: string;\r\n updated_at?: string;\r\n}\r\n\r\n/**\r\n * Raw API ticket response\r\n */\r\ninterface ApiTicket {\r\n uuid?: string;\r\n id?: number;\r\n ID?: number;\r\n ticketNumber?: string;\r\n ticket_number?: string;\r\n orderId?: string | number;\r\n order_id?: string | number;\r\n attendeeFirstName?: string;\r\n attendee_first_name?: string;\r\n firstName?: string;\r\n attendeeLastName?: string;\r\n attendee_last_name?: string;\r\n lastName?: string;\r\n attendeeEmail?: string;\r\n attendee_email?: string;\r\n email?: string;\r\n ticketName?: string;\r\n ticket_name?: string;\r\n name?: string;\r\n ticketTypeId?: number;\r\n ticket_type_id?: number;\r\n purchasePrice?: number;\r\n purchase_price?: number;\r\n price?: number;\r\n status?: string;\r\n checkedIn?: boolean;\r\n checked_in?: boolean;\r\n checkedInAt?: string;\r\n checked_in_at?: string;\r\n}\r\n\r\n/**\r\n * Transform a raw API ticket to normalized PurchasedTicket\r\n */\r\nexport function transformTicket(apiTicket: ApiTicket): PurchasedTicket {\r\n return {\r\n uuid: apiTicket.uuid || String(apiTicket.id || apiTicket.ID || ''),\r\n id: apiTicket.id || apiTicket.ID,\r\n ticketNumber: apiTicket.ticketNumber || apiTicket.ticket_number,\r\n orderId: apiTicket.orderId || apiTicket.order_id,\r\n attendeeFirstName:\r\n apiTicket.attendeeFirstName ||\r\n apiTicket.attendee_first_name ||\r\n apiTicket.firstName,\r\n attendeeLastName:\r\n apiTicket.attendeeLastName ||\r\n apiTicket.attendee_last_name ||\r\n apiTicket.lastName,\r\n attendeeEmail:\r\n apiTicket.attendeeEmail || apiTicket.attendee_email || apiTicket.email,\r\n ticketName:\r\n apiTicket.ticketName || apiTicket.ticket_name || apiTicket.name || '',\r\n ticketTypeId: apiTicket.ticketTypeId || apiTicket.ticket_type_id,\r\n purchasePrice:\r\n apiTicket.purchasePrice ||\r\n apiTicket.purchase_price ||\r\n apiTicket.price ||\r\n 0,\r\n status: apiTicket.status,\r\n checkedIn: apiTicket.checkedIn || apiTicket.checked_in,\r\n checkedInAt: apiTicket.checkedInAt || apiTicket.checked_in_at,\r\n };\r\n}\r\n\r\n/**\r\n * Transform a raw API order to normalized Order\r\n *\r\n * Handles various field name patterns:\r\n * - camelCase (customerEmail)\r\n * - snake_case (customer_email)\r\n * - Shortened names (email)\r\n */\r\nexport function transformOrder(apiOrder: ApiOrder): Order {\r\n // Extract tickets array from various possible field names\r\n const rawTickets =\r\n apiOrder.purchasedTickets ||\r\n apiOrder.tickets ||\r\n apiOrder.purchased_tickets ||\r\n [];\r\n\r\n return {\r\n uuid: apiOrder.uuid || String(apiOrder.id || apiOrder.ID || ''),\r\n id: apiOrder.id || apiOrder.ID,\r\n customerEmail:\r\n apiOrder.customerEmail ||\r\n apiOrder.email ||\r\n apiOrder.customer_email ||\r\n '',\r\n customerFirstName:\r\n apiOrder.customerFirstName ||\r\n apiOrder.firstName ||\r\n apiOrder.first_name,\r\n customerLastName:\r\n apiOrder.customerLastName ||\r\n apiOrder.lastName ||\r\n apiOrder.last_name,\r\n status: apiOrder.status || 'unknown',\r\n totalAmount:\r\n apiOrder.totalAmount ||\r\n apiOrder.total ||\r\n apiOrder.total_amount ||\r\n 0,\r\n subtotal: apiOrder.subtotal,\r\n serviceFeesAmount:\r\n apiOrder.serviceFeesAmount ||\r\n apiOrder.serviceFee ||\r\n apiOrder.service_fee ||\r\n apiOrder.service_fees_amount ||\r\n 0,\r\n taxAmount:\r\n apiOrder.taxAmount || apiOrder.tax || apiOrder.tax_amount || 0,\r\n discount: apiOrder.discount || 0,\r\n paymentIntentId:\r\n apiOrder.paymentIntentId || apiOrder.payment_intent_id,\r\n paymentMethod: apiOrder.paymentMethod || apiOrder.payment_method,\r\n purchasedTickets: rawTickets.map(transformTicket),\r\n createdAt: apiOrder.createdAt || apiOrder.created_at,\r\n updatedAt: apiOrder.updatedAt || apiOrder.updated_at,\r\n };\r\n}\r\n\r\n/**\r\n * Transform order for display on success page\r\n *\r\n * Returns a simplified object with display-ready values.\r\n */\r\nexport function transformOrderForDisplay(apiOrder: ApiOrder): {\r\n orderId: string;\r\n displayOrderId: string;\r\n email: string;\r\n customerName: string;\r\n total: number;\r\n formattedTotal: string;\r\n ticketCount: number;\r\n status: string;\r\n} {\r\n const order = transformOrder(apiOrder);\r\n const displayId = order.uuid.split('-')[0] || order.uuid;\r\n\r\n return {\r\n orderId: order.uuid,\r\n displayOrderId: displayId,\r\n email: order.customerEmail,\r\n customerName: [order.customerFirstName, order.customerLastName]\r\n .filter(Boolean)\r\n .join(' '),\r\n total: order.totalAmount,\r\n formattedTotal: `${formatCurrency((order.totalAmount / 100) as USD /* FIXME(canonical-cleanup:toFixed): this cast bypasses the brand boundary; replace with toCents/toUSD at the API-response-transform layer. */)}`,\r\n ticketCount: order.purchasedTickets.length,\r\n status: order.status,\r\n };\r\n}\r\n","/**\r\n * Event Transformer\r\n *\r\n * Normalizes API event responses to a consistent format.\r\n * Handles image URL resolution and CTA state calculation.\r\n */\r\n\r\nimport type { Event, AvailableTicket } from '../types.js';\r\n\r\n// CDN base URL for images\r\nconst CDN_BASE_URL = 'https://micdrop-images.sfo3.digitaloceanspaces.com';\r\n\r\n/**\r\n * Raw API event response (may have varying field names)\r\n */\r\ninterface ApiEvent {\r\n eventID?: number;\r\n id?: number;\r\n ID?: number;\r\n name?: string;\r\n title?: string;\r\n slug?: string;\r\n description?: string;\r\n date?: string;\r\n startDateTime?: string;\r\n start_date_time?: string;\r\n endDateTime?: string;\r\n end_date_time?: string;\r\n doorsOpenTime?: string;\r\n doors_open_time?: string;\r\n timezone?: string;\r\n time_zone?: string;\r\n venueId?: number;\r\n venue_id?: number;\r\n venueName?: string;\r\n venue_name?: string;\r\n venueAddress?: string;\r\n venue_address?: string;\r\n location?: string;\r\n imageUrl?: string;\r\n imageURL?: string;\r\n image_url?: string;\r\n image?: string;\r\n status?: string;\r\n isPublished?: boolean;\r\n is_published?: boolean;\r\n isCancelled?: boolean;\r\n is_cancelled?: boolean;\r\n availableTickets?: any[];\r\n available_tickets?: any[];\r\n tickets?: any[];\r\n ticketsAvailable?: number;\r\n tickets_available?: number;\r\n ticketsSold?: number;\r\n tickets_sold?: number;\r\n minPrice?: number;\r\n min_price?: number;\r\n maxPrice?: number;\r\n max_price?: number;\r\n ctaText?: string;\r\n cta_text?: string;\r\n ctaState?: string;\r\n cta_state?: string;\r\n showPerformers?: boolean;\r\n show_performers?: boolean;\r\n eventSeriesId?: number;\r\n event_series_id?: number;\r\n seriesInstanceNumber?: number;\r\n series_instance_number?: number;\r\n}\r\n\r\n/**\r\n * Get CDN image URL\r\n *\r\n * Prepends the CDN base URL if the path is relative.\r\n */\r\nexport function getCDNImageUrl(path: string | undefined): string {\r\n if (!path) return '';\r\n if (path.startsWith('http')) return path;\r\n return `${CDN_BASE_URL}/${path.replace(/^\\//, '')}`;\r\n}\r\n\r\n/**\r\n * Extract image URL from event with fallbacks\r\n */\r\nexport function getEventImageUrl(apiEvent: ApiEvent): string {\r\n const rawUrl =\r\n apiEvent.imageUrl ||\r\n apiEvent.imageURL ||\r\n apiEvent.image_url ||\r\n apiEvent.image ||\r\n '';\r\n\r\n return getCDNImageUrl(rawUrl);\r\n}\r\n\r\n/**\r\n * Calculate CTA state based on ticket availability\r\n */\r\nexport function calculateCtaState(\r\n apiEvent: ApiEvent\r\n): 'available' | 'sold_out' | 'coming_soon' | 'ended' {\r\n // Check explicit CTA state first\r\n const explicitState = apiEvent.ctaState || apiEvent.cta_state;\r\n if (explicitState) {\r\n return explicitState as any;\r\n }\r\n\r\n // Check if event is cancelled or ended\r\n if (apiEvent.isCancelled || apiEvent.is_cancelled) {\r\n return 'ended';\r\n }\r\n\r\n // Check event date\r\n const eventDate = apiEvent.startDateTime || apiEvent.start_date_time || apiEvent.date;\r\n if (eventDate) {\r\n const eventTime = new Date(eventDate).getTime();\r\n const now = Date.now();\r\n\r\n if (eventTime < now) {\r\n return 'ended';\r\n }\r\n }\r\n\r\n // Check ticket availability\r\n const availableCount =\r\n apiEvent.ticketsAvailable ?? apiEvent.tickets_available;\r\n\r\n if (availableCount !== undefined) {\r\n if (availableCount <= 0) {\r\n return 'sold_out';\r\n }\r\n return 'available';\r\n }\r\n\r\n // Check tickets array\r\n const tickets =\r\n apiEvent.availableTickets ||\r\n apiEvent.available_tickets ||\r\n apiEvent.tickets ||\r\n [];\r\n\r\n if (tickets.length === 0) {\r\n return 'coming_soon';\r\n }\r\n\r\n const totalAvailable = tickets.reduce((sum: number, t: any) => {\r\n const qty =\r\n t.quantityAvailable ?? t.quantity_available ?? t.quantity ?? 0;\r\n const sold = t.quantitySold ?? t.quantity_sold ?? 0;\r\n return sum + Math.max(0, qty - sold);\r\n }, 0);\r\n\r\n if (totalAvailable <= 0) {\r\n return 'sold_out';\r\n }\r\n\r\n return 'available';\r\n}\r\n\r\n/**\r\n * Transform a raw API ticket to normalized AvailableTicket\r\n */\r\nexport function transformTicket(apiTicket: any): AvailableTicket {\r\n return {\r\n id: apiTicket.id || apiTicket.ID,\r\n name: apiTicket.name || apiTicket.ticketName || '',\r\n description: apiTicket.description,\r\n price: apiTicket.price || 0,\r\n quantity: apiTicket.quantity || apiTicket.totalQuantity || 0,\r\n quantitySold: apiTicket.quantitySold || apiTicket.quantity_sold || 0,\r\n quantityAvailable:\r\n apiTicket.quantityAvailable ||\r\n apiTicket.quantity_available ||\r\n (apiTicket.quantity || 0) - (apiTicket.quantitySold || 0),\r\n minPerOrder: apiTicket.minPerOrder || apiTicket.min_per_order || 1,\r\n maxPerOrder: apiTicket.maxPerOrder || apiTicket.max_per_order || 10,\r\n saleStartDate: apiTicket.saleStartDate || apiTicket.sale_start_date,\r\n saleEndDate: apiTicket.saleEndDate || apiTicket.sale_end_date,\r\n isHidden: apiTicket.isHidden || apiTicket.is_hidden || false,\r\n revealWithPromoCode:\r\n apiTicket.revealWithPromoCode || apiTicket.reveal_with_promo_code,\r\n ticketType: apiTicket.ticketType || apiTicket.ticket_type || 0,\r\n sectionId: apiTicket.sectionId || apiTicket.section_id,\r\n sortOrder: apiTicket.sortOrder || apiTicket.sort_order || 0,\r\n };\r\n}\r\n\r\n/**\r\n * Transform a raw API event to normalized Event\r\n */\r\nexport function transformEvent(apiEvent: ApiEvent): Event {\r\n // Extract tickets array from various possible field names\r\n const rawTickets =\r\n apiEvent.availableTickets ||\r\n apiEvent.available_tickets ||\r\n apiEvent.tickets ||\r\n [];\r\n\r\n const tickets = rawTickets.map(transformTicket);\r\n\r\n // Calculate min/max prices from tickets\r\n const prices = tickets.map((t) => t.price).filter((p) => p > 0);\r\n const minPrice = prices.length > 0 ? Math.min(...prices) : undefined;\r\n const maxPrice = prices.length > 0 ? Math.max(...prices) : undefined;\r\n\r\n return {\r\n eventID: apiEvent.eventID || apiEvent.id || apiEvent.ID || 0,\r\n id: apiEvent.id || apiEvent.ID,\r\n name: apiEvent.name || apiEvent.title || '',\r\n title: apiEvent.title || apiEvent.name,\r\n slug: apiEvent.slug,\r\n description: apiEvent.description,\r\n date: apiEvent.date || apiEvent.startDateTime || apiEvent.start_date_time || '',\r\n startDateTime: apiEvent.startDateTime || apiEvent.start_date_time,\r\n endDateTime: apiEvent.endDateTime || apiEvent.end_date_time,\r\n doorsOpenTime: apiEvent.doorsOpenTime || apiEvent.doors_open_time,\r\n timezone: apiEvent.timezone || apiEvent.time_zone,\r\n venueId: apiEvent.venueId || apiEvent.venue_id,\r\n venueName: apiEvent.venueName || apiEvent.venue_name,\r\n venueAddress: apiEvent.venueAddress || apiEvent.venue_address,\r\n location: apiEvent.location || apiEvent.venueAddress || apiEvent.venue_address,\r\n imageUrl: getEventImageUrl(apiEvent),\r\n imageURL: getEventImageUrl(apiEvent),\r\n status: apiEvent.status,\r\n isPublished: apiEvent.isPublished ?? apiEvent.is_published,\r\n isCancelled: apiEvent.isCancelled ?? apiEvent.is_cancelled,\r\n availableTickets: tickets,\r\n ticketsAvailable:\r\n apiEvent.ticketsAvailable ??\r\n apiEvent.tickets_available ??\r\n tickets.reduce((sum, t) => sum + (t.quantityAvailable || 0), 0),\r\n ticketsSold: apiEvent.ticketsSold ?? apiEvent.tickets_sold,\r\n minPrice: apiEvent.minPrice ?? apiEvent.min_price ?? minPrice,\r\n maxPrice: apiEvent.maxPrice ?? apiEvent.max_price ?? maxPrice,\r\n ctaText: apiEvent.ctaText || apiEvent.cta_text,\r\n ctaState: calculateCtaState(apiEvent),\r\n showPerformers: apiEvent.showPerformers ?? apiEvent.show_performers,\r\n eventSeriesId: apiEvent.eventSeriesId || apiEvent.event_series_id,\r\n seriesInstanceNumber:\r\n apiEvent.seriesInstanceNumber || apiEvent.series_instance_number,\r\n };\r\n}\r\n\r\n/**\r\n * Legacy transformer name for backwards compatibility\r\n */\r\nexport const transformEventData = transformEvent;\r\n","/**\r\n * Venue Transformer\r\n *\r\n * Normalizes API venue responses to a consistent format.\r\n */\r\n\r\nimport type { Venue } from '../types.js';\r\n\r\n// CDN base URL for images\r\nconst CDN_BASE_URL = 'https://micdrop-images.sfo3.digitaloceanspaces.com';\r\n\r\n/**\r\n * Raw API venue response (may have varying field names)\r\n */\r\ninterface ApiVenue {\r\n id?: number;\r\n ID?: number;\r\n name?: string;\r\n slug?: string;\r\n address?: string;\r\n googleLocationNameCache?: string;\r\n google_location_name_cache?: string;\r\n city?: string;\r\n state?: string;\r\n zipCode?: string;\r\n zip_code?: string;\r\n country?: string;\r\n timezone?: string;\r\n time_zone?: string;\r\n logoUrl?: string;\r\n logo_url?: string;\r\n logo?: string;\r\n serviceFeePercentage?: number;\r\n service_fee_percentage?: number;\r\n serviceFeeCents?: number;\r\n service_fee_cents?: number;\r\n taxPercentage?: number;\r\n tax_percentage?: number;\r\n organizationId?: number;\r\n organization_id?: number;\r\n}\r\n\r\n/**\r\n * Get CDN image URL for venue logo\r\n */\r\nfunction getLogoUrl(path: string | undefined): string {\r\n if (!path) return '';\r\n if (path.startsWith('http')) return path;\r\n return `${CDN_BASE_URL}/${path.replace(/^\\//, '')}`;\r\n}\r\n\r\n/**\r\n * Transform a raw API venue to normalized Venue\r\n */\r\nexport function transformVenue(apiVenue: ApiVenue): Venue {\r\n const logoPath =\r\n apiVenue.logoUrl || apiVenue.logo_url || apiVenue.logo;\r\n\r\n return {\r\n id: apiVenue.id || apiVenue.ID || 0,\r\n name: apiVenue.name || '',\r\n slug: apiVenue.slug,\r\n address: apiVenue.address,\r\n googleLocationNameCache:\r\n apiVenue.googleLocationNameCache ||\r\n apiVenue.google_location_name_cache,\r\n city: apiVenue.city,\r\n state: apiVenue.state,\r\n zipCode: apiVenue.zipCode || apiVenue.zip_code,\r\n country: apiVenue.country,\r\n timezone: apiVenue.timezone || apiVenue.time_zone,\r\n logoUrl: getLogoUrl(logoPath),\r\n serviceFeePercentage:\r\n apiVenue.serviceFeePercentage ??\r\n apiVenue.service_fee_percentage ??\r\n 0,\r\n serviceFeeCents:\r\n apiVenue.serviceFeeCents ?? apiVenue.service_fee_cents ?? 0,\r\n taxPercentage:\r\n apiVenue.taxPercentage ?? apiVenue.tax_percentage ?? 0,\r\n organizationId:\r\n apiVenue.organizationId || apiVenue.organization_id,\r\n };\r\n}\r\n\r\n/**\r\n * Extract fee configuration from venue\r\n */\r\nexport function extractVenueFees(apiVenue: ApiVenue): {\r\n serviceFeePercentage: number;\r\n serviceFeeCents: number;\r\n taxPercentage: number;\r\n} {\r\n return {\r\n serviceFeePercentage:\r\n apiVenue.serviceFeePercentage ??\r\n apiVenue.service_fee_percentage ??\r\n 0,\r\n serviceFeeCents:\r\n apiVenue.serviceFeeCents ?? apiVenue.service_fee_cents ?? 0,\r\n taxPercentage:\r\n apiVenue.taxPercentage ?? apiVenue.tax_percentage ?? 0,\r\n };\r\n}\r\n\r\n/**\r\n * Get formatted venue address\r\n */\r\nexport function formatVenueAddress(venue: Venue): string {\r\n const parts = [\r\n venue.address,\r\n venue.city,\r\n venue.state,\r\n venue.zipCode,\r\n ].filter(Boolean);\r\n\r\n return parts.join(', ');\r\n}\r\n"],"names":["logger","createLogger","DEFAULT_CONFIG","error","globalConfig","configureApi","config","getApiConfig","getPublicBaseUrl","getLegacyPublicUrl","getOrdersV2Url","getClientIP","sleep","ms","resolve","fetchWithRetry","url","init","cfg","method","maxAttempts","lastError","attempt","controller","timeoutId","callerSignal","onCallerAbort","response","err","apiGet","endpoint","options","apiRequest","apiPost","body","apiPut","apiDelete","errorData","message","errorMessage","simpleFetch","createPaymentIntent","cartId","quantities","donationAmounts","apiResult","AppError","getCartByUUID","cartUUID","expectedEventID","raw","uuid","eventID","status","expiresAt","reservations","r","rec","updateCartQuantities","numericQuantities","k","v","n","numericDonations","completeReservation","orderUuid","cancelReservation","createOrder","eventId","promoCode","getOrder","orderId","validatePaymentIntent","payload","result","extendCheckoutSession","getSessionStatus","initiateOrder","cartData","trackUTMSource","venueId","utmSource","ORDERS_V2_PUBLIC","validatePromoCode","code","encodedCode","hasPromoCodes","applyPromoCode","removePromoCode","_eventDetailsInflight","fetchEventDetails","customFetch","key","inflight","run","fetchEventTickets","tickets","fetchEventPerformers","data","fetchAllVenues","orgId","venues","fetchVenueEvents","events","getMonthEvents","year","month","getOrgMonthEvents","getSeriesOccurrences","eventSeriesId","fetchSeriesOccurrences","resolvePublicEntity","id","slug","qs","fetchSeriesPage","seriesId","fetchPublicCollection","collectionId","password","checkCollectionPassword","encodedPassword","checkEventPassword","testNetworkConnection","getVenue","getVenueFees","venue","getVenueBySlug","encodedSlug","API_BASE_URL","ORDERS_V2_URL","createGiftCardPurchase","req","applyGiftCard","removeGiftCard","completeGiftCardPayment","customerDetails","WAITLIST_ERROR_MESSAGES","joinWaitlist","email","phone","smsOptIn","getWaitlistStatus","fallback","isHiddenTicketPurchasable","ticket","now","salesBegin","salesEnd","remaining","computeCtaState","event","cancelled","isRegistration","waitlistEnabled","eventEnd","hiddenAvailable","publicTickets","t","hasPurchasable","allSoldOut","allComingSoon","earliestSalesStart","isSoldOut","isScheduled","hasSalesEnded","startDate","diffMs","diffHours","diffDays","dateText","formatTime","formatDateRaw","d","transformTicket","apiTicket","transformOrder","apiOrder","rawTickets","transformOrderForDisplay","order","displayId","formatCurrency","CDN_BASE_URL","getCDNImageUrl","path","getEventImageUrl","apiEvent","rawUrl","calculateCtaState","explicitState","eventDate","eventTime","availableCount","sum","qty","sold","transformEvent","prices","p","minPrice","maxPrice","transformEventData","getLogoUrl","transformVenue","apiVenue","logoPath","extractVenueFees","formatVenueAddress"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { c as i } from "./VenueCalendar-n-T-MmLU.js";
1
+ import { c as i } from "./VenueCalendar-BoSdP7xI.js";
2
2
  import "svelte/internal/disclose-version";
3
3
  import "svelte/internal/client";
4
4
  import "svelte/transition";
@@ -7,4 +7,4 @@ const r = i("VC-shim");
7
7
  typeof process > "u" && r.warn(
8
8
  "$lib/utils/api.js is deprecated — import from $lib/api instead."
9
9
  );
10
- //# sourceMappingURL=api-Bj-wXy71.js.map
10
+ //# sourceMappingURL=api-CCKXC9Qs.js.map