@getmicdrop/venue-calendar 4.0.150 → 4.0.151

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 (53) hide show
  1. package/dist/{CartView-DTfCjFlW.js → CartView-DuL0j798.js} +9 -9
  2. package/dist/{CartView-DTfCjFlW.js.map → CartView-DuL0j798.js.map} +1 -1
  3. package/dist/{Checkout-CYeMAcWC.js → Checkout-DNJ8X58u.js} +6 -6
  4. package/dist/{Checkout-CYeMAcWC.js.map → Checkout-DNJ8X58u.js.map} +1 -1
  5. package/dist/{Checkout-BX3B0qVK.js → Checkout-_K4mPvxp.js} +9 -9
  6. package/dist/{Checkout-BX3B0qVK.js.map → Checkout-_K4mPvxp.js.map} +1 -1
  7. package/dist/{CheckoutTimer-C23GHiGd.js → CheckoutTimer-4lzeiUaX.js} +5 -5
  8. package/dist/{CheckoutTimer-C23GHiGd.js.map → CheckoutTimer-4lzeiUaX.js.map} +1 -1
  9. package/dist/{ClockIcon-CSN1rGrR.js → ClockIcon-BErTPIEg.js} +2 -2
  10. package/dist/{ClockIcon-CSN1rGrR.js.map → ClockIcon-BErTPIEg.js.map} +1 -1
  11. package/dist/{CollectionView-CX_xA6jl.js → CollectionView-C_FGDsbe.js} +5 -5
  12. package/dist/{CollectionView-CX_xA6jl.js.map → CollectionView-C_FGDsbe.js.map} +1 -1
  13. package/dist/{Event-BHq4mPM4.js → Event-VeRj8o7D.js} +8 -8
  14. package/dist/{Event-BHq4mPM4.js.map → Event-VeRj8o7D.js.map} +1 -1
  15. package/dist/{EventPage-D7_j7lSt.js → EventPage-Cu3-bvF7.js} +8 -8
  16. package/dist/{EventPage-D7_j7lSt.js.map → EventPage-Cu3-bvF7.js.map} +1 -1
  17. package/dist/{Heading-DYLMLMNI.js → Heading-DY9O-thS.js} +2 -2
  18. package/dist/{Heading-DYLMLMNI.js.map → Heading-DY9O-thS.js.map} +1 -1
  19. package/dist/{ScarcityBadge-Cqgd7yXK.js → ScarcityBadge-Cp_KeuQN.js} +2 -2
  20. package/dist/{ScarcityBadge-Cqgd7yXK.js.map → ScarcityBadge-Cp_KeuQN.js.map} +1 -1
  21. package/dist/{SeriesPage-v8Dv4tJU.js → SeriesPage-rv54iB1u.js} +5 -5
  22. package/dist/{SeriesPage-v8Dv4tJU.js.map → SeriesPage-rv54iB1u.js.map} +1 -1
  23. package/dist/{Spinner-Cha16y5e.js → Spinner-BjG6EZwO.js} +2 -2
  24. package/dist/{Spinner-Cha16y5e.js.map → Spinner-BjG6EZwO.js.map} +1 -1
  25. package/dist/{Success-Bi88-2yx.js → Success-CeINMglr.js} +9 -9
  26. package/dist/{Success-Bi88-2yx.js.map → Success-CeINMglr.js.map} +1 -1
  27. package/dist/{Text-DQTInF7b.js → Text-BZ2br-0X.js} +2 -2
  28. package/dist/{Text-DQTInF7b.js.map → Text-BZ2br-0X.js.map} +1 -1
  29. package/dist/{VenueCalendar-CjSz3oKW.js → VenueCalendar-CU9NyjNN.js} +13 -13
  30. package/dist/{VenueCalendar-CjSz3oKW.js.map → VenueCalendar-CU9NyjNN.js.map} +1 -1
  31. package/dist/{ViewTicketsEmbed-CIEPMJek.js → ViewTicketsEmbed-B5qos3AF.js} +5 -5
  32. package/dist/{ViewTicketsEmbed-CIEPMJek.js.map → ViewTicketsEmbed-B5qos3AF.js.map} +1 -1
  33. package/dist/{index-3MxcX_e0.js → index-BYApjm9m.js} +3 -3
  34. package/dist/{index-3MxcX_e0.js.map → index-BYApjm9m.js.map} +1 -1
  35. package/dist/{modalManager.svelte-TaC2JCw2.js → modalManager.svelte-B7YmeOym.js} +2 -2
  36. package/dist/{modalManager.svelte-TaC2JCw2.js.map → modalManager.svelte-B7YmeOym.js.map} +1 -1
  37. package/dist/{promo-DHZDGke6.js → promo-3lEvBf-I.js} +2 -2
  38. package/dist/{promo-DHZDGke6.js.map → promo-3lEvBf-I.js.map} +1 -1
  39. package/dist/{shareCopyFeedback.svelte-CBy7K-wD.js → shareCopyFeedback.svelte-Cky-b7Ne.js} +2 -2
  40. package/dist/{shareCopyFeedback.svelte-CBy7K-wD.js.map → shareCopyFeedback.svelte-Cky-b7Ne.js.map} +1 -1
  41. package/dist/{showcase-state-options-DqhUaMPx.js → showcase-state-options-hjKUMz3Z.js} +2 -2
  42. package/dist/{showcase-state-options-DqhUaMPx.js.map → showcase-state-options-hjKUMz3Z.js.map} +1 -1
  43. package/dist/{transform-CkDswNi6.js → transform-CU3Mahyu.js} +2 -2
  44. package/dist/{transform-CkDswNi6.js.map → transform-CU3Mahyu.js.map} +1 -1
  45. package/dist/{utm-vf1sKPfQ.js → utm-xeqSXwE6.js} +2 -2
  46. package/dist/{utm-vf1sKPfQ.js.map → utm-xeqSXwE6.js.map} +1 -1
  47. package/dist/venue-calendar.css +1 -1
  48. package/dist/venue-calendar.es.js +2 -2
  49. package/dist/venue-calendar.iife.js +2 -2
  50. package/dist/venue-calendar.iife.js.map +1 -1
  51. package/dist/venue-calendar.umd.js +1 -1
  52. package/dist/venue-calendar.umd.js.map +1 -1
  53. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"showcase-state-options-DqhUaMPx.js","sources":["../src/lib/public-calendar-flow/mock-data.ts","../src/lib/public-calendar-flow/data-toggle-store.svelte.ts","../src/lib/public-calendar-flow/showcase-state-options.ts"],"sourcesContent":["import { getDefaultTimezone } from '@getmicdrop/svelte-components/utils/timezones';\r\nimport { DEFAULT_TIMEZONE } from '$lib/utils/timezone.js';\r\n// Premium Ticket Experience — Mock Data\r\n// Realistic event data for all design variants. DO NOT MODIFY per-variant.\r\n\r\nimport type {\r\n EventData,\r\n PerformerData,\r\n FAQItem,\r\n VenueData,\r\n TicketTypeData,\r\n} from './types';\r\n\r\n// All dates here are anchored to \"the upcoming Friday at 8pm\" so the showcase\r\n// stays in the future regardless of when it's loaded. Hardcoded calendar dates\r\n// rot every few months and cause `event_past` CTAs even when status === 'on_sale'.\r\nfunction showcaseDate(\r\n daysFromFriday: number,\r\n hour: number,\r\n minute = 0\r\n): string {\r\n const now = new Date(); // @datetime-escape: mock/demo fixture data — not a live datetime path\r\n const day = now.getUTCDay(); // 0=Sun..6=Sat\r\n const daysToFriday = (5 - day + 7) % 7 || 7; // always the NEXT Friday (never today)\r\n // The marker must sit WITHIN the `new Date(...)` expression's own line span —\r\n // the rule matches comments on lines [node.start, node.end], so a marker on\r\n // the line ABOVE is silently ignored (vc#609). On a multi-line construction\r\n // that means trailing the opening line, not preceding it.\r\n const base = new Date( // @datetime-escape: mock/demo fixture data — not a live datetime path\r\n Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate())\r\n );\r\n base.setUTCDate(base.getUTCDate() + daysToFriday + daysFromFriday);\r\n const y = base.getUTCFullYear();\r\n const m = String(base.getUTCMonth() + 1).padStart(2, '0');\r\n const d = String(base.getUTCDate()).padStart(2, '0');\r\n const hh = String(hour).padStart(2, '0');\r\n const mm = String(minute).padStart(2, '0');\r\n return `${y}-${m}-${d}T${hh}:${mm}:00-08:00`;\r\n}\r\n\r\nfunction showcaseDateOnly(daysFromFriday: number): string {\r\n return showcaseDate(daysFromFriday, 0).slice(0, 10);\r\n}\r\n\r\n// --- Venue ---\r\nexport const mockVenue: VenueData = {\r\n id: 101,\r\n name: 'The Laugh Factory',\r\n address: '8001 Sunset Blvd, Los Angeles, CA 90046',\r\n timezone: getDefaultTimezone(),\r\n serviceFeePercentage: 10,\r\n serviceFeeCents: 0,\r\n taxPercentage: 9.5,\r\n contactEmail: 'help@thelaughfactory.com',\r\n};\r\n\r\n// --- Performers ---\r\nexport const mockPerformers: PerformerData[] = [\r\n {\r\n id: 1,\r\n displayName: 'Dave Martinez',\r\n profileImage:\r\n 'https://images.unsplash.com/photo-1506794778202-cad84cf45f1d?w=200&h=200&fit=crop',\r\n },\r\n {\r\n id: 2,\r\n displayName: 'Sarah Chen',\r\n profileImage:\r\n 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=200&h=200&fit=crop',\r\n },\r\n {\r\n id: 3,\r\n displayName: 'Mike Thompson',\r\n profileImage:\r\n 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=200&h=200&fit=crop',\r\n },\r\n];\r\n\r\n// --- FAQs ---\r\nexport const mockFaqs: FAQItem[] = [\r\n {\r\n question: 'What time do doors open?',\r\n answer:\r\n 'Doors open at 7:00 PM, one hour before showtime. We recommend arriving early to get the best seats.',\r\n },\r\n {\r\n question: 'Is there a drink minimum?',\r\n answer:\r\n 'Yes, there is a 2-drink minimum per person. Both alcoholic and non-alcoholic beverages count toward the minimum.',\r\n },\r\n {\r\n question: 'Can I get a refund?',\r\n answer:\r\n 'Tickets are non-refundable but can be transferred to another person up to 24 hours before the show. Contact us for transfers.',\r\n },\r\n {\r\n question: 'Is the venue accessible?',\r\n answer:\r\n 'Yes, the venue is fully wheelchair accessible with ADA-compliant seating available. Please contact us to reserve accessible seating.',\r\n },\r\n];\r\n\r\n// --- Ticket Types ---\r\nexport const mockTickets: TicketTypeData[] = [\r\n\t{\r\n\t\tid: 101,\r\n\t\tname: 'General Admission',\r\n\t\tdescription: 'Standard seating in the main room',\r\n\t\tprice: 25,\r\n\t\tfee: 2.5,\r\n\t\tquantityAvailable: 12,\r\n\t\tquantityTotal: 150,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 8,\r\n\t\tstatus: 'on_sale',\r\n\t\tsalesEndDate: '2026-02-20T20:00:00-08:00',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 102,\r\n\t\tname: 'VIP Front Row',\r\n\t\tdescription: 'Premium seats in the first two rows with a complimentary drink',\r\n\t\tprice: 55,\r\n\t\tfee: 5.5,\r\n\t\tquantityAvailable: 3,\r\n\t\tquantityTotal: 20,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 4,\r\n\t\tstatus: 'on_sale',\r\n\t\tsalesEndDate: '2026-02-20T20:00:00-08:00',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 103,\r\n\t\tname: 'Table for 4',\r\n\t\tdescription: 'Reserved table for four guests with bottle service',\r\n\t\tprice: 180,\r\n\t\tfee: 18,\r\n\t\tquantityAvailable: 8,\r\n\t\tquantityTotal: 15,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 3,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 104,\r\n\t\tname: 'Student Discount',\r\n\t\tdescription: 'Valid student ID required at the door',\r\n\t\tprice: 15,\r\n\t\tfee: 1.5,\r\n\t\tquantityAvailable: 45,\r\n\t\tquantityTotal: 50,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 2,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 105,\r\n\t\tname: 'Early Bird Special',\r\n\t\tdescription: 'Limited early bird pricing — first come, first served',\r\n\t\tprice: 20,\r\n\t\tfee: 2,\r\n\t\tquantityAvailable: 15,\r\n\t\tquantityTotal: 30,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 4,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 106,\r\n\t\tname: 'Senior (65+)',\r\n\t\tdescription: 'Senior discount with valid ID at the door',\r\n\t\tprice: 18,\r\n\t\tfee: 1.8,\r\n\t\tquantityAvailable: 30,\r\n\t\tquantityTotal: 40,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 4,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 107,\r\n\t\tname: 'Industry Comp',\r\n\t\tdescription: 'Discount for industry professionals — credentials required',\r\n\t\tprice: 12,\r\n\t\tfee: 1.2,\r\n\t\tquantityAvailable: 25,\r\n\t\tquantityTotal: 30,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 2,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 108,\r\n\t\tname: 'Group of 6',\r\n\t\tdescription: 'Reserved booth for six guests with priority seating',\r\n\t\tprice: 240,\r\n\t\tfee: 24,\r\n\t\tquantityAvailable: 5,\r\n\t\tquantityTotal: 8,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 2,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 109,\r\n\t\tname: 'Standing Room',\r\n\t\tdescription: 'Standing room only at the back of the venue',\r\n\t\tprice: 12,\r\n\t\tfee: 1.2,\r\n\t\tquantityAvailable: 50,\r\n\t\tquantityTotal: 60,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 6,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 110,\r\n\t\tname: 'Day-of Door',\r\n\t\tdescription: 'Day-of pricing for walk-ins — limited availability',\r\n\t\tprice: 35,\r\n\t\tfee: 3.5,\r\n\t\tquantityAvailable: 20,\r\n\t\tquantityTotal: 25,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 4,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t}\r\n];\r\n\r\n// --- Main Event (on sale, multiple ticket types, scarcity on VIP) ---\r\n// Computed relative to today (showcase use): always lands ~21 days in the\r\n// future so the BookingWidget renders the on-sale state, not \"Sales ended\".\r\n// Memory: [[user_mastermind_date_awareness]] — never hardcode showcase dates.\r\nconst _now = new Date(); // @datetime-escape: mock/demo fixture data — not a live datetime path\r\nconst _evDate = new Date(_now.getFullYear(), _now.getMonth(), _now.getDate() + 21); // @datetime-escape: mock/demo fixture data — not a live datetime path\r\nconst _ymd = `${_evDate.getFullYear()}-${String(_evDate.getMonth() + 1).padStart(2, '0')}-${String(_evDate.getDate()).padStart(2, '0')}`;\r\n\r\nexport const mockEvent: EventData = {\r\n id: 2405,\r\n title: 'Friday Night Comedy Throwdown',\r\n slug: 'friday-night-comedy-throwdown',\r\n description: `Get ready for the funniest night of the week! The Friday Night Comedy Throwdown brings together three of LA's hottest stand-up comics for two hours of non-stop laughs.\r\n\r\nHeadliner Dave Martinez (as seen on Netflix's \"Comedy Knockout\") brings his signature high-energy style, while Sarah Chen delivers her razor-sharp observational humor that's earned her a devoted following. Host Mike Thompson keeps the energy up between sets with crowd work that'll have you crying laughing.\r\n\r\nWhether you're a comedy regular or a first-timer, this show delivers. Grab your crew, grab some drinks, and prepare to laugh until your abs hurt.`,\r\n\tdate: _ymd,\r\n\tstartDateTime: `${_ymd}T20:00:00-08:00`,\r\n\tendDateTime: `${_ymd}T22:00:00-08:00`,\r\n\tdoorsOpenTime: `${_ymd}T19:00:00-08:00`,\r\n\ttimezone: DEFAULT_TIMEZONE,\r\n\timageUrl: '/posters/Friday Night Showdown.jpg', // wide landscape 800×400\r\n\tvenue: mockVenue,\r\n\tperformers: mockPerformers,\r\n\ttickets: mockTickets,\r\n\tfaqs: mockFaqs,\r\n\tdisclaimer: '',\r\n\tstatus: 'on_sale',\r\n\tisPasswordProtected: false,\r\n\tisRegistrationEvent: false,\r\n\ttotalTicketsRemaining: 68,\r\n\ttotalTicketsCapacity: 265,\r\n\tdisplayStartTime: true,\r\n\tdisplayEndTime: true,\r\n\tdisplayDoorsTime: true\r\n};\r\n\r\n// --- Sold Out Event (no end time shown) ---\r\nexport const mockSoldOutEvent: EventData = {\r\n ...mockEvent,\r\n id: 2406,\r\n title: 'Saturday Night Special',\r\n slug: 'saturday-night-special',\r\n imageUrl: '/posters/the-duel-square.webp', // square 3000×3000\r\n date: showcaseDateOnly(1),\r\n startDateTime: showcaseDate(1, 21),\r\n endDateTime: showcaseDate(1, 23),\r\n displayEndTime: false,\r\n status: 'sold_out',\r\n totalTicketsRemaining: 0,\r\n tickets: mockTickets.map(t => ({\r\n ...t,\r\n quantityAvailable: 0,\r\n status: 'sold_out' as const,\r\n })),\r\n};\r\n\r\n// --- Free Event (no doors time shown) ---\r\nexport const mockFreeEvent: EventData = {\r\n ...mockEvent,\r\n id: 2407,\r\n title: 'Open Mic Night',\r\n slug: 'open-mic-night',\r\n imageUrl: '/posters/OpenMic-Twitter.jpg', // wide landscape 2127×1075\r\n date: showcaseDateOnly(-2),\r\n startDateTime: showcaseDate(-2, 19),\r\n endDateTime: showcaseDate(-2, 21),\r\n displayDoorsTime: false,\r\n description:\r\n 'Free open mic night! Sign up at the door. All skill levels welcome.',\r\n status: 'on_sale',\r\n tickets: [\r\n {\r\n id: 201,\r\n name: 'Free Entry',\r\n description: 'Sign up at the door for a 5-minute set',\r\n price: 0,\r\n fee: 0,\r\n quantityAvailable: 40,\r\n quantityTotal: 50,\r\n minPerOrder: 1,\r\n maxPerOrder: 2,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n ],\r\n totalTicketsRemaining: 40,\r\n totalTicketsCapacity: 50,\r\n};\r\n\r\n// --- Series Event (with occurrences) ---\r\nexport const mockSeriesEvent: EventData = {\r\n ...mockEvent,\r\n id: 2410,\r\n title: 'Improv Throwdown',\r\n slug: 'improv-throwdown',\r\n imageUrl: '/posters/laughlab-tall.webp', // tall portrait 2550×3300\r\n eventSeriesId: 42,\r\n description:\r\n 'Weekly improv comedy show featuring rotating guest performers and audience participation games.',\r\n seriesOccurrences: [\r\n // Same-day shows (Fri Feb 20 — 7pm, 8pm, 9:30pm)\r\n {\r\n id: 2410,\r\n slug: 'improv-throwdown-feb-20-7pm',\r\n startDateTime: showcaseDate(0, 19),\r\n endDateTime: showcaseDate(0, 20, 30),\r\n status: 'sold_out',\r\n ctaText: 'Sold out',\r\n ctaDisabled: true,\r\n },\r\n {\r\n id: 2414,\r\n slug: 'improv-throwdown-feb-20-8pm',\r\n startDateTime: showcaseDate(0, 20),\r\n endDateTime: showcaseDate(0, 21, 30),\r\n status: 'on_sale',\r\n ctaText: 'Get tickets',\r\n ctaDisabled: false,\r\n },\r\n {\r\n id: 2415,\r\n slug: 'improv-throwdown-feb-20-930pm',\r\n startDateTime: showcaseDate(0, 21, 30),\r\n endDateTime: showcaseDate(0, 23),\r\n status: 'on_sale',\r\n ctaText: 'Get tickets',\r\n ctaDisabled: false,\r\n },\r\n // Single show days\r\n {\r\n id: 2411,\r\n slug: 'improv-throwdown-feb-27',\r\n startDateTime: showcaseDate(7, 20),\r\n endDateTime: showcaseDate(7, 22),\r\n status: 'sold_out',\r\n ctaText: 'Sold out',\r\n ctaDisabled: true,\r\n },\r\n {\r\n id: 2412,\r\n slug: 'improv-throwdown-mar-06',\r\n startDateTime: showcaseDate(14, 20),\r\n endDateTime: showcaseDate(14, 22),\r\n status: 'on_sale',\r\n ctaText: 'Get tickets',\r\n ctaDisabled: false,\r\n },\r\n {\r\n id: 2413,\r\n slug: 'improv-throwdown-mar-13',\r\n startDateTime: showcaseDate(21, 20),\r\n endDateTime: showcaseDate(21, 22),\r\n status: 'coming_soon',\r\n ctaText: 'Coming soon',\r\n ctaDisabled: true,\r\n },\r\n ],\r\n};\r\n\r\n// --- Registration Event (workshop — no time shown, just date + doors) ---\r\nexport const mockRegistrationEvent: EventData = {\r\n ...mockEvent,\r\n id: 2408,\r\n title: 'Stand-Up Comedy Workshop',\r\n slug: 'standup-comedy-workshop',\r\n imageUrl: '/posters/stand up 101.png', // 16:9 landscape 1920×1080\r\n description:\r\n 'Learn the fundamentals of stand-up comedy in this 3-hour intensive workshop. Write, refine, and perform your first 5-minute set.',\r\n isRegistrationEvent: true,\r\n displayStartTime: false,\r\n displayEndTime: false,\r\n status: 'on_sale',\r\n tickets: [\r\n {\r\n id: 301,\r\n name: 'Workshop Seat',\r\n description: 'Includes materials and performance slot',\r\n price: 75,\r\n fee: 7.5,\r\n quantityAvailable: 8,\r\n quantityTotal: 12,\r\n minPerOrder: 1,\r\n maxPerOrder: 1,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n ],\r\n totalTicketsRemaining: 8,\r\n totalTicketsCapacity: 12,\r\n};\r\n\r\n// --- Donation Event ---\r\nexport const mockDonationEvent: EventData = {\r\n ...mockEvent,\r\n id: 2414,\r\n title: 'Charity Comedy Benefit',\r\n slug: 'charity-comedy-benefit',\r\n imageUrl: '/posters/Friday Night Showdown.jpg',\r\n description:\r\n 'All proceeds go to the LA Comedy Relief Fund. Choose your own donation amount or grab a standard ticket.',\r\n status: 'on_sale',\r\n tickets: [\r\n {\r\n id: 401,\r\n name: 'Donation',\r\n description: 'Support the cause — choose your amount',\r\n price: 0,\r\n fee: 0,\r\n quantityAvailable: 200,\r\n quantityTotal: 200,\r\n minPerOrder: 1,\r\n maxPerOrder: 10,\r\n status: 'on_sale',\r\n isDonation: true,\r\n isHidden: false,\r\n ticketType: 2,\r\n },\r\n {\r\n id: 402,\r\n name: 'Standard Admission',\r\n description: 'Includes one drink ticket',\r\n price: 30,\r\n fee: 3,\r\n quantityAvailable: 80,\r\n quantityTotal: 100,\r\n minPerOrder: 1,\r\n maxPerOrder: 6,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n ],\r\n totalTicketsRemaining: 280,\r\n totalTicketsCapacity: 300,\r\n};\r\n\r\n// --- Mixed Event (ALL ticket states in one event) ---\r\nexport const mockMixedEvent: EventData = {\r\n ...mockEvent,\r\n id: 2415,\r\n title: 'The Everything Show',\r\n slug: 'the-everything-show',\r\n imageUrl: '/posters/the-duel-square.webp',\r\n description:\r\n 'A showcase event with every ticket state possible — for testing all edge cases.',\r\n status: 'on_sale',\r\n tickets: [\r\n {\r\n id: 501,\r\n name: 'General Admission',\r\n description: 'Standard seating in the main room',\r\n price: 25,\r\n fee: 2.5,\r\n quantityAvailable: 45,\r\n quantityTotal: 150,\r\n minPerOrder: 1,\r\n maxPerOrder: 8,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 502,\r\n name: 'Basic Entry',\r\n price: 15,\r\n fee: 1.5,\r\n quantityAvailable: 60,\r\n quantityTotal: 80,\r\n minPerOrder: 1,\r\n maxPerOrder: 4,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 503,\r\n name: 'VIP Front Row',\r\n description: 'Premium seats with complimentary drink',\r\n price: 75,\r\n fee: 7.5,\r\n quantityAvailable: 2,\r\n quantityTotal: 20,\r\n minPerOrder: 1,\r\n maxPerOrder: 4,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 504,\r\n name: 'Early Bird',\r\n description: 'Limited early bird pricing',\r\n price: 20,\r\n fee: 2,\r\n quantityAvailable: 0,\r\n quantityTotal: 30,\r\n minPerOrder: 1,\r\n maxPerOrder: 4,\r\n status: 'sold_out',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 505,\r\n name: 'Late Night Add-On',\r\n description: 'Access to the after-party at midnight',\r\n price: 40,\r\n fee: 4,\r\n quantityAvailable: 50,\r\n quantityTotal: 50,\r\n minPerOrder: 1,\r\n maxPerOrder: 2,\r\n status: 'coming_soon',\r\n salesStartDate: showcaseDate(9, 10),\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 506,\r\n name: 'Weekend Bundle',\r\n description: 'Includes Saturday + Sunday shows',\r\n price: 45,\r\n fee: 4.5,\r\n quantityAvailable: 0,\r\n quantityTotal: 25,\r\n minPerOrder: 1,\r\n maxPerOrder: 4,\r\n status: 'sales_ended',\r\n salesEndDate: showcaseDate(-10, 23, 59),\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 507,\r\n name: 'Donation',\r\n description: 'Support the performers directly',\r\n price: 0,\r\n fee: 0,\r\n quantityAvailable: 100,\r\n quantityTotal: 100,\r\n minPerOrder: 1,\r\n maxPerOrder: 5,\r\n status: 'on_sale',\r\n isDonation: true,\r\n isHidden: false,\r\n ticketType: 2,\r\n },\r\n {\r\n id: 508,\r\n name: 'Secret VIP Lounge',\r\n description: 'Backstage access with meet & greet',\r\n price: 150,\r\n fee: 15,\r\n quantityAvailable: 10,\r\n quantityTotal: 10,\r\n minPerOrder: 1,\r\n maxPerOrder: 2,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: true,\r\n },\r\n {\r\n id: 509,\r\n name: 'Industry Comp',\r\n description: 'Complimentary ticket for industry professionals',\r\n price: 0,\r\n fee: 0,\r\n quantityAvailable: 20,\r\n quantityTotal: 20,\r\n minPerOrder: 1,\r\n maxPerOrder: 1,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: true,\r\n },\r\n ],\r\n totalTicketsRemaining: 287,\r\n totalTicketsCapacity: 485,\r\n};\r\n\r\n// --- Promo Event (hidden tickets for promo reveal testing) ---\r\nexport const mockPromoEvent: EventData = {\r\n ...mockEvent,\r\n id: 2417,\r\n title: 'Secret Show',\r\n slug: 'secret-show',\r\n imageUrl: '/posters/luke-null-tall.webp',\r\n description:\r\n 'An intimate comedy experience. Some tickets are only available with a promo code.',\r\n status: 'on_sale',\r\n tickets: [\r\n {\r\n id: 701,\r\n name: 'General Admission',\r\n price: 30,\r\n fee: 3,\r\n quantityAvailable: 40,\r\n quantityTotal: 60,\r\n minPerOrder: 1,\r\n maxPerOrder: 6,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 702,\r\n name: 'Premium Seat',\r\n description: 'Reserved seating in rows 1-5',\r\n price: 50,\r\n fee: 5,\r\n quantityAvailable: 15,\r\n quantityTotal: 30,\r\n minPerOrder: 1,\r\n maxPerOrder: 4,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 703,\r\n name: 'Artist Meet & Greet',\r\n description:\r\n 'Backstage pass with photo opportunity — promo code required',\r\n price: 100,\r\n fee: 10,\r\n quantityAvailable: 8,\r\n quantityTotal: 10,\r\n minPerOrder: 1,\r\n maxPerOrder: 2,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: true,\r\n },\r\n {\r\n id: 704,\r\n name: 'Industry Comp',\r\n description: 'Complimentary entry for industry professionals',\r\n price: 0,\r\n fee: 0,\r\n quantityAvailable: 10,\r\n quantityTotal: 10,\r\n minPerOrder: 1,\r\n maxPerOrder: 1,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: true,\r\n },\r\n ],\r\n totalTicketsRemaining: 73,\r\n totalTicketsCapacity: 110,\r\n};\r\n\r\n// --- Hidden-Only Event (MIC-1039) — no visible tickets, only hidden remain ---\r\n// Lands the user on a page where the only purchasable seats are gated behind\r\n// a promo code. With zero visible tickets the page should suppress the ticket\r\n// list entirely and render only the PromoCodeInput.\r\nexport const mockHiddenOnlyEvent: EventData = {\r\n ...mockEvent,\r\n id: 2419,\r\n title: 'Industry Showcase',\r\n slug: 'industry-showcase',\r\n description:\r\n 'A private comedy showcase. Tickets are only available with a promo code.',\r\n status: 'on_sale',\r\n tickets: [\r\n {\r\n id: 902,\r\n name: 'Industry Comp',\r\n description:\r\n 'Complimentary entry for industry professionals — promo code required',\r\n price: 0,\r\n fee: 0,\r\n quantityAvailable: 15,\r\n quantityTotal: 20,\r\n minPerOrder: 1,\r\n maxPerOrder: 2,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: true,\r\n },\r\n {\r\n id: 903,\r\n name: 'Artist Hold',\r\n description: 'Held for artist guests — promo code required',\r\n price: 50,\r\n fee: 5,\r\n quantityAvailable: 5,\r\n quantityTotal: 10,\r\n minPerOrder: 1,\r\n maxPerOrder: 4,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: true,\r\n },\r\n ],\r\n totalTicketsRemaining: 0,\r\n totalTicketsCapacity: 0,\r\n};\r\n\r\n// --- Password Protected Event ---\r\nexport const mockPasswordEvent: EventData = {\r\n ...mockEvent,\r\n id: 2409,\r\n title: 'Secret Comedy Club',\r\n slug: 'secret-comedy-club',\r\n imageUrl: '/posters/luke-null-tall.webp', // tall portrait 625×937\r\n description: 'An exclusive underground comedy experience. Password required.',\r\n isPasswordProtected: true,\r\n status: 'on_sale',\r\n};\r\n","export type DataVariant =\r\n\t| 'default'\r\n\t| 'sold_out'\r\n\t| 'free'\r\n\t| 'registration'\r\n\t| 'series'\r\n\t| 'series_instance'\r\n\t| 'collection'\r\n\t| 'donation'\r\n\t| 'mixed'\r\n\t| 'sections'\r\n\t| 'promo'\r\n\t| 'multi_stage'\r\n\t| 'long'\r\n\t| 'wide';\r\n\r\nexport interface ToggleOption {\r\n\tvalue: string;\r\n\tlabel: string;\r\n\tcolor: string;\r\n}\r\n\r\nclass DataToggleStore {\r\n\tcurrent = $state<string>('default');\r\n\toptions = $state<ToggleOption[]>([]);\r\n\tisActive = $state(false);\r\n}\r\n\r\nexport const dataToggleStore = new DataToggleStore();\r\n","/**\r\n * Canonical state-option sets for the public-calendar-flow showcase.\r\n *\r\n * Per R-PATTERN-01 (canonicals-golden-rules.md): function form is the source,\r\n * static snapshots derive at module init. Every showcase surface that drives\r\n * `dataToggleStore` reads its option set from here — Checkout and Success each\r\n * used to inline their own array beside the variant union they switch on, so\r\n * the same `{ default, free, registration, donation }` core lived in several\r\n * places and could drift silently.\r\n *\r\n * A third set, `getShowcaseEventStates`, was removed in #615: its only caller\r\n * was `ShowcaseEvent.svelte`, deleted in the same change as dead code.\r\n *\r\n * Ordering is per-surface and deliberate: Checkout lists donation before\r\n * registration, Success lists registration before donation. The sets stay\r\n * distinct rather than merged so no surface's toggle order changes.\r\n */\r\nimport type { ToggleOption } from '$lib/public-calendar-flow/data-toggle-store.svelte';\r\n\r\n/**\r\n * Categorical hues for the showcase toggle dots — keyed by hue role, not by\r\n * state, so each class is named once and reused across every set.\r\n *\r\n * `info` is raw Tailwind palette (`bg-sky-500`) rather than an SC semantic\r\n * token, carried over verbatim from the arrays this module absorbed. It is the\r\n * one non-token hue here; replacing it is a color-category call, not an\r\n * options-array one.\r\n */\r\nconst HUE = {\r\n\tsuccess: 'bg-accent-success',\r\n\tneutral: 'bg-muted-foreground',\r\n\tinfo: 'bg-sky-500',\r\n\tbrand: 'bg-brand-primary',\r\n\tdanger: 'bg-accent-danger',\r\n\twarning: 'bg-accent-warning',\r\n\twarningSubtle: 'bg-status-warning-bg0',\r\n} as const;\r\n\r\nexport function getShowcaseBrowseStates(): ToggleOption[] {\r\n\treturn [\r\n\t\t{ value: 'default', label: 'Default', color: HUE.success },\r\n\t\t{ value: 'empty', label: 'Empty', color: HUE.neutral },\r\n\t\t{ value: 'sparse', label: '2 events', color: HUE.info },\r\n\t\t{ value: 'busy', label: 'Many events', color: HUE.brand },\r\n\t];\r\n}\r\n\r\nexport function getShowcaseCalendarStates(): ToggleOption[] {\r\n\treturn [\r\n\t\t{ value: 'default', label: 'Default', color: HUE.success },\r\n\t\t{ value: 'empty', label: 'Empty month', color: HUE.neutral },\r\n\t\t{ value: 'busy', label: 'Busy month', color: HUE.brand },\r\n\t];\r\n}\r\n\r\nexport function getShowcaseCheckoutStates(): ToggleOption[] {\r\n\treturn [\r\n\t\t{ value: 'default', label: 'Standard', color: HUE.success },\r\n\t\t{ value: 'free', label: 'Free', color: HUE.info },\r\n\t\t{ value: 'donation', label: 'Donation', color: HUE.danger },\r\n\t\t{ value: 'registration', label: 'Registration', color: HUE.brand },\r\n\t\t{ value: 'timer_warning', label: 'Timer warning', color: HUE.warningSubtle },\r\n\t\t{ value: 'expired', label: 'Expired', color: HUE.danger },\r\n\t\t{ value: 'promo', label: 'Promo discount', color: HUE.success },\r\n\t];\r\n}\r\n\r\nexport function getShowcaseSuccessStates(): ToggleOption[] {\r\n\treturn [\r\n\t\t{ value: 'default', label: 'Standard', color: HUE.success },\r\n\t\t{ value: 'free', label: 'Free', color: HUE.info },\r\n\t\t{ value: 'registration', label: 'Registration', color: HUE.brand },\r\n\t\t{ value: 'donation', label: 'Donation', color: HUE.danger },\r\n\t];\r\n}\r\n/** Static snapshots derived from the functions above — for non-reactive consumers. */\r\nexport const SHOWCASE_BROWSE_STATES = getShowcaseBrowseStates();\r\nexport const SHOWCASE_CALENDAR_STATES = getShowcaseCalendarStates();\r\n"],"names":["showcaseDate","daysFromFriday","hour","minute","now","daysToFriday","base","y","m","d","hh","mm","showcaseDateOnly","mockVenue","getDefaultTimezone","mockPerformers","mockFaqs","mockTickets","_now","_evDate","_ymd","mockEvent","DEFAULT_TIMEZONE","t","mockFreeEvent","mockRegistrationEvent","mockDonationEvent","DataToggleStore","#current","$","#isActive","dataToggleStore","HUE","getShowcaseCheckoutStates","getShowcaseSuccessStates"],"mappings":"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"}
