tf-checkout-react 2.0.0-beta.0 → 2.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2643,22 +2643,29 @@ var getOrderReview = async (orderHash) => {
2643
2643
  };
2644
2644
  };
2645
2645
  var mapProfileToBilling = (profile) => {
2646
- var _a, _b, _c;
2646
+ var _a, _b, _c, _d;
2647
2647
  const str = (v) => v == null || v === "" ? void 0 : String(v);
2648
2648
  const idStr = (v) => {
2649
2649
  const s = str(v);
2650
2650
  return s === void 0 || s === "0" || s === "-1" ? void 0 : s;
2651
2651
  };
2652
+ const dobParts = /^(\d{4})-(\d{2})-(\d{2})/.exec((_a = profile.dateOfBirth) != null ? _a : "");
2653
+ const dob = dobParts && Number(dobParts[1]) > 1900 ? {
2654
+ dobYear: Number(dobParts[1]),
2655
+ dobMonth: Number(dobParts[2]),
2656
+ dobDay: Number(dobParts[3])
2657
+ } : {};
2652
2658
  return {
2653
- firstName: (_a = profile.firstName) != null ? _a : "",
2654
- lastName: (_b = profile.lastName) != null ? _b : "",
2655
- email: (_c = profile.email) != null ? _c : "",
2659
+ firstName: (_b = profile.firstName) != null ? _b : "",
2660
+ lastName: (_c = profile.lastName) != null ? _c : "",
2661
+ email: (_d = profile.email) != null ? _d : "",
2656
2662
  phone: str(profile.phone),
2657
2663
  streetAddress: str(profile.streetAddress),
2658
2664
  city: str(profile.city),
2659
2665
  zip: str(profile.zipCode),
2660
2666
  countryId: idStr(profile.countryId),
2661
- stateId: idStr(profile.stateId)
2667
+ stateId: idStr(profile.stateId),
2668
+ ...dob
2662
2669
  };
2663
2670
  };
2664
2671
  var completeFreeRegistration = async (orderHash) => {
@@ -3583,6 +3590,10 @@ var createEngine = (config) => {
3583
3590
  reset: () => {
3584
3591
  clearCartGuestToken();
3585
3592
  store.reset();
3593
+ },
3594
+ expireCart: () => {
3595
+ clearCartGuestToken();
3596
+ store.expireCart();
3586
3597
  }
3587
3598
  };
3588
3599
  };
@@ -4089,6 +4100,12 @@ var useCheckout = (config) => {
4089
4100
  return () => clearInterval(t);
4090
4101
  }, [snapshot.expiresAt]);
4091
4102
  const secondsLeft = snapshot.expiresAt != null ? Math.max(0, Math.round((snapshot.expiresAt - now) / 1e3)) : void 0;
