@gomusdev/web-components 4.13.0 → 4.14.0

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.
@@ -11113,9 +11113,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11113
11113
  if (time) ({hour: hour, minute: minute, second: second, millisecond: millisecond} = time);
11114
11114
  return new $2aaf608024c21ca1$export$ca871e8dbb80966f(date.calendar, date.era, date.year, date.month, date.day, hour, minute, second, millisecond);
11115
11115
  }
11116
- function $d07e34cce18680fd$export$d33f79e3ffc3dc83(dateTime) {
11117
- return new $2aaf608024c21ca1$export$680ea196effce5f(dateTime.hour, dateTime.minute, dateTime.second, dateTime.millisecond);
11118
- }
11119
11116
  function $d07e34cce18680fd$export$b4a036af3fc0b032(date, calendar) {
11120
11117
  if ($ad063034c8620db8$export$dbc69fd56b53d5e(date.calendar, calendar)) return date;
11121
11118
  let calendarDate = calendar.fromJulianDay(date.calendar.toJulianDay(date));
@@ -11273,14 +11270,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11273
11270
  time.millisecond += duration.milliseconds || 0;
11274
11271
  return $435a2ceaa8778ed8$var$balanceTime(time);
11275
11272
  }
11276
- function $435a2ceaa8778ed8$export$7ed87b6bc2506470(time, duration) {
11277
- let res = time.copy();
11278
- $435a2ceaa8778ed8$var$addTimeFields(res, duration);
11279
- return res;
11280
- }
11281
- function $435a2ceaa8778ed8$export$fe34d3a381cd7501(time, duration) {
11282
- return $435a2ceaa8778ed8$export$7ed87b6bc2506470(time, $435a2ceaa8778ed8$export$3e2544e88a25bff8(duration));
11283
- }
11284
11273
  function $435a2ceaa8778ed8$export$d52ced6badfb9a4c(value, field, amount, options) {
11285
11274
  let mutable = value.copy();
11286
11275
  switch (field) {
@@ -11562,46 +11551,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11562
11551
  return $ad063034c8620db8$export$68781ddf31c0090f(this, b);
11563
11552
  }
11564
11553
  };