1
+ {"version":3,"file":"showcase-state-options-hjKUMz3Z.js","sources":["../src/lib/public-calendar-flow/mock-data.ts","../src/lib/public-calendar-flow/data-toggle-store.svelte.ts","../src/lib/public-calendar-flow/showcase-state-options.ts"],"sourcesContent":["import { getDefaultTimezone } from '@getmicdrop/svelte-components/utils/timezones';\r\nimport { DEFAULT_TIMEZONE } from '$lib/utils/timezone.js';\r\n// Premium Ticket Experience — Mock Data\r\n// Realistic event data for all design variants. DO NOT MODIFY per-variant.\r\n\r\nimport type {\r\n EventData,\r\n PerformerData,\r\n FAQItem,\r\n VenueData,\r\n TicketTypeData,\r\n} from './types';\r\n\r\n// All dates here are anchored to \"the upcoming Friday at 8pm\" so the showcase\r\n// stays in the future regardless of when it's loaded. Hardcoded calendar dates\r\n// rot every few months and cause `event_past` CTAs even when status === 'on_sale'.\r\nfunction showcaseDate(\r\n daysFromFriday: number,\r\n hour: number,\r\n minute = 0\r\n): string {\r\n const now = new Date(); // @datetime-escape: mock/demo fixture data — not a live datetime path\r\n const day = now.getUTCDay(); // 0=Sun..6=Sat\r\n const daysToFriday = (5 - day + 7) % 7 || 7; // always the NEXT Friday (never today)\r\n // The marker must sit WITHIN the `new Date(...)` expression's own line span —\r\n // the rule matches comments on lines [node.start, node.end], so a marker on\r\n // the line ABOVE is silently ignored (vc#609). On a multi-line construction\r\n // that means trailing the opening line, not preceding it.\r\n const base = new Date( // @datetime-escape: mock/demo fixture data — not a live datetime path\r\n Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate())\r\n );\r\n base.setUTCDate(base.getUTCDate() + daysToFriday + daysFromFriday);\r\n const y = base.getUTCFullYear();\r\n const m = String(base.getUTCMonth() + 1).padStart(2, '0');\r\n const d = String(base.getUTCDate()).padStart(2, '0');\r\n const hh = String(hour).padStart(2, '0');\r\n const mm = String(minute).padStart(2, '0');\r\n return `${y}-${m}-${d}T${hh}:${mm}:00-08:00`;\r\n}\r\n\r\nfunction showcaseDateOnly(daysFromFriday: number): string {\r\n return showcaseDate(daysFromFriday, 0).slice(0, 10);\r\n}\r\n\r\n// --- Venue ---\r\nexport const mockVenue: VenueData = {\r\n id: 101,\r\n name: 'The Laugh Factory',\r\n address: '8001 Sunset Blvd, Los Angeles, CA 90046',\r\n timezone: getDefaultTimezone(),\r\n serviceFeePercentage: 10,\r\n serviceFeeCents: 0,\r\n taxPercentage: 9.5,\r\n contactEmail: 'help@thelaughfactory.com',\r\n};\r\n\r\n// --- Performers ---\r\nexport const mockPerformers: PerformerData[] = [\r\n {\r\n id: 1,\r\n displayName: 'Dave Martinez',\r\n profileImage:\r\n 'https://images.unsplash.com/photo-1506794778202-cad84cf45f1d?w=200&h=200&fit=crop',\r\n },\r\n {\r\n id: 2,\r\n displayName: 'Sarah Chen',\r\n profileImage:\r\n 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=200&h=200&fit=crop',\r\n },\r\n {\r\n id: 3,\r\n displayName: 'Mike Thompson',\r\n profileImage:\r\n 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=200&h=200&fit=crop',\r\n },\r\n];\r\n\r\n// --- FAQs ---\r\nexport const mockFaqs: FAQItem[] = [\r\n {\r\n question: 'What time do doors open?',\r\n answer:\r\n 'Doors open at 7:00 PM, one hour before showtime. We recommend arriving early to get the best seats.',\r\n },\r\n {\r\n question: 'Is there a drink minimum?',\r\n answer:\r\n 'Yes, there is a 2-drink minimum per person. Both alcoholic and non-alcoholic beverages count toward the minimum.',\r\n },\r\n {\r\n question: 'Can I get a refund?',\r\n answer:\r\n 'Tickets are non-refundable but can be transferred to another person up to 24 hours before the show. Contact us for transfers.',\r\n },\r\n {\r\n question: 'Is the venue accessible?',\r\n answer:\r\n 'Yes, the venue is fully wheelchair accessible with ADA-compliant seating available. Please contact us to reserve accessible seating.',\r\n },\r\n];\r\n\r\n// --- Ticket Types ---\r\nexport const mockTickets: TicketTypeData[] = [\r\n\t{\r\n\t\tid: 101,\r\n\t\tname: 'General Admission',\r\n\t\tdescription: 'Standard seating in the main room',\r\n\t\tprice: 25,\r\n\t\tfee: 2.5,\r\n\t\tquantityAvailable: 12,\r\n\t\tquantityTotal: 150,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 8,\r\n\t\tstatus: 'on_sale',\r\n\t\tsalesEndDate: '2026-02-20T20:00:00-08:00',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 102,\r\n\t\tname: 'VIP Front Row',\r\n\t\tdescription: 'Premium seats in the first two rows with a complimentary drink',\r\n\t\tprice: 55,\r\n\t\tfee: 5.5,\r\n\t\tquantityAvailable: 3,\r\n\t\tquantityTotal: 20,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 4,\r\n\t\tstatus: 'on_sale',\r\n\t\tsalesEndDate: '2026-02-20T20:00:00-08:00',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 103,\r\n\t\tname: 'Table for 4',\r\n\t\tdescription: 'Reserved table for four guests with bottle service',\r\n\t\tprice: 180,\r\n\t\tfee: 18,\r\n\t\tquantityAvailable: 8,\r\n\t\tquantityTotal: 15,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 3,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 104,\r\n\t\tname: 'Student Discount',\r\n\t\tdescription: 'Valid student ID required at the door',\r\n\t\tprice: 15,\r\n\t\tfee: 1.5,\r\n\t\tquantityAvailable: 45,\r\n\t\tquantityTotal: 50,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 2,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 105,\r\n\t\tname: 'Early Bird Special',\r\n\t\tdescription: 'Limited early bird pricing — first come, first served',\r\n\t\tprice: 20,\r\n\t\tfee: 2,\r\n\t\tquantityAvailable: 15,\r\n\t\tquantityTotal: 30,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 4,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 106,\r\n\t\tname: 'Senior (65+)',\r\n\t\tdescription: 'Senior discount with valid ID at the door',\r\n\t\tprice: 18,\r\n\t\tfee: 1.8,\r\n\t\tquantityAvailable: 30,\r\n\t\tquantityTotal: 40,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 4,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 107,\r\n\t\tname: 'Industry Comp',\r\n\t\tdescription: 'Discount for industry professionals — credentials required',\r\n\t\tprice: 12,\r\n\t\tfee: 1.2,\r\n\t\tquantityAvailable: 25,\r\n\t\tquantityTotal: 30,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 2,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 108,\r\n\t\tname: 'Group of 6',\r\n\t\tdescription: 'Reserved booth for six guests with priority seating',\r\n\t\tprice: 240,\r\n\t\tfee: 24,\r\n\t\tquantityAvailable: 5,\r\n\t\tquantityTotal: 8,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 2,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 109,\r\n\t\tname: 'Standing Room',\r\n\t\tdescription: 'Standing room only at the back of the venue',\r\n\t\tprice: 12,\r\n\t\tfee: 1.2,\r\n\t\tquantityAvailable: 50,\r\n\t\tquantityTotal: 60,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 6,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t},\r\n\t{\r\n\t\tid: 110,\r\n\t\tname: 'Day-of Door',\r\n\t\tdescription: 'Day-of pricing for walk-ins — limited availability',\r\n\t\tprice: 35,\r\n\t\tfee: 3.5,\r\n\t\tquantityAvailable: 20,\r\n\t\tquantityTotal: 25,\r\n\t\tminPerOrder: 1,\r\n\t\tmaxPerOrder: 4,\r\n\t\tstatus: 'on_sale',\r\n\t\tisDonation: false,\r\n\t\tisHidden: false\r\n\t}\r\n];\r\n\r\n// --- Main Event (on sale, multiple ticket types, scarcity on VIP) ---\r\n// Computed relative to today (showcase use): always lands ~21 days in the\r\n// future so the BookingWidget renders the on-sale state, not \"Sales ended\".\r\n// Memory: [[user_mastermind_date_awareness]] — never hardcode showcase dates.\r\nconst _now = new Date(); // @datetime-escape: mock/demo fixture data — not a live datetime path\r\nconst _evDate = new Date(_now.getFullYear(), _now.getMonth(), _now.getDate() + 21); // @datetime-escape: mock/demo fixture data — not a live datetime path\r\nconst _ymd = `${_evDate.getFullYear()}-${String(_evDate.getMonth() + 1).padStart(2, '0')}-${String(_evDate.getDate()).padStart(2, '0')}`;\r\n\r\nexport const mockEvent: EventData = {\r\n id: 2405,\r\n title: 'Friday Night Comedy Throwdown',\r\n slug: 'friday-night-comedy-throwdown',\r\n description: `Get ready for the funniest night of the week! The Friday Night Comedy Throwdown brings together three of LA's hottest stand-up comics for two hours of non-stop laughs.\r\n\r\nHeadliner Dave Martinez (as seen on Netflix's \"Comedy Knockout\") brings his signature high-energy style, while Sarah Chen delivers her razor-sharp observational humor that's earned her a devoted following. Host Mike Thompson keeps the energy up between sets with crowd work that'll have you crying laughing.\r\n\r\nWhether you're a comedy regular or a first-timer, this show delivers. Grab your crew, grab some drinks, and prepare to laugh until your abs hurt.`,\r\n\tdate: _ymd,\r\n\tstartDateTime: `${_ymd}T20:00:00-08:00`,\r\n\tendDateTime: `${_ymd}T22:00:00-08:00`,\r\n\tdoorsOpenTime: `${_ymd}T19:00:00-08:00`,\r\n\ttimezone: DEFAULT_TIMEZONE,\r\n\timageUrl: '/posters/Friday Night Showdown.jpg', // wide landscape 800×400\r\n\tvenue: mockVenue,\r\n\tperformers: mockPerformers,\r\n\ttickets: mockTickets,\r\n\tfaqs: mockFaqs,\r\n\tdisclaimer: '',\r\n\tstatus: 'on_sale',\r\n\tisPasswordProtected: false,\r\n\tisRegistrationEvent: false,\r\n\ttotalTicketsRemaining: 68,\r\n\ttotalTicketsCapacity: 265,\r\n\tdisplayStartTime: true,\r\n\tdisplayEndTime: true,\r\n\tdisplayDoorsTime: true\r\n};\r\n\r\n// --- Sold Out Event (no end time shown) ---\r\nexport const mockSoldOutEvent: EventData = {\r\n ...mockEvent,\r\n id: 2406,\r\n title: 'Saturday Night Special',\r\n slug: 'saturday-night-special',\r\n imageUrl: '/posters/the-duel-square.webp', // square 3000×3000\r\n date: showcaseDateOnly(1),\r\n startDateTime: showcaseDate(1, 21),\r\n endDateTime: showcaseDate(1, 23),\r\n displayEndTime: false,\r\n status: 'sold_out',\r\n totalTicketsRemaining: 0,\r\n tickets: mockTickets.map(t => ({\r\n ...t,\r\n quantityAvailable: 0,\r\n status: 'sold_out' as const,\r\n })),\r\n};\r\n\r\n// --- Free Event (no doors time shown) ---\r\nexport const mockFreeEvent: EventData = {\r\n ...mockEvent,\r\n id: 2407,\r\n title: 'Open Mic Night',\r\n slug: 'open-mic-night',\r\n imageUrl: '/posters/OpenMic-Twitter.jpg', // wide landscape 2127×1075\r\n date: showcaseDateOnly(-2),\r\n startDateTime: showcaseDate(-2, 19),\r\n endDateTime: showcaseDate(-2, 21),\r\n displayDoorsTime: false,\r\n description:\r\n 'Free open mic night! Sign up at the door. All skill levels welcome.',\r\n status: 'on_sale',\r\n tickets: [\r\n {\r\n id: 201,\r\n name: 'Free Entry',\r\n description: 'Sign up at the door for a 5-minute set',\r\n price: 0,\r\n fee: 0,\r\n quantityAvailable: 40,\r\n quantityTotal: 50,\r\n minPerOrder: 1,\r\n maxPerOrder: 2,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n ],\r\n totalTicketsRemaining: 40,\r\n totalTicketsCapacity: 50,\r\n};\r\n\r\n// --- Series Event (with occurrences) ---\r\nexport const mockSeriesEvent: EventData = {\r\n ...mockEvent,\r\n id: 2410,\r\n title: 'Improv Throwdown',\r\n slug: 'improv-throwdown',\r\n imageUrl: '/posters/laughlab-tall.webp', // tall portrait 2550×3300\r\n eventSeriesId: 42,\r\n description:\r\n 'Weekly improv comedy show featuring rotating guest performers and audience participation games.',\r\n seriesOccurrences: [\r\n // Same-day shows (Fri Feb 20 — 7pm, 8pm, 9:30pm)\r\n {\r\n id: 2410,\r\n slug: 'improv-throwdown-feb-20-7pm',\r\n startDateTime: showcaseDate(0, 19),\r\n endDateTime: showcaseDate(0, 20, 30),\r\n status: 'sold_out',\r\n ctaText: 'Sold out',\r\n ctaDisabled: true,\r\n },\r\n {\r\n id: 2414,\r\n slug: 'improv-throwdown-feb-20-8pm',\r\n startDateTime: showcaseDate(0, 20),\r\n endDateTime: showcaseDate(0, 21, 30),\r\n status: 'on_sale',\r\n ctaText: 'Get tickets',\r\n ctaDisabled: false,\r\n },\r\n {\r\n id: 2415,\r\n slug: 'improv-throwdown-feb-20-930pm',\r\n startDateTime: showcaseDate(0, 21, 30),\r\n endDateTime: showcaseDate(0, 23),\r\n status: 'on_sale',\r\n ctaText: 'Get tickets',\r\n ctaDisabled: false,\r\n },\r\n // Single show days\r\n {\r\n id: 2411,\r\n slug: 'improv-throwdown-feb-27',\r\n startDateTime: showcaseDate(7, 20),\r\n endDateTime: showcaseDate(7, 22),\r\n status: 'sold_out',\r\n ctaText: 'Sold out',\r\n ctaDisabled: true,\r\n },\r\n {\r\n id: 2412,\r\n slug: 'improv-throwdown-mar-06',\r\n startDateTime: showcaseDate(14, 20),\r\n endDateTime: showcaseDate(14, 22),\r\n status: 'on_sale',\r\n ctaText: 'Get tickets',\r\n ctaDisabled: false,\r\n },\r\n {\r\n id: 2413,\r\n slug: 'improv-throwdown-mar-13',\r\n startDateTime: showcaseDate(21, 20),\r\n endDateTime: showcaseDate(21, 22),\r\n status: 'coming_soon',\r\n ctaText: 'Coming soon',\r\n ctaDisabled: true,\r\n },\r\n ],\r\n};\r\n\r\n// --- Registration Event (workshop — no time shown, just date + doors) ---\r\nexport const mockRegistrationEvent: EventData = {\r\n ...mockEvent,\r\n id: 2408,\r\n title: 'Stand-Up Comedy Workshop',\r\n slug: 'standup-comedy-workshop',\r\n imageUrl: '/posters/stand up 101.png', // 16:9 landscape 1920×1080\r\n description:\r\n 'Learn the fundamentals of stand-up comedy in this 3-hour intensive workshop. Write, refine, and perform your first 5-minute set.',\r\n isRegistrationEvent: true,\r\n displayStartTime: false,\r\n displayEndTime: false,\r\n status: 'on_sale',\r\n tickets: [\r\n {\r\n id: 301,\r\n name: 'Workshop Seat',\r\n description: 'Includes materials and performance slot',\r\n price: 75,\r\n fee: 7.5,\r\n quantityAvailable: 8,\r\n quantityTotal: 12,\r\n minPerOrder: 1,\r\n maxPerOrder: 1,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n ],\r\n totalTicketsRemaining: 8,\r\n totalTicketsCapacity: 12,\r\n};\r\n\r\n// --- Donation Event ---\r\nexport const mockDonationEvent: EventData = {\r\n ...mockEvent,\r\n id: 2414,\r\n title: 'Charity Comedy Benefit',\r\n slug: 'charity-comedy-benefit',\r\n imageUrl: '/posters/Friday Night Showdown.jpg',\r\n description:\r\n 'All proceeds go to the LA Comedy Relief Fund. Choose your own donation amount or grab a standard ticket.',\r\n status: 'on_sale',\r\n tickets: [\r\n {\r\n id: 401,\r\n name: 'Donation',\r\n description: 'Support the cause — choose your amount',\r\n price: 0,\r\n fee: 0,\r\n quantityAvailable: 200,\r\n quantityTotal: 200,\r\n minPerOrder: 1,\r\n maxPerOrder: 10,\r\n status: 'on_sale',\r\n isDonation: true,\r\n isHidden: false,\r\n ticketType: 2,\r\n },\r\n {\r\n id: 402,\r\n name: 'Standard Admission',\r\n description: 'Includes one drink ticket',\r\n price: 30,\r\n fee: 3,\r\n quantityAvailable: 80,\r\n quantityTotal: 100,\r\n minPerOrder: 1,\r\n maxPerOrder: 6,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n ],\r\n totalTicketsRemaining: 280,\r\n totalTicketsCapacity: 300,\r\n};\r\n\r\n// --- Mixed Event (ALL ticket states in one event) ---\r\nexport const mockMixedEvent: EventData = {\r\n ...mockEvent,\r\n id: 2415,\r\n title: 'The Everything Show',\r\n slug: 'the-everything-show',\r\n imageUrl: '/posters/the-duel-square.webp',\r\n description:\r\n 'A showcase event with every ticket state possible — for testing all edge cases.',\r\n status: 'on_sale',\r\n tickets: [\r\n {\r\n id: 501,\r\n name: 'General Admission',\r\n description: 'Standard seating in the main room',\r\n price: 25,\r\n fee: 2.5,\r\n quantityAvailable: 45,\r\n quantityTotal: 150,\r\n minPerOrder: 1,\r\n maxPerOrder: 8,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 502,\r\n name: 'Basic Entry',\r\n price: 15,\r\n fee: 1.5,\r\n quantityAvailable: 60,\r\n quantityTotal: 80,\r\n minPerOrder: 1,\r\n maxPerOrder: 4,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 503,\r\n name: 'VIP Front Row',\r\n description: 'Premium seats with complimentary drink',\r\n price: 75,\r\n fee: 7.5,\r\n quantityAvailable: 2,\r\n quantityTotal: 20,\r\n minPerOrder: 1,\r\n maxPerOrder: 4,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 504,\r\n name: 'Early Bird',\r\n description: 'Limited early bird pricing',\r\n price: 20,\r\n fee: 2,\r\n quantityAvailable: 0,\r\n quantityTotal: 30,\r\n minPerOrder: 1,\r\n maxPerOrder: 4,\r\n status: 'sold_out',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 505,\r\n name: 'Late Night Add-On',\r\n description: 'Access to the after-party at midnight',\r\n price: 40,\r\n fee: 4,\r\n quantityAvailable: 50,\r\n quantityTotal: 50,\r\n minPerOrder: 1,\r\n maxPerOrder: 2,\r\n status: 'coming_soon',\r\n salesStartDate: showcaseDate(9, 10),\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 506,\r\n name: 'Weekend Bundle',\r\n description: 'Includes Saturday + Sunday shows',\r\n price: 45,\r\n fee: 4.5,\r\n quantityAvailable: 0,\r\n quantityTotal: 25,\r\n minPerOrder: 1,\r\n maxPerOrder: 4,\r\n status: 'sales_ended',\r\n salesEndDate: showcaseDate(-10, 23, 59),\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 507,\r\n name: 'Donation',\r\n description: 'Support the performers directly',\r\n price: 0,\r\n fee: 0,\r\n quantityAvailable: 100,\r\n quantityTotal: 100,\r\n minPerOrder: 1,\r\n maxPerOrder: 5,\r\n status: 'on_sale',\r\n isDonation: true,\r\n isHidden: false,\r\n ticketType: 2,\r\n },\r\n {\r\n id: 508,\r\n name: 'Secret VIP Lounge',\r\n description: 'Backstage access with meet & greet',\r\n price: 150,\r\n fee: 15,\r\n quantityAvailable: 10,\r\n quantityTotal: 10,\r\n minPerOrder: 1,\r\n maxPerOrder: 2,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: true,\r\n },\r\n {\r\n id: 509,\r\n name: 'Industry Comp',\r\n description: 'Complimentary ticket for industry professionals',\r\n price: 0,\r\n fee: 0,\r\n quantityAvailable: 20,\r\n quantityTotal: 20,\r\n minPerOrder: 1,\r\n maxPerOrder: 1,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: true,\r\n },\r\n ],\r\n totalTicketsRemaining: 287,\r\n totalTicketsCapacity: 485,\r\n};\r\n\r\n// --- Promo Event (hidden tickets for promo reveal testing) ---\r\nexport const mockPromoEvent: EventData = {\r\n ...mockEvent,\r\n id: 2417,\r\n title: 'Secret Show',\r\n slug: 'secret-show',\r\n imageUrl: '/posters/luke-null-tall.webp',\r\n description:\r\n 'An intimate comedy experience. Some tickets are only available with a promo code.',\r\n status: 'on_sale',\r\n tickets: [\r\n {\r\n id: 701,\r\n name: 'General Admission',\r\n price: 30,\r\n fee: 3,\r\n quantityAvailable: 40,\r\n quantityTotal: 60,\r\n minPerOrder: 1,\r\n maxPerOrder: 6,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 702,\r\n name: 'Premium Seat',\r\n description: 'Reserved seating in rows 1-5',\r\n price: 50,\r\n fee: 5,\r\n quantityAvailable: 15,\r\n quantityTotal: 30,\r\n minPerOrder: 1,\r\n maxPerOrder: 4,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: false,\r\n },\r\n {\r\n id: 703,\r\n name: 'Artist Meet & Greet',\r\n description:\r\n 'Backstage pass with photo opportunity — promo code required',\r\n price: 100,\r\n fee: 10,\r\n quantityAvailable: 8,\r\n quantityTotal: 10,\r\n minPerOrder: 1,\r\n maxPerOrder: 2,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: true,\r\n },\r\n {\r\n id: 704,\r\n name: 'Industry Comp',\r\n description: 'Complimentary entry for industry professionals',\r\n price: 0,\r\n fee: 0,\r\n quantityAvailable: 10,\r\n quantityTotal: 10,\r\n minPerOrder: 1,\r\n maxPerOrder: 1,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: true,\r\n },\r\n ],\r\n totalTicketsRemaining: 73,\r\n totalTicketsCapacity: 110,\r\n};\r\n\r\n// --- Hidden-Only Event (MIC-1039) — no visible tickets, only hidden remain ---\r\n// Lands the user on a page where the only purchasable seats are gated behind\r\n// a promo code. With zero visible tickets the page should suppress the ticket\r\n// list entirely and render only the PromoCodeInput.\r\nexport const mockHiddenOnlyEvent: EventData = {\r\n ...mockEvent,\r\n id: 2419,\r\n title: 'Industry Showcase',\r\n slug: 'industry-showcase',\r\n description:\r\n 'A private comedy showcase. Tickets are only available with a promo code.',\r\n status: 'on_sale',\r\n tickets: [\r\n {\r\n id: 902,\r\n name: 'Industry Comp',\r\n description:\r\n 'Complimentary entry for industry professionals — promo code required',\r\n price: 0,\r\n fee: 0,\r\n quantityAvailable: 15,\r\n quantityTotal: 20,\r\n minPerOrder: 1,\r\n maxPerOrder: 2,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: true,\r\n },\r\n {\r\n id: 903,\r\n name: 'Artist Hold',\r\n description: 'Held for artist guests — promo code required',\r\n price: 50,\r\n fee: 5,\r\n quantityAvailable: 5,\r\n quantityTotal: 10,\r\n minPerOrder: 1,\r\n maxPerOrder: 4,\r\n status: 'on_sale',\r\n isDonation: false,\r\n isHidden: true,\r\n },\r\n ],\r\n totalTicketsRemaining: 0,\r\n totalTicketsCapacity: 0,\r\n};\r\n\r\n// --- Password Protected Event ---\r\nexport const mockPasswordEvent: EventData = {\r\n ...mockEvent,\r\n id: 2409,\r\n title: 'Secret Comedy Club',\r\n slug: 'secret-comedy-club',\r\n imageUrl: '/posters/luke-null-tall.webp', // tall portrait 625×937\r\n description: 'An exclusive underground comedy experience. Password required.',\r\n isPasswordProtected: true,\r\n status: 'on_sale',\r\n};\r\n","export type DataVariant =\r\n\t| 'default'\r\n\t| 'sold_out'\r\n\t| 'free'\r\n\t| 'registration'\r\n\t| 'series'\r\n\t| 'series_instance'\r\n\t| 'collection'\r\n\t| 'donation'\r\n\t| 'mixed'\r\n\t| 'sections'\r\n\t| 'promo'\r\n\t| 'multi_stage'\r\n\t| 'long'\r\n\t| 'wide';\r\n\r\nexport interface ToggleOption {\r\n\tvalue: string;\r\n\tlabel: string;\r\n\tcolor: string;\r\n}\r\n\r\nclass DataToggleStore {\r\n\tcurrent = $state<string>('default');\r\n\toptions = $state<ToggleOption[]>([]);\r\n\tisActive = $state(false);\r\n}\r\n\r\nexport const dataToggleStore = new DataToggleStore();\r\n","/**\r\n * Canonical state-option sets for the public-calendar-flow showcase.\r\n *\r\n * Per R-PATTERN-01 (canonicals-golden-rules.md): function form is the source,\r\n * static snapshots derive at module init. Every showcase surface that drives\r\n * `dataToggleStore` reads its option set from here — Checkout and Success each\r\n * used to inline their own array beside the variant union they switch on, so\r\n * the same `{ default, free, registration, donation }` core lived in several\r\n * places and could drift silently.\r\n *\r\n * A third set, `getShowcaseEventStates`, was removed in #615: its only caller\r\n * was `ShowcaseEvent.svelte`, deleted in the same change as dead code.\r\n *\r\n * Ordering is per-surface and deliberate: Checkout lists donation before\r\n * registration, Success lists registration before donation. The sets stay\r\n * distinct rather than merged so no surface's toggle order changes.\r\n */\r\nimport type { ToggleOption } from '$lib/public-calendar-flow/data-toggle-store.svelte';\r\n\r\n/**\r\n * Categorical hues for the showcase toggle dots — keyed by hue role, not by\r\n * state, so each class is named once and reused across every set.\r\n *\r\n * `info` is raw Tailwind palette (`bg-sky-500`) rather than an SC semantic\r\n * token, carried over verbatim from the arrays this module absorbed. It is the\r\n * one non-token hue here; replacing it is a color-category call, not an\r\n * options-array one.\r\n */\r\nconst HUE = {\r\n\tsuccess: 'bg-accent-success',\r\n\tneutral: 'bg-muted-foreground',\r\n\tinfo: 'bg-sky-500',\r\n\tbrand: 'bg-brand-primary',\r\n\tdanger: 'bg-accent-danger',\r\n\twarning: 'bg-accent-warning',\r\n\twarningSubtle: 'bg-status-warning-bg0',\r\n} as const;\r\n\r\nexport function getShowcaseBrowseStates(): ToggleOption[] {\r\n\treturn [\r\n\t\t{ value: 'default', label: 'Default', color: HUE.success },\r\n\t\t{ value: 'empty', label: 'Empty', color: HUE.neutral },\r\n\t\t{ value: 'sparse', label: '2 events', color: HUE.info },\r\n\t\t{ value: 'busy', label: 'Many events', color: HUE.brand },\r\n\t];\r\n}\r\n\r\nexport function getShowcaseCalendarStates(): ToggleOption[] {\r\n\treturn [\r\n\t\t{ value: 'default', label: 'Default', color: HUE.success },\r\n\t\t{ value: 'empty', label: 'Empty month', color: HUE.neutral },\r\n\t\t{ value: 'busy', label: 'Busy month', color: HUE.brand },\r\n\t];\r\n}\r\n\r\nexport function getShowcaseCheckoutStates(): ToggleOption[] {\r\n\treturn [\r\n\t\t{ value: 'default', label: 'Standard', color: HUE.success },\r\n\t\t{ value: 'free', label: 'Free', color: HUE.info },\r\n\t\t{ value: 'donation', label: 'Donation', color: HUE.danger },\r\n\t\t{ value: 'registration', label: 'Registration', color: HUE.brand },\r\n\t\t{ value: 'timer_warning', label: 'Timer warning', color: HUE.warningSubtle },\r\n\t\t{ value: 'expired', label: 'Expired', color: HUE.danger },\r\n\t\t{ value: 'promo', label: 'Promo discount', color: HUE.success },\r\n\t];\r\n}\r\n\r\nexport function getShowcaseSuccessStates(): ToggleOption[] {\r\n\treturn [\r\n\t\t{ value: 'default', label: 'Standard', color: HUE.success },\r\n\t\t{ value: 'free', label: 'Free', color: HUE.info },\r\n\t\t{ value: 'registration', label: 'Registration', color: HUE.brand },\r\n\t\t{ value: 'donation', label: 'Donation', color: HUE.danger },\r\n\t];\r\n}\r\n/** Static snapshots derived from the functions above — for non-reactive consumers. */\r\nexport const SHOWCASE_BROWSE_STATES = getShowcaseBrowseStates();\r\nexport const SHOWCASE_CALENDAR_STATES = getShowcaseCalendarStates();\r\n"],"names":["showcaseDate","daysFromFriday","hour","minute","now","daysToFriday","base","y","m","d","hh","mm","showcaseDateOnly","mockVenue","getDefaultTimezone","mockPerformers","mockFaqs","mockTickets","_now","_evDate","_ymd","mockEvent","DEFAULT_TIMEZONE","t","mockFreeEvent","mockRegistrationEvent","mockDonationEvent","DataToggleStore","#current","$","#isActive","dataToggleStore","HUE","getShowcaseCheckoutStates","getShowcaseSuccessStates"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { aN as D, b6 as g, b1 as _, b7 as b, an as v, ao as y, ap as q } from "./VenueCalendar-CjSz3oKW.js";
1
+ import { aN as D, b6 as g, b1 as _, b7 as b, an as v, ao as y, ap as q } from "./VenueCalendar-CU9NyjNN.js";
2
2
  function P(t) {
3
3
  if (!t) return [];
4
4
  const a = t.split(",").map((r) => r.trim());
@@ -268,4 +268,4 @@ export {
268
268
  A as f,
269
269
  x as t
270
270
  };
271
- //# sourceMappingURL=transform-CkDswNi6.js.map
271
+ //# sourceMappingURL=transform-CU3Mahyu.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"transform-CkDswNi6.js","sources":["../src/lib/api/transformers/address.ts","../src/lib/api/transformers/series.ts","../src/lib/api/transformers/collection.ts","../src/lib/public-calendar-flow/transform.ts"],"sourcesContent":["/**\r\n * Address helpers — shared between the event, series and collection page\r\n * transformers.\r\n *\r\n * Lifted verbatim from public-calendar-flow/transform.ts so the series and\r\n * collection canonicals (and the in-place transformApiEvent) read a single\r\n * source instead of each carrying a private copy. Behavior is byte-identical\r\n * to the previous module-private versions.\r\n */\r\n\r\n/**\r\n * Parse a single-line address string into display lines.\r\n * E.g. \"123 Main St, Los Angeles, CA 90012\" -> [\"123 Main St\", \"Los Angeles, CA 90012\"]\r\n */\r\nexport function parseAddress(addressStr: string): string[] {\r\n if (!addressStr) return [];\r\n const parts = addressStr.split(',').map(p => p.trim());\r\n if (parts.length < 2) return [addressStr];\r\n const lastPart = parts[parts.length - 1];\r\n const stateZipMatch = lastPart.match(/^([A-Z]{2})\\s+(\\d{5}(-\\d{4})?)$/);\r\n if (stateZipMatch && parts.length >= 3) {\r\n const state = stateZipMatch[1];\r\n const zip = stateZipMatch[2];\r\n const city = parts[parts.length - 2];\r\n const lines = parts.slice(0, -2);\r\n lines.push(`${city}, ${state} ${zip}`);\r\n return lines;\r\n }\r\n return [parts[0], parts.slice(1).join(', ')];\r\n}\r\n\r\n/**\r\n * Build a Google Maps search URL from an address string.\r\n */\r\nexport function buildGoogleMapsUrl(address: string): string {\r\n if (!address) return '';\r\n return `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(address)}`;\r\n}\r\n","/**\r\n * Series Page Transformer\r\n *\r\n * Wire->domain boundary for the public series page. Maps a SeriesPageData\r\n * payload (from the series API) into the clean EventData shape consumed by\r\n * SeriesPage.svelte / EventExperience (full-width series mode, set via\r\n * eventSeriesId).\r\n *\r\n * Lifted byte-identically from public-calendar-flow/transform.ts's\r\n * transformSeriesPageData. Every ||/?? fallthrough is preserved exactly;\r\n * characterization tests pin the output. transformSeriesPageData now delegates\r\n * here.\r\n *\r\n * COMPOSITION NOTE — why this does NOT reuse parseVenue:\r\n * The api `parseVenue` returns the api-domain `Venue` (raw timezone string,\r\n * fee fields read from the payload). The series page needs the pcf `VenueData`\r\n * shape: timezone is the IANA-RESOLVED zone (getIANATimezone) and the fee\r\n * fields are hard-zeroed (the series payload carries no venue fees). Those\r\n * shapes are not byte-compatible, so the venue sub-shape stays local.\r\n */\r\n\r\nimport { getIANATimezone } from '@getmicdrop/svelte-components';\r\nimport { resolveImageUrl } from '@getmicdrop/svelte-components';\r\nimport { formatDateKey } from '$lib/utils/datetime.js';\r\nimport { parseAddress, buildGoogleMapsUrl } from './address.js';\r\nimport type { SeriesPageData } from '../types.js';\r\nimport type {\r\n EventData,\r\n EventStatus,\r\n PerformerData,\r\n FAQItem,\r\n SeriesOccurrence,\r\n} from '$lib/public-calendar-flow/types';\r\n\r\n/**\r\n * Transform SeriesPageData (from the series API) into our clean EventData interface.\r\n * Sets eventSeriesId so EventExperience renders in full-width series mode.\r\n */\r\nexport function parseSeries(series: SeriesPageData): EventData {\r\n // Mirror the event transform: raw series carry lowercase `timezone`\r\n // (some PascalCase `timeZone` / snake `time_zone`). Read all casings so a\r\n // non-UTC series doesn't silently fall back to UTC.\r\n const seriesAny = series as SeriesPageData & {\r\n timezone?: string;\r\n time_zone?: string;\r\n };\r\n const timezone = getIANATimezone(\r\n series.timeZone || seriesAny.timezone || seriesAny.time_zone || 'UTC'\r\n );\r\n\r\n // Build image URL — SC resolveImageUrl already passes absolute URLs through,\r\n // so no local startsWith('http') guard is needed.\r\n const imageUrl = resolveImageUrl(series.image || '', { cdn: true });\r\n\r\n // Map occurrences to SeriesOccurrence[]\r\n const seriesOccurrences: SeriesOccurrence[] = (series.occurrences || []).map(\r\n occ => ({\r\n id: occ.id,\r\n slug: occ.slug || '',\r\n startDateTime: occ.startDateTime,\r\n endDateTime: occ.endDateTime || '',\r\n status: (occ.ctaState?.reason === 'sold_out'\r\n ? 'sold_out'\r\n : 'on_sale') as EventStatus,\r\n ctaText: occ.ctaState?.text || 'Get Tickets',\r\n ctaDisabled: occ.ctaState?.disabled || false,\r\n })\r\n );\r\n\r\n // Use first occurrence for date fields\r\n const firstOcc = series.occurrences?.[0];\r\n const date = firstOcc?.startDateTime\r\n ? formatDateKey(firstOcc.startDateTime, timezone)\r\n : '';\r\n\r\n // Map FAQs\r\n const rawFaq = series.venue?.faq;\r\n let faqs: FAQItem[] = [];\r\n if (Array.isArray(rawFaq)) {\r\n faqs = rawFaq.map(f => ({\r\n question: f.question || '',\r\n answer: f.answer || '',\r\n }));\r\n } else if (typeof rawFaq === 'string' && rawFaq) {\r\n faqs = [{ question: 'FAQ', answer: rawFaq }];\r\n }\r\n\r\n // Map performers\r\n const performers: PerformerData[] = (series.performers || []).map(\r\n (p, index) => ({\r\n id: index + 1,\r\n displayName:\r\n p.displayName || [p.firstName, p.lastName].filter(Boolean).join(' '),\r\n profileImage: p.profileImage || undefined,\r\n })\r\n );\r\n\r\n // Venue address\r\n const venueAddress =\r\n series.venue?.location || series.venue?.googleLocationNameCache || '';\r\n\r\n return {\r\n id: series.id,\r\n title: series.title || '',\r\n slug: '',\r\n description: series.description || series.eventSummary || '',\r\n date,\r\n startDateTime: firstOcc?.startDateTime || '',\r\n endDateTime: firstOcc?.endDateTime || '',\r\n doorsOpenTime: '',\r\n timezone,\r\n imageUrl,\r\n venue: {\r\n id: series.venue?.id || 0,\r\n name: series.venue?.name || '',\r\n address: venueAddress,\r\n timezone,\r\n serviceFeePercentage: 0,\r\n serviceFeeCents: 0,\r\n taxPercentage: 0,\r\n },\r\n performers,\r\n tickets: [],\r\n faqs,\r\n disclaimer: series.venue?.disclaimer || undefined,\r\n status: 'on_sale',\r\n eventSeriesId: series.id,\r\n seriesOccurrences,\r\n isPasswordProtected: false,\r\n isRegistrationEvent: false,\r\n totalTicketsRemaining: 0,\r\n totalTicketsCapacity: 0,\r\n venueAddressLines: parseAddress(venueAddress),\r\n googleMapsUrl: buildGoogleMapsUrl(venueAddress),\r\n };\r\n}\r\n\r\n/**\r\n * Back-compat alias — the public-calendar-flow shaper name. Existing call\r\n * sites importing transformSeriesPageData continue to work unchanged.\r\n */\r\nexport const transformSeriesPageData = parseSeries;\r\n","/**\r\n * Collection Page Transformer\r\n *\r\n * Wire->domain boundary for the public collection page. Maps a\r\n * PublicCollectionData payload (from the collection API) into the clean\r\n * EventData shape consumed by CollectionView.svelte / EventExperience\r\n * (full-width collection mode, set via collectionId).\r\n *\r\n * Lifted byte-identically from public-calendar-flow/transform.ts's\r\n * transformCollectionData. Every ||/?? fallthrough is preserved exactly;\r\n * characterization tests pin the output. transformCollectionData now delegates\r\n * here.\r\n *\r\n * COMPOSITION NOTE — why this does NOT reuse parseVenue/parseEvent:\r\n * The collection payload has no venue and no timezone; the EventData it\r\n * produces hard-codes an empty venue and 'UTC'. The per-event mapping is a\r\n * tiny CollectionEvent card shape (id/name/slug/image/startDateTime/status),\r\n * not the full Event domain — reusing parseEvent would change the output.\r\n * Both stay local.\r\n */\r\n\r\nimport { resolveImageUrl } from '@getmicdrop/svelte-components';\r\nimport type { PublicCollectionData } from '../types.js';\r\nimport type {\r\n EventData,\r\n EventStatus,\r\n CollectionEvent,\r\n} from '$lib/public-calendar-flow/types';\r\n\r\n/**\r\n * Transform PublicCollectionData (from the collection API) into our clean EventData interface.\r\n * Sets collectionId so EventExperience renders in full-width collection mode.\r\n */\r\nexport function parseCollection(collection: PublicCollectionData): EventData {\r\n // Map collection events to CollectionEvent[]\r\n const collectionEvents: CollectionEvent[] = (collection.events || []).map(\r\n ev => {\r\n return {\r\n id: ev.id,\r\n name: ev.title || '',\r\n slug: ev.slug || '',\r\n // SC's resolveImageUrl passes absolute http(s)/data/blob URLs through\r\n // untouched, so no local startsWith('http') guard is needed.\r\n image: resolveImageUrl(ev.image || '', { cdn: true }),\r\n startDateTime: ev.startDateTime || '',\r\n status: (ev.status || 'on_sale') as EventStatus,\r\n };\r\n }\r\n );\r\n\r\n // Cover image — SC resolveImageUrl already passes absolute URLs through.\r\n const imageUrl = resolveImageUrl(collection.coverImage || '', { cdn: true });\r\n\r\n return {\r\n id: collection.id,\r\n title: collection.collectionTitle || '',\r\n slug: '',\r\n description: collection.description || collection.summary || '',\r\n date: '',\r\n startDateTime: '',\r\n endDateTime: '',\r\n doorsOpenTime: '',\r\n timezone: 'UTC',\r\n imageUrl,\r\n venue: {\r\n id: 0,\r\n name: '',\r\n address: '',\r\n timezone: 'UTC',\r\n serviceFeePercentage: 0,\r\n serviceFeeCents: 0,\r\n taxPercentage: 0,\r\n },\r\n performers: [],\r\n tickets: [],\r\n faqs: [],\r\n status: 'on_sale',\r\n collectionId: collection.id,\r\n collectionEvents,\r\n isPasswordProtected: false,\r\n isRegistrationEvent: false,\r\n totalTicketsRemaining: 0,\r\n totalTicketsCapacity: 0,\r\n };\r\n}\r\n\r\n/**\r\n * Back-compat alias — the public-calendar-flow shaper name. Existing call\r\n * sites importing transformCollectionData continue to work unchanged.\r\n */\r\nexport const transformCollectionData = parseCollection;\r\n","import { getIANATimezone } from '@getmicdrop/svelte-components';\r\nimport {\r\n browserNow,\r\n compareInstants,\r\n toInstantOrNull,\r\n} from '@getmicdrop/svelte-components/datetime';\r\nimport { formatDateKey } from '$lib/utils/datetime.js';\r\n// Premium Ticket Experience — API → EventData Transformer\r\n// Maps raw API event responses to our clean EventData interface.\r\n// Used when plugging in real API data. The showcase continues using mock-data.ts directly.\r\n\r\nimport { resolveImageUrl } from '@getmicdrop/svelte-components';\r\nimport {\r\n parseAddress,\r\n buildGoogleMapsUrl,\r\n} from '$lib/api/transformers/address';\r\n// Canonical wire→domain boundary — all event-level scalar reads go through it.\r\nimport { parseEvent } from '$lib/api/transformers/event';\r\nimport { parseSeries } from '$lib/api/transformers/series';\r\nimport { parseCollection } from '$lib/api/transformers/collection';\r\nimport type {\r\n EventData,\r\n EventStatus,\r\n TicketTypeData,\r\n TicketStatus,\r\n VenueData,\r\n PerformerData,\r\n FAQItem,\r\n SeriesOccurrence,\r\n} from './types';\r\nimport type { SeriesPageData, PublicCollectionData } from '$lib/api/types';\r\n\r\n/**\r\n * A wire price that isn't a finite number — missing (null/undefined) OR malformed\r\n * (NaN, a non-numeric string) — resolves to null, so the ticket + order lines\r\n * render an em-dash and checkout hard-blocks, rather than a coerced $0/\"Free\" or a\r\n * NaN that later throws in toUSD (mf#2383 / vc#619). A numeric string (\"25\") is\r\n * preserved as its number.\r\n */\r\nexport function finitePriceOrNull(value: unknown): number | null {\r\n if (value == null) return null;\r\n const n = Number(value);\r\n return Number.isFinite(n) ? n : null;\r\n}\r\n\r\n/**\r\n * Map a raw API ticket status/state to our TicketStatus union.\r\n */\r\nfunction mapTicketStatus(ticket: any): TicketStatus {\r\n const now = browserNow();\r\n const remaining =\r\n ticket.remainingCapacity ??\r\n ticket.quantityRemaining ??\r\n ticket.quantity ??\r\n 0;\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\r\n if (remaining <= 0) return 'sold_out';\r\n const salesEndAt = toInstantOrNull(salesEnd);\r\n if (salesEndAt && compareInstants(salesEndAt, now) < 0) return 'sales_ended';\r\n const salesBeginAt = toInstantOrNull(salesBegin);\r\n if (salesBeginAt && compareInstants(salesBeginAt, now) > 0)\r\n return 'coming_soon';\r\n return 'on_sale';\r\n}\r\n\r\n/**\r\n * Map a raw API event status string to our EventStatus union.\r\n */\r\nfunction mapEventStatus(\r\n rawStatus: string,\r\n tickets: TicketTypeData[]\r\n): EventStatus {\r\n const s = (rawStatus || '').toLowerCase().replace(/\\s+/g, '_');\r\n\r\n if (s === 'cancelled' || s === 'canceled') return 'cancelled';\r\n\r\n // Check if event is past based on end time (handled by caller if needed)\r\n if (s === 'past' || s === 'ended') return 'past';\r\n\r\n // MIC-1039: if any hidden ticket is still on sale, the event is \"on_sale\"\r\n // regardless of visible-ticket states — the user just needs a promo code.\r\n // NOTE: this operates on the pcf DOMAIN ticket shape (post-transform, with a\r\n // computed `status` string), NOT the wire shape SC's\r\n // `isHiddenTicketPurchasable` reads (raw visibility/salesChannel/sale-window\r\n // fields). The sale-window math already happened in `mapTicketStatus`, so the\r\n // SC predicate can't honestly serve this site — kept deliberately local.\r\n const hasPurchasableHiddenTickets = tickets.some(\r\n t => t.isHidden && t.status === 'on_sale'\r\n );\r\n if (hasPurchasableHiddenTickets) return 'on_sale';\r\n\r\n // Derive from ticket states\r\n const publicTickets = tickets.filter(t => !t.isHidden);\r\n if (publicTickets.length > 0) {\r\n if (publicTickets.every(t => t.status === 'sold_out')) return 'sold_out';\r\n if (publicTickets.every(t => t.status === 'coming_soon'))\r\n return 'coming_soon';\r\n if (\r\n publicTickets.every(\r\n t => t.status === 'sales_ended' || t.status === 'sold_out'\r\n )\r\n )\r\n return 'sales_ended';\r\n }\r\n\r\n if (s === 'sold_out' || s === 'soldout') return 'sold_out';\r\n if (s === 'coming_soon' || s === 'comingsoon') return 'coming_soon';\r\n if (s === 'sales_ended' || s === 'salesended') return 'sales_ended';\r\n\r\n return 'on_sale';\r\n}\r\n\r\n/**\r\n * Transform a raw API event response into our clean EventData interface.\r\n * This is the bridge between the API and our premium ticket experience components.\r\n *\r\n * COMPOSITION NOTE (events convergence): the wire is parsed ONCE through the\r\n * canonical parseEvent ($lib/api/transformers/event); every event-level\r\n * scalar below projects off the domain Event. Three deliberate wire seams\r\n * remain, characterization-pinned in\r\n * utils/event-shapers.characterization.test.js:\r\n * 1. TICKETS — the TicketTypeData map uses `??` (nullish) semantics over\r\n * raw ticket fields (remainingCapacity/visibility/fee/…) that\r\n * parseTicket's `||`-folding AvailableTicket neither carries nor\r\n * preserves; routing through parseTicket would change rendered output.\r\n * 2. IMAGE — image→imageUrl→image_url precedence intentionally differs\r\n * from the canonical resolver's (imageUrl-first); see the note in\r\n * api/transformers/event.ts.\r\n * 3. VENUE/PERFORMERS — mapped from the raw passthrough objects\r\n * (domain.venue / domain.performers) with B-specific `??` fee/tax\r\n * semantics; the performer canonical lands in PR #260 and should\r\n * absorb the performer map then.\r\n */\r\nexport function transformApiEvent(rawEvent: any): EventData {\r\n // Wire→domain ONCE (see composition note).\r\n const domain = parseEvent(rawEvent);\r\n const rawVenue = domain.venue || {};\r\n // Event-level timeZone is an OPTIONAL per-event override; when absent/blank it\r\n // must inherit the venue timezone. Falling straight to 'UTC' here rendered\r\n // venue-local times (e.g. a Fri 10pm Central show) in UTC (\"Sat 3:00 AM\"),\r\n // which made already-ended events look like future ones.\r\n // (domain.timeZone is the verbatim PascalCase passthrough; domain.timezone\r\n // folds lowercase + snake_case — same chain as before.)\r\n const timezone = getIANATimezone(\r\n domain.timeZone ||\r\n domain.timezone ||\r\n rawVenue.timeZone ||\r\n rawVenue.timezone ||\r\n 'UTC'\r\n );\r\n\r\n // Transform tickets — TICKET SEAM: raw wire tickets by contract (see note).\r\n const rawTickets = rawEvent.availableTickets || [];\r\n const tickets: TicketTypeData[] = rawTickets.map((t: any) => ({\r\n id: t.id || t.ID,\r\n name: t.name || t.title || '',\r\n description: t.description || undefined,\r\n // A missing OR malformed wire price stays null → the ticket + order lines\r\n // render an em-dash and checkout hard-blocks, never a coerced $0/\"Free\" or a\r\n // NaN that throws in toUSD (mf#2383).\r\n price: finitePriceOrNull(t.price),\r\n // Legitimate-zero: a ticket with no per-ticket fee is a real 0, not a\r\n // missing price (mf#2234's separately-ruled class). A ternary keeps the 0\r\n // default without a `?? 0` money-field flag AND without a file-level escape\r\n // that would blind the price site above.\r\n fee: t.fee == null ? 0 : t.fee,\r\n quantityAvailable:\r\n t.remainingCapacity ?? t.quantityRemaining ?? t.quantity ?? 0,\r\n quantityTotal: t.totalCapacity ?? t.quantity ?? 0,\r\n minPerOrder: t.minPerOrder ?? t.minQuantity ?? 1,\r\n maxPerOrder: t.maxPerOrder ?? t.maxQuantity ?? 10,\r\n status: mapTicketStatus(t),\r\n salesStartDate:\r\n t.salesBegin || t.salesStart || t.saleBegin || t.onSaleStart || undefined,\r\n salesEndDate: t.salesEnd || t.saleEnd || t.onSaleEnd || undefined,\r\n isDonation: t.type === 2 || t.ticketType === 2 || t.isDonation === true,\r\n isHidden: t.visibility === 2 || t.isHidden === true,\r\n ticketType: t.type || t.ticketType || undefined,\r\n sectionName: t.sectionName || t.section || undefined,\r\n }));\r\n\r\n // Calculate totals from public tickets\r\n const publicTickets = tickets.filter(t => !t.isHidden && !t.isDonation);\r\n const totalRemaining = publicTickets.reduce(\r\n (sum, t) => sum + t.quantityAvailable,\r\n 0\r\n );\r\n const totalCapacity = publicTickets.reduce(\r\n (sum, t) => sum + t.quantityTotal,\r\n 0\r\n );\r\n\r\n // Determine event status\r\n const status = mapEventStatus(domain.status as string, tickets);\r\n\r\n // Build image URL — IMAGE SEAM: image-first precedence (see note).\r\n const rawImage =\r\n rawEvent.image || rawEvent.imageUrl || rawEvent.image_url || '';\r\n const imageUrl = rawImage.startsWith('http')\r\n ? rawImage\r\n : resolveImageUrl(rawImage, { cdn: true });\r\n\r\n // Venue\r\n const venue: VenueData = {\r\n id: rawVenue.id || rawVenue.ID || 0,\r\n name: rawVenue.name || rawVenue.googleLocationNameCache || '',\r\n address: rawVenue.address || rawVenue.googleLocationNameCache || '',\r\n timezone,\r\n serviceFeePercentage: rawVenue.serviceFeePercentage ?? rawVenue.fee ?? 0,\r\n // Legitimate-zero venue fee config (mf#2234's ruled-separate class): a venue\r\n // with no flat service fee is a real 0. Ternary keeps the default without a\r\n // `?? 0` money-field flag (this file also carries the price site above, so a\r\n // file-level escape would wrongly blind it).\r\n serviceFeeCents:\r\n rawVenue.serviceFeeCents == null ? 0 : rawVenue.serviceFeeCents,\r\n taxPercentage: rawVenue.taxPercentage ?? rawVenue.tax ?? 0,\r\n contactEmail: rawVenue.contactEmail || rawVenue.email || undefined,\r\n };\r\n\r\n // Performers — VENUE/PERFORMERS SEAM: raw passthrough map (see note).\r\n const rawPerformers = domain.performers || [];\r\n const performers: PerformerData[] = rawPerformers.map((p: any) => ({\r\n id: p.id || p.ID,\r\n displayName: p.displayName || p.name || '',\r\n profileImage: p.avatar || p.profileImage || undefined,\r\n role: p.role || undefined,\r\n }));\r\n\r\n // FAQs (may not be in API response)\r\n const faqs: FAQItem[] = (domain.faqs || []).map((f: any) => ({\r\n question: f.question || '',\r\n answer: f.answer || '',\r\n }));\r\n\r\n // Series showtimes → occurrences. A single series-event detail carries a\r\n // `showtimes` array; the v2 <ShowtimeDesigns> renders event.seriesOccurrences\r\n // under \"Upcoming Shows\". Without this map the section is always empty.\r\n const seriesOccurrences: SeriesOccurrence[] = (domain.showtimes || [])\r\n .filter((s: any) => s.published !== false)\r\n .map((s: any, i: number) => ({\r\n id: s.id ?? s.eventId ?? i + 1,\r\n slug: s.slug || '',\r\n startDateTime: s.startDateTime || s.startTime || '',\r\n endDateTime: s.endDateTime || s.endTime || '',\r\n status: (s.ctaState?.reason === 'sold_out'\r\n ? 'sold_out'\r\n : 'on_sale') as EventStatus,\r\n ctaText: s.ctaState?.text || 'Get tickets',\r\n ctaDisabled: s.ctaState?.disabled || false,\r\n }));\r\n\r\n // Date in venue timezone\r\n const date = domain.startDateTime\r\n ? formatDateKey(domain.startDateTime, timezone)\r\n : '';\r\n\r\n return {\r\n id: domain.id,\r\n title: domain.title || '',\r\n slug: domain.slug || '',\r\n description: domain.description || domain.eventSummary || '',\r\n date,\r\n startDateTime: domain.startDateTime || '',\r\n endDateTime: domain.endDateTime || '',\r\n doorsOpenTime: domain.doorsOpenTime || '',\r\n timezone,\r\n imageUrl,\r\n venue,\r\n performers,\r\n tickets,\r\n faqs,\r\n disclaimer: domain.disclaimer || undefined,\r\n status,\r\n eventSeriesId: domain.eventSeriesId || undefined,\r\n seriesOccurrences: seriesOccurrences.length ? seriesOccurrences : undefined,\r\n // Public API hides the actual password (json:\"-\") and exposes a boolean\r\n // `hasPassword` flag instead; fall back to a populated `password` for\r\n // admin-shaped payloads.\r\n isPasswordProtected: domain.hasPassword === true || !!domain.password,\r\n isRegistrationEvent:\r\n domain.ticketType === 1 || domain.eventTicketingType === 1,\r\n totalTicketsRemaining: totalRemaining,\r\n totalTicketsCapacity: totalCapacity,\r\n stageName: domain.stage?.name || domain.stageName || undefined,\r\n ageRestriction: domain.ageRestriction || undefined,\r\n displayAgeRestriction: domain.displayAgeRestriction ?? false,\r\n displayStartTime: domain.displayStartTime ?? true,\r\n displayEndTime: domain.displayEndTime ?? true,\r\n displayDoorsTime: domain.displayDoorsTime ?? true,\r\n collectionId: domain.collectionId || undefined, // domain folds collection_id\r\n venueAddressLines: parseAddress(\r\n rawVenue.address || rawVenue.googleLocationNameCache || ''\r\n ),\r\n googleMapsUrl: buildGoogleMapsUrl(\r\n rawVenue.address || rawVenue.googleLocationNameCache || ''\r\n ),\r\n };\r\n}\r\n\r\n/**\r\n * Transform SeriesPageData (from the series API) into our clean EventData interface.\r\n * Sets eventSeriesId so EventExperience renders in full-width series mode.\r\n */\r\nexport function transformSeriesPageData(series: SeriesPageData): EventData {\r\n // Implementation moved to the canonical transformer home\r\n // (`$lib/api/transformers/series.ts`). This export stays as a thin delegate\r\n // so SeriesPage.svelte and other consumers don't churn.\r\n return parseSeries(series);\r\n}\r\n\r\n/**\r\n * Transform PublicCollectionData (from the collection API) into our clean EventData interface.\r\n * Sets collectionId so EventExperience renders in full-width collection mode.\r\n */\r\nexport function transformCollectionData(\r\n collection: PublicCollectionData\r\n): EventData {\r\n // Implementation moved to the canonical transformer home\r\n // (`$lib/api/transformers/collection.ts`). This export stays as a thin\r\n // delegate so CollectionView.svelte and other consumers don't churn.\r\n return parseCollection(collection);\r\n}\r\n"],"names":["parseAddress","addressStr","parts","p","stateZipMatch","state","zip","city","lines","buildGoogleMapsUrl","address","parseSeries","series","seriesAny","timezone","getIANATimezone","imageUrl","resolveImageUrl","seriesOccurrences","occ","firstOcc","date","formatDateKey","rawFaq","faqs","f","performers","index","venueAddress","parseCollection","collection","collectionEvents","ev","finitePriceOrNull","value","n","mapTicketStatus","ticket","now","browserNow","remaining","salesBegin","salesEnd","salesEndAt","toInstantOrNull","compareInstants","salesBeginAt","mapEventStatus","rawStatus","tickets","t","publicTickets","transformApiEvent","rawEvent","domain","parseEvent","rawVenue","totalRemaining","sum","totalCapacity","status","rawImage","venue","s","i","transformSeriesPageData","transformCollectionData"],"mappings":"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"}
1
+ {"version":3,"file":"transform-CU3Mahyu.js","sources":["../src/lib/api/transformers/address.ts","../src/lib/api/transformers/series.ts","../src/lib/api/transformers/collection.ts","../src/lib/public-calendar-flow/transform.ts"],"sourcesContent":["/**\r\n * Address helpers — shared between the event, series and collection page\r\n * transformers.\r\n *\r\n * Lifted verbatim from public-calendar-flow/transform.ts so the series and\r\n * collection canonicals (and the in-place transformApiEvent) read a single\r\n * source instead of each carrying a private copy. Behavior is byte-identical\r\n * to the previous module-private versions.\r\n */\r\n\r\n/**\r\n * Parse a single-line address string into display lines.\r\n * E.g. \"123 Main St, Los Angeles, CA 90012\" -> [\"123 Main St\", \"Los Angeles, CA 90012\"]\r\n */\r\nexport function parseAddress(addressStr: string): string[] {\r\n if (!addressStr) return [];\r\n const parts = addressStr.split(',').map(p => p.trim());\r\n if (parts.length < 2) return [addressStr];\r\n const lastPart = parts[parts.length - 1];\r\n const stateZipMatch = lastPart.match(/^([A-Z]{2})\\s+(\\d{5}(-\\d{4})?)$/);\r\n if (stateZipMatch && parts.length >= 3) {\r\n const state = stateZipMatch[1];\r\n const zip = stateZipMatch[2];\r\n const city = parts[parts.length - 2];\r\n const lines = parts.slice(0, -2);\r\n lines.push(`${city}, ${state} ${zip}`);\r\n return lines;\r\n }\r\n return [parts[0], parts.slice(1).join(', ')];\r\n}\r\n\r\n/**\r\n * Build a Google Maps search URL from an address string.\r\n */\r\nexport function buildGoogleMapsUrl(address: string): string {\r\n if (!address) return '';\r\n return `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(address)}`;\r\n}\r\n","/**\r\n * Series Page Transformer\r\n *\r\n * Wire->domain boundary for the public series page. Maps a SeriesPageData\r\n * payload (from the series API) into the clean EventData shape consumed by\r\n * SeriesPage.svelte / EventExperience (full-width series mode, set via\r\n * eventSeriesId).\r\n *\r\n * Lifted byte-identically from public-calendar-flow/transform.ts's\r\n * transformSeriesPageData. Every ||/?? fallthrough is preserved exactly;\r\n * characterization tests pin the output. transformSeriesPageData now delegates\r\n * here.\r\n *\r\n * COMPOSITION NOTE — why this does NOT reuse parseVenue:\r\n * The api `parseVenue` returns the api-domain `Venue` (raw timezone string,\r\n * fee fields read from the payload). The series page needs the pcf `VenueData`\r\n * shape: timezone is the IANA-RESOLVED zone (getIANATimezone) and the fee\r\n * fields are hard-zeroed (the series payload carries no venue fees). Those\r\n * shapes are not byte-compatible, so the venue sub-shape stays local.\r\n */\r\n\r\nimport { getIANATimezone } from '@getmicdrop/svelte-components';\r\nimport { resolveImageUrl } from '@getmicdrop/svelte-components';\r\nimport { formatDateKey } from '$lib/utils/datetime.js';\r\nimport { parseAddress, buildGoogleMapsUrl } from './address.js';\r\nimport type { SeriesPageData } from '../types.js';\r\nimport type {\r\n EventData,\r\n EventStatus,\r\n PerformerData,\r\n FAQItem,\r\n SeriesOccurrence,\r\n} from '$lib/public-calendar-flow/types';\r\n\r\n/**\r\n * Transform SeriesPageData (from the series API) into our clean EventData interface.\r\n * Sets eventSeriesId so EventExperience renders in full-width series mode.\r\n */\r\nexport function parseSeries(series: SeriesPageData): EventData {\r\n // Mirror the event transform: raw series carry lowercase `timezone`\r\n // (some PascalCase `timeZone` / snake `time_zone`). Read all casings so a\r\n // non-UTC series doesn't silently fall back to UTC.\r\n const seriesAny = series as SeriesPageData & {\r\n timezone?: string;\r\n time_zone?: string;\r\n };\r\n const timezone = getIANATimezone(\r\n series.timeZone || seriesAny.timezone || seriesAny.time_zone || 'UTC'\r\n );\r\n\r\n // Build image URL — SC resolveImageUrl already passes absolute URLs through,\r\n // so no local startsWith('http') guard is needed.\r\n const imageUrl = resolveImageUrl(series.image || '', { cdn: true });\r\n\r\n // Map occurrences to SeriesOccurrence[]\r\n const seriesOccurrences: SeriesOccurrence[] = (series.occurrences || []).map(\r\n occ => ({\r\n id: occ.id,\r\n slug: occ.slug || '',\r\n startDateTime: occ.startDateTime,\r\n endDateTime: occ.endDateTime || '',\r\n status: (occ.ctaState?.reason === 'sold_out'\r\n ? 'sold_out'\r\n : 'on_sale') as EventStatus,\r\n ctaText: occ.ctaState?.text || 'Get Tickets',\r\n ctaDisabled: occ.ctaState?.disabled || false,\r\n })\r\n );\r\n\r\n // Use first occurrence for date fields\r\n const firstOcc = series.occurrences?.[0];\r\n const date = firstOcc?.startDateTime\r\n ? formatDateKey(firstOcc.startDateTime, timezone)\r\n : '';\r\n\r\n // Map FAQs\r\n const rawFaq = series.venue?.faq;\r\n let faqs: FAQItem[] = [];\r\n if (Array.isArray(rawFaq)) {\r\n faqs = rawFaq.map(f => ({\r\n question: f.question || '',\r\n answer: f.answer || '',\r\n }));\r\n } else if (typeof rawFaq === 'string' && rawFaq) {\r\n faqs = [{ question: 'FAQ', answer: rawFaq }];\r\n }\r\n\r\n // Map performers\r\n const performers: PerformerData[] = (series.performers || []).map(\r\n (p, index) => ({\r\n id: index + 1,\r\n displayName:\r\n p.displayName || [p.firstName, p.lastName].filter(Boolean).join(' '),\r\n profileImage: p.profileImage || undefined,\r\n })\r\n );\r\n\r\n // Venue address\r\n const venueAddress =\r\n series.venue?.location || series.venue?.googleLocationNameCache || '';\r\n\r\n return {\r\n id: series.id,\r\n title: series.title || '',\r\n slug: '',\r\n description: series.description || series.eventSummary || '',\r\n date,\r\n startDateTime: firstOcc?.startDateTime || '',\r\n endDateTime: firstOcc?.endDateTime || '',\r\n doorsOpenTime: '',\r\n timezone,\r\n imageUrl,\r\n venue: {\r\n id: series.venue?.id || 0,\r\n name: series.venue?.name || '',\r\n address: venueAddress,\r\n timezone,\r\n serviceFeePercentage: 0,\r\n serviceFeeCents: 0,\r\n taxPercentage: 0,\r\n },\r\n performers,\r\n tickets: [],\r\n faqs,\r\n disclaimer: series.venue?.disclaimer || undefined,\r\n status: 'on_sale',\r\n eventSeriesId: series.id,\r\n seriesOccurrences,\r\n isPasswordProtected: false,\r\n isRegistrationEvent: false,\r\n totalTicketsRemaining: 0,\r\n totalTicketsCapacity: 0,\r\n venueAddressLines: parseAddress(venueAddress),\r\n googleMapsUrl: buildGoogleMapsUrl(venueAddress),\r\n };\r\n}\r\n\r\n/**\r\n * Back-compat alias — the public-calendar-flow shaper name. Existing call\r\n * sites importing transformSeriesPageData continue to work unchanged.\r\n */\r\nexport const transformSeriesPageData = parseSeries;\r\n","/**\r\n * Collection Page Transformer\r\n *\r\n * Wire->domain boundary for the public collection page. Maps a\r\n * PublicCollectionData payload (from the collection API) into the clean\r\n * EventData shape consumed by CollectionView.svelte / EventExperience\r\n * (full-width collection mode, set via collectionId).\r\n *\r\n * Lifted byte-identically from public-calendar-flow/transform.ts's\r\n * transformCollectionData. Every ||/?? fallthrough is preserved exactly;\r\n * characterization tests pin the output. transformCollectionData now delegates\r\n * here.\r\n *\r\n * COMPOSITION NOTE — why this does NOT reuse parseVenue/parseEvent:\r\n * The collection payload has no venue and no timezone; the EventData it\r\n * produces hard-codes an empty venue and 'UTC'. The per-event mapping is a\r\n * tiny CollectionEvent card shape (id/name/slug/image/startDateTime/status),\r\n * not the full Event domain — reusing parseEvent would change the output.\r\n * Both stay local.\r\n */\r\n\r\nimport { resolveImageUrl } from '@getmicdrop/svelte-components';\r\nimport type { PublicCollectionData } from '../types.js';\r\nimport type {\r\n EventData,\r\n EventStatus,\r\n CollectionEvent,\r\n} from '$lib/public-calendar-flow/types';\r\n\r\n/**\r\n * Transform PublicCollectionData (from the collection API) into our clean EventData interface.\r\n * Sets collectionId so EventExperience renders in full-width collection mode.\r\n */\r\nexport function parseCollection(collection: PublicCollectionData): EventData {\r\n // Map collection events to CollectionEvent[]\r\n const collectionEvents: CollectionEvent[] = (collection.events || []).map(\r\n ev => {\r\n return {\r\n id: ev.id,\r\n name: ev.title || '',\r\n slug: ev.slug || '',\r\n // SC's resolveImageUrl passes absolute http(s)/data/blob URLs through\r\n // untouched, so no local startsWith('http') guard is needed.\r\n image: resolveImageUrl(ev.image || '', { cdn: true }),\r\n startDateTime: ev.startDateTime || '',\r\n status: (ev.status || 'on_sale') as EventStatus,\r\n };\r\n }\r\n );\r\n\r\n // Cover image — SC resolveImageUrl already passes absolute URLs through.\r\n const imageUrl = resolveImageUrl(collection.coverImage || '', { cdn: true });\r\n\r\n return {\r\n id: collection.id,\r\n title: collection.collectionTitle || '',\r\n slug: '',\r\n description: collection.description || collection.summary || '',\r\n date: '',\r\n startDateTime: '',\r\n endDateTime: '',\r\n doorsOpenTime: '',\r\n timezone: 'UTC',\r\n imageUrl,\r\n venue: {\r\n id: 0,\r\n name: '',\r\n address: '',\r\n timezone: 'UTC',\r\n serviceFeePercentage: 0,\r\n serviceFeeCents: 0,\r\n taxPercentage: 0,\r\n },\r\n performers: [],\r\n tickets: [],\r\n faqs: [],\r\n status: 'on_sale',\r\n collectionId: collection.id,\r\n collectionEvents,\r\n isPasswordProtected: false,\r\n isRegistrationEvent: false,\r\n totalTicketsRemaining: 0,\r\n totalTicketsCapacity: 0,\r\n };\r\n}\r\n\r\n/**\r\n * Back-compat alias — the public-calendar-flow shaper name. Existing call\r\n * sites importing transformCollectionData continue to work unchanged.\r\n */\r\nexport const transformCollectionData = parseCollection;\r\n","import { getIANATimezone } from '@getmicdrop/svelte-components';\r\nimport {\r\n browserNow,\r\n compareInstants,\r\n toInstantOrNull,\r\n} from '@getmicdrop/svelte-components/datetime';\r\nimport { formatDateKey } from '$lib/utils/datetime.js';\r\n// Premium Ticket Experience — API → EventData Transformer\r\n// Maps raw API event responses to our clean EventData interface.\r\n// Used when plugging in real API data. The showcase continues using mock-data.ts directly.\r\n\r\nimport { resolveImageUrl } from '@getmicdrop/svelte-components';\r\nimport {\r\n parseAddress,\r\n buildGoogleMapsUrl,\r\n} from '$lib/api/transformers/address';\r\n// Canonical wire→domain boundary — all event-level scalar reads go through it.\r\nimport { parseEvent } from '$lib/api/transformers/event';\r\nimport { parseSeries } from '$lib/api/transformers/series';\r\nimport { parseCollection } from '$lib/api/transformers/collection';\r\nimport type {\r\n EventData,\r\n EventStatus,\r\n TicketTypeData,\r\n TicketStatus,\r\n VenueData,\r\n PerformerData,\r\n FAQItem,\r\n SeriesOccurrence,\r\n} from './types';\r\nimport type { SeriesPageData, PublicCollectionData } from '$lib/api/types';\r\n\r\n/**\r\n * A wire price that isn't a finite number — missing (null/undefined) OR malformed\r\n * (NaN, a non-numeric string) — resolves to null, so the ticket + order lines\r\n * render an em-dash and checkout hard-blocks, rather than a coerced $0/\"Free\" or a\r\n * NaN that later throws in toUSD (mf#2383 / vc#619). A numeric string (\"25\") is\r\n * preserved as its number.\r\n */\r\nexport function finitePriceOrNull(value: unknown): number | null {\r\n if (value == null) return null;\r\n const n = Number(value);\r\n return Number.isFinite(n) ? n : null;\r\n}\r\n\r\n/**\r\n * Map a raw API ticket status/state to our TicketStatus union.\r\n */\r\nfunction mapTicketStatus(ticket: any): TicketStatus {\r\n const now = browserNow();\r\n const remaining =\r\n ticket.remainingCapacity ??\r\n ticket.quantityRemaining ??\r\n ticket.quantity ??\r\n 0;\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\r\n if (remaining <= 0) return 'sold_out';\r\n const salesEndAt = toInstantOrNull(salesEnd);\r\n if (salesEndAt && compareInstants(salesEndAt, now) < 0) return 'sales_ended';\r\n const salesBeginAt = toInstantOrNull(salesBegin);\r\n if (salesBeginAt && compareInstants(salesBeginAt, now) > 0)\r\n return 'coming_soon';\r\n return 'on_sale';\r\n}\r\n\r\n/**\r\n * Map a raw API event status string to our EventStatus union.\r\n */\r\nfunction mapEventStatus(\r\n rawStatus: string,\r\n tickets: TicketTypeData[]\r\n): EventStatus {\r\n const s = (rawStatus || '').toLowerCase().replace(/\\s+/g, '_');\r\n\r\n if (s === 'cancelled' || s === 'canceled') return 'cancelled';\r\n\r\n // Check if event is past based on end time (handled by caller if needed)\r\n if (s === 'past' || s === 'ended') return 'past';\r\n\r\n // MIC-1039: if any hidden ticket is still on sale, the event is \"on_sale\"\r\n // regardless of visible-ticket states — the user just needs a promo code.\r\n // NOTE: this operates on the pcf DOMAIN ticket shape (post-transform, with a\r\n // computed `status` string), NOT the wire shape SC's\r\n // `isHiddenTicketPurchasable` reads (raw visibility/salesChannel/sale-window\r\n // fields). The sale-window math already happened in `mapTicketStatus`, so the\r\n // SC predicate can't honestly serve this site — kept deliberately local.\r\n const hasPurchasableHiddenTickets = tickets.some(\r\n t => t.isHidden && t.status === 'on_sale'\r\n );\r\n if (hasPurchasableHiddenTickets) return 'on_sale';\r\n\r\n // Derive from ticket states\r\n const publicTickets = tickets.filter(t => !t.isHidden);\r\n if (publicTickets.length > 0) {\r\n if (publicTickets.every(t => t.status === 'sold_out')) return 'sold_out';\r\n if (publicTickets.every(t => t.status === 'coming_soon'))\r\n return 'coming_soon';\r\n if (\r\n publicTickets.every(\r\n t => t.status === 'sales_ended' || t.status === 'sold_out'\r\n )\r\n )\r\n return 'sales_ended';\r\n }\r\n\r\n if (s === 'sold_out' || s === 'soldout') return 'sold_out';\r\n if (s === 'coming_soon' || s === 'comingsoon') return 'coming_soon';\r\n if (s === 'sales_ended' || s === 'salesended') return 'sales_ended';\r\n\r\n return 'on_sale';\r\n}\r\n\r\n/**\r\n * Transform a raw API event response into our clean EventData interface.\r\n * This is the bridge between the API and our premium ticket experience components.\r\n *\r\n * COMPOSITION NOTE (events convergence): the wire is parsed ONCE through the\r\n * canonical parseEvent ($lib/api/transformers/event); every event-level\r\n * scalar below projects off the domain Event. Three deliberate wire seams\r\n * remain, characterization-pinned in\r\n * utils/event-shapers.characterization.test.js:\r\n * 1. TICKETS — the TicketTypeData map uses `??` (nullish) semantics over\r\n * raw ticket fields (remainingCapacity/visibility/fee/…) that\r\n * parseTicket's `||`-folding AvailableTicket neither carries nor\r\n * preserves; routing through parseTicket would change rendered output.\r\n * 2. IMAGE — image→imageUrl→image_url precedence intentionally differs\r\n * from the canonical resolver's (imageUrl-first); see the note in\r\n * api/transformers/event.ts.\r\n * 3. VENUE/PERFORMERS — mapped from the raw passthrough objects\r\n * (domain.venue / domain.performers) with B-specific `??` fee/tax\r\n * semantics; the performer canonical lands in PR #260 and should\r\n * absorb the performer map then.\r\n */\r\nexport function transformApiEvent(rawEvent: any): EventData {\r\n // Wire→domain ONCE (see composition note).\r\n const domain = parseEvent(rawEvent);\r\n const rawVenue = domain.venue || {};\r\n // Event-level timeZone is an OPTIONAL per-event override; when absent/blank it\r\n // must inherit the venue timezone. Falling straight to 'UTC' here rendered\r\n // venue-local times (e.g. a Fri 10pm Central show) in UTC (\"Sat 3:00 AM\"),\r\n // which made already-ended events look like future ones.\r\n // (domain.timeZone is the verbatim PascalCase passthrough; domain.timezone\r\n // folds lowercase + snake_case — same chain as before.)\r\n const timezone = getIANATimezone(\r\n domain.timeZone ||\r\n domain.timezone ||\r\n rawVenue.timeZone ||\r\n rawVenue.timezone ||\r\n 'UTC'\r\n );\r\n\r\n // Transform tickets — TICKET SEAM: raw wire tickets by contract (see note).\r\n const rawTickets = rawEvent.availableTickets || [];\r\n const tickets: TicketTypeData[] = rawTickets.map((t: any) => ({\r\n id: t.id || t.ID,\r\n name: t.name || t.title || '',\r\n description: t.description || undefined,\r\n // A missing OR malformed wire price stays null → the ticket + order lines\r\n // render an em-dash and checkout hard-blocks, never a coerced $0/\"Free\" or a\r\n // NaN that throws in toUSD (mf#2383).\r\n price: finitePriceOrNull(t.price),\r\n // Legitimate-zero: a ticket with no per-ticket fee is a real 0, not a\r\n // missing price (mf#2234's separately-ruled class). A ternary keeps the 0\r\n // default without a `?? 0` money-field flag AND without a file-level escape\r\n // that would blind the price site above.\r\n fee: t.fee == null ? 0 : t.fee,\r\n quantityAvailable:\r\n t.remainingCapacity ?? t.quantityRemaining ?? t.quantity ?? 0,\r\n quantityTotal: t.totalCapacity ?? t.quantity ?? 0,\r\n minPerOrder: t.minPerOrder ?? t.minQuantity ?? 1,\r\n maxPerOrder: t.maxPerOrder ?? t.maxQuantity ?? 10,\r\n status: mapTicketStatus(t),\r\n salesStartDate:\r\n t.salesBegin || t.salesStart || t.saleBegin || t.onSaleStart || undefined,\r\n salesEndDate: t.salesEnd || t.saleEnd || t.onSaleEnd || undefined,\r\n isDonation: t.type === 2 || t.ticketType === 2 || t.isDonation === true,\r\n isHidden: t.visibility === 2 || t.isHidden === true,\r\n ticketType: t.type || t.ticketType || undefined,\r\n sectionName: t.sectionName || t.section || undefined,\r\n }));\r\n\r\n // Calculate totals from public tickets\r\n const publicTickets = tickets.filter(t => !t.isHidden && !t.isDonation);\r\n const totalRemaining = publicTickets.reduce(\r\n (sum, t) => sum + t.quantityAvailable,\r\n 0\r\n );\r\n const totalCapacity = publicTickets.reduce(\r\n (sum, t) => sum + t.quantityTotal,\r\n 0\r\n );\r\n\r\n // Determine event status\r\n const status = mapEventStatus(domain.status as string, tickets);\r\n\r\n // Build image URL — IMAGE SEAM: image-first precedence (see note).\r\n const rawImage =\r\n rawEvent.image || rawEvent.imageUrl || rawEvent.image_url || '';\r\n const imageUrl = rawImage.startsWith('http')\r\n ? rawImage\r\n : resolveImageUrl(rawImage, { cdn: true });\r\n\r\n // Venue\r\n const venue: VenueData = {\r\n id: rawVenue.id || rawVenue.ID || 0,\r\n name: rawVenue.name || rawVenue.googleLocationNameCache || '',\r\n address: rawVenue.address || rawVenue.googleLocationNameCache || '',\r\n timezone,\r\n serviceFeePercentage: rawVenue.serviceFeePercentage ?? rawVenue.fee ?? 0,\r\n // Legitimate-zero venue fee config (mf#2234's ruled-separate class): a venue\r\n // with no flat service fee is a real 0. Ternary keeps the default without a\r\n // `?? 0` money-field flag (this file also carries the price site above, so a\r\n // file-level escape would wrongly blind it).\r\n serviceFeeCents:\r\n rawVenue.serviceFeeCents == null ? 0 : rawVenue.serviceFeeCents,\r\n taxPercentage: rawVenue.taxPercentage ?? rawVenue.tax ?? 0,\r\n contactEmail: rawVenue.contactEmail || rawVenue.email || undefined,\r\n };\r\n\r\n // Performers — VENUE/PERFORMERS SEAM: raw passthrough map (see note).\r\n const rawPerformers = domain.performers || [];\r\n const performers: PerformerData[] = rawPerformers.map((p: any) => ({\r\n id: p.id || p.ID,\r\n displayName: p.displayName || p.name || '',\r\n profileImage: p.avatar || p.profileImage || undefined,\r\n role: p.role || undefined,\r\n }));\r\n\r\n // FAQs (may not be in API response)\r\n const faqs: FAQItem[] = (domain.faqs || []).map((f: any) => ({\r\n question: f.question || '',\r\n answer: f.answer || '',\r\n }));\r\n\r\n // Series showtimes → occurrences. A single series-event detail carries a\r\n // `showtimes` array; the v2 <ShowtimeDesigns> renders event.seriesOccurrences\r\n // under \"Upcoming Shows\". Without this map the section is always empty.\r\n const seriesOccurrences: SeriesOccurrence[] = (domain.showtimes || [])\r\n .filter((s: any) => s.published !== false)\r\n .map((s: any, i: number) => ({\r\n id: s.id ?? s.eventId ?? i + 1,\r\n slug: s.slug || '',\r\n startDateTime: s.startDateTime || s.startTime || '',\r\n endDateTime: s.endDateTime || s.endTime || '',\r\n status: (s.ctaState?.reason === 'sold_out'\r\n ? 'sold_out'\r\n : 'on_sale') as EventStatus,\r\n ctaText: s.ctaState?.text || 'Get tickets',\r\n ctaDisabled: s.ctaState?.disabled || false,\r\n }));\r\n\r\n // Date in venue timezone\r\n const date = domain.startDateTime\r\n ? formatDateKey(domain.startDateTime, timezone)\r\n : '';\r\n\r\n return {\r\n id: domain.id,\r\n title: domain.title || '',\r\n slug: domain.slug || '',\r\n description: domain.description || domain.eventSummary || '',\r\n date,\r\n startDateTime: domain.startDateTime || '',\r\n endDateTime: domain.endDateTime || '',\r\n doorsOpenTime: domain.doorsOpenTime || '',\r\n timezone,\r\n imageUrl,\r\n venue,\r\n performers,\r\n tickets,\r\n faqs,\r\n disclaimer: domain.disclaimer || undefined,\r\n status,\r\n eventSeriesId: domain.eventSeriesId || undefined,\r\n seriesOccurrences: seriesOccurrences.length ? seriesOccurrences : undefined,\r\n // Public API hides the actual password (json:\"-\") and exposes a boolean\r\n // `hasPassword` flag instead; fall back to a populated `password` for\r\n // admin-shaped payloads.\r\n isPasswordProtected: domain.hasPassword === true || !!domain.password,\r\n isRegistrationEvent:\r\n domain.ticketType === 1 || domain.eventTicketingType === 1,\r\n totalTicketsRemaining: totalRemaining,\r\n totalTicketsCapacity: totalCapacity,\r\n stageName: domain.stage?.name || domain.stageName || undefined,\r\n ageRestriction: domain.ageRestriction || undefined,\r\n displayAgeRestriction: domain.displayAgeRestriction ?? false,\r\n displayStartTime: domain.displayStartTime ?? true,\r\n displayEndTime: domain.displayEndTime ?? true,\r\n displayDoorsTime: domain.displayDoorsTime ?? true,\r\n collectionId: domain.collectionId || undefined, // domain folds collection_id\r\n venueAddressLines: parseAddress(\r\n rawVenue.address || rawVenue.googleLocationNameCache || ''\r\n ),\r\n googleMapsUrl: buildGoogleMapsUrl(\r\n rawVenue.address || rawVenue.googleLocationNameCache || ''\r\n ),\r\n };\r\n}\r\n\r\n/**\r\n * Transform SeriesPageData (from the series API) into our clean EventData interface.\r\n * Sets eventSeriesId so EventExperience renders in full-width series mode.\r\n */\r\nexport function transformSeriesPageData(series: SeriesPageData): EventData {\r\n // Implementation moved to the canonical transformer home\r\n // (`$lib/api/transformers/series.ts`). This export stays as a thin delegate\r\n // so SeriesPage.svelte and other consumers don't churn.\r\n return parseSeries(series);\r\n}\r\n\r\n/**\r\n * Transform PublicCollectionData (from the collection API) into our clean EventData interface.\r\n * Sets collectionId so EventExperience renders in full-width collection mode.\r\n */\r\nexport function transformCollectionData(\r\n collection: PublicCollectionData\r\n): EventData {\r\n // Implementation moved to the canonical transformer home\r\n // (`$lib/api/transformers/collection.ts`). This export stays as a thin\r\n // delegate so CollectionView.svelte and other consumers don't churn.\r\n return parseCollection(collection);\r\n}\r\n"],"names":["parseAddress","addressStr","parts","p","stateZipMatch","state","zip","city","lines","buildGoogleMapsUrl","address","parseSeries","series","seriesAny","timezone","getIANATimezone","imageUrl","resolveImageUrl","seriesOccurrences","occ","firstOcc","date","formatDateKey","rawFaq","faqs","f","performers","index","venueAddress","parseCollection","collection","collectionEvents","ev","finitePriceOrNull","value","n","mapTicketStatus","ticket","now","browserNow","remaining","salesBegin","salesEnd","salesEndAt","toInstantOrNull","compareInstants","salesBeginAt","mapEventStatus","rawStatus","tickets","t","publicTickets","transformApiEvent","rawEvent","domain","parseEvent","rawVenue","totalRemaining","sum","totalCapacity","status","rawImage","venue","s","i","transformSeriesPageData","transformCollectionData"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { w as C, aD as A, aE as $, aF as O, aG as U, aH as F } from "./VenueCalendar-CjSz3oKW.js";
1
+ import { w as C, aD as A, aE as $, aF as O, aG as U, aH as F } from "./VenueCalendar-CU9NyjNN.js";
2
2
  function h(e) {
3
3
  for (var t = 1; t < arguments.length; t++) {
4
4
  var r = arguments[t];
@@ -285,4 +285,4 @@ export {
285
285
  S as s,
286
286
  _ as t
287
287
  };
288
- //# sourceMappingURL=utm-vf1sKPfQ.js.map
288
+ //# sourceMappingURL=utm-xeqSXwE6.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utm-vf1sKPfQ.js","sources":["../node_modules/js-cookie/dist/js.cookie.mjs","../src/lib/utils/cookies.ts","../src/lib/utils/checkoutState.ts","../src/lib/utils/orderApi.ts","../src/lib/utils/utm.ts"],"sourcesContent":["/*! js-cookie v3.0.8 | MIT */\nfunction assign (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n for (var key in source) {\n if (key === '__proto__') continue\n target[key] = source[key];\n }\n }\n return target\n}\n\nvar defaultConverter = {\n read: function (value) {\n if (value[0] === '\"') {\n value = value.slice(1, -1);\n }\n return value.replace(/(%[\\dA-F]{2})+/gi, decodeURIComponent)\n },\n write: function (value) {\n return encodeURIComponent(value).replace(\n /%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,\n decodeURIComponent\n )\n }\n};\n\nfunction init(converter, defaultAttributes) {\n function set(name, value, attributes) {\n if (typeof document === 'undefined') {\n return\n }\n\n attributes = assign({}, defaultAttributes, attributes);\n\n if (typeof attributes.expires === 'number') {\n attributes.expires = new Date(Date.now() + attributes.expires * 864e5);\n }\n if (attributes.expires) {\n attributes.expires = attributes.expires.toUTCString();\n }\n\n name = encodeURIComponent(name)\n .replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent)\n .replace(/[()]/g, escape);\n\n var stringifiedAttributes = '';\n for (var attributeName in attributes) {\n if (!attributes[attributeName]) {\n continue\n }\n\n stringifiedAttributes += '; ' + attributeName;\n\n if (attributes[attributeName] === true) {\n continue\n }\n\n // Considers RFC 6265 section 5.2:\n // ...\n // 3. If the remaining unparsed-attributes contains a %x3B (\";\")\n // character:\n // Consume the characters of the unparsed-attributes up to,\n // not including, the first %x3B (\";\") character.\n // ...\n stringifiedAttributes += '=' + attributes[attributeName].split(';')[0];\n }\n\n return (document.cookie =\n name + '=' + converter.write(value, name) + stringifiedAttributes)\n }\n\n function get(name) {\n if (typeof document === 'undefined' || (arguments.length && !name)) {\n return\n }\n\n // To prevent the for loop in the first place assign an empty array\n // in case there are no cookies at all.\n var cookies = document.cookie ? document.cookie.split('; ') : [];\n var jar = {};\n for (var i = 0; i < cookies.length; i++) {\n var parts = cookies[i].split('=');\n var value = parts.slice(1).join('=');\n\n try {\n var found = decodeURIComponent(parts[0]);\n if (!(found in jar)) jar[found] = converter.read(value, found);\n if (name === found) {\n break\n }\n } catch (_e) {\n // Do nothing...\n }\n }\n\n return name ? jar[name] : jar\n }\n\n return Object.create(\n {\n set: set,\n get: get,\n remove: function (name, attributes) {\n set(\n name,\n '',\n assign({}, attributes, {\n expires: -1\n })\n );\n },\n withAttributes: function (attributes) {\n return init(this.converter, assign({}, this.attributes, attributes))\n },\n withConverter: function (converter) {\n return init(assign({}, this.converter, converter), this.attributes)\n }\n },\n {\n attributes: { value: Object.freeze(defaultAttributes) },\n converter: { value: Object.freeze(converter) }\n }\n )\n}\n\nvar api = init(defaultConverter, { path: '/' });\n\nexport { api as default };\n","/**\r\n * Cookie management wrappers around js-cookie.\r\n *\r\n * DIVERGENCE (no-shadowed-helper rename-keep): SC 6.24.109 exports canonical\r\n * `setCookie`/`getCookie`, but those are typed to the branded `CookieName`\r\n * registry (`COOKIE_NAMES` + builders), return `string | null`, and take a\r\n * `{ maxAge, path }` options shape while writing `document.cookie` directly\r\n * with a hardcoded `.get-micdrop.com` production domain. VC is a STANDALONE\r\n * embeddable widget: it reads/writes many widget-owned cookie names that are\r\n * NOT in SC's registry (`order-id-${eventId}`, `checkout-promo-reveal-*`,\r\n * `checkout-promo-discount-type-*`, …), passes plain `string` names, relies on\r\n * `string | undefined` reads, and uses js-cookie's `CookieAttributes` options\r\n * (@stale-doc-comment-allow: CookieAttributes — js-cookie ships no .d.ts of its\r\n * own and @types/js-cookie is not installed, so nothing in the tree can confirm\r\n * this name; it is a real js-cookie API, not a deleted local component.)\r\n * (`{ expires, path, … }`). Adopting SC's branded surface would be a large\r\n * behavioral migration (expiry semantics, branded-name minting, registry\r\n * additions in SC's repo) with no user-facing benefit, so the local js-cookie\r\n * wrapper is kept and re-exported under the public `setCookie`/`getCookie`\r\n * names. The aliased re-export satisfies `micdrop/no-shadowed-helper` without\r\n * suppression — no eslint-disable.\r\n */\r\nimport Cookies from 'js-cookie';\r\n\r\nfunction setCookieLocal(\r\n name: string,\r\n value: string,\r\n options: Parameters<typeof Cookies.set>[2] = {}\r\n): void {\r\n Cookies.set(name, value, options);\r\n}\r\n\r\nfunction getCookieLocal(name: string): string | undefined {\r\n return Cookies.get(name);\r\n}\r\n\r\nfunction removeCookieLocal(name: string): void {\r\n Cookies.remove(name);\r\n}\r\n\r\nexport {\r\n setCookieLocal as setCookie,\r\n getCookieLocal as getCookie,\r\n removeCookieLocal as removeCookie,\r\n};\r\n","// @storage-escape: Canonical checkout-state persistence wrapper — this\r\n// module IS the localStorage layer for checkout state (cart, promo,\r\n// totals) across page refreshes. utility-storage record documents\r\n// the persistence-wrapper shape as exempt.\r\n\r\nimport { createLogger } from '@getmicdrop/svelte-components';\r\n/**\r\n * Checkout state persistence: localStorage with cookie fallback for migration\r\n */\r\nimport { getCookie, setCookie, removeCookie } from './cookies';\r\n\r\nconst logger = createLogger('checkoutState');\r\n\r\ninterface CheckoutTicket {\r\n ID: number | string;\r\n name: string;\r\n price: number;\r\n type?: string;\r\n visibility?: string;\r\n salesChannel?: string;\r\n [key: string]: unknown;\r\n}\r\n\r\ninterface CheckoutState {\r\n quantities: Record<string, number>;\r\n donationAmounts: Record<string, number>;\r\n promocode: string;\r\n promoDiscountAmount: number;\r\n tickets: CheckoutTicket[];\r\n}\r\n\r\ninterface PersistCheckoutParams {\r\n eventID: string;\r\n quantities: Record<string, number>;\r\n donationAmounts?: Record<string, number>;\r\n promocode: string;\r\n promoDiscountAmount: number;\r\n tickets: CheckoutTicket[];\r\n}\r\n\r\n/**\r\n * Load checkout state from localStorage (preferred) with cookie fallback for migration\r\n */\r\nexport function loadCheckoutStateFromCookies(eventID: string): CheckoutState {\r\n let quantities: Record<string, number> = {};\r\n let donationAmounts: Record<string, number> = {};\r\n let tickets: CheckoutTicket[] = [];\r\n let promocode = '';\r\n let promoDiscountAmount = 0;\r\n\r\n if (typeof window === 'undefined') {\r\n return {\r\n quantities,\r\n donationAmounts,\r\n promocode,\r\n promoDiscountAmount,\r\n tickets,\r\n };\r\n }\r\n\r\n // Try localStorage first (new approach)\r\n try {\r\n const stored = localStorage.getItem(`checkout-state-${eventID}`); // @storage-escape: canonical checkout-state persistence wrapper — this module IS the localStorage layer (see file header)\r\n if (stored) {\r\n const parsed = JSON.parse(stored);\r\n return {\r\n quantities: parsed.quantities || {},\r\n donationAmounts: parsed.donationAmounts || {},\r\n promocode: parsed.promocode || '',\r\n promoDiscountAmount: parseFloat(parsed.promoDiscountAmount) || 0,\r\n tickets: parsed.tickets || [],\r\n };\r\n }\r\n } catch (e) {\r\n logger.warn('Failed to parse checkout state from localStorage:', e);\r\n }\r\n\r\n // Fallback to cookies for migration (old approach)\r\n try {\r\n quantities = JSON.parse(\r\n getCookie(`checkout-quantities-${eventID}`) || '{}'\r\n );\r\n } catch (e) {\r\n logger.warn('Failed to parse checkout quantities cookie:', e);\r\n quantities = {};\r\n }\r\n\r\n try {\r\n tickets = JSON.parse(getCookie(`checkout-tickets-${eventID}`) || '[]');\r\n } catch (e) {\r\n logger.warn('Failed to parse checkout tickets cookie:', e);\r\n tickets = [];\r\n }\r\n\r\n promocode = getCookie(`checkout-promocode-${eventID}`) || '';\r\n // Per-event, like every other promo cookie. Temporary local key —\r\n // `converge-promo-cookie-onto-sc-canonical` replaces it with the\r\n // svelte-components builder. See PromocodeInput.svelte for the full note.\r\n promoDiscountAmount = parseFloat(\r\n getCookie(`checkout-promo-discount-${eventID}`) || '0'\r\n );\r\n\r\n // If we found data in cookies, migrate it to localStorage and drop the\r\n // cookies we just migrated. Only those — the promo REVEAL cookies have no\r\n // localStorage home (CheckoutState has no reveal field; CartView reads them\r\n // straight from the jar), so a blanket clear here would silently revoke a\r\n // live reveal on the next page load, for a buyer still holding a valid code.\r\n if (Object.keys(quantities).length > 0 || tickets.length > 0 || promocode) {\r\n persistCheckoutState({\r\n eventID,\r\n quantities,\r\n donationAmounts,\r\n promocode,\r\n promoDiscountAmount,\r\n tickets,\r\n });\r\n clearMigratedCheckoutCookies(eventID);\r\n }\r\n\r\n return {\r\n quantities,\r\n donationAmounts,\r\n promocode,\r\n promoDiscountAmount,\r\n tickets,\r\n };\r\n}\r\n\r\n/**\r\n * The legacy cookies whose payload `loadCheckoutStateFromCookies` migrates into\r\n * localStorage. Cleared once they've been migrated — nothing is lost, the data\r\n * now lives in `checkout-state-${eventID}`.\r\n */\r\nfunction clearMigratedCheckoutCookies(eventID: string): void {\r\n removeCookie(`checkout-quantities-${eventID}`);\r\n removeCookie(`checkout-tickets-${eventID}`);\r\n removeCookie(`checkout-promocode-${eventID}`);\r\n removeCookie(`checkout-promo-discount-${eventID}`);\r\n}\r\n\r\n/**\r\n * Clear checkout state from both localStorage and cookies\r\n *\r\n * @stale-doc-comment-allow: Remove — the button's visible LABEL, not a component.\r\n *\r\n * This is the ONE cleanup point for a finished checkout — Success.svelte calls it\r\n * after a purchase, CartView calls it when the buyer abandons the cart. EVERY\r\n * cookie the checkout/promo flow writes for an event must die here; do not\r\n * sprinkle removeCookie() at call sites. The five promo cookies below are exactly\r\n * what PromocodeInput.svelte writes (its `Remove` button clears the same five),\r\n * two of which CartView.svelte also re-writes on a promo change.\r\n *\r\n * The three promo cookies past the code+amount pair used to survive checkout on a\r\n * 1-day expiry. `checkout-promo-reveal-*` is the ONLY thing hiding hidden tickets\r\n * — /tickets/event/{id} ships them in the payload with no promo code and there is\r\n * no server-side backstop — so a reveal cookie outliving the purchase left comps,\r\n * industry seats and VIP holds buyable, with no code entered, to whoever opened\r\n * the event next on that browser.\r\n */\r\nexport function clearCheckoutCookies(eventID: string): void {\r\n // Clear localStorage (new approach)\r\n if (typeof window !== 'undefined') {\r\n localStorage.removeItem(`checkout-state-${eventID}`); // @storage-escape: canonical checkout-state persistence wrapper — this module IS the localStorage layer (see file header)\r\n }\r\n\r\n clearMigratedCheckoutCookies(eventID);\r\n\r\n // The rest of what the promo flow writes. No localStorage home, no other\r\n // owner — the checkout ending is the only thing that retires them.\r\n removeCookie(`checkout-promo-discount-type-${eventID}`);\r\n removeCookie(`checkout-promo-reveal-${eventID}`);\r\n removeCookie(`checkout-promo-reveal-ids-${eventID}`);\r\n}\r\n\r\n/**\r\n * Persist checkout state to localStorage\r\n * Uses localStorage instead of cookies to avoid size limits and reduce request overhead\r\n */\r\nexport function persistCheckoutState({\r\n eventID,\r\n quantities,\r\n donationAmounts,\r\n promocode,\r\n promoDiscountAmount,\r\n tickets,\r\n}: PersistCheckoutParams): void {\r\n if (typeof window === 'undefined') return;\r\n\r\n // Store minimal ticket data to avoid storage bloat\r\n const minimalTickets = (tickets || []).map(t => ({\r\n ID: t.ID,\r\n name: t.name,\r\n price: t.price,\r\n type: t.type, // Include type for donation ticket detection\r\n visibility: t.visibility,\r\n salesChannel: t.salesChannel,\r\n }));\r\n\r\n const state = {\r\n quantities: quantities || {},\r\n donationAmounts: donationAmounts || {},\r\n promocode: promocode || '',\r\n promoDiscountAmount: promoDiscountAmount || 0,\r\n tickets: minimalTickets,\r\n updatedAt: Date.now(),\r\n };\r\n\r\n try {\r\n localStorage.setItem(`checkout-state-${eventID}`, JSON.stringify(state)); // @storage-escape: canonical checkout-state persistence wrapper — this module IS the localStorage layer (see file header)\r\n } catch (e) {\r\n logger.warn('Failed to persist checkout state to localStorage:', e);\r\n }\r\n}\r\n\r\n/**\r\n * Ensure order ID exists, create if not\r\n */\r\nexport async function ensureOrderIdExists(eventId: string): Promise<string> {\r\n const existingOrderId = getCookie(`order-id-${eventId}`);\r\n\r\n if (existingOrderId) {\r\n return existingOrderId;\r\n }\r\n\r\n const newOrderId = `order-${eventId}-${Date.now()}`;\r\n // SameSite=None; Secure so the cookie survives iframe embeds on\r\n // third-party origins (Safari ITP / Chrome SameSite-Lax-by-default).\r\n setCookie(`order-id-${eventId}`, newOrderId, {\r\n secure: true,\r\n sameSite: 'none' as const,\r\n path: '/',\r\n });\r\n\r\n return newOrderId;\r\n}\r\n","import { COOKIE_NAMES, createLogger } from '@getmicdrop/svelte-components';\r\nimport { ApiError } from '@getmicdrop/svelte-components/errors';\r\n/**\r\n * Order-related API calls: getVenueDetails, initiateOrder, getOrder,\r\n * createPaymentIntent, validatePaymentIntent, getClientIP\r\n *\r\n * @legacy-retire-with=?legacy=1\r\n * LEGACY — slated for deletion. Do NOT add new code here and do NOT build\r\n * canonicals against the untyped `[key: string]: unknown` bag interfaces below\r\n * (VenueResponse / PaymentIntentResponse / ValidatePaymentResponse /\r\n * OrderResponse). They survive only via `as` casts and exist purely for\r\n * backward compat. The canonical, typed wire->domain home for all of this is\r\n * `src/lib/api/transformers/*` (parseOrder, parseCart, parseGiftCardApplication,\r\n * parseEventPerformers, parseVenue, parseEvent) composed by the `src/lib/api/*`\r\n * clients (orders.ts, gift-cards.ts, events.ts). Retire this module behind the\r\n * `?legacy=1` flag once its remaining consumer is migrated to `$lib/api/*`.\r\n *\r\n * Live consumer (as of this change): `src/lib/utils/utils.js` re-exports\r\n * getClientIP / getVenueDetails / initiateOrder / getOrder / createPaymentIntent\r\n * / validatePaymentIntent from here (the `$lib/utils/utils.js` back-compat\r\n * barrel). That barrel is the single retirement blocker to plan around.\r\n */\r\nimport { apiGet, apiPost } from '$lib/api/client';\r\nimport { buildAuthHeaders } from '$lib/api/authHeaders';\r\nimport { getCookie, setCookie } from './cookies';\r\n\r\nconst logger = createLogger('orderApi');\r\n\r\ninterface OrderResult {\r\n success: boolean;\r\n uuid?: string;\r\n serviceFee?: number;\r\n subtotal?: number;\r\n error?: string;\r\n errorType?: 'inventory' | 'server' | 'network';\r\n}\r\n\r\ninterface CartData {\r\n eventID?: string | number;\r\n quantities?: Record<string, number>;\r\n donationAmounts?: Record<string, number>;\r\n [key: string]: unknown;\r\n}\r\n\r\ninterface PaymentIntentResponse {\r\n clientSecret?: string;\r\n stripe_publishable_key?: string;\r\n [key: string]: unknown;\r\n}\r\n\r\ninterface ValidatePaymentResponse {\r\n [key: string]: unknown;\r\n}\r\n\r\ninterface OrderResponse {\r\n [key: string]: unknown;\r\n}\r\n\r\ninterface VenueResponse {\r\n [key: string]: unknown;\r\n}\r\n\r\n/**\r\n * @deprecated IP is now resolved server-side via request headers\r\n */\r\nexport async function getClientIP(): Promise<string | null> {\r\n return null;\r\n}\r\n\r\nexport async function getVenueDetails(\r\n venueID: string | number\r\n): Promise<VenueResponse> {\r\n try {\r\n const result = await apiGet<VenueResponse>(`/venues/${venueID}`);\r\n\r\n if (!result.success) {\r\n throw new ApiError(\r\n result.error ?? `API error: ${result.statusCode}`,\r\n result.statusCode ?? 0,\r\n { endpoint: `/venues/${venueID}`, method: 'GET' }\r\n );\r\n }\r\n\r\n return result.data as VenueResponse;\r\n } catch (error) {\r\n logger.error('getVenueDetails error:', error);\r\n throw error;\r\n }\r\n}\r\n\r\nexport async function initiateOrder(\r\n cartData: CartData = {}\r\n): Promise<OrderResult> {\r\n try {\r\n const ip = await getClientIP();\r\n\r\n const { eventID, quantities, donationAmounts, ...restCartData } = cartData;\r\n\r\n // Convert quantities keys to numbers and eventID to number (API expects numeric types)\r\n const numericQuantities = quantities\r\n ? Object.fromEntries(\r\n Object.entries(quantities).map(([k, v]) => [parseInt(k, 10), v])\r\n )\r\n : {};\r\n\r\n // Convert donationAmounts keys to numbers and values to floats\r\n const numericDonationAmounts = donationAmounts\r\n ? Object.fromEntries(\r\n Object.entries(donationAmounts)\r\n .filter(([, v]) => parseFloat(String(v)) > 0)\r\n .map(([k, v]) => [parseInt(k, 10), parseFloat(String(v))])\r\n )\r\n : undefined;\r\n\r\n const orderPayload = {\r\n purchaserIP: ip,\r\n eventID: eventID ? parseInt(String(eventID), 10) : undefined,\r\n quantities: numericQuantities,\r\n ...(numericDonationAmounts &&\r\n Object.keys(numericDonationAmounts).length > 0\r\n ? { donationAmounts: numericDonationAmounts }\r\n : {}),\r\n ...restCartData,\r\n };\r\n\r\n const result = await apiPost<Record<string, unknown>>(\r\n `/orders/create`,\r\n orderPayload\r\n );\r\n\r\n const data = result.data ?? {};\r\n\r\n // Check for API errors (including 200-with-error-field pattern)\r\n if (!result.success || data['error']) {\r\n const errorMessage =\r\n (data['error'] as string) ||\r\n (data['message'] as string) ||\r\n result.error ||\r\n 'Order creation failed';\r\n // Check for inventory-related errors\r\n const isInventoryError =\r\n errorMessage.toLowerCase().includes('inventory') ||\r\n errorMessage.toLowerCase().includes('sold out') ||\r\n errorMessage.toLowerCase().includes('not available') ||\r\n errorMessage.toLowerCase().includes('insufficient') ||\r\n result.statusCode === 409; // Conflict status often used for inventory issues\r\n\r\n return {\r\n success: false,\r\n error: errorMessage,\r\n errorType: isInventoryError ? 'inventory' : 'server',\r\n };\r\n }\r\n\r\n // SameSite=None; Secure so the cookie survives iframe embeds on\r\n // third-party origins (Safari ITP / Chrome SameSite-Lax-by-default).\r\n // Without this, embedding the calendar in another venue's site\r\n // silently drops the cart on every navigation.\r\n setCookie(\r\n 'checkout-cartid',\r\n (data['uuid'] as string) || (data['cartUUID'] as string),\r\n {\r\n secure: true,\r\n sameSite: 'none' as const,\r\n path: '/',\r\n }\r\n );\r\n return {\r\n success: true,\r\n uuid: (data['uuid'] as string) || (data['cartUUID'] as string),\r\n serviceFee: (data['serviceFee'] as number) ?? 0,\r\n subtotal: (data['subtotal'] as number) ?? 0,\r\n };\r\n } catch (err: unknown) {\r\n const message = err instanceof Error ? err.message : 'Network error';\r\n logger.error('Order initiation failed:', err);\r\n return {\r\n success: false,\r\n error: message,\r\n errorType: 'network',\r\n };\r\n }\r\n}\r\n\r\nexport async function getOrder(orderId: string): Promise<OrderResponse> {\r\n try {\r\n const result = await apiGet<OrderResponse>(`/orders/${orderId}`);\r\n\r\n if (!result.success) {\r\n const errorMessage =\r\n result.error ?? `Failed to fetch order (${result.statusCode})`;\r\n logger.error('getOrder error response:', errorMessage);\r\n throw new ApiError(errorMessage, result.statusCode ?? 0, {\r\n endpoint: `/orders/${orderId}`,\r\n method: 'GET',\r\n });\r\n }\r\n\r\n return result.data as OrderResponse;\r\n } catch (err) {\r\n logger.error('getOrder error:', err);\r\n throw err;\r\n }\r\n}\r\n\r\nexport async function createPaymentIntent(\r\n cartId: string,\r\n quantities: Record<string, number>,\r\n donationAmounts?: Record<string, number>\r\n): Promise<PaymentIntentResponse> {\r\n const token = getCookie(COOKIE_NAMES.OPERATOR_TOKEN);\r\n\r\n try {\r\n const result = await apiPost<PaymentIntentResponse>(\r\n `/orders/${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 headers: buildAuthHeaders(token),\r\n }\r\n );\r\n\r\n if (!result.success) {\r\n logger.error('Payment intent creation failed:', result.error);\r\n throw new ApiError(\r\n result.error === 'Request timed out'\r\n ? 'Request timed out. Please check your connection and try again.'\r\n : result.error?.includes('Failed to fetch')\r\n ? 'Unable to connect to payment server. Please check your internet connection or try again later.'\r\n : (result.error ??\r\n `Failed to create payment intent: ${result.statusCode}`),\r\n result.statusCode ?? 0,\r\n { endpoint: `/orders/${cartId}/payment-intent`, method: 'POST' }\r\n );\r\n }\r\n\r\n return result.data as PaymentIntentResponse;\r\n } catch (err: unknown) {\r\n logger.error('createPaymentIntent error:', err);\r\n // Re-throw the error so the caller can handle it\r\n throw err;\r\n }\r\n}\r\n\r\nexport async function validatePaymentIntent(\r\n cartId: string,\r\n payload: Record<string, unknown>\r\n): Promise<ValidatePaymentResponse | null> {\r\n try {\r\n const token = getCookie(COOKIE_NAMES.OPERATOR_TOKEN);\r\n\r\n const result = await apiPost<ValidatePaymentResponse>(\r\n `/orders/${cartId}/validate-payment`,\r\n payload,\r\n {\r\n headers: buildAuthHeaders(token),\r\n }\r\n );\r\n\r\n return result.data ?? null;\r\n } catch (err) {\r\n logger.error('validatePaymentIntent error:', err);\r\n return null;\r\n }\r\n}\r\n","// @fetch-escape: widget-intentional.\r\n// @api-client-escape: fire-and-forget UTM beacon — keeps raw fetch (GET, no body, response ignored).\r\n// Migrating to apiPost broke the GET contract; apiGet would parse JSON on a no-body 200 and log a false-positive error.\r\nimport { createLogger } from '@getmicdrop/svelte-components';\r\nimport { normalizeUtmValue, DIRECT_SOURCE } from '../tracking/normalize.js';\r\nimport { trackEventView } from '../tracking/index.js';\r\nconst logger = createLogger('utm');\r\n\r\n/**\r\n * UTM source tracking\r\n */\r\n\r\n/**\r\n * Track UTM source for an event (parameter named venueID for backwards compatibility\r\n * but actually represents eventID).\r\n *\r\n * Bumps the legacy per-source click COUNTERS (utm_counters) that power the old\r\n * UTM analytics page. The source is normalized at write time (lowercased, spaces\r\n * → underscores) and an empty source resolves to the ONE canonical default\r\n * `direct` — so the counter buckets match the beacon + order buckets (the\r\n * historical `Direct`/`''`/`direct` split is dead).\r\n */\r\nexport async function trackUTMSource(venueID: string | number): Promise<void> {\r\n const urlParams = new URLSearchParams(window.location.search);\r\n const utmSource =\r\n normalizeUtmValue(urlParams.get('utm_source')) || DIRECT_SOURCE;\r\n\r\n try {\r\n await fetch(\r\n `https://get-micdrop.com/api/v2/public/utm/${venueID}/${encodeURIComponent(utmSource)}`\r\n );\r\n } catch (err) {\r\n logger.error('UTM tracking failed:', err);\r\n }\r\n}\r\n\r\n/**\r\n * Event-detail page-view tracking — the `event_view` funnel moment.\r\n *\r\n * Delegates to the canonical funnel-beacon service (`$lib/tracking`), which\r\n * fires the extended `POST /track/pageview` beacon carrying the normalized utm\r\n * set, persistent visitorId (consent-gated), sessionId, widgetId, deviceType,\r\n * referrer and pageUrl, and keeps the first-party attribution store fresh. The\r\n * beacon is deduplicated per session and fire-and-forget.\r\n *\r\n * Kept as a thin wrapper (rather than inlining `trackEventView` at the call\r\n * site) so the existing `trackPageView(eventId)` call in EventPage stays\r\n * unchanged and the pre-tracking-rebuild external surface is preserved.\r\n */\r\nexport async function trackPageView(eventID: string | number): Promise<void> {\r\n await trackEventView(eventID);\r\n}\r\n"],"names":["assign","target","i","source","key","defaultConverter","value","init","converter","defaultAttributes","set","name","attributes","stringifiedAttributes","attributeName","get","cookies","jar","parts","found","api","setCookieLocal","options","Cookies","getCookieLocal","removeCookieLocal","logger","createLogger","loadCheckoutStateFromCookies","eventID","quantities","donationAmounts","tickets","promocode","promoDiscountAmount","stored","parsed","e","getCookie","persistCheckoutState","clearMigratedCheckoutCookies","removeCookie","clearCheckoutCookies","minimalTickets","t","state","ensureOrderIdExists","eventId","existingOrderId","newOrderId","setCookie","getClientIP","getVenueDetails","venueID","result","apiGet","ApiError","error","initiateOrder","cartData","ip","restCartData","numericQuantities","k","v","numericDonationAmounts","orderPayload","apiPost","data","errorMessage","isInventoryError","err","message","getOrder","orderId","trackUTMSource","urlParams","utmSource","normalizeUtmValue","DIRECT_SOURCE"],"mappings":"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","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"utm-xeqSXwE6.js","sources":["../node_modules/js-cookie/dist/js.cookie.mjs","../src/lib/utils/cookies.ts","../src/lib/utils/checkoutState.ts","../src/lib/utils/orderApi.ts","../src/lib/utils/utm.ts"],"sourcesContent":["/*! js-cookie v3.0.8 | MIT */\nfunction assign (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n for (var key in source) {\n if (key === '__proto__') continue\n target[key] = source[key];\n }\n }\n return target\n}\n\nvar defaultConverter = {\n read: function (value) {\n if (value[0] === '\"') {\n value = value.slice(1, -1);\n }\n return value.replace(/(%[\\dA-F]{2})+/gi, decodeURIComponent)\n },\n write: function (value) {\n return encodeURIComponent(value).replace(\n /%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,\n decodeURIComponent\n )\n }\n};\n\nfunction init(converter, defaultAttributes) {\n function set(name, value, attributes) {\n if (typeof document === 'undefined') {\n return\n }\n\n attributes = assign({}, defaultAttributes, attributes);\n\n if (typeof attributes.expires === 'number') {\n attributes.expires = new Date(Date.now() + attributes.expires * 864e5);\n }\n if (attributes.expires) {\n attributes.expires = attributes.expires.toUTCString();\n }\n\n name = encodeURIComponent(name)\n .replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent)\n .replace(/[()]/g, escape);\n\n var stringifiedAttributes = '';\n for (var attributeName in attributes) {\n if (!attributes[attributeName]) {\n continue\n }\n\n stringifiedAttributes += '; ' + attributeName;\n\n if (attributes[attributeName] === true) {\n continue\n }\n\n // Considers RFC 6265 section 5.2:\n // ...\n // 3. If the remaining unparsed-attributes contains a %x3B (\";\")\n // character:\n // Consume the characters of the unparsed-attributes up to,\n // not including, the first %x3B (\";\") character.\n // ...\n stringifiedAttributes += '=' + attributes[attributeName].split(';')[0];\n }\n\n return (document.cookie =\n name + '=' + converter.write(value, name) + stringifiedAttributes)\n }\n\n function get(name) {\n if (typeof document === 'undefined' || (arguments.length && !name)) {\n return\n }\n\n // To prevent the for loop in the first place assign an empty array\n // in case there are no cookies at all.\n var cookies = document.cookie ? document.cookie.split('; ') : [];\n var jar = {};\n for (var i = 0; i < cookies.length; i++) {\n var parts = cookies[i].split('=');\n var value = parts.slice(1).join('=');\n\n try {\n var found = decodeURIComponent(parts[0]);\n if (!(found in jar)) jar[found] = converter.read(value, found);\n if (name === found) {\n break\n }\n } catch (_e) {\n // Do nothing...\n }\n }\n\n return name ? jar[name] : jar\n }\n\n return Object.create(\n {\n set: set,\n get: get,\n remove: function (name, attributes) {\n set(\n name,\n '',\n assign({}, attributes, {\n expires: -1\n })\n );\n },\n withAttributes: function (attributes) {\n return init(this.converter, assign({}, this.attributes, attributes))\n },\n withConverter: function (converter) {\n return init(assign({}, this.converter, converter), this.attributes)\n }\n },\n {\n attributes: { value: Object.freeze(defaultAttributes) },\n converter: { value: Object.freeze(converter) }\n }\n )\n}\n\nvar api = init(defaultConverter, { path: '/' });\n\nexport { api as default };\n","/**\r\n * Cookie management wrappers around js-cookie.\r\n *\r\n * DIVERGENCE (no-shadowed-helper rename-keep): SC 6.24.109 exports canonical\r\n * `setCookie`/`getCookie`, but those are typed to the branded `CookieName`\r\n * registry (`COOKIE_NAMES` + builders), return `string | null`, and take a\r\n * `{ maxAge, path }` options shape while writing `document.cookie` directly\r\n * with a hardcoded `.get-micdrop.com` production domain. VC is a STANDALONE\r\n * embeddable widget: it reads/writes many widget-owned cookie names that are\r\n * NOT in SC's registry (`order-id-${eventId}`, `checkout-promo-reveal-*`,\r\n * `checkout-promo-discount-type-*`, …), passes plain `string` names, relies on\r\n * `string | undefined` reads, and uses js-cookie's `CookieAttributes` options\r\n * (@stale-doc-comment-allow: CookieAttributes — js-cookie ships no .d.ts of its\r\n * own and @types/js-cookie is not installed, so nothing in the tree can confirm\r\n * this name; it is a real js-cookie API, not a deleted local component.)\r\n * (`{ expires, path, … }`). Adopting SC's branded surface would be a large\r\n * behavioral migration (expiry semantics, branded-name minting, registry\r\n * additions in SC's repo) with no user-facing benefit, so the local js-cookie\r\n * wrapper is kept and re-exported under the public `setCookie`/`getCookie`\r\n * names. The aliased re-export satisfies `micdrop/no-shadowed-helper` without\r\n * suppression — no eslint-disable.\r\n */\r\nimport Cookies from 'js-cookie';\r\n\r\nfunction setCookieLocal(\r\n name: string,\r\n value: string,\r\n options: Parameters<typeof Cookies.set>[2] = {}\r\n): void {\r\n Cookies.set(name, value, options);\r\n}\r\n\r\nfunction getCookieLocal(name: string): string | undefined {\r\n return Cookies.get(name);\r\n}\r\n\r\nfunction removeCookieLocal(name: string): void {\r\n Cookies.remove(name);\r\n}\r\n\r\nexport {\r\n setCookieLocal as setCookie,\r\n getCookieLocal as getCookie,\r\n removeCookieLocal as removeCookie,\r\n};\r\n","// @storage-escape: Canonical checkout-state persistence wrapper — this\r\n// module IS the localStorage layer for checkout state (cart, promo,\r\n// totals) across page refreshes. utility-storage record documents\r\n// the persistence-wrapper shape as exempt.\r\n\r\nimport { createLogger } from '@getmicdrop/svelte-components';\r\n/**\r\n * Checkout state persistence: localStorage with cookie fallback for migration\r\n */\r\nimport { getCookie, setCookie, removeCookie } from './cookies';\r\n\r\nconst logger = createLogger('checkoutState');\r\n\r\ninterface CheckoutTicket {\r\n ID: number | string;\r\n name: string;\r\n price: number;\r\n type?: string;\r\n visibility?: string;\r\n salesChannel?: string;\r\n [key: string]: unknown;\r\n}\r\n\r\ninterface CheckoutState {\r\n quantities: Record<string, number>;\r\n donationAmounts: Record<string, number>;\r\n promocode: string;\r\n promoDiscountAmount: number;\r\n tickets: CheckoutTicket[];\r\n}\r\n\r\ninterface PersistCheckoutParams {\r\n eventID: string;\r\n quantities: Record<string, number>;\r\n donationAmounts?: Record<string, number>;\r\n promocode: string;\r\n promoDiscountAmount: number;\r\n tickets: CheckoutTicket[];\r\n}\r\n\r\n/**\r\n * Load checkout state from localStorage (preferred) with cookie fallback for migration\r\n */\r\nexport function loadCheckoutStateFromCookies(eventID: string): CheckoutState {\r\n let quantities: Record<string, number> = {};\r\n let donationAmounts: Record<string, number> = {};\r\n let tickets: CheckoutTicket[] = [];\r\n let promocode = '';\r\n let promoDiscountAmount = 0;\r\n\r\n if (typeof window === 'undefined') {\r\n return {\r\n quantities,\r\n donationAmounts,\r\n promocode,\r\n promoDiscountAmount,\r\n tickets,\r\n };\r\n }\r\n\r\n // Try localStorage first (new approach)\r\n try {\r\n const stored = localStorage.getItem(`checkout-state-${eventID}`); // @storage-escape: canonical checkout-state persistence wrapper — this module IS the localStorage layer (see file header)\r\n if (stored) {\r\n const parsed = JSON.parse(stored);\r\n return {\r\n quantities: parsed.quantities || {},\r\n donationAmounts: parsed.donationAmounts || {},\r\n promocode: parsed.promocode || '',\r\n promoDiscountAmount: parseFloat(parsed.promoDiscountAmount) || 0,\r\n tickets: parsed.tickets || [],\r\n };\r\n }\r\n } catch (e) {\r\n logger.warn('Failed to parse checkout state from localStorage:', e);\r\n }\r\n\r\n // Fallback to cookies for migration (old approach)\r\n try {\r\n quantities = JSON.parse(\r\n getCookie(`checkout-quantities-${eventID}`) || '{}'\r\n );\r\n } catch (e) {\r\n logger.warn('Failed to parse checkout quantities cookie:', e);\r\n quantities = {};\r\n }\r\n\r\n try {\r\n tickets = JSON.parse(getCookie(`checkout-tickets-${eventID}`) || '[]');\r\n } catch (e) {\r\n logger.warn('Failed to parse checkout tickets cookie:', e);\r\n tickets = [];\r\n }\r\n\r\n promocode = getCookie(`checkout-promocode-${eventID}`) || '';\r\n // Per-event, like every other promo cookie. Temporary local key —\r\n // `converge-promo-cookie-onto-sc-canonical` replaces it with the\r\n // svelte-components builder. See PromocodeInput.svelte for the full note.\r\n promoDiscountAmount = parseFloat(\r\n getCookie(`checkout-promo-discount-${eventID}`) || '0'\r\n );\r\n\r\n // If we found data in cookies, migrate it to localStorage and drop the\r\n // cookies we just migrated. Only those — the promo REVEAL cookies have no\r\n // localStorage home (CheckoutState has no reveal field; CartView reads them\r\n // straight from the jar), so a blanket clear here would silently revoke a\r\n // live reveal on the next page load, for a buyer still holding a valid code.\r\n if (Object.keys(quantities).length > 0 || tickets.length > 0 || promocode) {\r\n persistCheckoutState({\r\n eventID,\r\n quantities,\r\n donationAmounts,\r\n promocode,\r\n promoDiscountAmount,\r\n tickets,\r\n });\r\n clearMigratedCheckoutCookies(eventID);\r\n }\r\n\r\n return {\r\n quantities,\r\n donationAmounts,\r\n promocode,\r\n promoDiscountAmount,\r\n tickets,\r\n };\r\n}\r\n\r\n/**\r\n * The legacy cookies whose payload `loadCheckoutStateFromCookies` migrates into\r\n * localStorage. Cleared once they've been migrated — nothing is lost, the data\r\n * now lives in `checkout-state-${eventID}`.\r\n */\r\nfunction clearMigratedCheckoutCookies(eventID: string): void {\r\n removeCookie(`checkout-quantities-${eventID}`);\r\n removeCookie(`checkout-tickets-${eventID}`);\r\n removeCookie(`checkout-promocode-${eventID}`);\r\n removeCookie(`checkout-promo-discount-${eventID}`);\r\n}\r\n\r\n/**\r\n * Clear checkout state from both localStorage and cookies\r\n *\r\n * @stale-doc-comment-allow: Remove — the button's visible LABEL, not a component.\r\n *\r\n * This is the ONE cleanup point for a finished checkout — Success.svelte calls it\r\n * after a purchase, CartView calls it when the buyer abandons the cart. EVERY\r\n * cookie the checkout/promo flow writes for an event must die here; do not\r\n * sprinkle removeCookie() at call sites. The five promo cookies below are exactly\r\n * what PromocodeInput.svelte writes (its `Remove` button clears the same five),\r\n * two of which CartView.svelte also re-writes on a promo change.\r\n *\r\n * The three promo cookies past the code+amount pair used to survive checkout on a\r\n * 1-day expiry. `checkout-promo-reveal-*` is the ONLY thing hiding hidden tickets\r\n * — /tickets/event/{id} ships them in the payload with no promo code and there is\r\n * no server-side backstop — so a reveal cookie outliving the purchase left comps,\r\n * industry seats and VIP holds buyable, with no code entered, to whoever opened\r\n * the event next on that browser.\r\n */\r\nexport function clearCheckoutCookies(eventID: string): void {\r\n // Clear localStorage (new approach)\r\n if (typeof window !== 'undefined') {\r\n localStorage.removeItem(`checkout-state-${eventID}`); // @storage-escape: canonical checkout-state persistence wrapper — this module IS the localStorage layer (see file header)\r\n }\r\n\r\n clearMigratedCheckoutCookies(eventID);\r\n\r\n // The rest of what the promo flow writes. No localStorage home, no other\r\n // owner — the checkout ending is the only thing that retires them.\r\n removeCookie(`checkout-promo-discount-type-${eventID}`);\r\n removeCookie(`checkout-promo-reveal-${eventID}`);\r\n removeCookie(`checkout-promo-reveal-ids-${eventID}`);\r\n}\r\n\r\n/**\r\n * Persist checkout state to localStorage\r\n * Uses localStorage instead of cookies to avoid size limits and reduce request overhead\r\n */\r\nexport function persistCheckoutState({\r\n eventID,\r\n quantities,\r\n donationAmounts,\r\n promocode,\r\n promoDiscountAmount,\r\n tickets,\r\n}: PersistCheckoutParams): void {\r\n if (typeof window === 'undefined') return;\r\n\r\n // Store minimal ticket data to avoid storage bloat\r\n const minimalTickets = (tickets || []).map(t => ({\r\n ID: t.ID,\r\n name: t.name,\r\n price: t.price,\r\n type: t.type, // Include type for donation ticket detection\r\n visibility: t.visibility,\r\n salesChannel: t.salesChannel,\r\n }));\r\n\r\n const state = {\r\n quantities: quantities || {},\r\n donationAmounts: donationAmounts || {},\r\n promocode: promocode || '',\r\n promoDiscountAmount: promoDiscountAmount || 0,\r\n tickets: minimalTickets,\r\n updatedAt: Date.now(),\r\n };\r\n\r\n try {\r\n localStorage.setItem(`checkout-state-${eventID}`, JSON.stringify(state)); // @storage-escape: canonical checkout-state persistence wrapper — this module IS the localStorage layer (see file header)\r\n } catch (e) {\r\n logger.warn('Failed to persist checkout state to localStorage:', e);\r\n }\r\n}\r\n\r\n/**\r\n * Ensure order ID exists, create if not\r\n */\r\nexport async function ensureOrderIdExists(eventId: string): Promise<string> {\r\n const existingOrderId = getCookie(`order-id-${eventId}`);\r\n\r\n if (existingOrderId) {\r\n return existingOrderId;\r\n }\r\n\r\n const newOrderId = `order-${eventId}-${Date.now()}`;\r\n // SameSite=None; Secure so the cookie survives iframe embeds on\r\n // third-party origins (Safari ITP / Chrome SameSite-Lax-by-default).\r\n setCookie(`order-id-${eventId}`, newOrderId, {\r\n secure: true,\r\n sameSite: 'none' as const,\r\n path: '/',\r\n });\r\n\r\n return newOrderId;\r\n}\r\n","import { COOKIE_NAMES, createLogger } from '@getmicdrop/svelte-components';\r\nimport { ApiError } from '@getmicdrop/svelte-components/errors';\r\n/**\r\n * Order-related API calls: getVenueDetails, initiateOrder, getOrder,\r\n * createPaymentIntent, validatePaymentIntent, getClientIP\r\n *\r\n * @legacy-retire-with=?legacy=1\r\n * LEGACY — slated for deletion. Do NOT add new code here and do NOT build\r\n * canonicals against the untyped `[key: string]: unknown` bag interfaces below\r\n * (VenueResponse / PaymentIntentResponse / ValidatePaymentResponse /\r\n * OrderResponse). They survive only via `as` casts and exist purely for\r\n * backward compat. The canonical, typed wire->domain home for all of this is\r\n * `src/lib/api/transformers/*` (parseOrder, parseCart, parseGiftCardApplication,\r\n * parseEventPerformers, parseVenue, parseEvent) composed by the `src/lib/api/*`\r\n * clients (orders.ts, gift-cards.ts, events.ts). Retire this module behind the\r\n * `?legacy=1` flag once its remaining consumer is migrated to `$lib/api/*`.\r\n *\r\n * Live consumer (as of this change): `src/lib/utils/utils.js` re-exports\r\n * getClientIP / getVenueDetails / initiateOrder / getOrder / createPaymentIntent\r\n * / validatePaymentIntent from here (the `$lib/utils/utils.js` back-compat\r\n * barrel). That barrel is the single retirement blocker to plan around.\r\n */\r\nimport { apiGet, apiPost } from '$lib/api/client';\r\nimport { buildAuthHeaders } from '$lib/api/authHeaders';\r\nimport { getCookie, setCookie } from './cookies';\r\n\r\nconst logger = createLogger('orderApi');\r\n\r\ninterface OrderResult {\r\n success: boolean;\r\n uuid?: string;\r\n serviceFee?: number;\r\n subtotal?: number;\r\n error?: string;\r\n errorType?: 'inventory' | 'server' | 'network';\r\n}\r\n\r\ninterface CartData {\r\n eventID?: string | number;\r\n quantities?: Record<string, number>;\r\n donationAmounts?: Record<string, number>;\r\n [key: string]: unknown;\r\n}\r\n\r\ninterface PaymentIntentResponse {\r\n clientSecret?: string;\r\n stripe_publishable_key?: string;\r\n [key: string]: unknown;\r\n}\r\n\r\ninterface ValidatePaymentResponse {\r\n [key: string]: unknown;\r\n}\r\n\r\ninterface OrderResponse {\r\n [key: string]: unknown;\r\n}\r\n\r\ninterface VenueResponse {\r\n [key: string]: unknown;\r\n}\r\n\r\n/**\r\n * @deprecated IP is now resolved server-side via request headers\r\n */\r\nexport async function getClientIP(): Promise<string | null> {\r\n return null;\r\n}\r\n\r\nexport async function getVenueDetails(\r\n venueID: string | number\r\n): Promise<VenueResponse> {\r\n try {\r\n const result = await apiGet<VenueResponse>(`/venues/${venueID}`);\r\n\r\n if (!result.success) {\r\n throw new ApiError(\r\n result.error ?? `API error: ${result.statusCode}`,\r\n result.statusCode ?? 0,\r\n { endpoint: `/venues/${venueID}`, method: 'GET' }\r\n );\r\n }\r\n\r\n return result.data as VenueResponse;\r\n } catch (error) {\r\n logger.error('getVenueDetails error:', error);\r\n throw error;\r\n }\r\n}\r\n\r\nexport async function initiateOrder(\r\n cartData: CartData = {}\r\n): Promise<OrderResult> {\r\n try {\r\n const ip = await getClientIP();\r\n\r\n const { eventID, quantities, donationAmounts, ...restCartData } = cartData;\r\n\r\n // Convert quantities keys to numbers and eventID to number (API expects numeric types)\r\n const numericQuantities = quantities\r\n ? Object.fromEntries(\r\n Object.entries(quantities).map(([k, v]) => [parseInt(k, 10), v])\r\n )\r\n : {};\r\n\r\n // Convert donationAmounts keys to numbers and values to floats\r\n const numericDonationAmounts = donationAmounts\r\n ? Object.fromEntries(\r\n Object.entries(donationAmounts)\r\n .filter(([, v]) => parseFloat(String(v)) > 0)\r\n .map(([k, v]) => [parseInt(k, 10), parseFloat(String(v))])\r\n )\r\n : undefined;\r\n\r\n const orderPayload = {\r\n purchaserIP: ip,\r\n eventID: eventID ? parseInt(String(eventID), 10) : undefined,\r\n quantities: numericQuantities,\r\n ...(numericDonationAmounts &&\r\n Object.keys(numericDonationAmounts).length > 0\r\n ? { donationAmounts: numericDonationAmounts }\r\n : {}),\r\n ...restCartData,\r\n };\r\n\r\n const result = await apiPost<Record<string, unknown>>(\r\n `/orders/create`,\r\n orderPayload\r\n );\r\n\r\n const data = result.data ?? {};\r\n\r\n // Check for API errors (including 200-with-error-field pattern)\r\n if (!result.success || data['error']) {\r\n const errorMessage =\r\n (data['error'] as string) ||\r\n (data['message'] as string) ||\r\n result.error ||\r\n 'Order creation failed';\r\n // Check for inventory-related errors\r\n const isInventoryError =\r\n errorMessage.toLowerCase().includes('inventory') ||\r\n errorMessage.toLowerCase().includes('sold out') ||\r\n errorMessage.toLowerCase().includes('not available') ||\r\n errorMessage.toLowerCase().includes('insufficient') ||\r\n result.statusCode === 409; // Conflict status often used for inventory issues\r\n\r\n return {\r\n success: false,\r\n error: errorMessage,\r\n errorType: isInventoryError ? 'inventory' : 'server',\r\n };\r\n }\r\n\r\n // SameSite=None; Secure so the cookie survives iframe embeds on\r\n // third-party origins (Safari ITP / Chrome SameSite-Lax-by-default).\r\n // Without this, embedding the calendar in another venue's site\r\n // silently drops the cart on every navigation.\r\n setCookie(\r\n 'checkout-cartid',\r\n (data['uuid'] as string) || (data['cartUUID'] as string),\r\n {\r\n secure: true,\r\n sameSite: 'none' as const,\r\n path: '/',\r\n }\r\n );\r\n return {\r\n success: true,\r\n uuid: (data['uuid'] as string) || (data['cartUUID'] as string),\r\n serviceFee: (data['serviceFee'] as number) ?? 0,\r\n subtotal: (data['subtotal'] as number) ?? 0,\r\n };\r\n } catch (err: unknown) {\r\n const message = err instanceof Error ? err.message : 'Network error';\r\n logger.error('Order initiation failed:', err);\r\n return {\r\n success: false,\r\n error: message,\r\n errorType: 'network',\r\n };\r\n }\r\n}\r\n\r\nexport async function getOrder(orderId: string): Promise<OrderResponse> {\r\n try {\r\n const result = await apiGet<OrderResponse>(`/orders/${orderId}`);\r\n\r\n if (!result.success) {\r\n const errorMessage =\r\n result.error ?? `Failed to fetch order (${result.statusCode})`;\r\n logger.error('getOrder error response:', errorMessage);\r\n throw new ApiError(errorMessage, result.statusCode ?? 0, {\r\n endpoint: `/orders/${orderId}`,\r\n method: 'GET',\r\n });\r\n }\r\n\r\n return result.data as OrderResponse;\r\n } catch (err) {\r\n logger.error('getOrder error:', err);\r\n throw err;\r\n }\r\n}\r\n\r\nexport async function createPaymentIntent(\r\n cartId: string,\r\n quantities: Record<string, number>,\r\n donationAmounts?: Record<string, number>\r\n): Promise<PaymentIntentResponse> {\r\n const token = getCookie(COOKIE_NAMES.OPERATOR_TOKEN);\r\n\r\n try {\r\n const result = await apiPost<PaymentIntentResponse>(\r\n `/orders/${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 headers: buildAuthHeaders(token),\r\n }\r\n );\r\n\r\n if (!result.success) {\r\n logger.error('Payment intent creation failed:', result.error);\r\n throw new ApiError(\r\n result.error === 'Request timed out'\r\n ? 'Request timed out. Please check your connection and try again.'\r\n : result.error?.includes('Failed to fetch')\r\n ? 'Unable to connect to payment server. Please check your internet connection or try again later.'\r\n : (result.error ??\r\n `Failed to create payment intent: ${result.statusCode}`),\r\n result.statusCode ?? 0,\r\n { endpoint: `/orders/${cartId}/payment-intent`, method: 'POST' }\r\n );\r\n }\r\n\r\n return result.data as PaymentIntentResponse;\r\n } catch (err: unknown) {\r\n logger.error('createPaymentIntent error:', err);\r\n // Re-throw the error so the caller can handle it\r\n throw err;\r\n }\r\n}\r\n\r\nexport async function validatePaymentIntent(\r\n cartId: string,\r\n payload: Record<string, unknown>\r\n): Promise<ValidatePaymentResponse | null> {\r\n try {\r\n const token = getCookie(COOKIE_NAMES.OPERATOR_TOKEN);\r\n\r\n const result = await apiPost<ValidatePaymentResponse>(\r\n `/orders/${cartId}/validate-payment`,\r\n payload,\r\n {\r\n headers: buildAuthHeaders(token),\r\n }\r\n );\r\n\r\n return result.data ?? null;\r\n } catch (err) {\r\n logger.error('validatePaymentIntent error:', err);\r\n return null;\r\n }\r\n}\r\n","// @fetch-escape: widget-intentional.\r\n// @api-client-escape: fire-and-forget UTM beacon — keeps raw fetch (GET, no body, response ignored).\r\n// Migrating to apiPost broke the GET contract; apiGet would parse JSON on a no-body 200 and log a false-positive error.\r\nimport { createLogger } from '@getmicdrop/svelte-components';\r\nimport { normalizeUtmValue, DIRECT_SOURCE } from '../tracking/normalize.js';\r\nimport { trackEventView } from '../tracking/index.js';\r\nconst logger = createLogger('utm');\r\n\r\n/**\r\n * UTM source tracking\r\n */\r\n\r\n/**\r\n * Track UTM source for an event (parameter named venueID for backwards compatibility\r\n * but actually represents eventID).\r\n *\r\n * Bumps the legacy per-source click COUNTERS (utm_counters) that power the old\r\n * UTM analytics page. The source is normalized at write time (lowercased, spaces\r\n * → underscores) and an empty source resolves to the ONE canonical default\r\n * `direct` — so the counter buckets match the beacon + order buckets (the\r\n * historical `Direct`/`''`/`direct` split is dead).\r\n */\r\nexport async function trackUTMSource(venueID: string | number): Promise<void> {\r\n const urlParams = new URLSearchParams(window.location.search);\r\n const utmSource =\r\n normalizeUtmValue(urlParams.get('utm_source')) || DIRECT_SOURCE;\r\n\r\n try {\r\n await fetch(\r\n `https://get-micdrop.com/api/v2/public/utm/${venueID}/${encodeURIComponent(utmSource)}`\r\n );\r\n } catch (err) {\r\n logger.error('UTM tracking failed:', err);\r\n }\r\n}\r\n\r\n/**\r\n * Event-detail page-view tracking — the `event_view` funnel moment.\r\n *\r\n * Delegates to the canonical funnel-beacon service (`$lib/tracking`), which\r\n * fires the extended `POST /track/pageview` beacon carrying the normalized utm\r\n * set, persistent visitorId (consent-gated), sessionId, widgetId, deviceType,\r\n * referrer and pageUrl, and keeps the first-party attribution store fresh. The\r\n * beacon is deduplicated per session and fire-and-forget.\r\n *\r\n * Kept as a thin wrapper (rather than inlining `trackEventView` at the call\r\n * site) so the existing `trackPageView(eventId)` call in EventPage stays\r\n * unchanged and the pre-tracking-rebuild external surface is preserved.\r\n */\r\nexport async function trackPageView(eventID: string | number): Promise<void> {\r\n await trackEventView(eventID);\r\n}\r\n"],"names":["assign","target","i","source","key","defaultConverter","value","init","converter","defaultAttributes","set","name","attributes","stringifiedAttributes","attributeName","get","cookies","jar","parts","found","api","setCookieLocal","options","Cookies","getCookieLocal","removeCookieLocal","logger","createLogger","loadCheckoutStateFromCookies","eventID","quantities","donationAmounts","tickets","promocode","promoDiscountAmount","stored","parsed","e","getCookie","persistCheckoutState","clearMigratedCheckoutCookies","removeCookie","clearCheckoutCookies","minimalTickets","t","state","ensureOrderIdExists","eventId","existingOrderId","newOrderId","setCookie","getClientIP","getVenueDetails","venueID","result","apiGet","ApiError","error","initiateOrder","cartData","ip","restCartData","numericQuantities","k","v","numericDonationAmounts","orderPayload","apiPost","data","errorMessage","isInventoryError","err","message","getOrder","orderId","trackUTMSource","urlParams","utmSource","normalizeUtmValue","DIRECT_SOURCE"],"mappings":"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","x_google_ignoreList":[0]}