4103
+ (0, import_react3.useEffect)(() => {
4104
+ if (secondsLeft !== 0) return;
4105
+ if (snapshot.status === "placing" || snapshot.status === "succeeded") return;
4106
+ if (snapshot.status === "expired") return;
4107
+ engine.expireCart();
4108
+ }, [engine, secondsLeft, snapshot.status]);
4092
4109
  const missingRequiredAddonNames = missingRequiredAddOns(
4093
4110
  snapshot.requiredAddOns,
4094
4111
  snapshot.addOns
@@ -4268,7 +4285,91 @@ var en = {
4268
4285
  "referral.inviteFriends": "Invite friends",
4269
4286
  "referral.howToInvite": "How do you invite your friends?",
4270
4287
  "referral.sendThisLink": "Send them this link:",
4271
- "referral.howMuchCheaper": "How much cheaper?"
4288
+ "referral.howMuchCheaper": "How much cheaper?",
4289
+ // --- Checkout body (localization pass) ---------------------------------
4290
+ "common.submit": "Submit",
4291
+ "common.each": "each",
4292
+ "billing.heading": "Billing Information",
4293
+ "billing.continueToPayment": "Continue to payment",
4294
+ "billing.ttfOptIn": "Keep me updated about future events from The Ticket Fairy",
4295
+ "billing.fieldRequired": "This field is required.",
4296
+ "billing.firstNamePlaceholder": "First name *",
4297
+ "billing.lastNamePlaceholder": "Last name *",
4298
+ "billing.emailMustMatch": "Email addresses must match.",
4299
+ "billing.emailInvalid": "Enter a valid email address.",
4300
+ "billing.emailRegistered": "This email is already registered.",
4301
+ "billing.loginAutofill": "Log in to autofill your details",
4302
+ "billing.loginAutofillPlain": "Log in to autofill your details.",
4303
+ "billing.firstNameRequired": "First name is required.",
4304
+ "billing.lastNameRequired": "Last name is required.",
4305
+ "billing.streetRequired": "Street address is required.",
4306
+ "billing.cityRequired": "City is required.",
4307
+ "billing.postcodeRequired": "ZIP / postcode is required.",
4308
+ "billing.countryRequired": "Country is required.",
4309
+ "billing.stateRequired": "State / county is required.",
4310
+ "billing.countryEmpty": "\u2014 country * \u2014",
4311
+ "billing.stateEmpty": "\u2014 state / county \u2014",
4312
+ "billing.stateEmptyRequired": "\u2014 state / county * \u2014",
4313
+ "billing.holderTitle": "Ticket {{number}}",
4314
+ "billing.nationality": "Nationality",
4315
+ "billing.gender": "Gender",
4316
+ "billing.instagramHandle": "Instagram handle",
4317
+ "billing.phoneOptional": "Phone",
4318
+ "billing.phoneAria": "Phone",
4319
+ "billing.phoneInvalid": "Enter a valid phone number.",
4320
+ "billing.phonePlaceholder": "Phone number",
4321
+ "billing.dob": "Date of birth *",
4322
+ "billing.dobWithAge": "Date of birth * (must be {{age}}+)",
4323
+ "billing.dobRequired": "Date of birth is required.",
4324
+ "billing.ageMinimum": "You must be {{age}} or older.",
4325
+ "billing.privacyAgree": "I have read and agree to {{brand}}",
4326
+ "billing.privacyLink": "Privacy Policy.",
4327
+ "tickets.getTickets": "Get tickets",
4328
+ "tickets.selectOnMap": "Select on map",
4329
+ "tickets.selectSeats": "Select seats",
4330
+ "tickets.hideInfo": "Hide info",
4331
+ "tickets.viewInfo": "View info",
4332
+ "tickets.salesNotStarted": "Sales not started",
4333
+ "tickets.salesEnded": "Sales Ended",
4334
+ "tickets.accessCode": "Access code",
4335
+ "tickets.promoCode": "Promo code",
4336
+ "tickets.reserving": "Reserving\u2026",
4337
+ "addons.eyebrow": "Get Your Tickets",
4338
+ "addons.heading": "UPGRADES & ADD-ONS",
4339
+ "addons.confirmSelection": "CONFIRM SELECTION",
4340
+ "addons.updating": "Updating\u2026",
4341
+ "payment.title": "Payment",
4342
+ "payment.card": "Card",
4343
+ "payment.paymentPlan": "Payment plan",
4344
+ "payment.oxxo": "OXXO (pay in cash)",
4345
+ "payment.submitPayment": "Submit Payment",
4346
+ "payment.completeRegistration": "Complete Registration",
4347
+ "payment.placing": "Placing\u2026",
4348
+ "payment.testCard": "Test card: 4242 4242 4242 4242 \xB7 any future date \xB7 any CVC",
4349
+ "payment.testCardXendit": "Test card: 4000 0000 0000 0002 \xB7 any future date \xB7 any CVC",
4350
+ "confirmation.pending": "Payment pending",
4351
+ "confirmation.confirmed": "Your Tickets are Confirmed!",
4352
+ "confirmation.pendingBody": "We\u2019ll email your tickets as soon as the payment settles.",
4353
+ "confirmation.alreadyPaid": "This order was already paid \u2014 nothing was charged again.",
4354
+ "confirmation.available": "Your tickets are available in the My Tickets section \u2014 please bring them with you to the event.",
4355
+ "referral.copied": "Copied!",
4356
+ "referral.copyLink": "Copy link",
4357
+ "timer.completePurchase": "Please complete your purchase before the timer reaches zero.",
4358
+ "auth.logIn": "Log in",
4359
+ "auth.signUp": "Sign Up",
4360
+ "auth.passwordReset": "Password reset",
4361
+ "auth.backToLogin": "Back to log in",
4362
+ "auth.sendResetInstructions": "Send reset instructions",
4363
+ "auth.createAccount": "Create Account",
4364
+ "auth.forgotPassword": "Forgot password?",
4365
+ "auth.forgotIntro": "Enter your email and we\u2019ll send you instructions to reset your password.",
4366
+ "auth.missingToken": "This password-reset link is missing its token.",
4367
+ "auth.passwordTooShort": "Password must have at least 8 characters.",
4368
+ "auth.passwordNeedsSpecial": "Password must contain at least one special character.",
4369
+ "auth.passwordsMustMatch": "Passwords must match.",
4370
+ "auth.passwordChanged": "Your password has been changed. You can now log in.",
4371
+ "auth.selectState": "Select state / region",
4372
+ "auth.notRequired": "Not required"
4272
4373
  };
4273
4374
 
4274
4375
  // ../tf-checkout-shared/src/i18n/resolve.ts
@@ -4400,7 +4501,91 @@ var esMX = {
4400
4501
  "referral.inviteFriends": "Invita a tus amigos",
4401
4502
  "referral.howToInvite": "\xBFC\xF3mo invitas a tus amigos?",
4402
4503
  "referral.sendThisLink": "Env\xEDales este enlace:",
4403
- "referral.howMuchCheaper": "\xBFCu\xE1nto m\xE1s barato?"
4504
+ "referral.howMuchCheaper": "\xBFCu\xE1nto m\xE1s barato?",
4505
+ // --- Checkout body (localization pass) ---------------------------------
4506
+ "common.submit": "Enviar",
4507
+ "common.each": "c/u",
4508
+ "billing.heading": "Informaci\xF3n de facturaci\xF3n",
4509
+ "billing.continueToPayment": "Continuar al pago",
4510
+ "billing.ttfOptIn": "Quiero recibir novedades sobre pr\xF3ximos eventos de The Ticket Fairy",
4511
+ "billing.fieldRequired": "Este campo es obligatorio.",
4512
+ "billing.firstNamePlaceholder": "Nombre *",
4513
+ "billing.lastNamePlaceholder": "Apellido *",
4514
+ "billing.emailMustMatch": "Los correos electr\xF3nicos deben coincidir.",
4515
+ "billing.emailInvalid": "Ingresa un correo electr\xF3nico v\xE1lido.",
4516
+ "billing.emailRegistered": "Este correo ya est\xE1 registrado.",
4517
+ "billing.loginAutofill": "Inicia sesi\xF3n para completar tus datos",
4518
+ "billing.loginAutofillPlain": "Inicia sesi\xF3n para completar tus datos.",
4519
+ "billing.firstNameRequired": "El nombre es obligatorio.",
4520
+ "billing.lastNameRequired": "El apellido es obligatorio.",
4521
+ "billing.streetRequired": "La calle y n\xFAmero son obligatorios.",
4522
+ "billing.cityRequired": "La ciudad es obligatoria.",
4523
+ "billing.postcodeRequired": "El c\xF3digo postal es obligatorio.",
4524
+ "billing.countryRequired": "El pa\xEDs es obligatorio.",
4525
+ "billing.stateRequired": "El estado es obligatorio.",
4526
+ "billing.countryEmpty": "\u2014 pa\xEDs * \u2014",
4527
+ "billing.stateEmpty": "\u2014 estado \u2014",
4528
+ "billing.stateEmptyRequired": "\u2014 estado * \u2014",
4529
+ "billing.holderTitle": "Boleto {{number}}",
4530
+ "billing.nationality": "Nacionalidad",
4531
+ "billing.gender": "G\xE9nero",
4532
+ "billing.instagramHandle": "Usuario de Instagram",
4533
+ "billing.phoneOptional": "Tel\xE9fono",
4534
+ "billing.phoneAria": "Tel\xE9fono",
4535
+ "billing.phoneInvalid": "Ingresa un n\xFAmero de tel\xE9fono v\xE1lido.",
4536
+ "billing.phonePlaceholder": "N\xFAmero de tel\xE9fono",
4537
+ "billing.dob": "Fecha de nacimiento *",
4538
+ "billing.dobWithAge": "Fecha de nacimiento * (debes tener {{age}}+)",
4539
+ "billing.dobRequired": "La fecha de nacimiento es obligatoria.",
4540
+ "billing.ageMinimum": "Debes tener {{age}} a\xF1os o m\xE1s.",
4541
+ "billing.privacyAgree": "He le\xEDdo y acepto el",
4542
+ "billing.privacyLink": "Aviso de Privacidad.",
4543
+ "tickets.getTickets": "Comprar boletos",
4544
+ "tickets.selectOnMap": "Seleccionar en el mapa",
4545
+ "tickets.selectSeats": "Seleccionar asientos",
4546
+ "tickets.hideInfo": "Ocultar informaci\xF3n",
4547
+ "tickets.viewInfo": "Ver informaci\xF3n",
4548
+ "tickets.salesNotStarted": "Venta no iniciada",
4549
+ "tickets.salesEnded": "Venta finalizada",
4550
+ "tickets.accessCode": "C\xF3digo de acceso",
4551
+ "tickets.promoCode": "C\xF3digo promocional",
4552
+ "tickets.reserving": "Reservando\u2026",
4553
+ "addons.eyebrow": "Obt\xE9n tus boletos",
4554
+ "addons.heading": "MEJORAS Y COMPLEMENTOS",
4555
+ "addons.confirmSelection": "CONFIRMAR SELECCI\xD3N",
4556
+ "addons.updating": "Actualizando\u2026",
4557
+ "payment.title": "Pago",
4558
+ "payment.card": "Tarjeta",
4559
+ "payment.paymentPlan": "Plan de pagos",
4560
+ "payment.oxxo": "OXXO (pago en efectivo)",
4561
+ "payment.submitPayment": "Pagar",
4562
+ "payment.completeRegistration": "Completar registro",
4563
+ "payment.placing": "Procesando\u2026",
4564
+ "payment.testCard": "Tarjeta de prueba: 4242 4242 4242 4242 \xB7 cualquier fecha futura \xB7 cualquier CVC",
4565
+ "payment.testCardXendit": "Tarjeta de prueba: 4000 0000 0000 0002 \xB7 cualquier fecha futura \xB7 cualquier CVC",
4566
+ "confirmation.pending": "Pago pendiente",
4567
+ "confirmation.confirmed": "\xA1Tus boletos est\xE1n confirmados!",
4568
+ "confirmation.pendingBody": "Te enviaremos tus boletos por correo en cuanto se acredite el pago.",
4569
+ "confirmation.alreadyPaid": "Esta orden ya estaba pagada: no se te cobr\xF3 de nuevo.",
4570
+ "confirmation.available": "Tus boletos est\xE1n disponibles en la secci\xF3n Mis boletos. Recuerda llevarlos contigo al evento.",
4571
+ "referral.copied": "\xA1Copiado!",
4572
+ "referral.copyLink": "Copiar enlace",
4573
+ "timer.completePurchase": "Completa tu compra antes de que el temporizador llegue a cero.",
4574
+ "auth.logIn": "Iniciar sesi\xF3n",
4575
+ "auth.signUp": "Crear cuenta",
4576
+ "auth.passwordReset": "Restablecer contrase\xF1a",
4577
+ "auth.backToLogin": "Volver a iniciar sesi\xF3n",
4578
+ "auth.sendResetInstructions": "Enviar instrucciones",
4579
+ "auth.createAccount": "Crear cuenta",
4580
+ "auth.forgotPassword": "\xBFOlvidaste tu contrase\xF1a?",
4581
+ "auth.forgotIntro": "Ingresa tu correo y te enviaremos instrucciones para restablecer tu contrase\xF1a.",
4582
+ "auth.missingToken": "A este enlace de restablecimiento le falta el token.",
4583
+ "auth.passwordTooShort": "La contrase\xF1a debe tener al menos 8 caracteres.",
4584
+ "auth.passwordNeedsSpecial": "La contrase\xF1a debe incluir al menos un car\xE1cter especial.",
4585
+ "auth.passwordsMustMatch": "Las contrase\xF1as deben coincidir.",
4586
+ "auth.passwordChanged": "Tu contrase\xF1a se cambi\xF3. Ya puedes iniciar sesi\xF3n.",
4587
+ "auth.selectState": "Selecciona estado / regi\xF3n",
4588
+ "auth.notRequired": "No requerido"
4404
4589
  };
4405
4590
 
4406
4591
  // ../tf-checkout-shared/src/i18n/locales/index.ts
@@ -5290,6 +5475,7 @@ Button.displayName = "Button";
5290
5475
 
5291
5476
  // src/ui/InstallmentPicker.tsx
5292
5477
  var useInstallmentPicker = () => {
5478
+ const t = useT();
5293
5479
  const [pending, setPending] = (0, import_react8.useState)(null);
5294
5480
  const onInstallmentOffers = (0, import_react8.useCallback)(
5295
5481
  (offers) => new Promise((resolve) => setPending({ offers, resolve })),
@@ -5304,9 +5490,9 @@ var useInstallmentPicker = () => {
5304
5490
  {
5305
5491
  className: "tf-checkout-installments",
5306
5492
  role: "dialog",
5307
- "aria-label": "Choose installments"
5493
+ "aria-label": t("payment.chooseInstallments")
5308
5494
  },
5309
- /* @__PURE__ */ import_react8.default.createElement("div", { className: "tf-checkout-installments__box" }, /* @__PURE__ */ import_react8.default.createElement("strong", null, "Pay in installments?"), /* @__PURE__ */ import_react8.default.createElement("div", { className: "tf-checkout-installments__list" }, pending.offers.map((o, i) => {
5495
+ /* @__PURE__ */ import_react8.default.createElement("div", { className: "tf-checkout-installments__box" }, /* @__PURE__ */ import_react8.default.createElement("strong", null, t("payment.payInInstallments")), /* @__PURE__ */ import_react8.default.createElement("div", { className: "tf-checkout-installments__list" }, pending.offers.map((o, i) => {
5310
5496
  var _a;
5311
5497
  return /* @__PURE__ */ import_react8.default.createElement(
5312
5498
  "button",
@@ -5650,63 +5836,73 @@ var PaymentMethods = ({
5650
5836
  children,
5651
5837
  inputSlotFor,
5652
5838
  className
5653
- }) => /* @__PURE__ */ import_react13.default.createElement(
5654
- "div",
5655
- {
5656
- className: cx("tf-checkout-payment__methods", className),
5657
- role: "radiogroup",
5658
- "aria-label": "Payment method"
5659
- },
5660
- options.map((o) => {
5661
- var _a, _b, _c, _d, _e, _f;
5662
- const isSelected = o.value === selected;
5663
- const extraValue = o.extra === "phoneNumber" ? (_a = extraValues[o.value]) == null ? void 0 : _a.phoneNumber : (_b = extraValues[o.value]) == null ? void 0 : _b.cashtag;
5664
- const extraInvalid = Boolean(isSelected && o.extra && showValidation) && !(extraValue == null ? void 0 : extraValue.trim());
5665
- return /* @__PURE__ */ import_react13.default.createElement(
5666
- "label",
5667
- {
5668
- key: o.value,
5669
- className: cx(
5670
- "tf-checkout-payment__method",
5671
- isSelected && "tf-checkout-payment__method--selected"
5672
- )
5673
- },
5674
- /* @__PURE__ */ import_react13.default.createElement("span", { className: "tf-checkout-payment__method-head" }, /* @__PURE__ */ import_react13.default.createElement(
5675
- "input",
5676
- {
5677
- type: "radio",
5678
- name: "tf-pay-method",
5679
- className: "tf-checkout-payment__method-radio",
5680
- checked: isSelected,
5681
- onChange: () => onSelect(o.value)
5682
- }
5683
- ), o.iconUrl && /* @__PURE__ */ import_react13.default.createElement("img", { className: "tf-checkout-payment__method-icon", src: o.iconUrl, alt: "" }), /* @__PURE__ */ import_react13.default.createElement("span", { className: "tf-checkout-payment__method-label" }, o.label)),
5684
- isSelected && (o.value === inputSlotFor || o.extra) && /* @__PURE__ */ import_react13.default.createElement("div", { className: "tf-checkout-payment__method-body" }, o.value === inputSlotFor && children, o.extra && /* @__PURE__ */ import_react13.default.createElement(
5685
- Field,
5839
+ }) => {
5840
+ const t = useT();
5841
+ return /* @__PURE__ */ import_react13.default.createElement(
5842
+ "div",
5843
+ {
5844
+ className: cx("tf-checkout-payment__methods", className),
5845
+ role: "radiogroup",
5846
+ "aria-label": t("payment.method")
5847
+ },
5848
+ options.map((o) => {
5849
+ var _a, _b, _c, _d, _e, _f;
5850
+ const isSelected = o.value === selected;
5851
+ const extraValue = o.extra === "phoneNumber" ? (_a = extraValues[o.value]) == null ? void 0 : _a.phoneNumber : (_b = extraValues[o.value]) == null ? void 0 : _b.cashtag;
5852
+ const extraInvalid = Boolean(isSelected && o.extra && showValidation) && !(extraValue == null ? void 0 : extraValue.trim());
5853
+ return /* @__PURE__ */ import_react13.default.createElement(
5854
+ "label",
5686
5855
  {
5687
- label: `${EXTRA_LABEL[o.extra]} *`,
5688
- error: extraInvalid ? "This field is required." : void 0,
5689
- invalid: extraInvalid
5856
+ key: o.value,
5857
+ className: cx(
5858
+ "tf-checkout-payment__method",
5859
+ isSelected && "tf-checkout-payment__method--selected"
5860
+ )
5690
5861
  },
5691
- /* @__PURE__ */ import_react13.default.createElement(
5692
- Input,
5862
+ /* @__PURE__ */ import_react13.default.createElement("span", { className: "tf-checkout-payment__method-head" }, /* @__PURE__ */ import_react13.default.createElement(
5863
+ "input",
5693
5864
  {
5694
- inputMode: o.extra === "phoneNumber" ? "tel" : "text",
5695
- required: true,
5696
- invalid: extraInvalid,
5697
- "aria-invalid": extraInvalid,
5698
- placeholder: o.extra === "phoneNumber" ? "e.g. 081234567890" : "$cashtag",
5699
- value: o.extra === "phoneNumber" ? (_d = (_c = extraValues[o.value]) == null ? void 0 : _c.phoneNumber) != null ? _d : "" : (_f = (_e = extraValues[o.value]) == null ? void 0 : _e.cashtag) != null ? _f : "",
5700
- onChange: (e) => onExtraChange(
5701
- o.value,
5702
- o.extra === "phoneNumber" ? { phoneNumber: e.target.value } : { cashtag: e.target.value }
5703
- )
5865
+ type: "radio",
5866
+ name: "tf-pay-method",
5867
+ className: "tf-checkout-payment__method-radio",
5868
+ checked: isSelected,
5869
+ onChange: () => onSelect(o.value)
5704
5870
  }
5705
- )
5706
- ))
5707
- );
5708
- })
5709
- );
5871
+ ), o.iconUrl && /* @__PURE__ */ import_react13.default.createElement(
5872
+ "img",
5873
+ {
5874
+ className: "tf-checkout-payment__method-icon",
5875
+ src: o.iconUrl,
5876
+ alt: ""
5877
+ }
5878
+ ), /* @__PURE__ */ import_react13.default.createElement("span", { className: "tf-checkout-payment__method-label" }, o.label)),
5879
+ isSelected && (o.value === inputSlotFor || o.extra) && /* @__PURE__ */ import_react13.default.createElement("div", { className: "tf-checkout-payment__method-body" }, o.value === inputSlotFor && children, o.extra && /* @__PURE__ */ import_react13.default.createElement(
5880
+ Field,
5881
+ {
5882
+ label: `${EXTRA_LABEL[o.extra]} *`,
5883
+ error: extraInvalid ? t("billing.fieldRequired") : void 0,
5884
+ invalid: extraInvalid
5885
+ },
5886
+ /* @__PURE__ */ import_react13.default.createElement(
5887
+ Input,
5888
+ {
5889
+ inputMode: o.extra === "phoneNumber" ? "tel" : "text",
5890
+ required: true,
5891
+ invalid: extraInvalid,
5892
+ "aria-invalid": extraInvalid,
5893
+ placeholder: o.extra === "phoneNumber" ? "e.g. 081234567890" : "$cashtag",
5894
+ value: o.extra === "phoneNumber" ? (_d = (_c = extraValues[o.value]) == null ? void 0 : _c.phoneNumber) != null ? _d : "" : (_f = (_e = extraValues[o.value]) == null ? void 0 : _e.cashtag) != null ? _f : "",
5895
+ onChange: (e) => onExtraChange(
5896
+ o.value,
5897
+ o.extra === "phoneNumber" ? { phoneNumber: e.target.value } : { cashtag: e.target.value }
5898
+ )
5899
+ }
5900
+ )
5901
+ ))
5902
+ );
5903
+ })
5904
+ );
5905
+ };
5710
5906
 
5711
5907
  // src/ui/Stepper.tsx
5712
5908
  var import_react14 = __toESM(require("react"));
@@ -5795,9 +5991,10 @@ var clock2 = (s) => {
5795
5991
  var TimerBanner = ({
5796
5992
  seconds,
5797
5993
  urgentAt = 60,
5798
- message = "Please complete your purchase before the timer reaches zero.",
5994
+ message,
5799
5995
  className
5800
5996
  }) => {
5997
+ const t = useT();
5801
5998
  const [dismissed, setDismissed] = (0, import_react18.useState)(false);
5802
5999
  if (seconds === void 0 || seconds <= 0 || dismissed) return null;
5803
6000
  const urgent = seconds <= urgentAt;
@@ -5811,14 +6008,14 @@ var TimerBanner = ({
5811
6008
  className
5812
6009
  )
5813
6010
  },
5814
- /* @__PURE__ */ import_react18.default.createElement("span", { className: "tf-checkout-timerbanner__msg" }, message),
6011
+ /* @__PURE__ */ import_react18.default.createElement("span", { className: "tf-checkout-timerbanner__msg" }, message != null ? message : t("timer.completePurchase")),
5815
6012
  /* @__PURE__ */ import_react18.default.createElement("span", { className: "tf-checkout-timerbanner__clock" }, clock2(seconds)),
5816
6013
  /* @__PURE__ */ import_react18.default.createElement(
5817
6014
  "button",
5818
6015
  {
5819
6016
  type: "button",
5820
6017
  className: "tf-checkout-timerbanner__close",
5821
- "aria-label": "Dismiss",
6018
+ "aria-label": t("common.dismiss"),
5822
6019
  onClick: () => setDismissed(true)
5823
6020
  },
5824
6021
  "\xD7"
@@ -5851,9 +6048,9 @@ var ForgotPasswordForm = ({
5851
6048
  void onSubmit(email);
5852
6049
  };
5853
6050
  if (successMessage) {
5854
- return /* @__PURE__ */ import_react19.default.createElement("div", { className: "tf-checkout-auth__form" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "tf-checkout-auth__success", role: "status" }, successMessage), /* @__PURE__ */ import_react19.default.createElement(Button, { type: "button", block: true, onClick: () => onBackToLogin(email) }, "Back to log in"));
6051
+ return /* @__PURE__ */ import_react19.default.createElement("div", { className: "tf-checkout-auth__form" }, /* @__PURE__ */ import_react19.default.createElement("div", { className: "tf-checkout-auth__success", role: "status" }, successMessage), /* @__PURE__ */ import_react19.default.createElement(Button, { type: "button", block: true, onClick: () => onBackToLogin(email) }, t("auth.backToLogin")));
5855
6052
  }
5856
- return /* @__PURE__ */ import_react19.default.createElement("form", { className: "tf-checkout-auth__form", onSubmit: submit, noValidate: true }, /* @__PURE__ */ import_react19.default.createElement("p", { className: "tf-checkout-auth__intro" }, "Enter your email and we\u2019ll send you instructions to reset your password."), error && /* @__PURE__ */ import_react19.default.createElement("div", { className: "tf-checkout-auth__alert", role: "alert" }, error), /* @__PURE__ */ import_react19.default.createElement(Field, { label: t("auth.email"), error: errors.email }, /* @__PURE__ */ import_react19.default.createElement(
6053
+ return /* @__PURE__ */ import_react19.default.createElement("form", { className: "tf-checkout-auth__form", onSubmit: submit, noValidate: true }, /* @__PURE__ */ import_react19.default.createElement("p", { className: "tf-checkout-auth__intro" }, t("auth.forgotIntro")), error && /* @__PURE__ */ import_react19.default.createElement("div", { className: "tf-checkout-auth__alert", role: "alert" }, error), /* @__PURE__ */ import_react19.default.createElement(Field, { label: t("auth.email"), error: errors.email }, /* @__PURE__ */ import_react19.default.createElement(
5857
6054
  Input,
5858
6055
  {
5859
6056
  type: "email",
@@ -5868,14 +6065,14 @@ var ForgotPasswordForm = ({
5868
6065
  onFieldChange == null ? void 0 : onFieldChange();
5869
6066
  }
5870
6067
  }
5871
- )), /* @__PURE__ */ import_react19.default.createElement(Button, { type: "submit", block: true, loading }, "Send reset instructions"), /* @__PURE__ */ import_react19.default.createElement(
6068
+ )), /* @__PURE__ */ import_react19.default.createElement(Button, { type: "submit", block: true, loading }, t("auth.sendResetInstructions")), /* @__PURE__ */ import_react19.default.createElement(
5872
6069
  "button",
5873
6070
  {
5874
6071
  type: "button",
5875
6072
  className: "tf-checkout-auth__text-button tf-checkout-auth__back",
5876
6073
  onClick: () => onBackToLogin(email)
5877
6074
  },
5878
- "Back to log in"
6075
+ t("auth.backToLogin")
5879
6076
  ));
5880
6077
  };
5881
6078
 
@@ -5977,14 +6174,14 @@ var LoginForm = ({
5977
6174
  }
5978
6175
  }
5979
6176
  )
5980
- ), /* @__PURE__ */ import_react21.default.createElement(Button, { type: "submit", block: true, loading }, "Login"), allowPasswordReset && onForgotPassword && /* @__PURE__ */ import_react21.default.createElement(
6177
+ ), /* @__PURE__ */ import_react21.default.createElement(Button, { type: "submit", block: true, loading }, t("auth.logIn")), allowPasswordReset && onForgotPassword && /* @__PURE__ */ import_react21.default.createElement(
5981
6178
  "button",
5982
6179
  {
5983
6180
  type: "button",
5984
6181
  className: "tf-checkout-auth__text-button tf-checkout-auth__forgot",
5985
6182
  onClick: () => onForgotPassword(email)
5986
6183
  },
5987
- "Forgot password?"
6184
+ t("auth.forgotPassword")
5988
6185
  ));
5989
6186
  };
5990
6187
 
@@ -6211,7 +6408,7 @@ var RegisterForm = ({
6211
6408
  invalid: Boolean(errors.stateId),
6212
6409
  onChange: (event) => setField("stateId", event.target.value)
6213
6410
  },
6214
- /* @__PURE__ */ import_react22.default.createElement("option", { value: "" }, states.length > 0 ? "Select state / region" : "Not required"),
6411
+ /* @__PURE__ */ import_react22.default.createElement("option", { value: "" }, states.length > 0 ? t("auth.selectState") : t("auth.notRequired")),
6215
6412
  states.map((state) => /* @__PURE__ */ import_react22.default.createElement("option", { key: state.id, value: state.id }, state.name))
6216
6413
  )
6217
6414
  ), /* @__PURE__ */ import_react22.default.createElement(
@@ -6305,7 +6502,7 @@ var RegisterForm = ({
6305
6502
  }
6306
6503
  )
6307
6504
  )),
6308
- /* @__PURE__ */ import_react22.default.createElement(Button, { type: "submit", block: true, loading }, "Create Account")
6505
+ /* @__PURE__ */ import_react22.default.createElement(Button, { type: "submit", block: true, loading }, t("auth.createAccount"))
6309
6506
  );
6310
6507
  };
6311
6508
 
@@ -6344,6 +6541,8 @@ var AuthModal = ({
6344
6541
  const previouslyFocused = (0, import_react23.useRef)(null);
6345
6542
  const submittingRef = (0, import_react23.useRef)(auth.isSubmitting);
6346
6543
  submittingRef.current = auth.isSubmitting;
6544
+ const onCloseRef = (0, import_react23.useRef)(onClose);
6545
+ onCloseRef.current = onClose;
6347
6546
  (0, import_react23.useEffect)(() => {
6348
6547
  var _a, _b, _c;
6349
6548
  if (!open) return;
@@ -6364,7 +6563,7 @@ var AuthModal = ({
6364
6563
  initialFocus == null ? void 0 : initialFocus.focus();
6365
6564
  const onKeyDown = (event) => {
6366
6565
  var _a2;
6367
- if (event.key === "Escape" && !submittingRef.current) onClose();
6566
+ if (event.key === "Escape" && !submittingRef.current) onCloseRef.current();
6368
6567
  if (event.key !== "Tab") return;
6369
6568
  const elements = focusable();
6370
6569
  if (elements.length === 0) {
@@ -6389,13 +6588,13 @@ var AuthModal = ({
6389
6588
  document.body.style.overflow = previousOverflow;
6390
6589
  (_a2 = previouslyFocused.current) == null ? void 0 : _a2.focus();
6391
6590
  };
6392
- }, [onClose, open]);
6591
+ }, [open]);
6393
6592
  if (!open) return null;
6394
6593
  const closeFromBackdrop = (event) => {
6395
6594
  if (event.target === event.currentTarget && !auth.isSubmitting) onClose();
6396
6595
  };
6397
6596
  const isPasswordReset = auth.view === "forgot-password";
6398
- const title = isPasswordReset ? "Password reset" : "Ticket Fairy account";
6597
+ const title = isPasswordReset ? t("auth.passwordReset") : t("auth.title");
6399
6598
  return /* @__PURE__ */ import_react23.default.createElement("div", { className: cx("tf-checkout-auth", className), onMouseDown: closeFromBackdrop }, /* @__PURE__ */ import_react23.default.createElement(
6400
6599
  "div",
6401
6600
  {
@@ -6437,7 +6636,7 @@ var AuthModal = ({
6437
6636
  ),
6438
6637
  onClick: () => auth.showLogin(auth.suggestedEmail)
6439
6638
  },
6440
- "Login"
6639
+ t("auth.logIn")
6441
6640
  ),
6442
6641
  /* @__PURE__ */ import_react23.default.createElement(
6443
6642
  "button",
@@ -6451,7 +6650,7 @@ var AuthModal = ({
6451
6650
  ),
6452
6651
  onClick: () => auth.showRegister(auth.suggestedEmail)
6453
6652
  },
6454
- "Sign Up"
6653
+ t("auth.signUp")
6455
6654
  )
6456
6655
  ),
6457
6656
  logoUrl && /* @__PURE__ */ import_react23.default.createElement("div", { className: "tf-checkout-auth__logo-wrap" }, /* @__PURE__ */ import_react23.default.createElement(
@@ -6520,9 +6719,9 @@ var ResetPasswordForm = ({
6520
6719
  const validation = (0, import_react24.useMemo)(() => {
6521
6720
  if (!submitted) return {};
6522
6721
  return {
6523
- token: token ? "" : "This password-reset link is missing its token.",
6524
- password: password.length < 8 ? "Password must have at least 8 characters." : !/[@$!%*#?&]/.test(password) ? "Password must contain at least one special character." : "",
6525
- confirmation: password !== confirmation ? "Passwords must match." : ""
6722
+ token: token ? "" : t("auth.missingToken"),
6723
+ password: password.length < 8 ? t("auth.passwordTooShort") : !/[@$!%*#?&]/.test(password) ? t("auth.passwordNeedsSpecial") : "",
6724
+ confirmation: password !== confirmation ? t("auth.passwordsMustMatch") : ""
6526
6725
  };
6527
6726
  }, [confirmation, password, submitted, token]);
6528
6727
  const reset = hooks_exports.useResetPassword({
@@ -6539,7 +6738,7 @@ var ResetPasswordForm = ({
6539
6738
  reset.mutate({ token, password, passwordConfirmation: confirmation });
6540
6739
  };
6541
6740
  if (success) {
6542
- return /* @__PURE__ */ import_react24.default.createElement("div", { className: "tf-checkout-auth__form" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "tf-checkout-auth__success", role: "status" }, "Your password has been changed. You can now log in."), onBackToLogin && /* @__PURE__ */ import_react24.default.createElement(Button, { type: "button", block: true, onClick: onBackToLogin }, "Log in"));
6741
+ return /* @__PURE__ */ import_react24.default.createElement("div", { className: "tf-checkout-auth__form" }, /* @__PURE__ */ import_react24.default.createElement("div", { className: "tf-checkout-auth__success", role: "status" }, t("auth.passwordChanged")), onBackToLogin && /* @__PURE__ */ import_react24.default.createElement(Button, { type: "button", block: true, onClick: onBackToLogin }, t("auth.logIn")));
6543
6742
  }
6544
6743
  return /* @__PURE__ */ import_react24.default.createElement("form", { className: "tf-checkout-auth__form", onSubmit: submit, noValidate: true }, /* @__PURE__ */ import_react24.default.createElement("h2", { className: "tf-checkout-auth__title" }, t("auth.changePassword")), validation.token && /* @__PURE__ */ import_react24.default.createElement("div", { className: "tf-checkout-auth__alert", role: "alert" }, validation.token), reset.error && /* @__PURE__ */ import_react24.default.createElement("div", { className: "tf-checkout-auth__alert", role: "alert" }, errorMessage(reset.error)), /* @__PURE__ */ import_react24.default.createElement(Field, { label: t("auth.newPassword"), error: validation.password }, /* @__PURE__ */ import_react24.default.createElement(
6545
6744
  Input,
@@ -6563,7 +6762,7 @@ var ResetPasswordForm = ({
6563
6762
  invalid: Boolean(validation.confirmation),
6564
6763
  onChange: (event) => setConfirmation(event.target.value)
6565
6764
  }
6566
- )), /* @__PURE__ */ import_react24.default.createElement(Button, { type: "submit", block: true, loading: reset.isPending, disabled: !token }, "Submit"));
6765
+ )), /* @__PURE__ */ import_react24.default.createElement(Button, { type: "submit", block: true, loading: reset.isPending, disabled: !token }, t("common.submit")));
6567
6766
  };
6568
6767
 
6569
6768
  // src/sections/Tickets.tsx
@@ -6618,7 +6817,7 @@ var Tickets = ({
6618
6817
  eventId,
6619
6818
  title = false,
6620
6819
  onContinue,
6621
- buttonLabel = "Get tickets",
6820
+ buttonLabel,
6622
6821
  timeSlotDates,
6623
6822
  step,
6624
6823
  onSelectSeats,
@@ -6628,7 +6827,9 @@ var Tickets = ({
6628
6827
  className
6629
6828
  }) => {
6630
6829
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
6830
+ const tr = useT();
6631
6831
  const checkout = useCheckoutContext();
6832
+ const buttonText = buttonLabel != null ? buttonLabel : tr("tickets.getTickets");
6632
6833
  const ticketsQuery = hooks_exports.useTicketsWithMeta(eventId);
6633
6834
  const promoMeta = (_a = ticketsQuery.data) == null ? void 0 : _a.promo;
6634
6835
  const showWaitingList = (_c = (_b = ticketsQuery.data) == null ? void 0 : _b.showWaitingList) != null ? _c : false;
@@ -6714,7 +6915,7 @@ var Tickets = ({
6714
6915
  const seatMapRow = (t) => isSeated && !t.allowDirectPurchase;
6715
6916
  const hasSeatMapTickets = tickets.some(seatMapRow);
6716
6917
  const directPurchasable = tickets.filter((t) => !seatMapRow(t));
6717
- const seatCtaLabel = (eventInfo == null ? void 0 : eventInfo.tableMapEnabled) ? "Select on map" : "Select seats";
6918
+ const seatCtaLabel = (eventInfo == null ? void 0 : eventInfo.tableMapEnabled) ? tr("tickets.selectOnMap") : tr("tickets.selectSeats");
6718
6919
  const firstTableIndex = tickets.findIndex((t) => t.isTable);
6719
6920
  const firstTableId = firstTableIndex > 0 && tickets.slice(0, firstTableIndex).some((t) => !t.isTable) ? tickets[firstTableIndex].id : void 0;
6720
6921
  const prime = () => {
@@ -6747,7 +6948,7 @@ var Tickets = ({
6747
6948
  const ticketIndex = tickets.findIndex((candidate) => candidate.id === t.id);
6748
6949
  const previousTicket = ticketIndex > 0 ? tickets[ticketIndex - 1] : void 0;
6749
6950
  const startsNamedGroup = Boolean(t.groupName) && t.groupName !== (previousTicket == null ? void 0 : previousTicket.groupName);
6750
- return /* @__PURE__ */ import_react25.default.createElement(import_react25.Fragment, { key: t.id }, startsNamedGroup ? /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__group" }, t.groupName) : t.id === firstTableId && /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__group" }, "Reserve tables"), /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__row-wrap" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__row" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__info" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__name" }, /* @__PURE__ */ import_react25.default.createElement("span", null, t.name), t.descriptionRich && /* @__PURE__ */ import_react25.default.createElement(
6951
+ return /* @__PURE__ */ import_react25.default.createElement(import_react25.Fragment, { key: t.id }, startsNamedGroup ? /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__group" }, t.groupName) : t.id === firstTableId && /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__group" }, tr("tickets.reserveTables")), /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__row-wrap" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__row" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__info" }, /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__name" }, /* @__PURE__ */ import_react25.default.createElement("span", null, t.name), t.descriptionRich && /* @__PURE__ */ import_react25.default.createElement(
6751
6952
  "button",
6752
6953
  {
6753
6954
  type: "button",
@@ -6756,7 +6957,7 @@ var Tickets = ({
6756
6957
  "aria-controls": `ticket-description-${t.id}`,
6757
6958
  onClick: () => setVisibleDescription((current2) => current2 === t.id ? null : t.id)
6758
6959
  },
6759
- visibleDescription === t.id ? "Hide info" : "View info"
6960
+ visibleDescription === t.id ? tr("tickets.hideInfo") : tr("tickets.viewInfo")
6760
6961
  )), /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__price" }, discounted && /* @__PURE__ */ import_react25.default.createElement("span", { className: "tf-checkout-tickets__old" }, money(sym, original)), /* @__PURE__ */ import_react25.default.createElement(
6761
6962
  "span",
6762
6963
  {
@@ -6766,7 +6967,7 @@ var Tickets = ({
6766
6967
  )
6767
6968
  },
6768
6969
  isFree ? "FREE" : money(sym, t.price)
6769
- ), !isFree && !t.soldOut && /* @__PURE__ */ import_react25.default.createElement("span", { className: "tf-checkout-tickets__fees" }, "(", money(sym, t.priceWithFees), " with fees)"), t.depositPercent != null && /* @__PURE__ */ import_react25.default.createElement("span", { className: "tf-checkout-tickets__deposit" }, t.depositPercent.toFixed(2), "% DEPOSIT"))), seatMapRow(t) ? null : unavailable ? /* @__PURE__ */ import_react25.default.createElement("span", { className: "tf-checkout-tickets__soldout" }, t.soldOut ? "Sold out" : notStarted ? "Sales not started" : "Sales Ended") : /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__qty" }, t.isTable && /* @__PURE__ */ import_react25.default.createElement("span", { className: "tf-checkout-tickets__guests" }, "Guests"), /* @__PURE__ */ import_react25.default.createElement(
6970
+ ), !isFree && !t.soldOut && /* @__PURE__ */ import_react25.default.createElement("span", { className: "tf-checkout-tickets__fees" }, "(", money(sym, t.priceWithFees), " with fees)"), t.depositPercent != null && /* @__PURE__ */ import_react25.default.createElement("span", { className: "tf-checkout-tickets__deposit" }, t.depositPercent.toFixed(2), "% DEPOSIT"))), seatMapRow(t) ? null : unavailable ? /* @__PURE__ */ import_react25.default.createElement("span", { className: "tf-checkout-tickets__soldout" }, t.soldOut ? tr("tickets.soldOut") : notStarted ? tr("tickets.salesNotStarted") : tr("tickets.salesEnded")) : /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__qty" }, t.isTable && /* @__PURE__ */ import_react25.default.createElement("span", { className: "tf-checkout-tickets__guests" }, tr("tickets.guests")), /* @__PURE__ */ import_react25.default.createElement(
6770
6971
  QuantitySelect,
6771
6972
  {
6772
6973
  value: (_a2 = qty[t.id]) != null ? _a2 : 0,
@@ -6813,7 +7014,7 @@ var Tickets = ({
6813
7014
  title: title || "",
6814
7015
  pills: listQuery.isFetching && !listQuery.isLoading ? /* @__PURE__ */ import_react25.default.createElement(Loader, null) : void 0
6815
7016
  }
6816
- ), listQuery.isLoading && /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__loading" }, /* @__PURE__ */ import_react25.default.createElement(Loader, { className: "tf-checkout-tickets__loading-spinner" })), listQuery.error && /* @__PURE__ */ import_react25.default.createElement("p", { className: "tf-checkout-error-text" }, listQuery.error.message), isTimeSlot && dates.length > 0 && /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__currency" }, /* @__PURE__ */ import_react25.default.createElement("span", { className: "tf-checkout-tickets__currency-label" }, "Date"), /* @__PURE__ */ import_react25.default.createElement(
7017
+ ), listQuery.isLoading && /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__loading" }, /* @__PURE__ */ import_react25.default.createElement(Loader, { className: "tf-checkout-tickets__loading-spinner" })), listQuery.error && /* @__PURE__ */ import_react25.default.createElement("p", { className: "tf-checkout-error-text" }, listQuery.error.message), isTimeSlot && dates.length > 0 && /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__currency" }, /* @__PURE__ */ import_react25.default.createElement("span", { className: "tf-checkout-tickets__currency-label" }, tr("common.date")), /* @__PURE__ */ import_react25.default.createElement(
6817
7018
  "select",
6818
7019
  {
6819
7020
  className: "tf-checkout-select",
@@ -6824,7 +7025,7 @@ var Tickets = ({
6824
7025
  }
6825
7026
  },
6826
7027
  dates.map((d) => /* @__PURE__ */ import_react25.default.createElement("option", { key: d, value: d }, d))
6827
- )), checkout.currency && checkout.currency.available.length > 1 && /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__currency" }, /* @__PURE__ */ import_react25.default.createElement("span", { className: "tf-checkout-tickets__currency-label" }, "Currency"), /* @__PURE__ */ import_react25.default.createElement(
7028
+ )), checkout.currency && checkout.currency.available.length > 1 && /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__currency" }, /* @__PURE__ */ import_react25.default.createElement("span", { className: "tf-checkout-tickets__currency-label" }, tr("common.currency")), /* @__PURE__ */ import_react25.default.createElement(
6828
7029
  "select",
6829
7030
  {
6830
7031
  className: "tf-checkout-select",
@@ -6832,7 +7033,7 @@ var Tickets = ({
6832
7033
  onChange: (e) => changeCurrency(e.target.value)
6833
7034
  },
6834
7035
  checkout.currency.available.map((c) => /* @__PURE__ */ import_react25.default.createElement("option", { key: c.code, value: c.code }, c.name, " (", c.code, ")"))
6835
- )), isTimeSlot && !slotQuery.isLoading && tickets.length === 0 && slotDate && /* @__PURE__ */ import_react25.default.createElement("p", { className: "tf-checkout-note" }, "No sessions available on this date."), isTimeSlot ? timeGroups.map((g) => /* @__PURE__ */ import_react25.default.createElement(import_react25.Fragment, { key: g.time }, g.time && /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__slot-time" }, g.time), g.items.map(renderRow))) : tickets.map(renderRow), showCodeInput && /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__promo" }, !isAccess && !promoOpen ? /* @__PURE__ */ import_react25.default.createElement(
7036
+ )), isTimeSlot && !slotQuery.isLoading && tickets.length === 0 && slotDate && /* @__PURE__ */ import_react25.default.createElement("p", { className: "tf-checkout-note" }, tr("tickets.noSessions")), isTimeSlot ? timeGroups.map((g) => /* @__PURE__ */ import_react25.default.createElement(import_react25.Fragment, { key: g.time }, g.time && /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__slot-time" }, g.time), g.items.map(renderRow))) : tickets.map(renderRow), showCodeInput && /* @__PURE__ */ import_react25.default.createElement("div", { className: "tf-checkout-tickets__promo" }, !isAccess && !promoOpen ? /* @__PURE__ */ import_react25.default.createElement(
6836
7037
  "button",
6837
7038
  {
6838
7039
  type: "button",
@@ -6843,7 +7044,7 @@ var Tickets = ({
6843
7044
  ) : /* @__PURE__ */ import_react25.default.createElement(import_react25.default.Fragment, null, /* @__PURE__ */ import_react25.default.createElement(FieldRow, null, /* @__PURE__ */ import_react25.default.createElement(Field, null, /* @__PURE__ */ import_react25.default.createElement(
6844
7045
  Input,
6845
7046
  {
6846
- placeholder: isAccess ? "Access code" : "Promo code",
7047
+ placeholder: isAccess ? tr("tickets.accessCode") : tr("tickets.promoCode"),
6847
7048
  value: code,
6848
7049
  onChange: (e) => setCode(e.target.value),
6849
7050
  onKeyDown: (e) => e.key === "Enter" && applyCode()
@@ -6874,7 +7075,7 @@ var Tickets = ({
6874
7075
  loading: checkout.isBusy,
6875
7076
  disabled: checkout.isBusy || selected.length === 0
6876
7077
  },
6877
- checkout.isBusy ? "Reserving\u2026" : selectionIsTable ? "Reserve tables" : buttonLabel
7078
+ checkout.isBusy ? tr("tickets.reserving") : selectionIsTable ? tr("tickets.reserveTables") : buttonText
6878
7079
  ), hasSeatMapTickets && /* @__PURE__ */ import_react25.default.createElement(Button, { block: true, onClick: () => onSelectSeats == null ? void 0 : onSelectSeats() }, seatCtaLabel), (error || checkout.error) && /* @__PURE__ */ import_react25.default.createElement("p", { className: "tf-checkout-error-text" }, error || checkout.error));
6879
7080
  };
6880
7081
 
@@ -7235,13 +7436,17 @@ var AddOns = ({
7235
7436
  eventId,
7236
7437
  onContinue,
7237
7438
  onSkip,
7238
- buttonLabel = "CONFIRM SELECTION",
7239
- eyebrow = "Get Your Tickets",
7240
- heading = "UPGRADES & ADD-ONS",
7439
+ buttonLabel,
7440
+ eyebrow,
7441
+ heading,
7241
7442
  className
7242
7443
  }) => {
7243
7444
  var _a, _b, _c, _d, _e, _f, _g, _h;
7445
+ const t = useT();
7244
7446
  const checkout = useCheckoutContext();
7447
+ const buttonText = buttonLabel != null ? buttonLabel : t("addons.confirmSelection");
7448
+ const eyebrowText = eyebrow != null ? eyebrow : t("addons.eyebrow");
7449
+ const headingText = heading != null ? heading : t("addons.heading");
7245
7450
  const combined = !onContinue;
7246
7451
  const addonsQuery = hooks_exports.useEventAddons(eventId);
7247
7452
  const all = (_a = addonsQuery.data) != null ? _a : [];
@@ -7271,14 +7476,14 @@ var AddOns = ({
7271
7476
  return ((_a3 = selection[id]) != null ? _a3 : 0) > 0;
7272
7477
  })
7273
7478
  );
7274
- const t = setTimeout(() => {
7479
+ const t2 = setTimeout(() => {
7275
7480
  checkout.setAddonDataCapture(captureForSelected);
7276
7481
  checkout.setAddons(selection).catch((e) => setError(errorMessage(e)));
7277
7482
  }, 500);
7278
- return () => clearTimeout(t);
7483
+ return () => clearTimeout(t2);
7279
7484
  }, [combined, qty, capture]);
7280
7485
  const hasRequired = ((_f = checkout.requiredAddOns) != null ? _f : []).some((a) => a.required);
7281
- const head = /* @__PURE__ */ import_react27.default.createElement("div", { className: "tf-checkout-addons__head" }, eyebrow && /* @__PURE__ */ import_react27.default.createElement("span", { className: "tf-checkout-addons__eyebrow" }, eyebrow), /* @__PURE__ */ import_react27.default.createElement("span", { className: "tf-checkout-addons__heading" }, heading), onSkip && !hasRequired && /* @__PURE__ */ import_react27.default.createElement("button", { type: "button", className: "tf-checkout-addons__skip", onClick: onSkip }, "Skip"));
7486
+ const head = /* @__PURE__ */ import_react27.default.createElement("div", { className: "tf-checkout-addons__head" }, eyebrowText && /* @__PURE__ */ import_react27.default.createElement("span", { className: "tf-checkout-addons__eyebrow" }, eyebrowText), /* @__PURE__ */ import_react27.default.createElement("span", { className: "tf-checkout-addons__heading" }, headingText), onSkip && !hasRequired && /* @__PURE__ */ import_react27.default.createElement("button", { type: "button", className: "tf-checkout-addons__skip", onClick: onSkip }, "Skip"));
7282
7487
  if (addonsQuery.isLoading) {
7283
7488
  return /* @__PURE__ */ import_react27.default.createElement(Card, { className }, head, /* @__PURE__ */ import_react27.default.createElement("div", { className: "tf-checkout-section-loader" }, /* @__PURE__ */ import_react27.default.createElement(Loader, null)));
7284
7489
  }
@@ -7325,7 +7530,7 @@ var AddOns = ({
7325
7530
  className: "tf-checkout-addons__desc",
7326
7531
  dangerouslySetInnerHTML: { __html: a.description }
7327
7532
  }
7328
- )), soldOut(a) ? /* @__PURE__ */ import_react27.default.createElement("span", { className: "tf-checkout-tickets__soldout" }, "Sold out") : /* @__PURE__ */ import_react27.default.createElement(
7533
+ )), soldOut(a) ? /* @__PURE__ */ import_react27.default.createElement("span", { className: "tf-checkout-tickets__soldout" }, t("tickets.soldOut")) : /* @__PURE__ */ import_react27.default.createElement(
7329
7534
  QuantitySelect,
7330
7535
  {
7331
7536
  value: n,
@@ -7356,7 +7561,7 @@ var AddOns = ({
7356
7561
  loading: checkout.isBusy,
7357
7562
  disabled: checkout.isBusy || selectedCount === 0
7358
7563
  },
7359
- checkout.isBusy ? "Updating\u2026" : buttonLabel
7564
+ checkout.isBusy ? t("addons.updating") : buttonText
7360
7565
  ), missing.length > 0 && /* @__PURE__ */ import_react27.default.createElement("p", { className: "tf-checkout-note" }, "Required add-on: ", missing.join(", "), "."), (error || checkout.error) && /* @__PURE__ */ import_react27.default.createElement("p", { className: "tf-checkout-error-text" }, error || checkout.error));
7361
7566
  };
7362
7567
 
@@ -7374,17 +7579,18 @@ var BillingAddressFields = ({
7374
7579
  setBilling
7375
7580
  }) => {
7376
7581
  var _a, _b, _c, _d, _e;
7582
+ const t = useT();
7377
7583
  const setValue = (key) => (event) => setBilling((current2) => ({ ...current2, [key]: event.target.value }));
7378
- return /* @__PURE__ */ import_react28.default.createElement(import_react28.default.Fragment, null, /* @__PURE__ */ import_react28.default.createElement("div", { className: "tf-checkout-billing__section-label" }, "Billing address *"), /* @__PURE__ */ import_react28.default.createElement(
7584
+ return /* @__PURE__ */ import_react28.default.createElement(import_react28.default.Fragment, null, /* @__PURE__ */ import_react28.default.createElement("div", { className: "tf-checkout-billing__section-label" }, t("billing.address")), /* @__PURE__ */ import_react28.default.createElement(
7379
7585
  Field,
7380
7586
  {
7381
- error: fieldError("Street address", "Street address is required."),
7587
+ error: fieldError("Street address", t("billing.streetRequired")),
7382
7588
  invalid: Boolean(fieldError("Street address"))
7383
7589
  },
7384
7590
  /* @__PURE__ */ import_react28.default.createElement(
7385
7591
  Input,
7386
7592
  {
7387
- placeholder: "Street address *",
7593
+ placeholder: t("billing.streetPlaceholder"),
7388
7594
  autoComplete: "street-address",
7389
7595
  value: (_a = billing.streetAddress) != null ? _a : "",
7390
7596
  required: true,
@@ -7396,13 +7602,13 @@ var BillingAddressFields = ({
7396
7602
  ), /* @__PURE__ */ import_react28.default.createElement(FieldRow, null, /* @__PURE__ */ import_react28.default.createElement(
7397
7603
  Field,
7398
7604
  {
7399
- error: fieldError("City", "City is required."),
7605
+ error: fieldError("City", t("billing.cityRequired")),
7400
7606
  invalid: Boolean(fieldError("City"))
7401
7607
  },
7402
7608
  /* @__PURE__ */ import_react28.default.createElement(
7403
7609
  Input,
7404
7610
  {
7405
- placeholder: "City *",
7611
+ placeholder: t("billing.cityPlaceholder"),
7406
7612
  autoComplete: "address-level2",
7407
7613
  value: (_b = billing.city) != null ? _b : "",
7408
7614
  required: true,
@@ -7414,13 +7620,13 @@ var BillingAddressFields = ({
7414
7620
  ), /* @__PURE__ */ import_react28.default.createElement(
7415
7621
  Field,
7416
7622
  {
7417
- error: fieldError("ZIP / postcode", "ZIP / postcode is required."),
7623
+ error: fieldError("ZIP / postcode", t("billing.postcodeRequired")),
7418
7624
  invalid: Boolean(fieldError("ZIP / postcode"))
7419
7625
  },
7420
7626
  /* @__PURE__ */ import_react28.default.createElement(
7421
7627
  Input,
7422
7628
  {
7423
- placeholder: "ZIP / Postcode *",
7629
+ placeholder: t("billing.postcodePlaceholder"),
7424
7630
  autoComplete: "postal-code",
7425
7631
  value: (_c = billing.zip) != null ? _c : "",
7426
7632
  required: true,
@@ -7432,14 +7638,14 @@ var BillingAddressFields = ({
7432
7638
  )), /* @__PURE__ */ import_react28.default.createElement(FieldRow, null, /* @__PURE__ */ import_react28.default.createElement(
7433
7639
  Field,
7434
7640
  {
7435
- error: fieldError("Country", "Country is required."),
7641
+ error: fieldError("Country", t("billing.countryRequired")),
7436
7642
  invalid: Boolean(fieldError("Country"))
7437
7643
  },
7438
7644
  /* @__PURE__ */ import_react28.default.createElement(
7439
7645
  Select,
7440
7646
  {
7441
7647
  value: (_d = billing.countryId) != null ? _d : "",
7442
- "aria-label": "Country",
7648
+ "aria-label": t("billing.countryLabel"),
7443
7649
  required: true,
7444
7650
  invalid: Boolean(fieldError("Country")),
7445
7651
  "aria-invalid": Boolean(fieldError("Country")),
@@ -7459,13 +7665,13 @@ var BillingAddressFields = ({
7459
7665
  });
7460
7666
  }
7461
7667
  },
7462
- /* @__PURE__ */ import_react28.default.createElement("option", { value: "" }, "\u2014 country * \u2014"),
7668
+ /* @__PURE__ */ import_react28.default.createElement("option", { value: "" }, t("billing.countryEmpty")),
7463
7669
  countries.map((country) => /* @__PURE__ */ import_react28.default.createElement("option", { key: country.id, value: country.id }, country.name))
7464
7670
  )
7465
7671
  ), /* @__PURE__ */ import_react28.default.createElement(
7466
7672
  Field,
7467
7673
  {
7468
- error: fieldError("State / county", "State / county is required."),
7674
+ error: fieldError("State / county", t("billing.stateRequired")),
7469
7675
  invalid: Boolean(fieldError("State / county"))
7470
7676
  },
7471
7677
  /* @__PURE__ */ import_react28.default.createElement(
@@ -7473,7 +7679,7 @@ var BillingAddressFields = ({
7473
7679
  {
7474
7680
  value: (_e = billing.stateId) != null ? _e : "",
7475
7681
  disabled: !billing.countryId || states.length === 0,
7476
- "aria-label": "State / region",
7682
+ "aria-label": t("billing.stateLabel"),
7477
7683
  required: states.length > 0,
7478
7684
  invalid: Boolean(fieldError("State / county")),
7479
7685
  "aria-invalid": Boolean(fieldError("State / county")),
@@ -7488,7 +7694,7 @@ var BillingAddressFields = ({
7488
7694
  }));
7489
7695
  }
7490
7696
  },
7491
- /* @__PURE__ */ import_react28.default.createElement("option", { value: "" }, "\u2014 state / county", states.length > 0 ? " *" : "", " \u2014"),
7697
+ /* @__PURE__ */ import_react28.default.createElement("option", { value: "" }, states.length > 0 ? t("billing.stateEmptyRequired") : t("billing.stateEmpty")),
7492
7698
  states.map((state) => /* @__PURE__ */ import_react28.default.createElement("option", { key: state.id, value: state.id }, state.name))
7493
7699
  )
7494
7700
  )));
@@ -7544,6 +7750,19 @@ var BuyerField = ({
7544
7750
  ));
7545
7751
  };
7546
7752
 
7753
+ // src/sections/billing/fieldRules.ts
7754
+ var isBlankPhone = (phone) => !phone || /^\+?\d{0,4}$/.test(phone.trim());
7755
+ var DOB_MIN = "1900-01-01";
7756
+ var todayISO = () => {
7757
+ const now = /* @__PURE__ */ new Date();
7758
+ return [
7759
+ now.getFullYear(),
7760
+ String(now.getMonth() + 1).padStart(2, "0"),
7761
+ String(now.getDate()).padStart(2, "0")
7762
+ ].join("-");
7763
+ };
7764
+ var toDateInputValue = (year, month, day) => year && month && day ? `${year}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}` : void 0;
7765
+
7547
7766
  // src/sections/billing/TicketHoldersCard.tsx
7548
7767
  var import_react30 = __toESM(require("react"));
7549
7768
  var import_react_international_phone2 = require("react-international-phone");
@@ -7555,112 +7774,121 @@ var TicketHoldersCard = ({
7555
7774
  fieldError,
7556
7775
  renderCustomFields,
7557
7776
  patchHolder
7558
- }) => /* @__PURE__ */ import_react30.default.createElement(Card, { className: "tf-checkout-billing__holders-card" }, /* @__PURE__ */ import_react30.default.createElement(SectionHeader, { title: "Ticket Holders" }), holders.map((holder, index) => {
7559
- const firstNameKey = `Ticket ${index + 1} holder first name`;
7560
- const lastNameKey = `Ticket ${index + 1} holder last name`;
7561
- const emailKey = `Ticket ${index + 1} holder email`;
7562
- const phoneKey = `Ticket ${index + 1} holder phone`;
7563
- return /* @__PURE__ */ import_react30.default.createElement("div", { key: index, className: "tf-checkout-billing__holder" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "tf-checkout-billing__holder-title" }, "Ticket ", index + 1), holderNamesRequired && /* @__PURE__ */ import_react30.default.createElement(FieldRow, null, /* @__PURE__ */ import_react30.default.createElement(
7564
- Field,
7565
- {
7566
- label: "First Name *",
7567
- error: fieldError(firstNameKey, "First name is required."),
7568
- invalid: Boolean(fieldError(firstNameKey))
7569
- },
7570
- /* @__PURE__ */ import_react30.default.createElement(
7571
- Input,
7777
+ }) => {
7778
+ const t = useT();
7779
+ return /* @__PURE__ */ import_react30.default.createElement(Card, { className: "tf-checkout-billing__holders-card" }, /* @__PURE__ */ import_react30.default.createElement(SectionHeader, { title: t("billing.ticketHolders") }), holders.map((holder, index) => {
7780
+ const firstNameKey = `Ticket ${index + 1} holder first name`;
7781
+ const lastNameKey = `Ticket ${index + 1} holder last name`;
7782
+ const emailKey = `Ticket ${index + 1} holder email`;
7783
+ const phoneKey = `Ticket ${index + 1} holder phone`;
7784
+ return /* @__PURE__ */ import_react30.default.createElement("div", { key: index, className: "tf-checkout-billing__holder" }, /* @__PURE__ */ import_react30.default.createElement("div", { className: "tf-checkout-billing__holder-title" }, t("billing.holderTitle", { number: index + 1 })), holderNamesRequired && /* @__PURE__ */ import_react30.default.createElement(FieldRow, null, /* @__PURE__ */ import_react30.default.createElement(
7785
+ Field,
7572
7786
  {
7573
- value: holder.firstName,
7574
- required: true,
7575
- invalid: Boolean(fieldError(firstNameKey)),
7576
- "aria-invalid": Boolean(fieldError(firstNameKey)),
7577
- onChange: (event) => patchHolder(index, { firstName: event.target.value })
7578
- }
7579
- )
7580
- ), /* @__PURE__ */ import_react30.default.createElement(
7581
- Field,
7582
- {
7583
- label: "Last Name *",
7584
- error: fieldError(lastNameKey, "Last name is required."),
7585
- invalid: Boolean(fieldError(lastNameKey))
7586
- },
7587
- /* @__PURE__ */ import_react30.default.createElement(
7588
- Input,
7787
+ label: t("billing.holderFirstName"),
7788
+ error: fieldError(firstNameKey, t("billing.firstNameRequired")),
7789
+ invalid: Boolean(fieldError(firstNameKey))
7790
+ },
7791
+ /* @__PURE__ */ import_react30.default.createElement(
7792
+ Input,
7793
+ {
7794
+ value: holder.firstName,
7795
+ required: true,
7796
+ invalid: Boolean(fieldError(firstNameKey)),
7797
+ "aria-invalid": Boolean(fieldError(firstNameKey)),
7798
+ onChange: (event) => patchHolder(index, { firstName: event.target.value })
7799
+ }
7800
+ )
7801
+ ), /* @__PURE__ */ import_react30.default.createElement(
7802
+ Field,
7589
7803
  {
7590
- value: holder.lastName,
7591
- required: true,
7592
- invalid: Boolean(fieldError(lastNameKey)),
7593
- "aria-invalid": Boolean(fieldError(lastNameKey)),
7594
- onChange: (event) => patchHolder(index, { lastName: event.target.value })
7595
- }
7596
- )
7597
- )), collectHolderContact && /* @__PURE__ */ import_react30.default.createElement(FieldRow, null, /* @__PURE__ */ import_react30.default.createElement(
7598
- Field,
7599
- {
7600
- label: "Email Address *",
7601
- error: fieldError(emailKey, "Enter a valid email address."),
7602
- invalid: Boolean(fieldError(emailKey))
7603
- },
7604
- /* @__PURE__ */ import_react30.default.createElement(
7605
- Input,
7804
+ label: t("billing.holderLastName"),
7805
+ error: fieldError(lastNameKey, t("billing.lastNameRequired")),
7806
+ invalid: Boolean(fieldError(lastNameKey))
7807
+ },
7808
+ /* @__PURE__ */ import_react30.default.createElement(
7809
+ Input,
7810
+ {
7811
+ value: holder.lastName,
7812
+ required: true,
7813
+ invalid: Boolean(fieldError(lastNameKey)),
7814
+ "aria-invalid": Boolean(fieldError(lastNameKey)),
7815
+ onChange: (event) => patchHolder(index, { lastName: event.target.value })
7816
+ }
7817
+ )
7818
+ )), collectHolderContact && /* @__PURE__ */ import_react30.default.createElement(FieldRow, null, /* @__PURE__ */ import_react30.default.createElement(
7819
+ Field,
7606
7820
  {
7607
- type: "email",
7608
- autoComplete: "email",
7609
- value: holder.email,
7610
- required: true,
7611
- invalid: Boolean(fieldError(emailKey)),
7612
- "aria-invalid": Boolean(fieldError(emailKey)),
7613
- onChange: (event) => patchHolder(index, { email: event.target.value })
7614
- }
7615
- )
7616
- ), /* @__PURE__ */ import_react30.default.createElement(
7617
- Field,
7618
- {
7619
- label: "Phone *",
7620
- error: fieldError(phoneKey, "Enter a valid phone number."),
7621
- invalid: Boolean(fieldError(phoneKey))
7622
- },
7623
- /* @__PURE__ */ import_react30.default.createElement(
7624
- import_react_international_phone2.PhoneInput,
7821
+ label: t("billing.email"),
7822
+ error: fieldError(emailKey, t("billing.emailInvalid")),
7823
+ invalid: Boolean(fieldError(emailKey))
7824
+ },
7825
+ /* @__PURE__ */ import_react30.default.createElement(
7826
+ Input,
7827
+ {
7828
+ type: "email",
7829
+ autoComplete: "email",
7830
+ value: holder.email,
7831
+ required: true,
7832
+ invalid: Boolean(fieldError(emailKey)),
7833
+ "aria-invalid": Boolean(fieldError(emailKey)),
7834
+ onChange: (event) => patchHolder(index, { email: event.target.value })
7835
+ }
7836
+ )
7837
+ ), /* @__PURE__ */ import_react30.default.createElement(
7838
+ Field,
7625
7839
  {
7626
- className: "tf-checkout-phone",
7627
- inputClassName: `tf-checkout-input tf-checkout-phone__input${fieldError(phoneKey) ? " tf-checkout-input--invalid" : ""}`,
7628
- defaultCountry: phoneCountry,
7629
- disableDialCodePrefill: true,
7630
- value: holder.phone,
7631
- required: true,
7632
- inputProps: {
7633
- autoComplete: "tel",
7634
- "aria-label": phoneKey,
7635
- "aria-invalid": Boolean(fieldError(phoneKey))
7636
- },
7637
- onChange: (phone) => patchHolder(index, { phone })
7638
- }
7639
- )
7640
- )), renderCustomFields(holder, index));
7641
- }));
7840
+ label: t("billing.phone"),
7841
+ error: fieldError(phoneKey, t("billing.phoneInvalid")),
7842
+ invalid: Boolean(fieldError(phoneKey))
7843
+ },
7844
+ /* @__PURE__ */ import_react30.default.createElement(
7845
+ import_react_international_phone2.PhoneInput,
7846
+ {
7847
+ className: "tf-checkout-phone",
7848
+ inputClassName: `tf-checkout-input tf-checkout-phone__input${fieldError(phoneKey) ? " tf-checkout-input--invalid" : ""}`,
7849
+ defaultCountry: phoneCountry,
7850
+ disableDialCodeAndPrefix: true,
7851
+ showDisabledDialCodeAndPrefix: true,
7852
+ disableDialCodePrefill: true,
7853
+ value: holder.phone,
7854
+ required: true,
7855
+ inputProps: {
7856
+ autoComplete: "tel",
7857
+ "aria-label": phoneKey,
7858
+ "aria-invalid": Boolean(fieldError(phoneKey))
7859
+ },
7860
+ onChange: (phone) => patchHolder(index, { phone })
7861
+ }
7862
+ )
7863
+ )), renderCustomFields(holder, index));
7864
+ }));
7865
+ };
7642
7866
 
7643
7867
  // src/sections/BillingInfo.tsx
7644
7868
  var BillingInfo = ({
7645
7869
  eventId,
7646
7870
  onContinue,
7647
- heading = "Billing Information",
7648
- buttonLabel = "Continue to payment",
7871
+ heading,
7872
+ buttonLabel,
7649
7873
  onLogin,
7650
7874
  skipWhenProfileComplete = false,
7651
7875
  requireEmailConfirmation = false,
7652
7876
  collectTicketHolders = false,
7653
7877
  collectHolderContact = false,
7654
- ttfOptInLabel = "Keep me updated about future events from The Ticket Fairy",
7878
+ ttfOptInLabel,
7655
7879
  brandOptInLabel,
7656
7880
  privacyPolicy,
7657
7881
  showPrivacyError = false,
7658
7882
  step,
7659
7883
  className
7660
7884
  }) => {
7661
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D;
7885
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E;
7886
+ const t = useT();
7662
7887
  const checkout = useCheckoutContext();
7663
7888
  const validation = useCheckoutValidation();
7889
+ const headingText = heading != null ? heading : t("billing.heading");
7890
+ const buttonText = buttonLabel != null ? buttonLabel : t("billing.continueToPayment");
7891
+ const ttfOptInText = ttfOptInLabel != null ? ttfOptInLabel : t("billing.ttfOptIn");
7664
7892
  const profile = hooks_exports.useProfile({ retry: false });
7665
7893
  const event = hooks_exports.useEvent(eventId);
7666
7894
  const combined = !onContinue;
@@ -7748,7 +7976,7 @@ var BillingInfo = ({
7748
7976
  lastName: prev.lastName || profileBilling.lastName || "",
7749
7977
  email: prev.email || profileBilling.email || "",
7750
7978
  confirmEmail: prev.confirmEmail || (checkout.isLoggedIn ? profileBilling.email : "") || "",
7751
- phone: prev.phone || profileBilling.phone,
7979
+ phone: (isBlankPhone(prev.phone) ? void 0 : prev.phone) || profileBilling.phone,
7752
7980
  streetAddress: prev.streetAddress || profileBilling.streetAddress,
7753
7981
  city: prev.city || profileBilling.city,
7754
7982
  zip: prev.zip || profileBilling.zip,
@@ -7758,6 +7986,12 @@ var BillingInfo = ({
7758
7986
  const keys = Object.keys(next);
7759
7987
  return keys.every((k) => next[k] === prev[k]) ? prev : next;
7760
7988
  });
7989
+ setDob((prev) => {
7990
+ var _a2;
7991
+ if (prev) return prev;
7992
+ const { dobYear: dobYear2, dobMonth: dobMonth2, dobDay: dobDay2 } = profileBilling;
7993
+ return (_a2 = toDateInputValue(dobYear2, dobMonth2, dobDay2)) != null ? _a2 : prev;
7994
+ });
7761
7995
  }, [profile.data, checkout.isLoggedIn]);
7762
7996
  (0, import_react31.useEffect)(() => {
7763
7997
  setHolders(
@@ -7795,11 +8029,11 @@ var BillingInfo = ({
7795
8029
  (0, import_react31.useEffect)(() => {
7796
8030
  const email = billing.email.trim();
7797
8031
  if (checkout.isLoggedIn || !isEmail(email)) return;
7798
- const t = setTimeout(
8032
+ const t2 = setTimeout(
7799
8033
  () => checkout.checkBuyerEmail(email).catch(() => void 0),
7800
8034
  600
7801
8035
  );
7802
- return () => clearTimeout(t);
8036
+ return () => clearTimeout(t2);
7803
8037
  }, [billing.email, checkout.isLoggedIn]);
7804
8038
  const emailTaken = !checkout.isLoggedIn && checkout.existingAccountEmail === billing.email.trim();
7805
8039
  const needsNationality = checkout.buyerFields.some((f) => f.kind === "nationality");
@@ -7839,6 +8073,7 @@ var BillingInfo = ({
7839
8073
  countryDefaultApplied.current = true;
7840
8074
  setBilling((current2) => {
7841
8075
  var _a3;
8076
+ if (current2.countryId) return current2;
7842
8077
  return {
7843
8078
  ...current2,
7844
8079
  countryId: String(preferred.id),
@@ -7879,24 +8114,30 @@ var BillingInfo = ({
7879
8114
  }, [billing.stateId, billing.stateCode, states]);
7880
8115
  const setB = (k) => (e) => setBilling((b) => ({ ...b, [k]: e.target.value }));
7881
8116
  const patchHolder = (i, patch2) => setHolders((hs) => hs.map((h, j) => j === i ? { ...h, ...patch2 } : h));
8117
+ const dobMax = (0, import_react31.useMemo)(todayISO, []);
7882
8118
  const [dobYear, dobMonth, dobDay] = dob ? dob.split("-").map(Number) : [];
8119
+ const buyerPhone = isBlankPhone(billing.phone) ? void 0 : billing.phone;
7883
8120
  const committedBilling = {
7884
8121
  ...checkout.billing,
7885
8122
  ...billing,
8123
+ phone: buyerPhone,
7886
8124
  stateRequired: gates.showAddress && Boolean(billing.countryId) && states.length > 0,
7887
8125
  dataCapture,
7888
8126
  dobDay,
7889
8127
  dobMonth,
7890
8128
  dobYear
7891
8129
  };
7892
- const committedHolders = holders.map((holder) => ({
7893
- firstName: holderNamesRequired ? holder.firstName : holder.firstName || billing.firstName,
7894
- lastName: holderNamesRequired ? holder.lastName : holder.lastName || billing.lastName,
7895
- email: showHolders && collectHolderContact ? holder.email : holder.email || billing.email,
7896
- phone: showHolders && collectHolderContact ? holder.phone : holder.phone || billing.phone,
7897
- ticketTypeId: holder.ticketTypeId,
7898
- ticketDataCapture: holder.ticketDataCapture
7899
- }));
8130
+ const committedHolders = holders.map((holder) => {
8131
+ const holderPhone = isBlankPhone(holder.phone) ? "" : holder.phone;
8132
+ return {
8133
+ firstName: holderNamesRequired ? holder.firstName : holder.firstName || billing.firstName,
8134
+ lastName: holderNamesRequired ? holder.lastName : holder.lastName || billing.lastName,
8135
+ email: showHolders && collectHolderContact ? holder.email : holder.email || billing.email,
8136
+ phone: showHolders && collectHolderContact ? holderPhone : holderPhone || buyerPhone || "",
8137
+ ticketTypeId: holder.ticketTypeId,
8138
+ ticketDataCapture: holder.ticketDataCapture
8139
+ };
8140
+ });
7900
8141
  const missingDetails = missingCheckoutDetails(
7901
8142
  {
7902
8143
  billing: committedBilling,
@@ -7916,7 +8157,7 @@ var BillingInfo = ({
7916
8157
  const complete = missingDetails.length === 0;
7917
8158
  const showValidation = validation.attempt > 0;
7918
8159
  const missingSet = new Set(missingDetails);
7919
- const fieldError = (key, message = "This field is required.") => showValidation && missingSet.has(key) ? message : void 0;
8160
+ const fieldError = (key, message = t("billing.fieldRequired")) => showValidation && missingSet.has(key) ? message : void 0;
7920
8161
  const dobError = showValidation ? missingDetails.find(
7921
8162
  (detail) => detail === "Date of birth" || detail.startsWith("Age ")
7922
8163
  ) : void 0;
@@ -7924,7 +8165,7 @@ var BillingInfo = ({
7924
8165
  const commit = () => {
7925
8166
  checkout.setBilling(committedBilling);
7926
8167
  checkout.setHolders(committedHolders);
7927
- if (ttfOptInLabel || brandOptInLabel) checkout.setConsent(consent);
8168
+ if (ttfOptInText || brandOptInLabel) checkout.setConsent(consent);
7928
8169
  };
7929
8170
  (0, import_react31.useEffect)(() => {
7930
8171
  if (combined) commit();
@@ -7946,7 +8187,7 @@ var BillingInfo = ({
7946
8187
  const hasEventSpecificDetails = checkout.buyerFields.length > 0 || checkout.customFields.some((group) => group.fields.length > 0) || showHolders || gates.showDob;
7947
8188
  const skipBilling = skipWhenProfileComplete && checkout.isLoggedIn && profile.isSuccess && complete && !hasEventSpecificDetails;
7948
8189
  if (skipBilling) return null;
7949
- return /* @__PURE__ */ import_react31.default.createElement(import_react31.default.Fragment, null, /* @__PURE__ */ import_react31.default.createElement(Card, { className }, /* @__PURE__ */ import_react31.default.createElement(SectionHeader, { step, title: heading }), onLogin && !checkout.isLoggedIn && /* @__PURE__ */ import_react31.default.createElement("div", { className: "tf-checkout-billing__login" }, /* @__PURE__ */ import_react31.default.createElement("span", null, "Login & skip ahead:"), /* @__PURE__ */ import_react31.default.createElement(
8190
+ return /* @__PURE__ */ import_react31.default.createElement(import_react31.default.Fragment, null, /* @__PURE__ */ import_react31.default.createElement(Card, { className }, /* @__PURE__ */ import_react31.default.createElement(SectionHeader, { step, title: headingText }), onLogin && !checkout.isLoggedIn && /* @__PURE__ */ import_react31.default.createElement("div", { className: "tf-checkout-billing__login" }, /* @__PURE__ */ import_react31.default.createElement("span", null, "Login & skip ahead:"), /* @__PURE__ */ import_react31.default.createElement(
7950
8191
  "button",
7951
8192
  {
7952
8193
  type: "button",
@@ -7963,7 +8204,7 @@ var BillingInfo = ({
7963
8204
  /* @__PURE__ */ import_react31.default.createElement(
7964
8205
  Input,
7965
8206
  {
7966
- placeholder: "First name *",
8207
+ placeholder: t("billing.firstNamePlaceholder"),
7967
8208
  value: billing.firstName,
7968
8209
  required: true,
7969
8210
  invalid: Boolean(fieldError("First name")),
@@ -7980,7 +8221,7 @@ var BillingInfo = ({
7980
8221
  /* @__PURE__ */ import_react31.default.createElement(
7981
8222
  Input,
7982
8223
  {
7983
- placeholder: "Last name *",
8224
+ placeholder: t("billing.lastNamePlaceholder"),
7984
8225
  value: billing.lastName,
7985
8226
  required: true,
7986
8227
  invalid: Boolean(fieldError("Last name")),
@@ -7999,7 +8240,7 @@ var BillingInfo = ({
7999
8240
  {
8000
8241
  type: "email",
8001
8242
  autoComplete: "email",
8002
- placeholder: "Email *",
8243
+ placeholder: t("billing.emailPlaceholder"),
8003
8244
  value: billing.email,
8004
8245
  required: true,
8005
8246
  invalid: Boolean(fieldError("Valid email address")),
@@ -8012,7 +8253,7 @@ var BillingInfo = ({
8012
8253
  {
8013
8254
  error: fieldError(
8014
8255
  "Matching email confirmation",
8015
- "Email addresses must match."
8256
+ t("billing.emailMustMatch")
8016
8257
  ),
8017
8258
  invalid: Boolean(fieldError("Matching email confirmation"))
8018
8259
  },
@@ -8021,7 +8262,7 @@ var BillingInfo = ({
8021
8262
  {
8022
8263
  type: "email",
8023
8264
  autoComplete: "email",
8024
- placeholder: "Confirm email *",
8265
+ placeholder: t("billing.confirmEmailPlaceholder"),
8025
8266
  value: (_C = billing.confirmEmail) != null ? _C : "",
8026
8267
  required: true,
8027
8268
  invalid: Boolean(fieldError("Matching email confirmation")),
@@ -8029,15 +8270,15 @@ var BillingInfo = ({
8029
8270
  onChange: setB("confirmEmail")
8030
8271
  }
8031
8272
  )
8032
- )), !showValidation && requireEmailConfirmation && billing.confirmEmail && billing.confirmEmail.trim().toLowerCase() !== billing.email.trim().toLowerCase() && /* @__PURE__ */ import_react31.default.createElement("p", { className: "tf-checkout-error-text" }, "The email addresses do not match."), emailTaken && /* @__PURE__ */ import_react31.default.createElement("p", { className: "tf-checkout-note tf-checkout-billing__email-taken" }, "This email is already registered.", " ", onLogin ? /* @__PURE__ */ import_react31.default.createElement(
8273
+ )), !showValidation && requireEmailConfirmation && billing.confirmEmail && billing.confirmEmail.trim().toLowerCase() !== billing.email.trim().toLowerCase() && /* @__PURE__ */ import_react31.default.createElement("p", { className: "tf-checkout-error-text" }, t("billing.emailMismatch")), emailTaken && /* @__PURE__ */ import_react31.default.createElement("p", { className: "tf-checkout-note tf-checkout-billing__email-taken" }, t("billing.emailRegistered"), " ", onLogin ? /* @__PURE__ */ import_react31.default.createElement(
8033
8274
  "button",
8034
8275
  {
8035
8276
  type: "button",
8036
8277
  className: "tf-checkout-billing__login-link",
8037
8278
  onClick: () => onLogin(billing.email)
8038
8279
  },
8039
- "Log in to autofill your details"
8040
- ) : "Log in to autofill your details."), checkout.buyerFields.map((f) => {
8280
+ t("billing.loginAutofill")
8281
+ ) : t("billing.loginAutofillPlain")), checkout.buyerFields.map((f) => {
8041
8282
  var _a2;
8042
8283
  return /* @__PURE__ */ import_react31.default.createElement(
8043
8284
  BuyerField,
@@ -8048,15 +8289,15 @@ var BillingInfo = ({
8048
8289
  onChange: (v) => setBilling((b) => ({ ...b, [f.key]: v })),
8049
8290
  countries,
8050
8291
  error: fieldError(
8051
- f.kind === "nationality" ? "Nationality" : f.kind === "gender" ? "Gender" : "Instagram handle"
8292
+ f.kind === "nationality" ? t("billing.nationality") : f.kind === "gender" ? t("billing.gender") : t("billing.instagramHandle")
8052
8293
  )
8053
8294
  }
8054
8295
  );
8055
8296
  }), gates.showPhone && /* @__PURE__ */ import_react31.default.createElement(
8056
8297
  Field,
8057
8298
  {
8058
- label: `Phone${gates.phoneRequired ? " *" : ""}`,
8059
- error: fieldError("Valid phone number", "Enter a valid phone number."),
8299
+ label: gates.phoneRequired ? t("billing.phone") : t("billing.phoneOptional"),
8300
+ error: fieldError("Valid phone number", t("billing.phoneInvalid")),
8060
8301
  invalid: Boolean(fieldError("Valid phone number"))
8061
8302
  },
8062
8303
  /* @__PURE__ */ import_react31.default.createElement(
@@ -8065,13 +8306,15 @@ var BillingInfo = ({
8065
8306
  className: "tf-checkout-phone",
8066
8307
  inputClassName: `tf-checkout-input tf-checkout-phone__input${fieldError("Valid phone number") ? " tf-checkout-input--invalid" : ""}`,
8067
8308
  defaultCountry: phoneCountry,
8309
+ disableDialCodeAndPrefix: true,
8310
+ showDisabledDialCodeAndPrefix: true,
8068
8311
  disableDialCodePrefill: true,
8069
8312
  value: (_D = billing.phone) != null ? _D : "",
8070
8313
  required: gates.phoneRequired,
8071
- placeholder: "Phone number",
8314
+ placeholder: t("billing.phonePlaceholder"),
8072
8315
  inputProps: {
8073
8316
  autoComplete: "tel",
8074
- "aria-label": "Phone",
8317
+ "aria-label": t("billing.phoneAria"),
8075
8318
  "aria-invalid": Boolean(fieldError("Valid phone number"))
8076
8319
  },
8077
8320
  onChange: (phone) => setBilling((current2) => ({ ...current2, phone }))
@@ -8080,8 +8323,8 @@ var BillingInfo = ({
8080
8323
  ), gates.showDob && /* @__PURE__ */ import_react31.default.createElement(
8081
8324
  Field,
8082
8325
  {
8083
- label: `Date of birth *${gates.minimumAge ? ` (must be ${gates.minimumAge}+)` : ""}`,
8084
- error: dobError === "Date of birth" ? "Date of birth is required." : dobError ? `You must be ${gates.minimumAge} or older.` : void 0,
8326
+ label: gates.minimumAge ? t("billing.dobWithAge", { age: gates.minimumAge }) : t("billing.dob"),
8327
+ error: dobError === "Date of birth" ? t("billing.dobRequired") : dobError ? t("billing.ageMinimum", { age: (_E = gates.minimumAge) != null ? _E : "" }) : void 0,
8085
8328
  invalid: Boolean(dobError)
8086
8329
  },
8087
8330
  /* @__PURE__ */ import_react31.default.createElement(
@@ -8090,6 +8333,8 @@ var BillingInfo = ({
8090
8333
  type: "date",
8091
8334
  value: dob,
8092
8335
  required: true,
8336
+ min: DOB_MIN,
8337
+ max: dobMax,
8093
8338
  invalid: Boolean(dobError),
8094
8339
  "aria-invalid": Boolean(dobError),
8095
8340
  onChange: (e) => setDob(e.target.value)
@@ -8130,17 +8375,17 @@ var BillingInfo = ({
8130
8375
  "aria-invalid": (showPrivacyError || showValidation) && !consent.ttfOptIn,
8131
8376
  onChange: (e) => setConsent((c) => ({ ...c, ttfOptIn: e.target.checked })),
8132
8377
  className: "tf-checkout-checkbox--consent",
8133
- label: /* @__PURE__ */ import_react31.default.createElement(import_react31.default.Fragment, null, "I have read and agree to ", privacyPolicy.brandName, " ", /* @__PURE__ */ import_react31.default.createElement("a", { href: privacyPolicy.url, target: "_blank", rel: "noreferrer" }, privacyPolicy.linkLabel || "Privacy Policy."), " *")
8378
+ label: /* @__PURE__ */ import_react31.default.createElement(import_react31.default.Fragment, null, t("billing.privacyAgree", { brand: privacyPolicy.brandName }), " ", /* @__PURE__ */ import_react31.default.createElement("a", { href: privacyPolicy.url, target: "_blank", rel: "noreferrer" }, privacyPolicy.linkLabel || t("billing.privacyLink")), " *")
8134
8379
  }
8135
8380
  ),
8136
- (showPrivacyError || showValidation) && !consent.ttfOptIn && /* @__PURE__ */ import_react31.default.createElement("div", { className: "tf-checkout-consent__error" }, "Required")
8137
- ) : ttfOptInLabel ? /* @__PURE__ */ import_react31.default.createElement(
8381
+ (showPrivacyError || showValidation) && !consent.ttfOptIn && /* @__PURE__ */ import_react31.default.createElement("div", { className: "tf-checkout-consent__error" }, t("common.required"))
8382
+ ) : ttfOptInText ? /* @__PURE__ */ import_react31.default.createElement(
8138
8383
  Checkbox,
8139
8384
  {
8140
8385
  checked: consent.ttfOptIn,
8141
8386
  onChange: (e) => setConsent((c) => ({ ...c, ttfOptIn: e.target.checked })),
8142
8387
  className: "tf-checkout-checkbox--consent",
8143
- label: ttfOptInLabel
8388
+ label: ttfOptInText
8144
8389
  }
8145
8390
  ) : null, !combined && /* @__PURE__ */ import_react31.default.createElement(import_react31.default.Fragment, null, /* @__PURE__ */ import_react31.default.createElement(
8146
8391
  Button,
@@ -8155,7 +8400,7 @@ var BillingInfo = ({
8155
8400
  onContinue == null ? void 0 : onContinue();
8156
8401
  }
8157
8402
  },
8158
- buttonLabel
8403
+ buttonText
8159
8404
  ))), showHolders && /* @__PURE__ */ import_react31.default.createElement(
8160
8405
  TicketHoldersCard,
8161
8406
  {
@@ -8190,12 +8435,13 @@ var import_react33 = __toESM(require("react"));
8190
8435
  var import_react32 = __toESM(require("react"));
8191
8436
  var OrderSummary = ({ eventId, className }) => {
8192
8437
  var _a, _b, _c;
8438
+ const t = useT();
8193
8439
  const checkout = useCheckoutContext();
8194
8440
  const event = hooks_exports.useEvent(eventId);
8195
8441
  const breakdown = checkout.breakdown;
8196
8442
  const detailed = checkout.priceBreakdown;
8197
8443
  if (!breakdown || breakdown.tickets.length === 0) return null;
8198
- return /* @__PURE__ */ import_react32.default.createElement(Card, { className: ["tf-checkout-order-summary", className].filter(Boolean).join(" ") }, ((_a = event.data) == null ? void 0 : _a.name) && /* @__PURE__ */ import_react32.default.createElement("div", { className: "tf-checkout-order-summary__group" }, /* @__PURE__ */ import_react32.default.createElement("div", { className: "tf-checkout-order-summary__label" }, "Event"), /* @__PURE__ */ import_react32.default.createElement("div", { className: "tf-checkout-order-summary__event" }, event.data.name)), /* @__PURE__ */ import_react32.default.createElement("div", { className: "tf-checkout-order-summary__group" }, /* @__PURE__ */ import_react32.default.createElement("div", { className: "tf-checkout-order-summary__label" }, "Your Tickets"), breakdown.tickets.map((ticket, index) => {
8444
+ return /* @__PURE__ */ import_react32.default.createElement(Card, { className: ["tf-checkout-order-summary", className].filter(Boolean).join(" ") }, ((_a = event.data) == null ? void 0 : _a.name) && /* @__PURE__ */ import_react32.default.createElement("div", { className: "tf-checkout-order-summary__group" }, /* @__PURE__ */ import_react32.default.createElement("div", { className: "tf-checkout-order-summary__label" }, t("common.event")), /* @__PURE__ */ import_react32.default.createElement("div", { className: "tf-checkout-order-summary__event" }, event.data.name)), /* @__PURE__ */ import_react32.default.createElement("div", { className: "tf-checkout-order-summary__group" }, /* @__PURE__ */ import_react32.default.createElement("div", { className: "tf-checkout-order-summary__label" }, t("tickets.yourTickets")), breakdown.tickets.map((ticket, index) => {
8199
8445
  var _a2;
8200
8446
  const detail = detailed == null ? void 0 : detailed.tickets[index];
8201
8447
  return /* @__PURE__ */ import_react32.default.createElement(
@@ -8204,7 +8450,7 @@ var OrderSummary = ({ eventId, className }) => {
8204
8450
  key: `${ticket.ticketTypeId}-${index}`,
8205
8451
  className: "tf-checkout-order-summary__item"
8206
8452
  },
8207
- /* @__PURE__ */ import_react32.default.createElement("div", { className: "tf-checkout-order-summary__ticket" }, ticket.quantity, " x ", ticket.name, " - ", (_a2 = detail == null ? void 0 : detail.unit_price) != null ? _a2 : ticket.unit, " ", "each"),
8453
+ /* @__PURE__ */ import_react32.default.createElement("div", { className: "tf-checkout-order-summary__ticket" }, ticket.quantity, " x ", ticket.name, " - ", (_a2 = detail == null ? void 0 : detail.unit_price) != null ? _a2 : ticket.unit, " ", t("common.each")),
8208
8454
  (detail == null ? void 0 : detail.line_total) && detail.line_total !== detail.unit_price && /* @__PURE__ */ import_react32.default.createElement("div", { className: "tf-checkout-order-summary__fees" }, "(", detail.line_total, " with fees)")
8209
8455
  );
8210
8456
  })), ((_b = detailed == null ? void 0 : detailed.add_ons.length) != null ? _b : 0) > 0 && /* @__PURE__ */ import_react32.default.createElement("div", { className: "tf-checkout-order-summary__group" }, /* @__PURE__ */ import_react32.default.createElement("div", { className: "tf-checkout-order-summary__label" }, (detailed == null ? void 0 : detailed.add_ons_title) || "Add-ons"), detailed == null ? void 0 : detailed.add_ons.map((addOn, index) => /* @__PURE__ */ import_react32.default.createElement(
@@ -8213,8 +8459,8 @@ var OrderSummary = ({ eventId, className }) => {
8213
8459
  key: `${addOn.name}-${index}`,
8214
8460
  className: "tf-checkout-order-summary__item"
8215
8461
  },
8216
- /* @__PURE__ */ import_react32.default.createElement("div", { className: "tf-checkout-order-summary__ticket" }, addOn.quantity, " x ", addOn.name, addOn.show_price ? ` - ${addOn.unit_price} each` : "")
8217
- ))), /* @__PURE__ */ import_react32.default.createElement("div", { className: "tf-checkout-order-summary__total" }, /* @__PURE__ */ import_react32.default.createElement("div", { className: "tf-checkout-order-summary__label" }, "Total"), /* @__PURE__ */ import_react32.default.createElement("div", { className: "tf-checkout-order-summary__amount" }, (_c = detailed == null ? void 0 : detailed.total) != null ? _c : `${breakdown.currencySymbol || `${breakdown.currencyCode} `}${Number(
8462
+ /* @__PURE__ */ import_react32.default.createElement("div", { className: "tf-checkout-order-summary__ticket" }, addOn.quantity, " x ", addOn.name, addOn.show_price ? ` - ${addOn.unit_price} ${t("common.each")}` : "")
8463
+ ))), /* @__PURE__ */ import_react32.default.createElement("div", { className: "tf-checkout-order-summary__total" }, /* @__PURE__ */ import_react32.default.createElement("div", { className: "tf-checkout-order-summary__label" }, t("common.total")), /* @__PURE__ */ import_react32.default.createElement("div", { className: "tf-checkout-order-summary__amount" }, (_c = detailed == null ? void 0 : detailed.total) != null ? _c : `${breakdown.currencySymbol || `${breakdown.currencyCode} `}${Number(
8218
8464
  breakdown.total
8219
8465
  ).toFixed(2)}`)));
8220
8466
  };
@@ -8256,7 +8502,8 @@ var Payment = ({
8256
8502
  showTestCardHint = false,
8257
8503
  className
8258
8504
  }) => {
8259
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
8505
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
8506
+ const t = useT();
8260
8507
  const checkout = useCheckoutContext();
8261
8508
  const validation = useCheckoutValidation();
8262
8509
  const [error, setError] = (0, import_react33.useState)("");
@@ -8278,13 +8525,19 @@ var Payment = ({
8278
8525
  const bd = checkout.breakdown;
8279
8526
  const isFree = bd != null && Number(bd.total) === 0;
8280
8527
  const isXendit = checkout.gateway === "xendit";
8528
+ const serverMethodTypes = (_a = checkout.stripeElementsConfig) == null ? void 0 : _a.paymentMethodTypes;
8529
+ const offersOxxo = Array.isArray(serverMethodTypes) && serverMethodTypes.includes("oxxo");
8281
8530
  const options = (0, import_react33.useMemo)(() => {
8282
- var _a2, _b2, _c2, _d2;
8531
+ var _a2, _b2, _c2;
8283
8532
  if (isFree || !methods) return [];
8284
8533
  const out = [];
8285
8534
  if (isXendit) {
8286
8535
  if (methods.xenditCard)
8287
- out.push({ id: { kind: "xenditCard" }, value: "xenditCard", label: "Card" });
8536
+ out.push({
8537
+ id: { kind: "xenditCard" },
8538
+ value: "xenditCard",
8539
+ label: t("payment.card")
8540
+ });
8288
8541
  for (const w of methods.xenditEWallets)
8289
8542
  out.push({
8290
8543
  id: { kind: "xenditEWallet", walletKey: w.key },
@@ -8296,23 +8549,23 @@ var Payment = ({
8296
8549
  } else if (checkout.gateway === "razorpay") {
8297
8550
  out.push({ id: { kind: "razorpay" }, value: "razorpay", label: "Razorpay" });
8298
8551
  } else {
8299
- out.push({ id: { kind: "card" }, value: "card", label: "Card" });
8300
- for (const t of (_b2 = checkout.redirectPaymentMethods) != null ? _b2 : []) {
8301
- if (t === "paypal" && methods.paypal) continue;
8552
+ out.push({ id: { kind: "card" }, value: "card", label: t("payment.card") });
8553
+ for (const t2 of (_b2 = checkout.redirectPaymentMethods) != null ? _b2 : []) {
8554
+ if (t2 === "paypal" && methods.paypal) continue;
8302
8555
  out.push({
8303
- id: { kind: "redirect", methodType: t },
8304
- value: `rd:${t}`,
8305
- label: redirectLabel(t)
8556
+ id: { kind: "redirect", methodType: t2 },
8557
+ value: `rd:${t2}`,
8558
+ label: redirectLabel(t2)
8306
8559
  });
8307
8560
  }
8308
8561
  if ((_c2 = checkout.paymentPlan) == null ? void 0 : _c2.available)
8309
8562
  out.push({
8310
8563
  id: { kind: "paymentPlan" },
8311
8564
  value: "paymentPlan",
8312
- label: "Payment plan"
8565
+ label: t("payment.paymentPlan")
8313
8566
  });
8314
- if (((_d2 = checkout.breakdown) == null ? void 0 : _d2.currencyCode) === "MXN")
8315
- out.push({ id: { kind: "oxxo" }, value: "oxxo", label: "OXXO (pay in cash)" });
8567
+ if (offersOxxo)
8568
+ out.push({ id: { kind: "oxxo" }, value: "oxxo", label: t("payment.oxxo") });
8316
8569
  }
8317
8570
  if (methods.paypal)
8318
8571
  out.push({ id: { kind: "paypal" }, value: "paypal", label: "PayPal" });
@@ -8324,7 +8577,7 @@ var Payment = ({
8324
8577
  checkout.gateway,
8325
8578
  checkout.redirectPaymentMethods,
8326
8579
  checkout.paymentPlan,
8327
- checkout.breakdown
8580
+ offersOxxo
8328
8581
  ]);
8329
8582
  (0, import_react33.useEffect)(() => {
8330
8583
  if (options.length && !options.some((o) => o.value === selected))
@@ -8334,14 +8587,14 @@ var Payment = ({
8334
8587
  const selectedOption = options.find((o) => o.value === selected);
8335
8588
  const isCardSelected = selected === cardValue;
8336
8589
  const isPlanSelected = (selectedOption == null ? void 0 : selectedOption.id.kind) === "paymentPlan";
8337
- const savedLast4 = (_a = checkout.paymentPlan) == null ? void 0 : _a.savedCardLast4;
8590
+ const savedLast4 = (_b = checkout.paymentPlan) == null ? void 0 : _b.savedCardLast4;
8338
8591
  const reuseSavedCard = Boolean(savedLast4) && useSavedCard;
8339
8592
  const usesCardDetails = !isFree && (isCardSelected || isPlanSelected && !reuseSavedCard);
8340
8593
  const cardWidgetReportsItsOwnError = usesCardDetails && !isXendit;
8341
8594
  const hasWallets = Boolean(
8342
- ((_b = checkout.walletAvailability) == null ? void 0 : _b.applePay) || ((_c = checkout.walletAvailability) == null ? void 0 : _c.googlePay)
8595
+ ((_c = checkout.walletAvailability) == null ? void 0 : _c.applePay) || ((_d = checkout.walletAvailability) == null ? void 0 : _d.googlePay)
8343
8596
  );
8344
- const useWalletElement = !isXendit && !isPlanSelected && hasWallets && ((_d = checkout.breakdown) == null ? void 0 : _d.currencyCode) !== "MXN" && Boolean((_e = checkout.stripeElementsConfig) == null ? void 0 : _e.mode);
8597
+ const useWalletElement = !isXendit && !isPlanSelected && hasWallets && ((_e = checkout.breakdown) == null ? void 0 : _e.currencyCode) !== "MXN" && Boolean((_f = checkout.stripeElementsConfig) == null ? void 0 : _f.mode);
8345
8598
  const onlyOption = options.length === 1 ? options[0] : void 0;
8346
8599
  const singleCard = (onlyOption == null ? void 0 : onlyOption.id.kind) === "card" || (onlyOption == null ? void 0 : onlyOption.id.kind) === "xenditCard";
8347
8600
  const b = checkout.billing;
@@ -8358,7 +8611,7 @@ var Payment = ({
8358
8611
  { requireEmailConfirmation, collectTicketHolders, requireHolderContact }
8359
8612
  );
8360
8613
  const billingReady = missingDetails.length === 0;
8361
- const conditions = [...(_f = checkout.conditions) != null ? _f : [], ...additionalConditions];
8614
+ const conditions = [...(_g = checkout.conditions) != null ? _g : [], ...additionalConditions];
8362
8615
  const requiredConditions = conditions.filter((c) => c.isRequired);
8363
8616
  const conditionsOk = requiredConditions.every(
8364
8617
  (c) => {
@@ -8367,10 +8620,10 @@ var Payment = ({
8367
8620
  }
8368
8621
  );
8369
8622
  const extra = selectedOption == null ? void 0 : selectedOption.extra;
8370
- const extrasOk = !extra || (extra === "cashtag" ? Boolean((_h = (_g = extras[selected]) == null ? void 0 : _g.cashtag) == null ? void 0 : _h.trim()) : Boolean((_j = (_i = extras[selected]) == null ? void 0 : _i.phoneNumber) == null ? void 0 : _j.trim()));
8623
+ const extrasOk = !extra || (extra === "cashtag" ? Boolean((_i = (_h = extras[selected]) == null ? void 0 : _h.cashtag) == null ? void 0 : _i.trim()) : Boolean((_k = (_j = extras[selected]) == null ? void 0 : _j.phoneNumber) == null ? void 0 : _k.trim()));
8371
8624
  const privacyOk = !requirePrivacyPolicy || checkout.consent.ttfOptIn;
8372
- const payLabel = isFree ? "Complete Registration" : isPlanSelected ? planConfirmLabel((_k = checkout.paymentPlan) == null ? void 0 : _k.configuration) : "Submit Payment";
8373
- const planTerms = paymentPlanTerms((_l = checkout.paymentPlan) == null ? void 0 : _l.configuration);
8625
+ const payLabel = isFree ? t("payment.completeRegistration") : isPlanSelected ? planConfirmLabel((_l = checkout.paymentPlan) == null ? void 0 : _l.configuration) : t("payment.submitPayment");
8626
+ const planTerms = paymentPlanTerms((_m = checkout.paymentPlan) == null ? void 0 : _m.configuration);
8374
8627
  const finalizing = checkout.status === "placing" || checkout.status === "succeeded";
8375
8628
  const pay = () => {
8376
8629
  setError("");
@@ -8450,15 +8703,15 @@ var Payment = ({
8450
8703
  }
8451
8704
  }
8452
8705
  ) : /* @__PURE__ */ import_react33.default.createElement(CardInput, null)
8453
- ), isXendit && cardAreaError && /* @__PURE__ */ import_react33.default.createElement("p", { className: "tf-checkout-error-text" }, cardAreaError), showTestCardHint && /* @__PURE__ */ import_react33.default.createElement("p", { className: "tf-checkout-note" }, isXendit ? "Test card: 4000 0000 0000 0002 \xB7 any future date \xB7 any CVC" : "Test card: 4242 4242 4242 4242 \xB7 any future date \xB7 any CVC")), isPlanSelected && planTerms.length > 0 && /* @__PURE__ */ import_react33.default.createElement("div", { className: "tf-checkout-payment__plan" }, /* @__PURE__ */ import_react33.default.createElement("strong", null, planTermsTitle(checkout.paymentPlan.configuration)), planTerms.map((part) => /* @__PURE__ */ import_react33.default.createElement("p", { key: part.id, className: "tf-checkout-note" }, part.text))), isPlanSelected && savedLast4 && /* @__PURE__ */ import_react33.default.createElement("div", { className: "tf-checkout-payment__plan-savedcard" }, /* @__PURE__ */ import_react33.default.createElement("p", { className: "tf-checkout-note" }, "Your payment will proceed with the card ending in", " ", /* @__PURE__ */ import_react33.default.createElement("strong", null, "**** ", savedLast4)), /* @__PURE__ */ import_react33.default.createElement(
8706
+ ), isXendit && cardAreaError && /* @__PURE__ */ import_react33.default.createElement("p", { className: "tf-checkout-error-text" }, cardAreaError), showTestCardHint && /* @__PURE__ */ import_react33.default.createElement("p", { className: "tf-checkout-note" }, isXendit ? t("payment.testCardXendit") : t("payment.testCard"))), isPlanSelected && planTerms.length > 0 && /* @__PURE__ */ import_react33.default.createElement("div", { className: "tf-checkout-payment__plan" }, /* @__PURE__ */ import_react33.default.createElement("strong", null, planTermsTitle(checkout.paymentPlan.configuration)), planTerms.map((part) => /* @__PURE__ */ import_react33.default.createElement("p", { key: part.id, className: "tf-checkout-note" }, part.text))), isPlanSelected && savedLast4 && /* @__PURE__ */ import_react33.default.createElement("div", { className: "tf-checkout-payment__plan-savedcard" }, /* @__PURE__ */ import_react33.default.createElement("p", { className: "tf-checkout-note" }, "Your payment will proceed with the card ending in", " ", /* @__PURE__ */ import_react33.default.createElement("strong", null, "**** ", savedLast4)), /* @__PURE__ */ import_react33.default.createElement(
8454
8707
  Checkbox,
8455
8708
  {
8456
8709
  checked: useSavedCard,
8457
8710
  onChange: (e) => setUseSavedCard(e.target.checked),
8458
- label: "Use this card"
8711
+ label: t("payment.useThisCard")
8459
8712
  }
8460
8713
  )));
8461
- return /* @__PURE__ */ import_react33.default.createElement("div", { className: ["tf-checkout-payment-stack", className].filter(Boolean).join(" ") }, /* @__PURE__ */ import_react33.default.createElement(Card, null, /* @__PURE__ */ import_react33.default.createElement(SectionHeader, { title: "Payment" }), !isFree && /* @__PURE__ */ import_react33.default.createElement(import_react33.default.Fragment, null, !singleCard && /* @__PURE__ */ import_react33.default.createElement("div", { className: "tf-checkout-payment__label" }, "Payment method"), !methods ? /* @__PURE__ */ import_react33.default.createElement("div", { className: "tf-checkout-payment__cardbox" }, /* @__PURE__ */ import_react33.default.createElement(Loader, null)) : singleCard ? paymentInput : /* @__PURE__ */ import_react33.default.createElement(
8714
+ return /* @__PURE__ */ import_react33.default.createElement("div", { className: ["tf-checkout-payment-stack", className].filter(Boolean).join(" ") }, /* @__PURE__ */ import_react33.default.createElement(Card, null, /* @__PURE__ */ import_react33.default.createElement(SectionHeader, { title: t("payment.title") }), !isFree && /* @__PURE__ */ import_react33.default.createElement(import_react33.default.Fragment, null, !singleCard && /* @__PURE__ */ import_react33.default.createElement("div", { className: "tf-checkout-payment__label" }, t("payment.method")), !methods ? /* @__PURE__ */ import_react33.default.createElement("div", { className: "tf-checkout-payment__cardbox" }, /* @__PURE__ */ import_react33.default.createElement(Loader, null)) : singleCard ? paymentInput : /* @__PURE__ */ import_react33.default.createElement(
8462
8715
  PaymentMethods,
8463
8716
  {
8464
8717
  options,
@@ -8499,7 +8752,7 @@ var Payment = ({
8499
8752
  loading: finalizing,
8500
8753
  disabled: checkout.isBusy || finalizing || !isFree && !methods
8501
8754
  },
8502
- finalizing ? "Placing\u2026" : payLabel
8755
+ finalizing ? t("payment.placing") : payLabel
8503
8756
  )), bottomError && /* @__PURE__ */ import_react33.default.createElement("p", { className: "tf-checkout-error-text" }, bottomError));
8504
8757
  };
8505
8758
 
@@ -8546,6 +8799,7 @@ var Confirmation = ({
8546
8799
  children,
8547
8800
  className
8548
8801
  }) => {
8802
+ const t = useT();
8549
8803
  const checkout = useCheckoutContext();
8550
8804
  const order = checkout.order;
8551
8805
  const [copied, setCopied] = (0, import_react35.useState)(false);
@@ -8579,7 +8833,7 @@ var Confirmation = ({
8579
8833
  () => void 0
8580
8834
  );
8581
8835
  };
8582
- return /* @__PURE__ */ import_react35.default.createElement(Card, { className: cx("tf-checkout-confirmation", className) }, /* @__PURE__ */ import_react35.default.createElement("span", { className: "tf-checkout-confirmation__check" }, pending ? "\u23F3" : "\u2713"), /* @__PURE__ */ import_react35.default.createElement("strong", { className: "tf-checkout-confirmation__title" }, pending ? "Payment pending" : "Your Tickets are Confirmed!"), /* @__PURE__ */ import_react35.default.createElement("p", { className: "tf-checkout-note" }, pending ? "We\u2019ll email your tickets as soon as the payment settles." : order.alreadyPaid ? "This order was already paid \u2014 nothing was charged again." : "Your tickets are available in the My Tickets section \u2014 please bring them with you to the event."), order.orderHash && /* @__PURE__ */ import_react35.default.createElement("p", { className: "tf-checkout-confirmation__ref" }, "Reference: ", order.orderHash), pending && order.pendingVoucherUrl && /* @__PURE__ */ import_react35.default.createElement(
8836
+ return /* @__PURE__ */ import_react35.default.createElement(Card, { className: cx("tf-checkout-confirmation", className) }, /* @__PURE__ */ import_react35.default.createElement("span", { className: "tf-checkout-confirmation__check" }, pending ? "\u23F3" : "\u2713"), /* @__PURE__ */ import_react35.default.createElement("strong", { className: "tf-checkout-confirmation__title" }, pending ? t("confirmation.pending") : t("confirmation.confirmed")), /* @__PURE__ */ import_react35.default.createElement("p", { className: "tf-checkout-note" }, pending ? t("confirmation.pendingBody") : order.alreadyPaid ? t("confirmation.alreadyPaid") : t("confirmation.available")), order.orderHash && /* @__PURE__ */ import_react35.default.createElement("p", { className: "tf-checkout-confirmation__ref" }, "Reference: ", order.orderHash), pending && order.pendingVoucherUrl && /* @__PURE__ */ import_react35.default.createElement(
8583
8837
  "a",
8584
8838
  {
8585
8839
  className: "tf-checkout-button tf-checkout-button--secondary tf-checkout-button--block",
@@ -8595,7 +8849,7 @@ var Confirmation = ({
8595
8849
  href: viewOrderUrl
8596
8850
  },
8597
8851
  "View my tickets"
8598
- ), children, !pending && url && /* @__PURE__ */ import_react35.default.createElement("div", { className: "tf-checkout-confirmation__share" }, /* @__PURE__ */ import_react35.default.createElement("strong", null, "Your tickets can be cheaper \u2014 or even FREE!"), /* @__PURE__ */ import_react35.default.createElement("p", { className: "tf-checkout-note" }, "Invite friends with your link. When they buy, you get rewarded."), /* @__PURE__ */ import_react35.default.createElement("div", { className: "tf-checkout-confirmation__share-link" }, /* @__PURE__ */ import_react35.default.createElement("input", { className: "tf-checkout-input", readOnly: true, value: url }), /* @__PURE__ */ import_react35.default.createElement(Button, { variant: "secondary", onClick: copy }, copied ? "Copied!" : "Copy link")), /* @__PURE__ */ import_react35.default.createElement("div", { className: "tf-checkout-confirmation__socials" }, shares.map((s) => /* @__PURE__ */ import_react35.default.createElement(
8852
+ ), children, !pending && url && /* @__PURE__ */ import_react35.default.createElement("div", { className: "tf-checkout-confirmation__share" }, /* @__PURE__ */ import_react35.default.createElement("strong", null, t("referral.cheaperOrFree")), /* @__PURE__ */ import_react35.default.createElement("p", { className: "tf-checkout-note" }, "Invite friends with your link. When they buy, you get rewarded."), /* @__PURE__ */ import_react35.default.createElement("div", { className: "tf-checkout-confirmation__share-link" }, /* @__PURE__ */ import_react35.default.createElement("input", { className: "tf-checkout-input", readOnly: true, value: url }), /* @__PURE__ */ import_react35.default.createElement(Button, { variant: "secondary", onClick: copy }, copied ? t("referral.copied") : t("referral.copyLink"))), /* @__PURE__ */ import_react35.default.createElement("div", { className: "tf-checkout-confirmation__socials" }, shares.map((s) => /* @__PURE__ */ import_react35.default.createElement(
8599
8853
  "a",
8600
8854
  {
8601
8855
  key: s.label,
@@ -9011,32 +9265,41 @@ var EmbeddedCheckout = ({
9011
9265
  locale,
9012
9266
  messages,
9013
9267
  className
9014
- }) => /* @__PURE__ */ import_react38.default.createElement(CheckoutProvider, { theme, locale, messages, className }, /* @__PURE__ */ import_react38.default.createElement(
9015
- Flow,
9268
+ }) => /* @__PURE__ */ import_react38.default.createElement(
9269
+ CheckoutProvider,
9016
9270
  {
9017
- key: eventId,
9018
- eventId,
9019
- onComplete,
9020
- confirmationMode,
9021
- initialView,
9022
- onViewChange,
9023
- autoScroll,
9024
- requireEmailConfirmation,
9025
- collectTicketHolders,
9026
- collectHolderContact,
9027
- onLogin,
9028
- auth,
9029
- skipBillingWhenProfileComplete,
9030
- ttfOptInLabel,
9031
- brandOptInLabel,
9032
- privacyPolicy,
9033
- additionalConditions,
9034
- initialPromoCode,
9035
- referrer,
9036
- readAttributionFromUrl,
9037
- showTestCardHint
9038
- }
9039
- ));
9271
+ theme,
9272
+ locale,
9273
+ messages,
9274
+ className
9275
+ },
9276
+ /* @__PURE__ */ import_react38.default.createElement(
9277
+ Flow,
9278
+ {
9279
+ key: eventId,
9280
+ eventId,
9281
+ onComplete,
9282
+ confirmationMode,
9283
+ initialView,
9284
+ onViewChange,
9285
+ autoScroll,
9286
+ requireEmailConfirmation,
9287
+ collectTicketHolders,
9288
+ collectHolderContact,
9289
+ onLogin,
9290
+ auth,
9291
+ skipBillingWhenProfileComplete,
9292
+ ttfOptInLabel,
9293
+ brandOptInLabel,
9294
+ privacyPolicy,
9295
+ additionalConditions,
9296
+ initialPromoCode,
9297
+ referrer,
9298
+ readAttributionFromUrl,
9299
+ showTestCardHint
9300
+ }
9301
+ )
9302
+ );
9040
9303
 
9041
9304
  // src/ResumedCheckout.tsx
9042
9305
  var import_react39 = __toESM(require("react"));