@gomusdev/web-components 4.9.1 → 4.10.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.
package/README.md CHANGED
@@ -1,37 +1,55 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.10.0 (2026-07-23)
4
+
5
+ ### Features
6
+
7
+ * **shop:** warn in console when the configured locale is invalid
8
+
9
+ ### Bug Fixes
10
+
11
+ * **cart:** format prices in the shop currency instead of hardcoded EUR
12
+ * **currency:** fall back to de/EUR when Intl.NumberFormat rejects the shop config
13
+ * **types:** define the missing NotSignedIn result type
14
+
15
+ ## 4.9.2 (2026-07-20)
16
+
17
+ ### Bug Fixes
18
+
19
+ * **release:** strip gitlab links and issue refs from npm README changelog
20
+
3
21
  ## 4.9.1 (2026-07-20)
4
22
 
5
23
  ### Bug Fixes
6
24
 
7
- * **checkoutForm:** handle meta.status and payment_data on checkout, closes [#152](https://gitlab.giantmonkey.de/gomus/frontend/issues/152)
25
+ * **checkoutForm:** handle meta.status and payment_data on checkout
8
26
 
9
27
  ## 4.9.0 (2026-07-16)
10
28
 
11
29
  ### Features
12
30
 
13
- * **auth:** add go-set-password to complete the password reset flow, closes [#96](https://gitlab.giantmonkey.de/gomus/frontend/issues/96)
31
+ * **auth:** add go-set-password to complete the password reset flow
14
32
 
15
33
  ## 4.8.2 (2026-07-16)
16
34
 
17
35
  ### Bug Fixes
18
36
 
19
37
  * **mr2:** expand spec detection to include sibling `spec/` subdirectory
20
- * **ticket-selection:** derive day-ticket time per ticket, not from first quota (TC-04), closes [#136](https://gitlab.giantmonkey.de/gomus/frontend/issues/136)
38
+ * **ticket-selection:** derive day-ticket time per ticket, not from first quota (TC-04)
21
39
 
22
40
  ## 4.8.1 (2026-07-16)
23
41
 
24
42
  ### Bug Fixes
25
43
 
26
44
  * **couponRedemption:** clear stale error when flush() succeeds
27
- * **forms:** clear form-level api errors on valid submit, closes [#apiErrors](https://gitlab.giantmonkey.de/gomus/frontend/issues/apiErrors) [#147](https://gitlab.giantmonkey.de/gomus/frontend/issues/147)
45
+ * **forms:** clear form-level api errors on valid submit
28
46
  * **forms:** reset stale success message on valid submit
29
47
 
30
48
  ## 4.8.0 (2026-07-15)
31
49
 
32
50
  ### Features
33
51
 
34
- * **forms:** add dateOfBirth field for annual ticket personalization, closes [#149](https://gitlab.giantmonkey.de/gomus/frontend/issues/149)
52
+ * **forms:** add dateOfBirth field for annual ticket personalization
35
53
 
36
54
  ### Bug Fixes
37
55
 
@@ -41,20 +59,20 @@
41
59
 
42
60
  ### Features
43
61
 
44
- * **accessibility:** derive quantity control labels from event details, closes [#141](https://gitlab.giantmonkey.de/gomus/frontend/issues/141)
62
+ * **accessibility:** derive quantity control labels from event details
45
63
 
46
64
  ## 4.6.2 (2026-07-14)
47
65
 
48
66
  ### Bug Fixes
49
67
 
50
- * **a11y:** derive quantity control name from event title for flat-price rows, closes [#141](https://gitlab.giantmonkey.de/gomus/frontend/issues/141)
68
+ * **a11y:** derive quantity control name from event title for flat-price rows
51
69
  * **assets:** shorten /uploads cache to 60s
52
70
 
53
71
  ## 4.6.1 (2026-07-14)
54
72
 
55
73
  ### Bug Fixes
56
74
 
57
- * **go-order:** clear cart and guest session on token change, closes [gomus/frontend#142](https://gitlab.giantmonkey.de/gomus/frontend/issues/142)
75
+ * **go-order:** clear cart and guest session on token change
58
76
 
59
77
  ## 4.6.0 (2026-07-14)
60
78
 
@@ -70,7 +88,7 @@
70
88
 
71
89
  ### Features
72
90
 
73
- * **checkout:** split guest and signed-in checkout, gated by go-if, closes [#data](https://gitlab.giantmonkey.de/gomus/frontend/issues/data)
91
+ * **checkout:** split guest and signed-in checkout, gated by go-if
74
92
 
75
93
  ## 4.4.0 (2026-07-13)
76
94
 
@@ -82,10 +100,10 @@
82
100
 
83
101
  ### Features
84
102
 
85
- * **cart:** render tour lines in go-cart (WI [#128](https://gitlab.giantmonkey.de/gomus/frontend/issues/128))
86
- * **cart:** tour product model layer for go.cart.addTour (WI [#128](https://gitlab.giantmonkey.de/gomus/frontend/issues/128))
87
- * **go:** go.api.cart.addTour for programmatic tour booking (WI [#128](https://gitlab.giantmonkey.de/gomus/frontend/issues/128))
88
- * **order:** render tour bookings in go-order breakdown (WI [#128](https://gitlab.giantmonkey.de/gomus/frontend/issues/128))
103
+ * **cart:** render tour lines in go-cart
104
+ * **cart:** tour product model layer for go.cart.addTour
105
+ * **go:** go.api.cart.addTour for programmatic tour booking
106
+ * **order:** render tour bookings in go-order breakdown
89
107
 
90
108
  ## 4.2.0 (2026-07-09)
91
109
 
@@ -99,7 +117,7 @@
99
117
 
100
118
  * **forms:** pass required type argument to HTMLAttributes
101
119
  * **forms:** resolve remaining typescript-eslint errors in InputAndLabel
102
- * **forms:** set field.value when a single payment mode is auto-selected, closes [#135](https://gitlab.giantmonkey.de/gomus/frontend/issues/135)
120
+ * **forms:** set field.value when a single payment mode is auto-selected
103
121
  * **forms:** type the field snippet map as Record<FieldType, Snippet>
104
122
 
105
123
  ## 4.1.0 (2026-07-09)
@@ -243,7 +261,7 @@
243
261
  * add audit-code skill — automate the full code-audit pipeline
244
262
  * **audit-report:** 'With screenshots' category (auto-populated from .shots dirs)
245
263
  * **audit-report:** click-to-peek source excerpts (+/-5 lines) on every link
246
- * **audit-report:** default 'All findings' section; Overview demoted below it, closes [#all](https://gitlab.giantmonkey.de/gomus/frontend/issues/all)
264
+ * **audit-report:** default 'All findings' section; Overview demoted below it
247
265
  * **audit-report:** hover source-code preview + annotated screenshot repro (PoC)
248
266
  * **audit-report:** password-protect report.html (password wc-bugs)
249
267
  * **audit-report:** per-finding markdown records with live triage state + sidebar-nav fix
@@ -378,7 +396,7 @@ Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
378
396
 
379
397
  * flush unsubmitted coupon token before checkout
380
398
  * include 2.1.1 patches from master
381
- * **shop:** remove dangerous clearCache() that wiped auth and cart, closes [this.#data](https://gitlab.giantmonkey.de/gomus/this./issues/data) [gomus/frontend#24](https://gitlab.giantmonkey.de/gomus/frontend/issues/24)
399
+ * **shop:** remove dangerous clearCache() that wiped auth and cart
382
400
  * validate coupon on go-after-validation, not just submit
383
401
 
384
402
  ### Documentation
@@ -416,7 +434,7 @@ Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
416
434
  ### Bug Fixes
417
435
 
418
436
  * flush unsubmitted coupon token before checkout
419
- * **shop:** remove dangerous clearCache() that wiped auth and cart, closes [this.#data](https://gitlab.giantmonkey.de/gomus/this./issues/data) [gomus/frontend#24](https://gitlab.giantmonkey.de/gomus/frontend/issues/24)
437
+ * **shop:** remove dangerous clearCache() that wiped auth and cart
420
438
  * validate coupon on go-after-validation, not just submit
421
439
 
422
440
  ### Documentation
@@ -853,8 +871,8 @@ Parent and child filters still need to stay consistent — no auto-inference bet
853
871
 
854
872
  ### Bug Fixes
855
873
 
856
- * remove unused `[#fields](https://gitlab.giantmonkey.de/gomus/frontend/issues/fields)` property in FormDetails class
857
- * remove unused `[#fields](https://gitlab.giantmonkey.de/gomus/frontend/issues/fields)` property in FormDetails class
874
+ * remove unused `#fields` property in FormDetails class
875
+ * remove unused `#fields` property in FormDetails class
858
876
 
859
877
  ## 1.33.1 (2026-01-15)
860
878
 
@@ -6370,6 +6370,15 @@ createHTML: (html) => {
6370
6370
  return Class;
6371
6371
  }
6372
6372
  //#endregion
6373
+ //#region src/lib/helpers/locale.ts
6374
+ function warnOnInvalidLocale(locale) {
6375
+ try {
6376
+ if (Intl.NumberFormat.supportedLocalesOf(locale).length === 0) console.warn(`[go] Unknown locale "${locale}" — the browser has no locale data for it; price and date formatting will fall back to the browser default.`);
6377
+ } catch {
6378
+ console.warn(`[go] Invalid locale "${locale}" — not a valid BCP 47 language tag (use "de", "de-CH", "en", …). Price and date formatting will throw.`);
6379
+ }
6380
+ }
6381
+ //#endregion
6373
6382
  //#region src/lib/helpers/urls.ts
6374
6383
  var ANGULAR_URLS = {
6375
6384
  account: () => "/#/user/account",
@@ -11811,13 +11820,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11811
11820
  ...options
11812
11821
  }).format(zoned.toDate());
11813
11822
  }
11814
- function formatCurrency$1(priceCents) {
11815
- if (priceCents === void 0) throw Error("priceCents is required");
11816
- return new Intl.NumberFormat("de-DE", {
11817
- style: "currency",
11818
- currency: "EUR"
11819
- }).format(priceCents / 100);
11820
- }
11821
11823
  //#endregion
11822
11824
  //#region src/lib/models/ticket/UITicket.svelte.ts
11823
11825
  function isUITicket(x) {
@@ -12181,6 +12183,49 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12181
12183
  });
12182
12184
  }
12183
12185
  //#endregion
12186
+ //#region src/lib/helpers/utils.ts
12187
+ function formatCurrency(priceCents) {
12188
+ let format;
12189
+ try {
12190
+ format = new Intl.NumberFormat(shop.locale ?? "de", {
12191
+ style: "currency",
12192
+ currency: shop.currency ?? "EUR"
12193
+ });
12194
+ } catch {
12195
+ format = new Intl.NumberFormat("de", {
12196
+ style: "currency",
12197
+ currency: "EUR"
12198
+ });
12199
+ }
12200
+ return format.format((priceCents ?? 0) / 100);
12201
+ }
12202
+ /**
12203
+ * Parses a comma-separated string of IDs into an array of positive numbers.
12204
+ *
12205
+ * This function takes a string containing comma-separated values and converts
12206
+ * them into an array of positive integers. Invalid values (non-numeric, zero,
12207
+ * or negative numbers) are filtered out.
12208
+ *
12209
+ * @param ids - A comma-separated string of IDs (e.g., "1,2,3" or "10, 20, 30")
12210
+ * @returns An array of positive numbers if valid IDs are found, undefined otherwise
12211
+ *
12212
+ * @example
12213
+ * ```ts
12214
+ * parseIds("1,2,3") // Returns [1, 2, 3]
12215
+ * parseIds("10, 20, 30") // Returns [10, 20, 30] (handles whitespace)
12216
+ * parseIds("1,abc,3") // Returns [1, 3] (filters out invalid values)
12217
+ * parseIds("0,-1,2") // Returns [2] (filters out zero and negative numbers)
12218
+ * parseIds("") // Returns undefined
12219
+ * parseIds(undefined) // Returns undefined
12220
+ * parseIds("abc,def") // Returns undefined (no valid IDs)
12221
+ * ```
12222
+ */
12223
+ function parseIds(ids) {
12224
+ if (!ids) return;
12225
+ const parsed = ids.split(",").map((id) => id.trim()).map(Number).filter((num) => !isNaN(num) && num > 0);
12226
+ return parsed.length > 0 ? parsed : void 0;
12227
+ }
12228
+ //#endregion
12184
12229
  //#region src/lib/models/tour/UITour.svelte.ts
12185
12230
  function isUITour(x) {
12186
12231
  return x?.type === "Tour";
@@ -12574,13 +12619,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
12574
12619
  if (products) products.forEach((p) => cart.addItem(createCartItem(p)));
12575
12620
  return cart;
12576
12621
  }
12577
- function formatCurrency(priceCents) {
12578
- priceCents = priceCents ?? 0;
12579
- return new Intl.NumberFormat("de-DE", {
12580
- style: "currency",
12581
- currency: "EUR"
12582
- }).format(priceCents / 100);
12583
- }
12584
12622
  function createMainCart() {
12585
12623
  const cart = proxy(createCart());
12586
12624
  syncCartToLocalStorage(cart);
@@ -13695,6 +13733,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
13695
13733
  get$2(this.#data).apiUrl = apiUrl;
13696
13734
  get$2(this.#data).shopDomain = shopDomain;
13697
13735
  get$2(this.#data).locale = locale || "de";
13736
+ warnOnInvalidLocale(get$2(this.#data).locale);
13698
13737
  this.#fetchStatus = {};
13699
13738
  get$2(this.#data).client = client(apiUrl, shopDomain);
13700
13739
  get$2(this.#data).capacityManager = createCapacityManager();
@@ -18875,51 +18914,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18875
18914
  delegate(["click", "keydown"]);
18876
18915
  create_custom_element(DonationCampaign, { campaign: {} }, [], [], { mode: "open" });
18877
18916
  //#endregion
18878
- //#region src/lib/helpers/utils.ts
18879
- function currency(value, currency) {
18880
- if (currency == "CHF") return new Intl.NumberFormat("de-CH", {
18881
- style: "currency",
18882
- currency
18883
- }).format(value);
18884
- else return new Intl.NumberFormat("de-DE", {
18885
- style: "currency",
18886
- currency
18887
- }).format(value);
18888
- }
18889
- /**
18890
- * Parses a comma-separated string of IDs into an array of positive numbers.
18891
- *
18892
- * This function takes a string containing comma-separated values and converts
18893
- * them into an array of positive integers. Invalid values (non-numeric, zero,
18894
- * or negative numbers) are filtered out.
18895
- *
18896
- * @param ids - A comma-separated string of IDs (e.g., "1,2,3" or "10, 20, 30")
18897
- * @returns An array of positive numbers if valid IDs are found, undefined otherwise
18898
- *
18899
- * @example
18900
- * ```ts
18901
- * parseIds("1,2,3") // Returns [1, 2, 3]
18902
- * parseIds("10, 20, 30") // Returns [10, 20, 30] (handles whitespace)
18903
- * parseIds("1,abc,3") // Returns [1, 3] (filters out invalid values)
18904
- * parseIds("0,-1,2") // Returns [2] (filters out zero and negative numbers)
18905
- * parseIds("") // Returns undefined
18906
- * parseIds(undefined) // Returns undefined
18907
- * parseIds("abc,def") // Returns undefined (no valid IDs)
18908
- * ```
18909
- */
18910
- function parseIds(ids) {
18911
- if (!ids) return;
18912
- const parsed = ids.split(",").map((id) => id.trim()).map(Number).filter((num) => !isNaN(num) && num > 0);
18913
- return parsed.length > 0 ? parsed : void 0;
18914
- }
18915
- //#endregion
18916
18917
  //#region src/components/donations/components/DonationSelector.svelte
18917
18918
  var root$39 = /* @__PURE__ */ from_html(`<button> </button>`);
18918
18919
  var root_1$11 = /* @__PURE__ */ from_html(`<form id="donationForm" action="" novalidate=""><div class="donation-custom form-group"><label for="donation-custom-amount"> </label> <input class="form-control" id="donation-custom-amount" type="number" min="1"/></div></form>`);
18919
18920
  var root_2$8 = /* @__PURE__ */ from_html(`<div class="donation-selection"><h3> </h3> <div class="donation-options"></div> <!></div>`);
18920
18921
  function DonationSelector($$anchor, $$props) {
18921
18922
  push($$props, true);
18922
- const guestMaxLimit = goDonation.campaign?.guest_limit / 100;
18923
+ const guestMaxLimit = goDonation.campaign?.guest_limit ? goDonation.campaign.guest_limit / 100 : void 0;
18923
18924
  let customAmount = /* @__PURE__ */ state(void 0);
18924
18925
  function selectAmount(amount) {
18925
18926
  goDonation.amount = amount;
@@ -18946,7 +18947,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
18946
18947
  template_effect(($0) => {
18947
18948
  classes = set_class(button, 1, "btn btn-default", null, classes, { selected: goDonation.amount === option });
18948
18949
  set_text(text_1, $0);
18949
- }, [() => currency(option / 100, shop.currency)]);
18950
+ }, [() => formatCurrency(option)]);
18950
18951
  delegated("click", button, () => selectAmount(option));
18951
18952
  append($$anchor, button);
18952
18953
  });
@@ -36443,7 +36444,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
36443
36444
  }, [
36444
36445
  () => orderDetails().downloadLink(item()),
36445
36446
  () => shop.t("common.download"),
36446
- () => formatCurrency$1(item().price_cents)
36447
+ () => formatCurrency(item().price_cents)
36447
36448
  ]);
36448
36449
  append($$anchor, li);
36449
36450
  return pop($$exports);
@@ -36611,7 +36612,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
36611
36612
  template_effect(($0) => {
36612
36613
  set_text(text, item().attributes.title);
36613
36614
  set_text(text_7, $0);
36614
- }, [() => formatCurrency$1(item().price_cents)]);
36615
+ }, [() => formatCurrency(item().price_cents)]);
36615
36616
  append($$anchor, li);
36616
36617
  });
36617
36618
  append($$anchor, fragment_1);
@@ -36664,7 +36665,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
36664
36665
  set_text(text_9, item().attributes.quantity);
36665
36666
  set_text(text_10, item().attributes.title);
36666
36667
  set_text(text_13, $0);
36667
- }, [() => formatCurrency$1(item().price_cents)]);
36668
+ }, [() => formatCurrency(item().price_cents)]);
36668
36669
  append($$anchor, li_6);
36669
36670
  };
36670
36671
  if_block(node, ($$render) => {
@@ -36763,7 +36764,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
36763
36764
  set_text(text, item().attributes.title);
36764
36765
  set_text(text_1, $0);
36765
36766
  set_text(text_5, $1);
36766
- }, [() => shop.t("cart.item.participants", { count: item().attributes.participants }), () => formatCurrency$1(item().price_cents)]);
36767
+ }, [() => shop.t("cart.item.participants", { count: item().attributes.participants }), () => formatCurrency(item().price_cents)]);
36767
36768
  append($$anchor, li);
36768
36769
  return pop($$exports);
36769
36770
  }
@@ -36848,7 +36849,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
36848
36849
  () => shop.t("common.table.count"),
36849
36850
  () => shop.t("common.table.product"),
36850
36851
  () => shop.t("common.table.price"),
36851
- () => shop.t("common.table.total", { value: formatCurrency$1(get$2(order).total_price_cents) })
36852
+ () => shop.t("common.table.total", { value: formatCurrency(get$2(order).total_price_cents) })
36852
36853
  ]);
36853
36854
  append($$anchor, ol);
36854
36855
  };
@@ -36947,11 +36948,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
36947
36948
  });
36948
36949
  let form = /* @__PURE__ */ state(void 0);
36949
36950
  const user = /* @__PURE__ */ user_derived(() => shop.getCustomer());
36951
+ const userData = /* @__PURE__ */ user_derived(() => get$2(user) && "data" in get$2(user) ? get$2(user).data : void 0);
36950
36952
  onMount(async () => {
36951
36953
  await shop.waitForAllFetches();
36952
36954
  await pollUntilTruthy(() => get$2(form).details);
36953
- await pollUntilTruthy(() => get$2(user).data);
36954
- get$2(form).details.fill(get$2(user).data);
36955
+ await pollUntilTruthy(() => get$2(userData));
36956
+ get$2(form).details.fill(get$2(userData));
36955
36957
  });
36956
36958
  var go_form = root$5();
36957
36959
  set_custom_element_data(go_form, "formId", "accountDetailsForm");
@@ -36966,7 +36968,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
36966
36968
  function Overview($$anchor, $$props) {
36967
36969
  push($$props, true);
36968
36970
  const user = /* @__PURE__ */ user_derived(() => shop.getCustomer());
36969
- const data = /* @__PURE__ */ user_derived(() => get$2(user)?.data);
36971
+ const data = /* @__PURE__ */ user_derived(() => get$2(user) && "data" in get$2(user) ? get$2(user).data : void 0);
36970
36972
  var fragment = comment();
36971
36973
  var node = first_child(fragment);
36972
36974
  var consequent = ($$anchor) => {
@@ -6369,6 +6369,15 @@ function create_custom_element(Component, props_definition, slots, exports, shad
6369
6369
  return Class;
6370
6370
  }
6371
6371
  //#endregion
6372
+ //#region src/lib/helpers/locale.ts
6373
+ function warnOnInvalidLocale(locale) {
6374
+ try {
6375
+ if (Intl.NumberFormat.supportedLocalesOf(locale).length === 0) console.warn(`[go] Unknown locale "${locale}" — the browser has no locale data for it; price and date formatting will fall back to the browser default.`);
6376
+ } catch {
6377
+ console.warn(`[go] Invalid locale "${locale}" — not a valid BCP 47 language tag (use "de", "de-CH", "en", …). Price and date formatting will throw.`);
6378
+ }
6379
+ }
6380
+ //#endregion
6372
6381
  //#region src/lib/helpers/urls.ts
6373
6382
  var ANGULAR_URLS = {
6374
6383
  account: () => "/#/user/account",
@@ -11810,13 +11819,6 @@ function formatDate(isoDateString, options = {
11810
11819
  ...options
11811
11820
  }).format(zoned.toDate());
11812
11821
  }
11813
- function formatCurrency$1(priceCents) {
11814
- if (priceCents === void 0) throw Error("priceCents is required");
11815
- return new Intl.NumberFormat("de-DE", {
11816
- style: "currency",
11817
- currency: "EUR"
11818
- }).format(priceCents / 100);
11819
- }
11820
11822
  //#endregion
11821
11823
  //#region src/lib/models/ticket/UITicket.svelte.ts
11822
11824
  function isUITicket(x) {
@@ -12180,6 +12182,49 @@ function dispatchCartEvents(cart) {
12180
12182
  });
12181
12183
  }
12182
12184
  //#endregion
12185
+ //#region src/lib/helpers/utils.ts
12186
+ function formatCurrency(priceCents) {
12187
+ let format;
12188
+ try {
12189
+ format = new Intl.NumberFormat(shop.locale ?? "de", {
12190
+ style: "currency",
12191
+ currency: shop.currency ?? "EUR"
12192
+ });
12193
+ } catch {
12194
+ format = new Intl.NumberFormat("de", {
12195
+ style: "currency",
12196
+ currency: "EUR"
12197
+ });
12198
+ }
12199
+ return format.format((priceCents ?? 0) / 100);
12200
+ }
12201
+ /**
12202
+ * Parses a comma-separated string of IDs into an array of positive numbers.
12203
+ *
12204
+ * This function takes a string containing comma-separated values and converts
12205
+ * them into an array of positive integers. Invalid values (non-numeric, zero,
12206
+ * or negative numbers) are filtered out.
12207
+ *
12208
+ * @param ids - A comma-separated string of IDs (e.g., "1,2,3" or "10, 20, 30")
12209
+ * @returns An array of positive numbers if valid IDs are found, undefined otherwise
12210
+ *
12211
+ * @example
12212
+ * ```ts
12213
+ * parseIds("1,2,3") // Returns [1, 2, 3]
12214
+ * parseIds("10, 20, 30") // Returns [10, 20, 30] (handles whitespace)
12215
+ * parseIds("1,abc,3") // Returns [1, 3] (filters out invalid values)
12216
+ * parseIds("0,-1,2") // Returns [2] (filters out zero and negative numbers)
12217
+ * parseIds("") // Returns undefined
12218
+ * parseIds(undefined) // Returns undefined
12219
+ * parseIds("abc,def") // Returns undefined (no valid IDs)
12220
+ * ```
12221
+ */
12222
+ function parseIds(ids) {
12223
+ if (!ids) return;
12224
+ const parsed = ids.split(",").map((id) => id.trim()).map(Number).filter((num) => !isNaN(num) && num > 0);
12225
+ return parsed.length > 0 ? parsed : void 0;
12226
+ }
12227
+ //#endregion
12183
12228
  //#region src/lib/models/tour/UITour.svelte.ts
12184
12229
  function isUITour(x) {
12185
12230
  return x?.type === "Tour";
@@ -12573,13 +12618,6 @@ function createCart(products, contingent = 20) {
12573
12618
  if (products) products.forEach((p) => cart.addItem(createCartItem(p)));
12574
12619
  return cart;
12575
12620
  }
12576
- function formatCurrency(priceCents) {
12577
- priceCents = priceCents ?? 0;
12578
- return new Intl.NumberFormat("de-DE", {
12579
- style: "currency",
12580
- currency: "EUR"
12581
- }).format(priceCents / 100);
12582
- }
12583
12621
  function createMainCart() {
12584
12622
  const cart = proxy(createCart());
12585
12623
  syncCartToLocalStorage(cart);
@@ -13694,6 +13732,7 @@ var Shop = class {
13694
13732
  get$2(this.#data).apiUrl = apiUrl;
13695
13733
  get$2(this.#data).shopDomain = shopDomain;
13696
13734
  get$2(this.#data).locale = locale || "de";
13735
+ warnOnInvalidLocale(get$2(this.#data).locale);
13697
13736
  this.#fetchStatus = {};
13698
13737
  get$2(this.#data).client = client(apiUrl, shopDomain);
13699
13738
  get$2(this.#data).capacityManager = createCapacityManager();
@@ -18874,51 +18913,13 @@ function DonationCampaign($$anchor, $$props) {
18874
18913
  delegate(["click", "keydown"]);
18875
18914
  create_custom_element(DonationCampaign, { campaign: {} }, [], [], { mode: "open" });
18876
18915
  //#endregion
18877
- //#region src/lib/helpers/utils.ts
18878
- function currency(value, currency) {
18879
- if (currency == "CHF") return new Intl.NumberFormat("de-CH", {
18880
- style: "currency",
18881
- currency
18882
- }).format(value);
18883
- else return new Intl.NumberFormat("de-DE", {
18884
- style: "currency",
18885
- currency
18886
- }).format(value);
18887
- }
18888
- /**
18889
- * Parses a comma-separated string of IDs into an array of positive numbers.
18890
- *
18891
- * This function takes a string containing comma-separated values and converts
18892
- * them into an array of positive integers. Invalid values (non-numeric, zero,
18893
- * or negative numbers) are filtered out.
18894
- *
18895
- * @param ids - A comma-separated string of IDs (e.g., "1,2,3" or "10, 20, 30")
18896
- * @returns An array of positive numbers if valid IDs are found, undefined otherwise
18897
- *
18898
- * @example
18899
- * ```ts
18900
- * parseIds("1,2,3") // Returns [1, 2, 3]
18901
- * parseIds("10, 20, 30") // Returns [10, 20, 30] (handles whitespace)
18902
- * parseIds("1,abc,3") // Returns [1, 3] (filters out invalid values)
18903
- * parseIds("0,-1,2") // Returns [2] (filters out zero and negative numbers)
18904
- * parseIds("") // Returns undefined
18905
- * parseIds(undefined) // Returns undefined
18906
- * parseIds("abc,def") // Returns undefined (no valid IDs)
18907
- * ```
18908
- */
18909
- function parseIds(ids) {
18910
- if (!ids) return;
18911
- const parsed = ids.split(",").map((id) => id.trim()).map(Number).filter((num) => !isNaN(num) && num > 0);
18912
- return parsed.length > 0 ? parsed : void 0;
18913
- }
18914
- //#endregion
18915
18916
  //#region src/components/donations/components/DonationSelector.svelte
18916
18917
  var root$39 = /* @__PURE__ */ from_html(`<button> </button>`);
18917
18918
  var root_1$11 = /* @__PURE__ */ from_html(`<form id="donationForm" action="" novalidate=""><div class="donation-custom form-group"><label for="donation-custom-amount"> </label> <input class="form-control" id="donation-custom-amount" type="number" min="1"/></div></form>`);
18918
18919
  var root_2$8 = /* @__PURE__ */ from_html(`<div class="donation-selection"><h3> </h3> <div class="donation-options"></div> <!></div>`);
18919
18920
  function DonationSelector($$anchor, $$props) {
18920
18921
  push($$props, true);
18921
- const guestMaxLimit = goDonation.campaign?.guest_limit / 100;
18922
+ const guestMaxLimit = goDonation.campaign?.guest_limit ? goDonation.campaign.guest_limit / 100 : void 0;
18922
18923
  let customAmount = /* @__PURE__ */ state(void 0);
18923
18924
  function selectAmount(amount) {
18924
18925
  goDonation.amount = amount;
@@ -18945,7 +18946,7 @@ function DonationSelector($$anchor, $$props) {
18945
18946
  template_effect(($0) => {
18946
18947
  classes = set_class(button, 1, "btn btn-default", null, classes, { selected: goDonation.amount === option });
18947
18948
  set_text(text_1, $0);
18948
- }, [() => currency(option / 100, shop.currency)]);
18949
+ }, [() => formatCurrency(option)]);
18949
18950
  delegated("click", button, () => selectAmount(option));
18950
18951
  append($$anchor, button);
18951
18952
  });
@@ -36442,7 +36443,7 @@ function Event$1($$anchor, $$props) {
36442
36443
  }, [
36443
36444
  () => orderDetails().downloadLink(item()),
36444
36445
  () => shop.t("common.download"),
36445
- () => formatCurrency$1(item().price_cents)
36446
+ () => formatCurrency(item().price_cents)
36446
36447
  ]);
36447
36448
  append($$anchor, li);
36448
36449
  return pop($$exports);
@@ -36610,7 +36611,7 @@ function TicketSale($$anchor, $$props) {
36610
36611
  template_effect(($0) => {
36611
36612
  set_text(text, item().attributes.title);
36612
36613
  set_text(text_7, $0);
36613
- }, [() => formatCurrency$1(item().price_cents)]);
36614
+ }, [() => formatCurrency(item().price_cents)]);
36614
36615
  append($$anchor, li);
36615
36616
  });
36616
36617
  append($$anchor, fragment_1);
@@ -36663,7 +36664,7 @@ function TicketSale($$anchor, $$props) {
36663
36664
  set_text(text_9, item().attributes.quantity);
36664
36665
  set_text(text_10, item().attributes.title);
36665
36666
  set_text(text_13, $0);
36666
- }, [() => formatCurrency$1(item().price_cents)]);
36667
+ }, [() => formatCurrency(item().price_cents)]);
36667
36668
  append($$anchor, li_6);
36668
36669
  };
36669
36670
  if_block(node, ($$render) => {
@@ -36762,7 +36763,7 @@ function Tour($$anchor, $$props) {
36762
36763
  set_text(text, item().attributes.title);
36763
36764
  set_text(text_1, $0);
36764
36765
  set_text(text_5, $1);
36765
- }, [() => shop.t("cart.item.participants", { count: item().attributes.participants }), () => formatCurrency$1(item().price_cents)]);
36766
+ }, [() => shop.t("cart.item.participants", { count: item().attributes.participants }), () => formatCurrency(item().price_cents)]);
36766
36767
  append($$anchor, li);
36767
36768
  return pop($$exports);
36768
36769
  }
@@ -36847,7 +36848,7 @@ function Breakdown($$anchor, $$props) {
36847
36848
  () => shop.t("common.table.count"),
36848
36849
  () => shop.t("common.table.product"),
36849
36850
  () => shop.t("common.table.price"),
36850
- () => shop.t("common.table.total", { value: formatCurrency$1(get$2(order).total_price_cents) })
36851
+ () => shop.t("common.table.total", { value: formatCurrency(get$2(order).total_price_cents) })
36851
36852
  ]);
36852
36853
  append($$anchor, ol);
36853
36854
  };
@@ -36946,11 +36947,12 @@ function Details$2($$anchor, $$props) {
36946
36947
  });
36947
36948
  let form = /* @__PURE__ */ state(void 0);
36948
36949
  const user = /* @__PURE__ */ user_derived(() => shop.getCustomer());
36950
+ const userData = /* @__PURE__ */ user_derived(() => get$2(user) && "data" in get$2(user) ? get$2(user).data : void 0);
36949
36951
  onMount(async () => {
36950
36952
  await shop.waitForAllFetches();
36951
36953
  await pollUntilTruthy(() => get$2(form).details);
36952
- await pollUntilTruthy(() => get$2(user).data);
36953
- get$2(form).details.fill(get$2(user).data);
36954
+ await pollUntilTruthy(() => get$2(userData));
36955
+ get$2(form).details.fill(get$2(userData));
36954
36956
  });
36955
36957
  var go_form = root$5();
36956
36958
  set_custom_element_data(go_form, "formId", "accountDetailsForm");
@@ -36965,7 +36967,7 @@ var root$4 = /* @__PURE__ */ from_html(`<div class="go-profile-fullname"> </div>
36965
36967
  function Overview($$anchor, $$props) {
36966
36968
  push($$props, true);
36967
36969
  const user = /* @__PURE__ */ user_derived(() => shop.getCustomer());
36968
- const data = /* @__PURE__ */ user_derived(() => get$2(user)?.data);
36970
+ const data = /* @__PURE__ */ user_derived(() => get$2(user) && "data" in get$2(user) ? get$2(user).data : void 0);
36969
36971
  var fragment = comment();
36970
36972
  var node = first_child(fragment);
36971
36973
  var consequent = ($$anchor) => {