11565
- var $2aaf608024c21ca1$export$680ea196effce5f = class $2aaf608024c21ca1$export$680ea196effce5f {
11566
- #type;
11567
- constructor(hour = 0, minute = 0, second = 0, millisecond = 0) {
11568
- this.hour = hour;
11569
- this.minute = minute;
11570
- this.second = second;
11571
- this.millisecond = millisecond;
11572
- $435a2ceaa8778ed8$export$7555de1e070510cb(this);
11573
- }
11574
- /** Returns a copy of this time. */ copy() {
11575
- return new $2aaf608024c21ca1$export$680ea196effce5f(this.hour, this.minute, this.second, this.millisecond);
11576
- }
11577
- /** Returns a new `Time` with the given duration added to it. */ add(duration) {
11578
- return $435a2ceaa8778ed8$export$7ed87b6bc2506470(this, duration);
11579
- }
11580
- /** Returns a new `Time` with the given duration subtracted from it. */ subtract(duration) {
11581
- return $435a2ceaa8778ed8$export$fe34d3a381cd7501(this, duration);
11582
- }
11583
- /**
11584
- * Returns a new `Time` with the given fields set to the provided values. Other fields will be
11585
- * constrained accordingly.
11586
- */ set(fields) {
11587
- return $435a2ceaa8778ed8$export$e5d5e1c1822b6e56(this, fields);
11588
- }
11589
- /**
11590
- * Returns a new `Time` with the given field adjusted by a specified amount.
11591
- * When the resulting value reaches the limits of the field, it wraps around.
11592
- */ cycle(field, amount, options) {
11593
- return $435a2ceaa8778ed8$export$dd02b3e0007dfe28(this, field, amount, options);
11594
- }
11595
- /** Converts the time to an ISO 8601 formatted string. */ toString() {
11596
- return $58246871e4652552$export$f59dee82248f5ad4(this);
11597
- }
11598
- /**
11599
- * Compares this time with another. A negative result indicates that this time is before the given
11600
- * one, and a positive time indicates that it is after.
11601
- */ compare(b) {
11602
- return $ad063034c8620db8$export$c19a80a9721b80f6(this, b);
11603
- }
11604
- };
11605
11554
  var $2aaf608024c21ca1$export$ca871e8dbb80966f = class $2aaf608024c21ca1$export$ca871e8dbb80966f {
11606
11555
  #type;
11607
11556
  constructor(...args) {
@@ -11826,19 +11775,31 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11826
11775
  }
11827
11776
  //#endregion
11828
11777
  //#region ../../packages/gomus-types/lib/helpers/utils.ts
11829
- function formatTime(value) {
11830
- return $d07e34cce18680fd$export$d33f79e3ffc3dc83($58246871e4652552$export$5adfdab05168c219(value, "Europe/Berlin")).toString().slice(0, -3);
11778
+ /** Named date presets — the single place defining what each rendering means (WI 151). */
11779
+ var DATE_FORMAT_PRESETS = {
11780
+ dayMonth: {
11781
+ month: "numeric",
11782
+ day: "numeric"
11783
+ },
11784
+ short: {
11785
+ year: "numeric",
11786
+ month: "numeric",
11787
+ day: "numeric"
11788
+ }
11789
+ };
11790
+ function formatTime(value, locale) {
11791
+ const zoned = $58246871e4652552$export$5adfdab05168c219(value, "Europe/Berlin");
11792
+ return new $12a3c853105e5a70$export$ad991b66133851cf(locale, {
11793
+ timeZone: zoned.timeZone,
11794
+ hour: "numeric",
11795
+ minute: "numeric"
11796
+ }).format(zoned.toDate());
11831
11797
  }
11832
- function formatDate(isoDateString, options = {
11833
- weekday: "long",
11834
- year: "numeric",
11835
- month: "long",
11836
- day: "numeric"
11837
- }, locale = "de") {
11798
+ function formatDate(isoDateString, preset, locale) {
11838
11799
  const zoned = $58246871e4652552$export$5adfdab05168c219(isoDateString instanceof Date ? isoDateString.toISOString() : isoDateString, "Europe/Berlin");
11839
11800
  return new $12a3c853105e5a70$export$ad991b66133851cf(locale, {
11840
11801
  timeZone: zoned.timeZone,
11841
- ...options
11802
+ ...DATE_FORMAT_PRESETS[preset]
11842
11803
  }).format(zoned.toDate());
11843
11804
  }
11844
11805
  //#endregion
@@ -13830,7 +13791,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13830
13791
  return "https://" + this.shopDomain;
13831
13792
  }
13832
13793
  get locale() {
13833
- return get$2(this.#data).locale;
13794
+ return get$2(this.#data).locale ?? "de";
13795
+ }
13796
+ formatTime(value) {
13797
+ return formatTime(value, this.locale);
13798
+ }
13799
+ formatDate(value, preset) {
13800
+ return formatDate(value, preset, this.locale);
13834
13801
  }
13835
13802
  get shop() {
13836
13803
  return this.fetchAndCache("/api/v4/shop", "shop", "shop");
@@ -15566,10 +15533,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15566
15533
  template_effect(($0, $1) => {
15567
15534
  set_text(text_2, $0);
15568
15535
  set_text(text_3, $1);
15569
- }, [() => formatDate(cartItem().time, {
15570
- month: "numeric",
15571
- day: "numeric"
15572
- }, shop.locale), () => formatTime(cartItem().time)]);
15536
+ }, [() => shop.formatDate(cartItem().time, "dayMonth"), () => shop.formatTime(cartItem().time)]);
15573
15537
  append($$anchor, fragment_1);
15574
15538
  };
15575
15539
  if_block(node, ($$render) => {
@@ -15628,16 +15592,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15628
15592
  var span_3 = root_1$19();
15629
15593
  var text_3 = child(span_3, true);
15630
15594
  reset(span_3);
15631
- template_effect(($0) => set_text(text_3, $0), [() => formatTime(cartItem().time)]);
15595
+ template_effect(($0) => set_text(text_3, $0), [() => shop.formatTime(cartItem().time)]);
15632
15596
  append($$anchor, span_3);
15633
15597
  };
15634
15598
  if_block(node_2, ($$render) => {
15635
15599
  if (cartItem().product.type === "Ticket" && cartItem().product.subtype === "timeslot") $$render(consequent_1);
15636
15600
  });
15637
- template_effect(($0) => set_text(text_2, $0), [() => formatDate(cartItem().time, {
15638
- month: "numeric",
15639
- day: "numeric"
15640
- }, shop.locale)]);
15601
+ template_effect(($0) => set_text(text_2, $0), [() => shop.formatDate(cartItem().time, "dayMonth")]);
15641
15602
  append($$anchor, fragment_1);
15642
15603
  };
15643
15604
  if_block(node_1, ($$render) => {
@@ -15662,12 +15623,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15662
15623
  if (!cartItem().time) return null;
15663
15624
  try {
15664
15625
  return {
15665
- date: formatDate(cartItem().time, {
15666
- year: "numeric",
15667
- month: "numeric",
15668
- day: "numeric"
15669
- }, shop.locale),
15670
- time: formatTime(cartItem().time)
15626
+ date: shop.formatDate(cartItem().time, "short"),
15627
+ time: shop.formatTime(cartItem().time)
15671
15628
  };
15672
15629
  } catch {
15673
15630
  return {
@@ -18143,12 +18100,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18143
18100
  * the visible row title: event rows compose it from event_title + time because a
18144
18101
  * flat-price event's price row carries no title (the row IS the event) — naming
18145
18102
  * the control from product.title alone left it unnamed (WI #141).
18103
+ *
18104
+ * Locale comes in as a parameter — shared/ components stay store-agnostic (WI #151).
18146
18105
  */
18147
- function quantityLabel(item) {
18106
+ function quantityLabel(item, locale) {
18148
18107
  const { product } = item;
18149
18108
  return isEventTicket(product) ? [
18150
18109
  product.event_title,
18151
- item.time && formatTime(item.time),
18110
+ item.time && formatTime(item.time, locale),
18152
18111
  product.title
18153
18112
  ].filter(Boolean).join(" - ") : product.title;
18154
18113
  }
@@ -18313,7 +18272,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18313
18272
  var alternate_1 = ($$anchor) => {
18314
18273
  {
18315
18274
  let $0 = /* @__PURE__ */ user_derived(() => displayItem().quantity ?? 0);
18316
- let $1 = /* @__PURE__ */ user_derived(() => quantityLabel(displayItem()));
18275
+ let $1 = /* @__PURE__ */ user_derived(() => quantityLabel(displayItem(), shop.locale));
18317
18276
  QuantityControl($$anchor, {
18318
18277
  get value() {
18319
18278
  return get$2($0);
@@ -35532,12 +35491,32 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
35532
35491
  "events:admission:day",
35533
35492
  "events:admission:timeslot",
35534
35493
  "events:price",
35535
- "coupon"
35494
+ "coupon",
35495
+ "tour"
35536
35496
  ];
35537
35497
  //#endregion
35538
35498
  //#region src/components/ticketSelection/filters/_helpers.ts
35539
35499
  var TWO_HOURS_MS = 7200 * 1e3;
35540
35500
  /**
35501
+ * The common tail of every ticket filter's `addToCart`: given the ticket
35502
+ * its loader resolved, build the cart line, reject if the ticket is unavailable
35503
+ * (sold out / unknown → the loader yielded nothing) or the quantity exceeds the
35504
+ * remaining capacity, add the line, and return its uuid. Subtype-agnostic — the
35505
+ * per-filter loader is the only thing that differs.
35506
+ */
35507
+ function addResolvedTicketToCart(ticket, { id, quantity, time }) {
35508
+ if (!(quantity > 0)) throw new Error(`(go.cart.addItem) 'quantity' must be a positive number`);
35509
+ if (!ticket) throw new Error(`(go.cart.addItem) ticket ${id} not available (sold out or unknown)`);
35510
+ const item = createCartItem(ticket, {
35511
+ quantity,
35512
+ time: time ?? ticket.selectedTime
35513
+ });
35514
+ const { max } = shop.capacityManager.capacity(shop.cart, item, createCart());
35515
+ if (quantity > max) throw new Error(`(go.cart.addItem) only ${max} left for ticket ${id}`);
35516
+ shop.cart.addItem(item);
35517
+ return item.uuid;
35518
+ }
35519
+ /**
35541
35520
  * When a segment opts into content attributes (with-content), batch-fetch
35542
35521
  * tickets/content for the given tickets and merge each entry's `content` onto
35543
35522
  * the matching ticket by id (mirrors the legacy `ticket.content = item.content`).
@@ -35597,433 +35576,566 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
35597
35576
  loadPickerQuotas(tsd, quotas);
35598
35577
  }
35599
35578
  //#endregion
35600
- //#region src/components/ticketSelection/filters/registry.ts
35601
- var REGISTRY = {
35602
- "ticket:timeslot": {
35603
- name: "ticket:timeslot",
35604
- calendarEndpoint: "tickets",
35605
- apiToken: "time_slot",
35606
- requires: [{
35607
- kind: "tsd",
35608
- field: "selectedDate"
35609
- }, {
35610
- kind: "tsd",
35611
- field: "selectedTimeslot"
35612
- }],
35613
- isCalendarVisible: () => true,
35614
- isTimeslotsVisible: (tsd) => Boolean(tsd.selectedDate),
35615
- isTicketsVisible: (tsd) => Boolean(tsd.selectedDate && tsd.selectedTimeslot),
35616
- async loadTimeslots(tsd) {
35617
- if (!tsd?.selectedDate) return;
35618
- const { quotas } = await shop.asyncFetch(() => shop.ticketsAndQuotas({
35619
- by_bookable: true,
35620
- valid_at: tsd.selectedDate.toString(),
35621
- by_ticket_type: "time_slot",
35622
- "by_museum_ids[]": tsd.museumIds,
35623
- "by_exhibition_ids[]": tsd.exhibitionIds,
35624
- "by_ticket_ids[]": tsd.ticketIds,
35625
- "by_ticket_group_ids[]": tsd.ticketGroupIds
35626
- }));
35627
- loadPickerQuotas(tsd, quotas);
35628
- },
35629
- async loadProducts(segment) {
35630
- const tsd = segment.ticketSelectionDetails;
35631
- if (!tsd?.selectedDate || !tsd.selectedTimeslot) return;
35632
- const { tickets, quotas } = await shop.asyncFetch(() => shop.ticketsAndQuotas({
35633
- by_bookable: true,
35634
- valid_at: tsd.selectedDate.toString(),
35635
- by_ticket_type: "time_slot",
35636
- "by_museum_ids[]": segment.museumIds ?? tsd.museumIds,
35637
- "by_exhibition_ids[]": tsd.exhibitionIds,
35638
- "by_ticket_ids[]": tsd.ticketIds,
35639
- "by_ticket_group_ids[]": segment.ticketGroupIds ?? tsd.ticketGroupIds
35640
- }));
35641
- shop.capacityManager.addQuotas(quotas);
35642
- const uiTickets = initUITimeslotTickets(filterAvailabletickets(tickets, tsd.selectedTime), tsd.selectedTime);
35643
- await enrichTicketsWithContent(segment, uiTickets);
35644
- for (const ticket of uiTickets) segment.preCart.addItem(createCartItem(ticket, { time: tsd.selectedTime }));
35645
- }
35579
+ //#region src/components/ticketSelection/filters/ticket/timeslot.ts
35580
+ async function loadTimeslotTickets(filters, selectedTime) {
35581
+ const { tickets, quotas } = await shop.asyncFetch(() => shop.ticketsAndQuotas({
35582
+ by_bookable: true,
35583
+ by_ticket_type: "time_slot",
35584
+ ...filters
35585
+ }));
35586
+ shop.capacityManager.addQuotas(quotas);
35587
+ return initUITimeslotTickets(filterAvailabletickets(tickets, selectedTime), selectedTime);
35588
+ }
35589
+ var filter$12 = {
35590
+ name: "ticket:timeslot",
35591
+ calendarEndpoint: "tickets",
35592
+ apiToken: "time_slot",
35593
+ requires: [{
35594
+ kind: "tsd",
35595
+ field: "selectedDate"
35596
+ }, {
35597
+ kind: "tsd",
35598
+ field: "selectedTimeslot"
35599
+ }],
35600
+ isCalendarVisible: () => true,
35601
+ isTimeslotsVisible: (tsd) => Boolean(tsd.selectedDate),
35602
+ isTicketsVisible: (tsd) => Boolean(tsd.selectedDate && tsd.selectedTimeslot),
35603
+ async addToCart(options) {
35604
+ const { id, quantity, time } = options;
35605
+ if (!time) throw new Error(`(go.cart.addItem) ticket:timeslot requires a 'time'`);
35606
+ const ticket = (await loadTimeslotTickets({
35607
+ valid_at: time.slice(0, 10),
35608
+ "by_ticket_ids[]": [id]
35609
+ }, time))[0];
35610
+ return addResolvedTicketToCart(ticket, {
35611
+ id,
35612
+ quantity,
35613
+ time
35614
+ });
35646
35615
  },
35647
- "ticket:day": {
35648
- name: "ticket:day",
35649
- calendarEndpoint: "tickets",
35650
- apiToken: "normal",
35651
- requires: [{
35652
- kind: "tsd",
35653
- field: "selectedDate"
35654
- }],
35655
- isCalendarVisible: () => true,
35656
- isTimeslotsVisible: () => false,
35657
- isTicketsVisible: (tsd) => Boolean(tsd.selectedDate),
35658
- async loadTimeslots() {},
35659
- async loadProducts(segment) {
35660
- const tsd = segment.ticketSelectionDetails;
35661
- if (!tsd?.selectedDate) return;
35662
- const { tickets, quotas } = await shop.asyncFetch(() => shop.ticketsAndQuotas({
35663
- by_bookable: true,
35664
- valid_at: tsd.selectedDate.toString(),
35665
- "by_ticket_types[]": ["normal"],
35666
- "by_museum_ids[]": segment.museumIds ?? tsd.museumIds,
35667
- "by_exhibition_ids[]": tsd.exhibitionIds,
35668
- "by_ticket_ids[]": tsd.ticketIds,
35669
- "by_ticket_group_ids[]": segment.ticketGroupIds ?? tsd.ticketGroupIds
35670
- }));
35671
- shop.capacityManager.addQuotas(quotas);
35672
- const uiTickets = initUIDayTickets(tickets);
35673
- await enrichTicketsWithContent(segment, uiTickets);
35674
- for (const ticket of uiTickets) segment.preCart.addItem(createCartItem(ticket, { time: ticket.selectedTime }));
35675
- }
35616
+ async loadTimeslots(tsd) {
35617
+ if (!tsd?.selectedDate) return;
35618
+ const { quotas } = await shop.asyncFetch(() => shop.ticketsAndQuotas({
35619
+ by_bookable: true,
35620
+ valid_at: tsd.selectedDate.toString(),
35621
+ by_ticket_type: "time_slot",
35622
+ "by_museum_ids[]": tsd.museumIds,
35623
+ "by_exhibition_ids[]": tsd.exhibitionIds,
35624
+ "by_ticket_ids[]": tsd.ticketIds,
35625
+ "by_ticket_group_ids[]": tsd.ticketGroupIds
35626
+ }));
35627
+ loadPickerQuotas(tsd, quotas);
35676
35628
  },
35677
- "ticket:annual": {
35678
- name: "ticket:annual",
35679
- calendarEndpoint: null,
35680
- apiToken: "annual",
35681
- requires: [],
35682
- isCalendarVisible: () => false,
35683
- isTimeslotsVisible: () => false,
35684
- isTicketsVisible: () => true,
35685
- async loadTimeslots() {},
35686
- async loadProducts(segment) {
35687
- const tsd = segment.ticketSelectionDetails;
35688
- if (!tsd) return;
35689
- const tickets = await shop.asyncFetch(() => shop.tickets({
35690
- by_bookable: true,
35691
- "by_ticket_types[]": ["annual"],
35692
- "by_ticket_ids[]": tsd.ticketIds,
35693
- "by_ticket_group_ids[]": segment.ticketGroupIds ?? tsd.ticketGroupIds
35694
- }));
35695
- const uiTickets = Object.values(tickets).map((t) => createUITicket(t));
35696
- await enrichTicketsWithContent(segment, uiTickets);
35697
- for (const ticket of uiTickets) segment.preCart.addItem(createCartItem(ticket));
35698
- }
35629
+ async loadProducts(segment) {
35630
+ const tsd = segment.ticketSelectionDetails;
35631
+ if (!tsd?.selectedDate || !tsd.selectedTimeslot) return;
35632
+ const uiTickets = await loadTimeslotTickets({
35633
+ valid_at: tsd.selectedDate.toString(),
35634
+ "by_museum_ids[]": segment.museumIds ?? tsd.museumIds,
35635
+ "by_exhibition_ids[]": tsd.exhibitionIds,
35636
+ "by_ticket_ids[]": tsd.ticketIds,
35637
+ "by_ticket_group_ids[]": segment.ticketGroupIds ?? tsd.ticketGroupIds
35638
+ }, tsd.selectedTimeslot);
35639
+ await enrichTicketsWithContent(segment, uiTickets);
35640
+ for (const ticket of uiTickets) segment.preCart.addItem(createCartItem(ticket, { time: tsd.selectedTime }));
35641
+ }
35642
+ };
35643
+ //#endregion
35644
+ //#region src/components/ticketSelection/filters/ticket/day.ts
35645
+ async function loadDayTickets(filters) {
35646
+ const { tickets, quotas } = await shop.asyncFetch(() => shop.ticketsAndQuotas({
35647
+ by_bookable: true,
35648
+ "by_ticket_types[]": ["normal"],
35649
+ ...filters
35650
+ }));
35651
+ shop.capacityManager.addQuotas(quotas);
35652
+ return initUIDayTickets(tickets);
35653
+ }
35654
+ var filter$11 = {
35655
+ name: "ticket:day",
35656
+ calendarEndpoint: "tickets",
35657
+ apiToken: "normal",
35658
+ requires: [{
35659
+ kind: "tsd",
35660
+ field: "selectedDate"
35661
+ }],
35662
+ isCalendarVisible: () => true,
35663
+ isTimeslotsVisible: () => false,
35664
+ isTicketsVisible: (tsd) => Boolean(tsd.selectedDate),
35665
+ async loadTimeslots() {},
35666
+ async addToCart(options) {
35667
+ const { id, quantity, date } = options;
35668
+ if (!date) throw new Error(`(go.cart.addItem) ticket:day requires a 'date'`);
35669
+ const ticket = (await loadDayTickets({
35670
+ valid_at: date,
35671
+ "by_ticket_ids[]": [id]
35672
+ }))[0];
35673
+ return addResolvedTicketToCart(ticket, {
35674
+ id,
35675
+ quantity
35676
+ });
35677
+ },
35678
+ async loadProducts(segment) {
35679
+ const tsd = segment.ticketSelectionDetails;
35680
+ if (!tsd?.selectedDate) return;
35681
+ const uiTickets = await loadDayTickets({
35682
+ valid_at: tsd.selectedDate.toString(),
35683
+ "by_museum_ids[]": segment.museumIds ?? tsd.museumIds,
35684
+ "by_exhibition_ids[]": tsd.exhibitionIds,
35685
+ "by_ticket_ids[]": tsd.ticketIds,
35686
+ "by_ticket_group_ids[]": segment.ticketGroupIds ?? tsd.ticketGroupIds
35687
+ });
35688
+ await enrichTicketsWithContent(segment, uiTickets);
35689
+ for (const ticket of uiTickets) segment.preCart.addItem(createCartItem(ticket, { time: ticket.selectedTime }));
35690
+ }
35691
+ };
35692
+ //#endregion
35693
+ //#region src/components/ticketSelection/filters/ticket/annual.ts
35694
+ async function loadAnnualTickets(filters) {
35695
+ const tickets = await shop.asyncFetch(() => shop.tickets({
35696
+ by_bookable: true,
35697
+ "by_ticket_types[]": ["annual"],
35698
+ ...filters
35699
+ }));
35700
+ return Object.values(tickets).map((t) => createUITicket(t));
35701
+ }
35702
+ var filter$10 = {
35703
+ name: "ticket:annual",
35704
+ calendarEndpoint: null,
35705
+ apiToken: "annual",
35706
+ requires: [],
35707
+ isCalendarVisible: () => false,
35708
+ isTimeslotsVisible: () => false,
35709
+ isTicketsVisible: () => true,
35710
+ async loadTimeslots() {},
35711
+ async addToCart(options) {
35712
+ const { id, quantity } = options;
35713
+ const ticket = (await loadAnnualTickets({ "by_ticket_ids[]": [id] }))[0];
35714
+ return addResolvedTicketToCart(ticket, {
35715
+ id,
35716
+ quantity
35717
+ });
35718
+ },
35719
+ async loadProducts(segment) {
35720
+ const tsd = segment.ticketSelectionDetails;
35721
+ if (!tsd) return;
35722
+ const uiTickets = await loadAnnualTickets({
35723
+ "by_ticket_ids[]": tsd.ticketIds,
35724
+ "by_ticket_group_ids[]": segment.ticketGroupIds ?? tsd.ticketGroupIds
35725
+ });
35726
+ await enrichTicketsWithContent(segment, uiTickets);
35727
+ for (const ticket of uiTickets) segment.preCart.addItem(createCartItem(ticket));
35728
+ }
35729
+ };
35730
+ //#endregion
35731
+ //#region src/components/ticketSelection/filters/event/admission.ts
35732
+ var filter$9 = {
35733
+ name: "event:admission",
35734
+ calendarEndpoint: "events",
35735
+ requires: [{
35736
+ kind: "tsd",
35737
+ field: "eventIds"
35738
+ }, {
35739
+ kind: "tsd",
35740
+ field: "selectedDate"
35741
+ }],
35742
+ isCalendarVisible: () => true,
35743
+ isTimeslotsVisible: (tsd) => Boolean(tsd.selectedDate),
35744
+ isTicketsVisible: (tsd) => Boolean(tsd.selectedDate && tsd.selectedTimeslot),
35745
+ async loadTimeslots(tsd) {
35746
+ if (!tsd?.eventIds?.length || !tsd.selectedDate) return;
35747
+ const event = await shop.asyncFetch(() => shop.getEvent(tsd.eventIds[0]));
35748
+ if (!event.tickets?.length) return;
35749
+ const { quotas } = await shop.asyncFetch(() => shop.ticketsAndQuotas({
35750
+ "by_ticket_ids[]": event.tickets,
35751
+ by_bookable: true,
35752
+ valid_at: tsd.selectedDate.toString()
35753
+ }));
35754
+ loadPickerQuotas(tsd, quotas);
35699
35755
  },
35700
- "event:admission": {
35701
- name: "event:admission",
35702
- calendarEndpoint: "events",
35703
- requires: [{
35756
+ async loadProducts(segment) {
35757
+ const tsd = segment.ticketSelectionDetails;
35758
+ if (!tsd?.eventIds?.length || !tsd.selectedDate) return;
35759
+ const event = await shop.asyncFetch(() => shop.getEvent(tsd.eventIds[0]));
35760
+ if (!event.tickets?.length) return;
35761
+ const { tickets, quotas } = await shop.asyncFetch(() => shop.ticketsAndQuotas({
35762
+ "by_ticket_ids[]": event.tickets,
35763
+ by_bookable: true,
35764
+ valid_at: tsd.selectedDate.toString()
35765
+ }));
35766
+ shop.capacityManager.addQuotas(quotas);
35767
+ const uiTickets = initUITimeslotTickets(filterAvailabletickets(tickets, tsd.selectedTime), tsd.selectedTime);
35768
+ await enrichTicketsWithContent(segment, uiTickets);
35769
+ for (const ticket of uiTickets) segment.preCart.addItem(createCartItem(ticket, { time: tsd.selectedTime }));
35770
+ }
35771
+ };
35772
+ //#endregion
35773
+ //#region src/components/ticketSelection/filters/event/admission-day.ts
35774
+ var filter$8 = {
35775
+ name: "event:admission:day",
35776
+ calendarEndpoint: "events",
35777
+ requires: [{
35778
+ kind: "tsd",
35779
+ field: "eventIds"
35780
+ }, {
35781
+ kind: "tsd",
35782
+ field: "selectedDate"
35783
+ }],
35784
+ isCalendarVisible: () => true,
35785
+ isTimeslotsVisible: () => false,
35786
+ isTicketsVisible: (tsd) => Boolean(tsd.selectedDate),
35787
+ async loadTimeslots() {},
35788
+ async loadProducts(segment) {
35789
+ const tsd = segment.ticketSelectionDetails;
35790
+ if (!tsd?.eventIds?.length || !tsd.selectedDate) return;
35791
+ const event = await shop.asyncFetch(() => shop.getEvent(tsd.eventIds[0]));
35792
+ if (!event.tickets?.length) return;
35793
+ const { tickets, quotas } = await shop.asyncFetch(() => shop.ticketsAndQuotas({
35794
+ "by_ticket_ids[]": event.tickets,
35795
+ "by_ticket_types[]": ["normal"],
35796
+ by_bookable: true,
35797
+ valid_at: tsd.selectedDate.toString()
35798
+ }));
35799
+ shop.capacityManager.addQuotas(quotas);
35800
+ const uiTickets = initUIDayTickets(tickets);
35801
+ await enrichTicketsWithContent(segment, uiTickets);
35802
+ for (const t of uiTickets) segment.preCart.addItem(createCartItem(t, { time: t.selectedTime }));
35803
+ }
35804
+ };
35805
+ //#endregion
35806
+ //#region src/components/ticketSelection/filters/event/admission-timeslot.ts
35807
+ var filter$7 = {
35808
+ name: "event:admission:timeslot",
35809
+ calendarEndpoint: "events",
35810
+ requires: [
35811
+ {
35704
35812
  kind: "tsd",
35705
35813
  field: "eventIds"
35706
- }, {
35814
+ },
35815
+ {
35707
35816
  kind: "tsd",
35708
35817
  field: "selectedDate"
35709
- }],
35710
- isCalendarVisible: () => true,
35711
- isTimeslotsVisible: (tsd) => Boolean(tsd.selectedDate),
35712
- isTicketsVisible: (tsd) => Boolean(tsd.selectedDate && tsd.selectedTimeslot),
35713
- async loadTimeslots(tsd) {
35714
- if (!tsd?.eventIds?.length || !tsd.selectedDate) return;
35715
- const event = await shop.asyncFetch(() => shop.getEvent(tsd.eventIds[0]));
35716
- if (!event.tickets?.length) return;
35717
- const { quotas } = await shop.asyncFetch(() => shop.ticketsAndQuotas({
35718
- "by_ticket_ids[]": event.tickets,
35719
- by_bookable: true,
35720
- valid_at: tsd.selectedDate.toString()
35721
- }));
35722
- loadPickerQuotas(tsd, quotas);
35723
35818
  },
35724
- async loadProducts(segment) {
35725
- const tsd = segment.ticketSelectionDetails;
35726
- if (!tsd?.eventIds?.length || !tsd.selectedDate) return;
35727
- const event = await shop.asyncFetch(() => shop.getEvent(tsd.eventIds[0]));
35728
- if (!event.tickets?.length) return;
35819
+ {
35820
+ kind: "tsd",
35821
+ field: "selectedTimeslot"
35822
+ }
35823
+ ],
35824
+ isCalendarVisible: () => true,
35825
+ isTimeslotsVisible: (tsd) => Boolean(tsd.selectedDate),
35826
+ isTicketsVisible: (tsd) => Boolean(tsd.selectedDate && tsd.selectedTimeslot),
35827
+ async loadTimeslots(tsd) {
35828
+ if (!tsd?.eventIds?.length || !tsd.selectedDate) return;
35829
+ const event = await shop.asyncFetch(() => shop.getEvent(tsd.eventIds[0]));
35830
+ if (!event.tickets?.length) return;
35831
+ const { quotas } = await shop.asyncFetch(() => shop.ticketsAndQuotas({
35832
+ "by_ticket_ids[]": event.tickets,
35833
+ by_ticket_type: "time_slot",
35834
+ by_bookable: true,
35835
+ valid_at: tsd.selectedDate.toString()
35836
+ }));
35837
+ loadPickerQuotas(tsd, quotas);
35838
+ },
35839
+ async loadProducts(segment) {
35840
+ const tsd = segment.ticketSelectionDetails;
35841
+ if (!tsd?.eventIds?.length || !tsd.selectedDate || !tsd.selectedTimeslot) return;
35842
+ const event = await shop.asyncFetch(() => shop.getEvent(tsd.eventIds[0]));
35843
+ if (!event.tickets?.length) return;
35844
+ const { tickets, quotas } = await shop.asyncFetch(() => shop.ticketsAndQuotas({
35845
+ "by_ticket_ids[]": event.tickets,
35846
+ by_ticket_type: "time_slot",
35847
+ by_bookable: true,
35848
+ valid_at: tsd.selectedDate.toString()
35849
+ }));
35850
+ shop.capacityManager.addQuotas(quotas);
35851
+ const uiTickets = initUITimeslotTickets(filterAvailabletickets(tickets, tsd.selectedTime), tsd.selectedTime);
35852
+ await enrichTicketsWithContent(segment, uiTickets);
35853
+ for (const t of uiTickets) segment.preCart.addItem(createCartItem(t, { time: tsd.selectedTime }));
35854
+ }
35855
+ };
35856
+ //#endregion
35857
+ //#region src/components/ticketSelection/filters/event/price.ts
35858
+ var filter$6 = {
35859
+ name: "event:price",
35860
+ calendarEndpoint: "events",
35861
+ requires: [{
35862
+ kind: "tsd",
35863
+ field: "eventIds"
35864
+ }, {
35865
+ kind: "segment",
35866
+ field: "dateId"
35867
+ }],
35868
+ isCalendarVisible: () => false,
35869
+ isTimeslotsVisible: () => false,
35870
+ isTicketsVisible: (tsd) => Boolean(tsd.eventIds?.length),
35871
+ loadTimeslots: async () => {},
35872
+ async loadProducts(segment) {
35873
+ const tsd = segment.ticketSelectionDetails;
35874
+ if (!tsd?.eventIds?.length || segment.dateId === void 0) return;
35875
+ const date = await shop.asyncFetch(() => shop.getEventDetailsOnDate(tsd.eventIds[0], segment.dateId));
35876
+ if (!date.prices?.length) return;
35877
+ for (const price of date.prices) {
35878
+ const ticket = createUIEventTicket(price, date.id, { event_title: date.event_title });
35879
+ segment.preCart.addItem(createCartItem(ticket, { time: date.start_time }));
35880
+ }
35881
+ if (date.seats) shop.capacityManager.addSeats(date.id, date.seats);
35882
+ }
35883
+ };
35884
+ //#endregion
35885
+ //#region src/components/ticketSelection/filters/events/admission.ts
35886
+ var filter$5 = {
35887
+ name: "events:admission",
35888
+ calendarEndpoint: "events",
35889
+ requires: [{
35890
+ kind: "tsd",
35891
+ field: "selectedDate"
35892
+ }, {
35893
+ kind: "tsd",
35894
+ field: "selectedTimeslot"
35895
+ }],
35896
+ isCalendarVisible: () => true,
35897
+ isTimeslotsVisible: () => true,
35898
+ isTicketsVisible: () => true,
35899
+ loadTimeslots: (tsd) => loadEventsTimeslots(tsd),
35900
+ async loadProducts(segment) {
35901
+ const tsd = segment.ticketSelectionDetails;
35902
+ if (!tsd?.selectedDate || !tsd.selectedTime) return;
35903
+ const dates = filterDatesInWindow(await shop.asyncFetch(() => shop.getDates({
35904
+ by_bookable: true,
35905
+ "by_museum_ids[]": segment.museumIds ?? tsd.museumIds,
35906
+ "by_exhibition_ids[]": tsd.exhibitionIds,
35907
+ "by_event_ids[]": tsd.eventIds,
35908
+ "by_language_ids[]": segment.languageIds,
35909
+ "by_catch_word_ids[]": segment.catchWordIds,
35910
+ start_at: tsd.selectedDate.toString(),
35911
+ per_page: segment.limit || 30
35912
+ })), tsd.selectedDate.toString(), tsd.selectedTime);
35913
+ for (const date of dates) {
35914
+ if (!date.event_id || !date.start_time) continue;
35915
+ const event = await shop.asyncFetch(() => shop.getEvent(date.event_id));
35916
+ if (!event?.tickets?.length) continue;
35729
35917
  const { tickets, quotas } = await shop.asyncFetch(() => shop.ticketsAndQuotas({
35730
35918
  "by_ticket_ids[]": event.tickets,
35731
35919
  by_bookable: true,
35732
- valid_at: tsd.selectedDate.toString()
35920
+ valid_at: date.start_time.slice(0, 10)
35733
35921
  }));
35734
35922
  shop.capacityManager.addQuotas(quotas);
35735
- const uiTickets = initUITimeslotTickets(filterAvailabletickets(tickets, tsd.selectedTime), tsd.selectedTime);
35923
+ const uiTickets = initUITimeslotTickets(filterAvailabletickets(tickets, date.start_time), date.start_time);
35736
35924
  await enrichTicketsWithContent(segment, uiTickets);
35737
- for (const ticket of uiTickets) segment.preCart.addItem(createCartItem(ticket, { time: tsd.selectedTime }));
35925
+ for (const ticket of uiTickets) segment.preCart.addItem(createCartItem(ticket, { time: date.start_time }));
35738
35926
  }
35739
- },
35740
- "event:admission:day": {
35741
- name: "event:admission:day",
35742
- calendarEndpoint: "events",
35743
- requires: [{
35744
- kind: "tsd",
35745
- field: "eventIds"
35746
- }, {
35747
- kind: "tsd",
35748
- field: "selectedDate"
35749
- }],
35750
- isCalendarVisible: () => true,
35751
- isTimeslotsVisible: () => false,
35752
- isTicketsVisible: (tsd) => Boolean(tsd.selectedDate),
35753
- async loadTimeslots() {},
35754
- async loadProducts(segment) {
35755
- const tsd = segment.ticketSelectionDetails;
35756
- if (!tsd?.eventIds?.length || !tsd.selectedDate) return;
35757
- const event = await shop.asyncFetch(() => shop.getEvent(tsd.eventIds[0]));
35758
- if (!event.tickets?.length) return;
35927
+ }
35928
+ };
35929
+ //#endregion
35930
+ //#region src/components/ticketSelection/filters/events/admission-day.ts
35931
+ var filter$4 = {
35932
+ name: "events:admission:day",
35933
+ calendarEndpoint: "events",
35934
+ requires: [{
35935
+ kind: "tsd",
35936
+ field: "selectedDate"
35937
+ }, {
35938
+ kind: "tsd",
35939
+ field: "selectedTimeslot"
35940
+ }],
35941
+ isCalendarVisible: () => true,
35942
+ isTimeslotsVisible: () => true,
35943
+ isTicketsVisible: () => true,
35944
+ loadTimeslots: (tsd) => loadEventsTimeslots(tsd),
35945
+ async loadProducts(segment) {
35946
+ const tsd = segment.ticketSelectionDetails;
35947
+ if (!tsd?.selectedDate || !tsd.selectedTime) return;
35948
+ const dates = filterDatesInWindow(await shop.asyncFetch(() => shop.getDates({
35949
+ by_bookable: true,
35950
+ "by_museum_ids[]": segment.museumIds ?? tsd.museumIds,
35951
+ "by_exhibition_ids[]": tsd.exhibitionIds,
35952
+ "by_event_ids[]": tsd.eventIds,
35953
+ "by_language_ids[]": segment.languageIds,
35954
+ "by_catch_word_ids[]": segment.catchWordIds,
35955
+ start_at: tsd.selectedDate.toString(),
35956
+ per_page: segment.limit || 30
35957
+ })), tsd.selectedDate.toString(), tsd.selectedTime);
35958
+ for (const date of dates) {
35959
+ if (!date.event_id || !date.start_time) continue;
35960
+ const event = await shop.asyncFetch(() => shop.getEvent(date.event_id));
35961
+ if (!event?.tickets?.length) continue;
35759
35962
  const { tickets, quotas } = await shop.asyncFetch(() => shop.ticketsAndQuotas({
35760
35963
  "by_ticket_ids[]": event.tickets,
35761
35964
  "by_ticket_types[]": ["normal"],
35762
35965
  by_bookable: true,
35763
- valid_at: tsd.selectedDate.toString()
35966
+ valid_at: date.start_time.slice(0, 10)
35764
35967
  }));
35765
35968
  shop.capacityManager.addQuotas(quotas);
35766
- const uiTickets = initUIDayTickets(tickets);
35969
+ const uiTickets = initUIDayTickets(tickets, date.start_time);
35767
35970
  await enrichTicketsWithContent(segment, uiTickets);
35768
35971
  for (const t of uiTickets) segment.preCart.addItem(createCartItem(t, { time: t.selectedTime }));
35769
35972
  }
35770
- },
35771
- "event:admission:timeslot": {
35772
- name: "event:admission:timeslot",
35773
- calendarEndpoint: "events",
35774
- requires: [
35775
- {
35776
- kind: "tsd",
35777
- field: "eventIds"
35778
- },
35779
- {
35780
- kind: "tsd",
35781
- field: "selectedDate"
35782
- },
35783
- {
35784
- kind: "tsd",
35785
- field: "selectedTimeslot"
35786
- }
35787
- ],
35788
- isCalendarVisible: () => true,
35789
- isTimeslotsVisible: (tsd) => Boolean(tsd.selectedDate),
35790
- isTicketsVisible: (tsd) => Boolean(tsd.selectedDate && tsd.selectedTimeslot),
35791
- async loadTimeslots(tsd) {
35792
- if (!tsd?.eventIds?.length || !tsd.selectedDate) return;
35793
- const event = await shop.asyncFetch(() => shop.getEvent(tsd.eventIds[0]));
35794
- if (!event.tickets?.length) return;
35795
- const { quotas } = await shop.asyncFetch(() => shop.ticketsAndQuotas({
35796
- "by_ticket_ids[]": event.tickets,
35797
- by_ticket_type: "time_slot",
35798
- by_bookable: true,
35799
- valid_at: tsd.selectedDate.toString()
35800
- }));
35801
- loadPickerQuotas(tsd, quotas);
35802
- },
35803
- async loadProducts(segment) {
35804
- const tsd = segment.ticketSelectionDetails;
35805
- if (!tsd?.eventIds?.length || !tsd.selectedDate || !tsd.selectedTimeslot) return;
35806
- const event = await shop.asyncFetch(() => shop.getEvent(tsd.eventIds[0]));
35807
- if (!event.tickets?.length) return;
35973
+ }
35974
+ };
35975
+ //#endregion
35976
+ //#region src/components/ticketSelection/filters/events/admission-timeslot.ts
35977
+ var filter$3 = {
35978
+ name: "events:admission:timeslot",
35979
+ calendarEndpoint: "events",
35980
+ requires: [{
35981
+ kind: "tsd",
35982
+ field: "selectedDate"
35983
+ }, {
35984
+ kind: "tsd",
35985
+ field: "selectedTimeslot"
35986
+ }],
35987
+ isCalendarVisible: () => true,
35988
+ isTimeslotsVisible: () => true,
35989
+ isTicketsVisible: () => true,
35990
+ loadTimeslots: (tsd) => loadEventsTimeslots(tsd),
35991
+ async loadProducts(segment) {
35992
+ const tsd = segment.ticketSelectionDetails;
35993
+ if (!tsd?.selectedDate || !tsd.selectedTime) return;
35994
+ const dates = filterDatesInWindow(await shop.asyncFetch(() => shop.getDates({
35995
+ by_bookable: true,
35996
+ "by_museum_ids[]": segment.museumIds ?? tsd.museumIds,
35997
+ "by_exhibition_ids[]": tsd.exhibitionIds,
35998
+ "by_event_ids[]": tsd.eventIds,
35999
+ "by_language_ids[]": segment.languageIds,
36000
+ "by_catch_word_ids[]": segment.catchWordIds,
36001
+ start_at: tsd.selectedDate.toString(),
36002
+ per_page: segment.limit || 30
36003
+ })), tsd.selectedDate.toString(), tsd.selectedTime);
36004
+ for (const date of dates) {
36005
+ if (!date.event_id || !date.start_time) continue;
36006
+ const event = await shop.asyncFetch(() => shop.getEvent(date.event_id));
36007
+ if (!event?.tickets?.length) continue;
35808
36008
  const { tickets, quotas } = await shop.asyncFetch(() => shop.ticketsAndQuotas({
35809
36009
  "by_ticket_ids[]": event.tickets,
35810
36010
  by_ticket_type: "time_slot",
35811
36011
  by_bookable: true,
35812
- valid_at: tsd.selectedDate.toString()
36012
+ valid_at: date.start_time.slice(0, 10)
35813
36013
  }));
35814
36014
  shop.capacityManager.addQuotas(quotas);
35815
- const uiTickets = initUITimeslotTickets(filterAvailabletickets(tickets, tsd.selectedTime), tsd.selectedTime);
36015
+ const uiTickets = initUITimeslotTickets(filterAvailabletickets(tickets, date.start_time), date.start_time);
35816
36016
  await enrichTicketsWithContent(segment, uiTickets);
35817
- for (const t of uiTickets) segment.preCart.addItem(createCartItem(t, { time: tsd.selectedTime }));
36017
+ for (const t of uiTickets) segment.preCart.addItem(createCartItem(t, { time: date.start_time }));
35818
36018
  }
35819
- },
35820
- "event:price": {
35821
- name: "event:price",
35822
- calendarEndpoint: "events",
35823
- requires: [{
35824
- kind: "tsd",
35825
- field: "eventIds"
35826
- }, {
35827
- kind: "segment",
35828
- field: "dateId"
35829
- }],
35830
- isCalendarVisible: () => false,
35831
- isTimeslotsVisible: () => false,
35832
- isTicketsVisible: (tsd) => Boolean(tsd.eventIds?.length),
35833
- loadTimeslots: async () => {},
35834
- async loadProducts(segment) {
35835
- const tsd = segment.ticketSelectionDetails;
35836
- if (!tsd?.eventIds?.length || segment.dateId === void 0) return;
35837
- const date = await shop.asyncFetch(() => shop.getEventDetailsOnDate(tsd.eventIds[0], segment.dateId));
35838
- if (!date.prices?.length) return;
35839
- for (const price of date.prices) {
36019
+ }
36020
+ };
36021
+ //#endregion
36022
+ //#region src/components/ticketSelection/filters/events/price.ts
36023
+ var filter$2 = {
36024
+ name: "events:price",
36025
+ calendarEndpoint: "events",
36026
+ requires: [{
36027
+ kind: "tsd",
36028
+ field: "selectedDate"
36029
+ }, {
36030
+ kind: "tsd",
36031
+ field: "selectedTimeslot"
36032
+ }],
36033
+ isCalendarVisible: () => true,
36034
+ isTimeslotsVisible: () => true,
36035
+ isTicketsVisible: () => true,
36036
+ loadTimeslots: (tsd) => loadEventsTimeslots(tsd),
36037
+ async loadProducts(segment) {
36038
+ const tsd = segment.ticketSelectionDetails;
36039
+ if (!tsd?.selectedDate || !tsd.selectedTime) return;
36040
+ const dates = filterDatesInWindow(await shop.asyncFetch(() => shop.getDates({
36041
+ by_bookable: true,
36042
+ "by_museum_ids[]": segment.museumIds ?? tsd.museumIds,
36043
+ "by_exhibition_ids[]": tsd.exhibitionIds,
36044
+ "by_event_ids[]": tsd.eventIds,
36045
+ "by_language_ids[]": segment.languageIds,
36046
+ "by_catch_word_ids[]": segment.catchWordIds,
36047
+ start_at: tsd.selectedDate.toString(),
36048
+ per_page: segment.limit || 30
36049
+ })), tsd.selectedDate.toString(), tsd.selectedTime);
36050
+ const query = segment.query;
36051
+ for (const date of dates) {
36052
+ if (!date.prices?.length) continue;
36053
+ const prices = query ? date.prices.filter((p) => p.title?.includes(query)) : date.prices;
36054
+ for (const price of prices) {
35840
36055
  const ticket = createUIEventTicket(price, date.id, { event_title: date.event_title });
35841
36056
  segment.preCart.addItem(createCartItem(ticket, { time: date.start_time }));
35842
36057
  }
35843
36058
  if (date.seats) shop.capacityManager.addSeats(date.id, date.seats);
35844
36059
  }
35845
- },
35846
- "events:admission": {
35847
- name: "events:admission",
35848
- calendarEndpoint: "events",
35849
- requires: [{
35850
- kind: "tsd",
35851
- field: "selectedDate"
35852
- }, {
35853
- kind: "tsd",
35854
- field: "selectedTimeslot"
35855
- }],
35856
- isCalendarVisible: () => true,
35857
- isTimeslotsVisible: () => true,
35858
- isTicketsVisible: () => true,
35859
- loadTimeslots: (tsd) => loadEventsTimeslots(tsd),
35860
- async loadProducts(segment) {
35861
- const tsd = segment.ticketSelectionDetails;
35862
- if (!tsd?.selectedDate || !tsd.selectedTime) return;
35863
- const dates = filterDatesInWindow(await shop.asyncFetch(() => shop.getDates({
35864
- by_bookable: true,
35865
- "by_museum_ids[]": segment.museumIds ?? tsd.museumIds,
35866
- "by_exhibition_ids[]": tsd.exhibitionIds,
35867
- "by_event_ids[]": tsd.eventIds,
35868
- "by_language_ids[]": segment.languageIds,
35869
- "by_catch_word_ids[]": segment.catchWordIds,
35870
- start_at: tsd.selectedDate.toString(),
35871
- per_page: segment.limit || 30
35872
- })), tsd.selectedDate.toString(), tsd.selectedTime);
35873
- for (const date of dates) {
35874
- if (!date.event_id || !date.start_time) continue;
35875
- const event = await shop.asyncFetch(() => shop.getEvent(date.event_id));
35876
- if (!event?.tickets?.length) continue;
35877
- const { tickets, quotas } = await shop.asyncFetch(() => shop.ticketsAndQuotas({
35878
- "by_ticket_ids[]": event.tickets,
35879
- by_bookable: true,
35880
- valid_at: date.start_time.slice(0, 10)
35881
- }));
35882
- shop.capacityManager.addQuotas(quotas);
35883
- const uiTickets = initUITimeslotTickets(filterAvailabletickets(tickets, date.start_time), date.start_time);
35884
- await enrichTicketsWithContent(segment, uiTickets);
35885
- for (const ticket of uiTickets) segment.preCart.addItem(createCartItem(ticket, { time: date.start_time }));
35886
- }
35887
- }
35888
- },
35889
- "events:admission:day": {
35890
- name: "events:admission:day",
35891
- calendarEndpoint: "events",
35892
- requires: [{
35893
- kind: "tsd",
35894
- field: "selectedDate"
35895
- }, {
35896
- kind: "tsd",
35897
- field: "selectedTimeslot"
35898
- }],
35899
- isCalendarVisible: () => true,
35900
- isTimeslotsVisible: () => true,
35901
- isTicketsVisible: () => true,
35902
- loadTimeslots: (tsd) => loadEventsTimeslots(tsd),
35903
- async loadProducts(segment) {
35904
- const tsd = segment.ticketSelectionDetails;
35905
- if (!tsd?.selectedDate || !tsd.selectedTime) return;
35906
- const dates = filterDatesInWindow(await shop.asyncFetch(() => shop.getDates({
35907
- by_bookable: true,
35908
- "by_museum_ids[]": segment.museumIds ?? tsd.museumIds,
35909
- "by_exhibition_ids[]": tsd.exhibitionIds,
35910
- "by_event_ids[]": tsd.eventIds,
35911
- "by_language_ids[]": segment.languageIds,
35912
- "by_catch_word_ids[]": segment.catchWordIds,
35913
- start_at: tsd.selectedDate.toString(),
35914
- per_page: segment.limit || 30
35915
- })), tsd.selectedDate.toString(), tsd.selectedTime);
35916
- for (const date of dates) {
35917
- if (!date.event_id || !date.start_time) continue;
35918
- const event = await shop.asyncFetch(() => shop.getEvent(date.event_id));
35919
- if (!event?.tickets?.length) continue;
35920
- const { tickets, quotas } = await shop.asyncFetch(() => shop.ticketsAndQuotas({
35921
- "by_ticket_ids[]": event.tickets,
35922
- "by_ticket_types[]": ["normal"],
35923
- by_bookable: true,
35924
- valid_at: date.start_time.slice(0, 10)
35925
- }));
35926
- shop.capacityManager.addQuotas(quotas);
35927
- const uiTickets = initUIDayTickets(tickets, date.start_time);
35928
- await enrichTicketsWithContent(segment, uiTickets);
35929
- for (const t of uiTickets) segment.preCart.addItem(createCartItem(t, { time: t.selectedTime }));
35930
- }
35931
- }
35932
- },
35933
- "events:admission:timeslot": {
35934
- name: "events:admission:timeslot",
35935
- calendarEndpoint: "events",
35936
- requires: [{
35937
- kind: "tsd",
35938
- field: "selectedDate"
35939
- }, {
35940
- kind: "tsd",
35941
- field: "selectedTimeslot"
35942
- }],
35943
- isCalendarVisible: () => true,
35944
- isTimeslotsVisible: () => true,
35945
- isTicketsVisible: () => true,
35946
- loadTimeslots: (tsd) => loadEventsTimeslots(tsd),
35947
- async loadProducts(segment) {
35948
- const tsd = segment.ticketSelectionDetails;
35949
- if (!tsd?.selectedDate || !tsd.selectedTime) return;
35950
- const dates = filterDatesInWindow(await shop.asyncFetch(() => shop.getDates({
35951
- by_bookable: true,
35952
- "by_museum_ids[]": segment.museumIds ?? tsd.museumIds,
35953
- "by_exhibition_ids[]": tsd.exhibitionIds,
35954
- "by_event_ids[]": tsd.eventIds,
35955
- "by_language_ids[]": segment.languageIds,
35956
- "by_catch_word_ids[]": segment.catchWordIds,
35957
- start_at: tsd.selectedDate.toString(),
35958
- per_page: segment.limit || 30
35959
- })), tsd.selectedDate.toString(), tsd.selectedTime);
35960
- for (const date of dates) {
35961
- if (!date.event_id || !date.start_time) continue;
35962
- const event = await shop.asyncFetch(() => shop.getEvent(date.event_id));
35963
- if (!event?.tickets?.length) continue;
35964
- const { tickets, quotas } = await shop.asyncFetch(() => shop.ticketsAndQuotas({
35965
- "by_ticket_ids[]": event.tickets,
35966
- by_ticket_type: "time_slot",
35967
- by_bookable: true,
35968
- valid_at: date.start_time.slice(0, 10)
35969
- }));
35970
- shop.capacityManager.addQuotas(quotas);
35971
- const uiTickets = initUITimeslotTickets(filterAvailabletickets(tickets, date.start_time), date.start_time);
35972
- await enrichTicketsWithContent(segment, uiTickets);
35973
- for (const t of uiTickets) segment.preCart.addItem(createCartItem(t, { time: date.start_time }));
35974
- }
35975
- }
35976
- },
35977
- "events:price": {
35978
- name: "events:price",
35979
- calendarEndpoint: "events",
35980
- requires: [{
35981
- kind: "tsd",
35982
- field: "selectedDate"
35983
- }, {
35984
- kind: "tsd",
35985
- field: "selectedTimeslot"
35986
- }],
35987
- isCalendarVisible: () => true,
35988
- isTimeslotsVisible: () => true,
35989
- isTicketsVisible: () => true,
35990
- loadTimeslots: (tsd) => loadEventsTimeslots(tsd),
35991
- async loadProducts(segment) {
35992
- const tsd = segment.ticketSelectionDetails;
35993
- if (!tsd?.selectedDate || !tsd.selectedTime) return;
35994
- const dates = filterDatesInWindow(await shop.asyncFetch(() => shop.getDates({
35995
- by_bookable: true,
35996
- "by_museum_ids[]": segment.museumIds ?? tsd.museumIds,
35997
- "by_exhibition_ids[]": tsd.exhibitionIds,
35998
- "by_event_ids[]": tsd.eventIds,
35999
- "by_language_ids[]": segment.languageIds,
36000
- "by_catch_word_ids[]": segment.catchWordIds,
36001
- start_at: tsd.selectedDate.toString(),
36002
- per_page: segment.limit || 30
36003
- })), tsd.selectedDate.toString(), tsd.selectedTime);
36004
- const query = segment.query;
36005
- for (const date of dates) {
36006
- if (!date.prices?.length) continue;
36007
- const prices = query ? date.prices.filter((p) => p.title?.includes(query)) : date.prices;
36008
- for (const price of prices) {
36009
- const ticket = createUIEventTicket(price, date.id, { event_title: date.event_title });
36010
- segment.preCart.addItem(createCartItem(ticket, { time: date.start_time }));
36011
- }
36012
- if (date.seats) shop.capacityManager.addSeats(date.id, date.seats);
36013
- }
36014
- }
36015
- },
36016
- coupon: {
36017
- name: "coupon",
36060
+ }
36061
+ };
36062
+ //#endregion
36063
+ //#region src/components/ticketSelection/filters/coupon.ts
36064
+ /**
36065
+ * `coupon` — sells the shop's purchasable coupons (German "Wertgutschein" /
36066
+ * gift card). Coupons are fixed-value, standalone products:
36067
+ * no calendar, no timeslots, no capacity. They are always listed, like a
36068
+ * shelf of products.
36069
+ */
36070
+ var filter$1 = {
36071
+ name: "coupon",
36072
+ calendarEndpoint: null,
36073
+ requires: [],
36074
+ isCalendarVisible: () => false,
36075
+ isTimeslotsVisible: () => false,
36076
+ isTicketsVisible: () => true,
36077
+ loadTimeslots: async () => {},
36078
+ async loadProducts(segment) {
36079
+ const coupons = await shop.asyncFetch(() => shop.getCoupons());
36080
+ for (const coupon of coupons ?? []) segment.preCart.addItem(createCartItem(createUICoupon(coupon)));
36081
+ }
36082
+ };
36083
+ //#endregion
36084
+ //#region src/components/ticketSelection/filters/tour.ts
36085
+ var REQUIRED = [
36086
+ "id",
36087
+ "time",
36088
+ "participants",
36089
+ "languageId",
36090
+ "totalPriceCents",
36091
+ "title"
36092
+ ];
36093
+ //#endregion
36094
+ //#region src/components/ticketSelection/filters/registry.ts
36095
+ var REGISTRY = {
36096
+ "ticket:timeslot": filter$12,
36097
+ "ticket:day": filter$11,
36098
+ "ticket:annual": filter$10,
36099
+ "event:admission": filter$9,
36100
+ "event:admission:day": filter$8,
36101
+ "event:admission:timeslot": filter$7,
36102
+ "event:price": filter$6,
36103
+ "events:admission": filter$5,
36104
+ "events:admission:day": filter$4,
36105
+ "events:admission:timeslot": filter$3,
36106
+ "events:price": filter$2,
36107
+ coupon: filter$1,
36108
+ tour: {
36109
+ name: "tour",
36018
36110
  calendarEndpoint: null,
36019
36111
  requires: [],
36020
36112
  isCalendarVisible: () => false,
36021
36113
  isTimeslotsVisible: () => false,
36022
36114
  isTicketsVisible: () => true,
36023
- loadTimeslots: async () => {},
36024
- async loadProducts(segment) {
36025
- const coupons = await shop.asyncFetch(() => shop.getCoupons());
36026
- for (const coupon of coupons ?? []) segment.preCart.addItem(createCartItem(createUICoupon(coupon)));
36115
+ async loadTimeslots() {},
36116
+ async loadProducts() {},
36117
+ /**
36118
+ * Adds a group-tour booking and returns the cart line's uuid. Every call
36119
+ * appends a NEW line — identical bookings coexist; use the uuid to dedupe or
36120
+ * remove. Tours are not priced by the shop API: `totalPriceCents` is the
36121
+ * integrator-supplied total (incl. mandatory surcharges), verified by the
36122
+ * backend only at checkout.
36123
+ */
36124
+ async addToCart(options) {
36125
+ const o = options;
36126
+ for (const key of REQUIRED) if (o[key] == null || o[key] === "") throw new Error(`(go.cart.addItem) tour '${key}' is required`);
36127
+ if (!(o.participants > 0)) throw new Error(`(go.cart.addItem) tour 'participants' must be a positive number`);
36128
+ if (o.quantities) {
36129
+ const quantitiesSum = sum(Object.values(o.quantities));
36130
+ if (quantitiesSum !== o.participants) throw new Error(`(go.cart.addItem) tour 'quantities' must sum to 'participants' (${quantitiesSum} !== ${o.participants})`);
36131
+ }
36132
+ const { time, ...attributes } = o;
36133
+ const item = createCartItem(createUITour(attributes), {
36134
+ quantity: 1,
36135
+ time
36136
+ });
36137
+ shop.cart.addItem(item);
36138
+ return item.uuid;
36027
36139
  }
36028
36140
  }
36029
36141
  };
@@ -36508,10 +36620,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
36508
36620
  template_effect(($0, $1) => {
36509
36621
  set_text(text_1, $0);
36510
36622
  set_text(text_2, $1);
36511
- }, [() => formatDate(item().attributes.start_time, {
36512
- month: "numeric",
36513
- day: "numeric"
36514
- }, shop.locale), () => formatTime(item().attributes.start_time)]);
36623
+ }, [() => shop.formatDate(item().attributes.start_time, "dayMonth"), () => shop.formatTime(item().attributes.start_time)]);
36515
36624
  append($$anchor, fragment);
36516
36625
  };
36517
36626
  if_block(node, ($$render) => {
@@ -36654,20 +36763,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
36654
36763
  template_effect(($0, $1) => {
36655
36764
  set_text(text_3, $0);
36656
36765
  set_text(text_4, $1);
36657
- }, [() => formatDate(item().attributes.start_time, {
36658
- month: "numeric",
36659
- day: "numeric"
36660
- }, shop.locale), () => formatTime(item().attributes.start_time)]);
36766
+ }, [() => shop.formatDate(item().attributes.start_time, "dayMonth"), () => shop.formatTime(item().attributes.start_time)]);
36661
36767
  append($$anchor, fragment_4);
36662
36768
  };
36663
36769
  var consequent_2 = ($$anchor) => {
36664
36770
  var span_5 = root_3$3();
36665
36771
  var text_5 = child(span_5, true);
36666
36772
  reset(span_5);
36667
- template_effect(($0) => set_text(text_5, $0), [() => formatDate(item().attributes.start_time, {
36668
- month: "numeric",
36669
- day: "numeric"
36670
- }, shop.locale)]);
36773
+ template_effect(($0) => set_text(text_5, $0), [() => shop.formatDate(item().attributes.start_time, "dayMonth")]);
36671
36774
  append($$anchor, span_5);
36672
36775
  };
36673
36776
  if_block(node_5, ($$render) => {
@@ -36859,10 +36962,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
36859
36962
  template_effect(($0, $1) => {
36860
36963
  set_text(text_2, $0);
36861
36964
  set_text(text_3, $1);
36862
- }, [() => formatDate(item().attributes.start_time, {
36863
- month: "numeric",
36864
- day: "numeric"
36865
- }, shop.locale), () => formatTime(item().attributes.start_time)]);
36965
+ }, [() => shop.formatDate(item().attributes.start_time, "dayMonth"), () => shop.formatTime(item().attributes.start_time)]);
36866
36966
  append($$anchor, fragment);
36867
36967
  };
36868
36968
  if_block(node, ($$render) => {
@@ -37636,7 +37736,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
37636
37736
  template_effect(($0) => {
37637
37737
  set_text(text, `${item().product.event_title ?? ""} - ${$0 ?? ""}`);
37638
37738
  set_text(text_1, item().product.title);
37639
- }, [() => formatTime(item().time)]);
37739
+ }, [() => shop.formatTime(item().time)]);
37640
37740
  append($$anchor, fragment);
37641
37741
  };
37642
37742
  const default_title = ($$anchor) => {
@@ -37745,7 +37845,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
37745
37845
  var li_6 = sibling(li_5, 2);
37746
37846
  var node_5 = child(li_6);
37747
37847
  {
37748
- let $0 = /* @__PURE__ */ user_derived(() => quantityLabel(item()));
37848
+ let $0 = /* @__PURE__ */ user_derived(() => quantityLabel(item(), shop.locale));
37749
37849
  QuantityControl(node_5, {
37750
37850
  get value() {
37751
37851
  return item().quantity;
@@ -37923,7 +38023,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
37923
38023
  this.timeslots = quotaManager.timeslotsOn(date, this.tsd?.timeslotTicketIds).map((x) => ({
37924
38024
  ...x,
37925
38025
  startAt: x.timeSlot,
37926
- timeFormatted: x.timeSlot.substring(11, 16),
38026
+ timeFormatted: shop.formatTime(x.timeSlot),
37927
38027
  available: x.capacity > 0
37928
38028
  }));
37929
38029
  }
@@ -38558,41 +38658,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
38558
38658
  } }, [], []));
38559
38659
  //#endregion
38560
38660
  //#region src/go/cart.ts
38561
- var REQUIRED = [
38562
- "id",
38563
- "time",
38564
- "participants",
38565
- "languageId",
38566
- "totalPriceCents",
38567
- "title"
38568
- ];
38569
- function validate(options) {
38570
- for (const key of REQUIRED) if (options[key] == null || options[key] === "") throw new Error(`(go.cart.addTour) '${key}' is required`);
38571
- if (!(options.participants > 0)) throw new Error(`(go.cart.addTour) 'participants' must be a positive number`);
38572
- if (options.quantities) {
38573
- const quantitiesSum = sum(Object.values(options.quantities));
38574
- if (quantitiesSum !== options.participants) throw new Error(`(go.cart.addTour) 'quantities' must sum to 'participants' (${quantitiesSum} !== ${options.participants})`);
38575
- }
38576
- }
38577
- /**
38578
- * Adds a group-tour booking to the cart and resolves with the cart line's
38579
- * uuid. Every call appends a NEW line — identical bookings coexist; use the
38580
- * returned uuid to deduplicate or remove.
38581
- *
38582
- * Tours are not priced by the shop API: `totalPriceCents` is the
38583
- * integrator-supplied booking total (incl. mandatory surcharges) and is
38584
- * verified by the backend only at checkout.
38585
- */
38586
- async function addTour(options) {
38587
- validate(options);
38588
- if (!shop.cart) throw new Error("(go.cart.addTour) shop not initialized — call go.init first");
38589
- const { time, ...attributes } = options;
38590
- const item = createCartItem(createUITour(attributes), {
38591
- quantity: 1,
38592
- time
38593
- });
38594
- shop.cart.addItem(item);
38595
- return item.uuid;
38661
+ /** Resolves with the new cart line's uuid. Throws if the filter can't add to
38662
+ * the cart, or on the filter's own validation / availability errors. */
38663
+ async function addItem({ filter, ...options }) {
38664
+ if (!shop.cart) throw new Error("(go.cart.addItem) shop not initialized — call go.init first");
38665
+ const module = getFilter(filter);
38666
+ if (!module?.addToCart) throw new Error(`(go.cart.addItem) filter '${filter}' cannot add to the cart`);
38667
+ return module.addToCart(options);
38596
38668
  }
38597
38669
  //#endregion
38598
38670
  //#region src/go/go.ts
@@ -38651,9 +38723,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
38651
38723
  return shop.asyncFetch(() => shop.getCustomerMemberships());
38652
38724
  }
38653
38725
  },
38654
- cart: { addTour: async (options) => {
38726
+ cart: { addItem: async (options) => {
38655
38727
  await ensureShopReady();
38656
- return addTour(options);
38728
+ return addItem(options);
38657
38729
  } }
38658
38730
  };
38659
38731
  (async () => {