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.esm.js CHANGED
@@ -2461,22 +2461,29 @@ var getOrderReview = async (orderHash) => {
2461
2461
  };
2462
2462
  };
2463
2463
  var mapProfileToBilling = (profile) => {
2464
- var _a, _b, _c;
2464
+ var _a, _b, _c, _d;
2465
2465
  const str = (v) => v == null || v === "" ? void 0 : String(v);
2466
2466
  const idStr = (v) => {
2467
2467
  const s = str(v);
2468
2468
  return s === void 0 || s === "0" || s === "-1" ? void 0 : s;
2469
2469
  };
2470
+ const dobParts = /^(\d{4})-(\d{2})-(\d{2})/.exec((_a = profile.dateOfBirth) != null ? _a : "");
2471
+ const dob = dobParts && Number(dobParts[1]) > 1900 ? {
2472
+ dobYear: Number(dobParts[1]),
2473
+ dobMonth: Number(dobParts[2]),
2474
+ dobDay: Number(dobParts[3])
2475
+ } : {};
2470
2476
  return {
2471
- firstName: (_a = profile.firstName) != null ? _a : "",
2472
- lastName: (_b = profile.lastName) != null ? _b : "",
2473
- email: (_c = profile.email) != null ? _c : "",
2477
+ firstName: (_b = profile.firstName) != null ? _b : "",
2478
+ lastName: (_c = profile.lastName) != null ? _c : "",
2479
+ email: (_d = profile.email) != null ? _d : "",
2474
2480
  phone: str(profile.phone),
2475
2481
  streetAddress: str(profile.streetAddress),
2476
2482
  city: str(profile.city),
2477
2483
  zip: str(profile.zipCode),
2478
2484
  countryId: idStr(profile.countryId),
2479
- stateId: idStr(profile.stateId)
2485
+ stateId: idStr(profile.stateId),
2486
+ ...dob
2480
2487
  };
2481
2488
  };
2482
2489
  var completeFreeRegistration = async (orderHash) => {
@@ -3401,6 +3408,10 @@ var createEngine = (config) => {
3401
3408
  reset: () => {
3402
3409
  clearCartGuestToken();
3403
3410
  store.reset();
3411
+ },
3412
+ expireCart: () => {
3413
+ clearCartGuestToken();
3414
+ store.expireCart();
3404
3415
  }
3405
3416
  };
3406
3417
  };
@@ -3907,6 +3918,12 @@ var useCheckout = (config) => {
3907
3918
  return () => clearInterval(t);
3908
3919
  }, [snapshot.expiresAt]);
3909
3920
  const secondsLeft = snapshot.expiresAt != null ? Math.max(0, Math.round((snapshot.expiresAt - now) / 1e3)) : void 0;
3921
+ useEffect(() => {
3922
+ if (secondsLeft !== 0) return;
3923
+ if (snapshot.status === "placing" || snapshot.status === "succeeded") return;
3924
+ if (snapshot.status === "expired") return;
3925
+ engine.expireCart();
3926
+ }, [engine, secondsLeft, snapshot.status]);
3910
3927
  const missingRequiredAddonNames = missingRequiredAddOns(
3911
3928
  snapshot.requiredAddOns,
3912
3929
  snapshot.addOns
@@ -4086,7 +4103,91 @@ var en = {
4086
4103
  "referral.inviteFriends": "Invite friends",
4087
4104
  "referral.howToInvite": "How do you invite your friends?",
4088
4105
  "referral.sendThisLink": "Send them this link:",
4089
- "referral.howMuchCheaper": "How much cheaper?"
4106
+ "referral.howMuchCheaper": "How much cheaper?",
4107
+ // --- Checkout body (localization pass) ---------------------------------
4108
+ "common.submit": "Submit",
4109
+ "common.each": "each",
4110
+ "billing.heading": "Billing Information",
4111
+ "billing.continueToPayment": "Continue to payment",
4112
+ "billing.ttfOptIn": "Keep me updated about future events from The Ticket Fairy",
4113
+ "billing.fieldRequired": "This field is required.",
4114
+ "billing.firstNamePlaceholder": "First name *",
4115
+ "billing.lastNamePlaceholder": "Last name *",
4116
+ "billing.emailMustMatch": "Email addresses must match.",
4117
+ "billing.emailInvalid": "Enter a valid email address.",
4118
+ "billing.emailRegistered": "This email is already registered.",
4119
+ "billing.loginAutofill": "Log in to autofill your details",
4120
+ "billing.loginAutofillPlain": "Log in to autofill your details.",
4121
+ "billing.firstNameRequired": "First name is required.",
4122
+ "billing.lastNameRequired": "Last name is required.",
4123
+ "billing.streetRequired": "Street address is required.",
4124
+ "billing.cityRequired": "City is required.",
4125
+ "billing.postcodeRequired": "ZIP / postcode is required.",
4126
+ "billing.countryRequired": "Country is required.",
4127
+ "billing.stateRequired": "State / county is required.",
4128
+ "billing.countryEmpty": "\u2014 country * \u2014",
4129
+ "billing.stateEmpty": "\u2014 state / county \u2014",
4130
+ "billing.stateEmptyRequired": "\u2014 state / county * \u2014",
4131
+ "billing.holderTitle": "Ticket {{number}}",
4132
+ "billing.nationality": "Nationality",
4133
+ "billing.gender": "Gender",
4134
+ "billing.instagramHandle": "Instagram handle",
4135
+ "billing.phoneOptional": "Phone",
4136
+ "billing.phoneAria": "Phone",
4137
+ "billing.phoneInvalid": "Enter a valid phone number.",
4138
+ "billing.phonePlaceholder": "Phone number",
4139
+ "billing.dob": "Date of birth *",
4140
+ "billing.dobWithAge": "Date of birth * (must be {{age}}+)",
4141
+ "billing.dobRequired": "Date of birth is required.",
4142
+ "billing.ageMinimum": "You must be {{age}} or older.",
4143
+ "billing.privacyAgree": "I have read and agree to {{brand}}",
4144
+ "billing.privacyLink": "Privacy Policy.",
4145
+ "tickets.getTickets": "Get tickets",
4146
+ "tickets.selectOnMap": "Select on map",
4147
+ "tickets.selectSeats": "Select seats",
4148
+ "tickets.hideInfo": "Hide info",
4149
+ "tickets.viewInfo": "View info",
4150
+ "tickets.salesNotStarted": "Sales not started",
4151
+ "tickets.salesEnded": "Sales Ended",
4152
+ "tickets.accessCode": "Access code",
4153
+ "tickets.promoCode": "Promo code",
4154
+ "tickets.reserving": "Reserving\u2026",
4155
+ "addons.eyebrow": "Get Your Tickets",
4156
+ "addons.heading": "UPGRADES & ADD-ONS",
4157
+ "addons.confirmSelection": "CONFIRM SELECTION",
4158
+ "addons.updating": "Updating\u2026",
4159
+ "payment.title": "Payment",
4160
+ "payment.card": "Card",
4161
+ "payment.paymentPlan": "Payment plan",
4162
+ "payment.oxxo": "OXXO (pay in cash)",
4163
+ "payment.submitPayment": "Submit Payment",
4164
+ "payment.completeRegistration": "Complete Registration",
4165
+ "payment.placing": "Placing\u2026",
4166
+ "payment.testCard": "Test card: 4242 4242 4242 4242 \xB7 any future date \xB7 any CVC",
4167
+ "payment.testCardXendit": "Test card: 4000 0000 0000 0002 \xB7 any future date \xB7 any CVC",
4168
+ "confirmation.pending": "Payment pending",
4169
+ "confirmation.confirmed": "Your Tickets are Confirmed!",
4170
+ "confirmation.pendingBody": "We\u2019ll email your tickets as soon as the payment settles.",
4171
+ "confirmation.alreadyPaid": "This order was already paid \u2014 nothing was charged again.",
4172
+ "confirmation.available": "Your tickets are available in the My Tickets section \u2014 please bring them with you to the event.",
4173
+ "referral.copied": "Copied!",
4174
+ "referral.copyLink": "Copy link",
4175
+ "timer.completePurchase": "Please complete your purchase before the timer reaches zero.",
4176
+ "auth.logIn": "Log in",
4177
+ "auth.signUp": "Sign Up",
4178
+ "auth.passwordReset": "Password reset",
4179
+ "auth.backToLogin": "Back to log in",
4180
+ "auth.sendResetInstructions": "Send reset instructions",
4181
+ "auth.createAccount": "Create Account",
4182
+ "auth.forgotPassword": "Forgot password?",
4183
+ "auth.forgotIntro": "Enter your email and we\u2019ll send you instructions to reset your password.",
4184
+ "auth.missingToken": "This password-reset link is missing its token.",
4185
+ "auth.passwordTooShort": "Password must have at least 8 characters.",
4186
+ "auth.passwordNeedsSpecial": "Password must contain at least one special character.",
4187
+ "auth.passwordsMustMatch": "Passwords must match.",
4188
+ "auth.passwordChanged": "Your password has been changed. You can now log in.",
4189
+ "auth.selectState": "Select state / region",
4190
+ "auth.notRequired": "Not required"
4090
4191
  };
4091
4192
 
4092
4193
  // ../tf-checkout-shared/src/i18n/resolve.ts
@@ -4218,7 +4319,91 @@ var esMX = {
4218
4319
  "referral.inviteFriends": "Invita a tus amigos",
4219
4320
  "referral.howToInvite": "\xBFC\xF3mo invitas a tus amigos?",
4220
4321
  "referral.sendThisLink": "Env\xEDales este enlace:",
4221
- "referral.howMuchCheaper": "\xBFCu\xE1nto m\xE1s barato?"
4322
+ "referral.howMuchCheaper": "\xBFCu\xE1nto m\xE1s barato?",
4323
+ // --- Checkout body (localization pass) ---------------------------------
4324
+ "common.submit": "Enviar",
4325
+ "common.each": "c/u",
4326
+ "billing.heading": "Informaci\xF3n de facturaci\xF3n",
4327
+ "billing.continueToPayment": "Continuar al pago",
4328
+ "billing.ttfOptIn": "Quiero recibir novedades sobre pr\xF3ximos eventos de The Ticket Fairy",
4329
+ "billing.fieldRequired": "Este campo es obligatorio.",
4330
+ "billing.firstNamePlaceholder": "Nombre *",
4331
+ "billing.lastNamePlaceholder": "Apellido *",
4332
+ "billing.emailMustMatch": "Los correos electr\xF3nicos deben coincidir.",
4333
+ "billing.emailInvalid": "Ingresa un correo electr\xF3nico v\xE1lido.",
4334
+ "billing.emailRegistered": "Este correo ya est\xE1 registrado.",
4335
+ "billing.loginAutofill": "Inicia sesi\xF3n para completar tus datos",
4336
+ "billing.loginAutofillPlain": "Inicia sesi\xF3n para completar tus datos.",
4337
+ "billing.firstNameRequired": "El nombre es obligatorio.",
4338
+ "billing.lastNameRequired": "El apellido es obligatorio.",
4339
+ "billing.streetRequired": "La calle y n\xFAmero son obligatorios.",
4340
+ "billing.cityRequired": "La ciudad es obligatoria.",
4341
+ "billing.postcodeRequired": "El c\xF3digo postal es obligatorio.",
4342
+ "billing.countryRequired": "El pa\xEDs es obligatorio.",
4343
+ "billing.stateRequired": "El estado es obligatorio.",
4344
+ "billing.countryEmpty": "\u2014 pa\xEDs * \u2014",
4345
+ "billing.stateEmpty": "\u2014 estado \u2014",
4346
+ "billing.stateEmptyRequired": "\u2014 estado * \u2014",
4347
+ "billing.holderTitle": "Boleto {{number}}",
4348
+ "billing.nationality": "Nacionalidad",
4349
+ "billing.gender": "G\xE9nero",
4350
+ "billing.instagramHandle": "Usuario de Instagram",
4351
+ "billing.phoneOptional": "Tel\xE9fono",
4352
+ "billing.phoneAria": "Tel\xE9fono",
4353
+ "billing.phoneInvalid": "Ingresa un n\xFAmero de tel\xE9fono v\xE1lido.",
4354
+ "billing.phonePlaceholder": "N\xFAmero de tel\xE9fono",
4355
+ "billing.dob": "Fecha de nacimiento *",
4356
+ "billing.dobWithAge": "Fecha de nacimiento * (debes tener {{age}}+)",
4357
+ "billing.dobRequired": "La fecha de nacimiento es obligatoria.",
4358
+ "billing.ageMinimum": "Debes tener {{age}} a\xF1os o m\xE1s.",
4359
+ "billing.privacyAgree": "He le\xEDdo y acepto el",
4360
+ "billing.privacyLink": "Aviso de Privacidad.",
4361
+ "tickets.getTickets": "Comprar boletos",
4362
+ "tickets.selectOnMap": "Seleccionar en el mapa",
4363
+ "tickets.selectSeats": "Seleccionar asientos",
4364
+ "tickets.hideInfo": "Ocultar informaci\xF3n",
4365
+ "tickets.viewInfo": "Ver informaci\xF3n",
4366
+ "tickets.salesNotStarted": "Venta no iniciada",
4367
+ "tickets.salesEnded": "Venta finalizada",
4368
+ "tickets.accessCode": "C\xF3digo de acceso",
4369
+ "tickets.promoCode": "C\xF3digo promocional",
4370
+ "tickets.reserving": "Reservando\u2026",
4371
+ "addons.eyebrow": "Obt\xE9n tus boletos",
4372
+ "addons.heading": "MEJORAS Y COMPLEMENTOS",
4373
+ "addons.confirmSelection": "CONFIRMAR SELECCI\xD3N",
4374
+ "addons.updating": "Actualizando\u2026",
4375
+ "payment.title": "Pago",
4376
+ "payment.card": "Tarjeta",
4377
+ "payment.paymentPlan": "Plan de pagos",
4378
+ "payment.oxxo": "OXXO (pago en efectivo)",
4379
+ "payment.submitPayment": "Pagar",
4380
+ "payment.completeRegistration": "Completar registro",
4381
+ "payment.placing": "Procesando\u2026",
4382
+ "payment.testCard": "Tarjeta de prueba: 4242 4242 4242 4242 \xB7 cualquier fecha futura \xB7 cualquier CVC",
4383
+ "payment.testCardXendit": "Tarjeta de prueba: 4000 0000 0000 0002 \xB7 cualquier fecha futura \xB7 cualquier CVC",
4384
+ "confirmation.pending": "Pago pendiente",
4385
+ "confirmation.confirmed": "\xA1Tus boletos est\xE1n confirmados!",
4386
+ "confirmation.pendingBody": "Te enviaremos tus boletos por correo en cuanto se acredite el pago.",
4387
+ "confirmation.alreadyPaid": "Esta orden ya estaba pagada: no se te cobr\xF3 de nuevo.",
4388
+ "confirmation.available": "Tus boletos est\xE1n disponibles en la secci\xF3n Mis boletos. Recuerda llevarlos contigo al evento.",
4389
+ "referral.copied": "\xA1Copiado!",
4390
+ "referral.copyLink": "Copiar enlace",
4391
+ "timer.completePurchase": "Completa tu compra antes de que el temporizador llegue a cero.",
4392
+ "auth.logIn": "Iniciar sesi\xF3n",
4393
+ "auth.signUp": "Crear cuenta",
4394
+ "auth.passwordReset": "Restablecer contrase\xF1a",
4395
+ "auth.backToLogin": "Volver a iniciar sesi\xF3n",
4396
+ "auth.sendResetInstructions": "Enviar instrucciones",
4397
+ "auth.createAccount": "Crear cuenta",
4398
+ "auth.forgotPassword": "\xBFOlvidaste tu contrase\xF1a?",
4399
+ "auth.forgotIntro": "Ingresa tu correo y te enviaremos instrucciones para restablecer tu contrase\xF1a.",
4400
+ "auth.missingToken": "A este enlace de restablecimiento le falta el token.",
4401
+ "auth.passwordTooShort": "La contrase\xF1a debe tener al menos 8 caracteres.",
4402
+ "auth.passwordNeedsSpecial": "La contrase\xF1a debe incluir al menos un car\xE1cter especial.",
4403
+ "auth.passwordsMustMatch": "Las contrase\xF1as deben coincidir.",
4404
+ "auth.passwordChanged": "Tu contrase\xF1a se cambi\xF3. Ya puedes iniciar sesi\xF3n.",
4405
+ "auth.selectState": "Selecciona estado / regi\xF3n",
4406
+ "auth.notRequired": "No requerido"
4222
4407
  };
4223
4408
 
4224
4409
  // ../tf-checkout-shared/src/i18n/locales/index.ts
@@ -5117,6 +5302,7 @@ Button.displayName = "Button";
5117
5302
 
5118
5303
  // src/ui/InstallmentPicker.tsx
5119
5304
  var useInstallmentPicker = () => {
5305
+ const t = useT();
5120
5306
  const [pending, setPending] = useState4(null);
5121
5307
  const onInstallmentOffers = useCallback3(
5122
5308
  (offers) => new Promise((resolve) => setPending({ offers, resolve })),
@@ -5131,9 +5317,9 @@ var useInstallmentPicker = () => {
5131
5317
  {
5132
5318
  className: "tf-checkout-installments",
5133
5319
  role: "dialog",
5134
- "aria-label": "Choose installments"
5320
+ "aria-label": t("payment.chooseInstallments")
5135
5321
  },
5136
- /* @__PURE__ */ React5.createElement("div", { className: "tf-checkout-installments__box" }, /* @__PURE__ */ React5.createElement("strong", null, "Pay in installments?"), /* @__PURE__ */ React5.createElement("div", { className: "tf-checkout-installments__list" }, pending.offers.map((o, i) => {
5322
+ /* @__PURE__ */ React5.createElement("div", { className: "tf-checkout-installments__box" }, /* @__PURE__ */ React5.createElement("strong", null, t("payment.payInInstallments")), /* @__PURE__ */ React5.createElement("div", { className: "tf-checkout-installments__list" }, pending.offers.map((o, i) => {
5137
5323
  var _a;
5138
5324
  return /* @__PURE__ */ React5.createElement(
5139
5325
  "button",
@@ -5479,63 +5665,73 @@ var PaymentMethods = ({
5479
5665
  children,
5480
5666
  inputSlotFor,
5481
5667
  className
5482
- }) => /* @__PURE__ */ React10.createElement(
5483
- "div",
5484
- {
5485
- className: cx("tf-checkout-payment__methods", className),
5486
- role: "radiogroup",
5487
- "aria-label": "Payment method"
5488
- },
5489
- options.map((o) => {
5490
- var _a, _b, _c, _d, _e, _f;
5491
- const isSelected = o.value === selected;
5492
- const extraValue = o.extra === "phoneNumber" ? (_a = extraValues[o.value]) == null ? void 0 : _a.phoneNumber : (_b = extraValues[o.value]) == null ? void 0 : _b.cashtag;
5493
- const extraInvalid = Boolean(isSelected && o.extra && showValidation) && !(extraValue == null ? void 0 : extraValue.trim());
5494
- return /* @__PURE__ */ React10.createElement(
5495
- "label",
5496
- {
5497
- key: o.value,
5498
- className: cx(
5499
- "tf-checkout-payment__method",
5500
- isSelected && "tf-checkout-payment__method--selected"
5501
- )
5502
- },
5503
- /* @__PURE__ */ React10.createElement("span", { className: "tf-checkout-payment__method-head" }, /* @__PURE__ */ React10.createElement(
5504
- "input",
5505
- {
5506
- type: "radio",
5507
- name: "tf-pay-method",
5508
- className: "tf-checkout-payment__method-radio",
5509
- checked: isSelected,
5510
- onChange: () => onSelect(o.value)
5511
- }
5512
- ), o.iconUrl && /* @__PURE__ */ React10.createElement("img", { className: "tf-checkout-payment__method-icon", src: o.iconUrl, alt: "" }), /* @__PURE__ */ React10.createElement("span", { className: "tf-checkout-payment__method-label" }, o.label)),
5513
- isSelected && (o.value === inputSlotFor || o.extra) && /* @__PURE__ */ React10.createElement("div", { className: "tf-checkout-payment__method-body" }, o.value === inputSlotFor && children, o.extra && /* @__PURE__ */ React10.createElement(
5514
- Field,
5668
+ }) => {
5669
+ const t = useT();
5670
+ return /* @__PURE__ */ React10.createElement(
5671
+ "div",
5672
+ {
5673
+ className: cx("tf-checkout-payment__methods", className),
5674
+ role: "radiogroup",
5675
+ "aria-label": t("payment.method")
5676
+ },
5677
+ options.map((o) => {
5678
+ var _a, _b, _c, _d, _e, _f;
5679
+ const isSelected = o.value === selected;
5680
+ const extraValue = o.extra === "phoneNumber" ? (_a = extraValues[o.value]) == null ? void 0 : _a.phoneNumber : (_b = extraValues[o.value]) == null ? void 0 : _b.cashtag;
5681
+ const extraInvalid = Boolean(isSelected && o.extra && showValidation) && !(extraValue == null ? void 0 : extraValue.trim());
5682
+ return /* @__PURE__ */ React10.createElement(
5683
+ "label",
5515
5684
  {
5516
- label: `${EXTRA_LABEL[o.extra]} *`,
5517
- error: extraInvalid ? "This field is required." : void 0,
5518
- invalid: extraInvalid
5685
+ key: o.value,
5686
+ className: cx(
5687
+ "tf-checkout-payment__method",
5688
+ isSelected && "tf-checkout-payment__method--selected"
5689
+ )
5519
5690
  },
5520
- /* @__PURE__ */ React10.createElement(
5521
- Input,
5691
+ /* @__PURE__ */ React10.createElement("span", { className: "tf-checkout-payment__method-head" }, /* @__PURE__ */ React10.createElement(
5692
+ "input",
5522
5693
  {
5523
- inputMode: o.extra === "phoneNumber" ? "tel" : "text",
5524
- required: true,
5525
- invalid: extraInvalid,
5526
- "aria-invalid": extraInvalid,
5527
- placeholder: o.extra === "phoneNumber" ? "e.g. 081234567890" : "$cashtag",
5528
- 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 : "",
5529
- onChange: (e) => onExtraChange(
5530
- o.value,
5531
- o.extra === "phoneNumber" ? { phoneNumber: e.target.value } : { cashtag: e.target.value }
5532
- )
5694
+ type: "radio",
5695
+ name: "tf-pay-method",
5696
+ className: "tf-checkout-payment__method-radio",
5697
+ checked: isSelected,
5698
+ onChange: () => onSelect(o.value)
5533
5699
  }
5534
- )
5535
- ))
5536
- );
5537
- })
5538
- );
5700
+ ), o.iconUrl && /* @__PURE__ */ React10.createElement(
5701
+ "img",
5702
+ {
5703
+ className: "tf-checkout-payment__method-icon",
5704
+ src: o.iconUrl,
5705
+ alt: ""
5706
+ }
5707
+ ), /* @__PURE__ */ React10.createElement("span", { className: "tf-checkout-payment__method-label" }, o.label)),
5708
+ isSelected && (o.value === inputSlotFor || o.extra) && /* @__PURE__ */ React10.createElement("div", { className: "tf-checkout-payment__method-body" }, o.value === inputSlotFor && children, o.extra && /* @__PURE__ */ React10.createElement(
5709
+ Field,
5710
+ {
5711
+ label: `${EXTRA_LABEL[o.extra]} *`,
5712
+ error: extraInvalid ? t("billing.fieldRequired") : void 0,
5713
+ invalid: extraInvalid
5714
+ },
5715
+ /* @__PURE__ */ React10.createElement(
5716
+ Input,
5717
+ {
5718
+ inputMode: o.extra === "phoneNumber" ? "tel" : "text",
5719
+ required: true,
5720
+ invalid: extraInvalid,
5721
+ "aria-invalid": extraInvalid,
5722
+ placeholder: o.extra === "phoneNumber" ? "e.g. 081234567890" : "$cashtag",
5723
+ 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 : "",
5724
+ onChange: (e) => onExtraChange(
5725
+ o.value,
5726
+ o.extra === "phoneNumber" ? { phoneNumber: e.target.value } : { cashtag: e.target.value }
5727
+ )
5728
+ }
5729
+ )
5730
+ ))
5731
+ );
5732
+ })
5733
+ );
5734
+ };
5539
5735
 
5540
5736
  // src/ui/Stepper.tsx
5541
5737
  import React11 from "react";
@@ -5624,9 +5820,10 @@ var clock2 = (s) => {
5624
5820
  var TimerBanner = ({
5625
5821
  seconds,
5626
5822
  urgentAt = 60,
5627
- message = "Please complete your purchase before the timer reaches zero.",
5823
+ message,
5628
5824
  className
5629
5825
  }) => {
5826
+ const t = useT();
5630
5827
  const [dismissed, setDismissed] = useState6(false);
5631
5828
  if (seconds === void 0 || seconds <= 0 || dismissed) return null;
5632
5829
  const urgent = seconds <= urgentAt;
@@ -5640,14 +5837,14 @@ var TimerBanner = ({
5640
5837
  className
5641
5838
  )
5642
5839
  },
5643
- /* @__PURE__ */ React15.createElement("span", { className: "tf-checkout-timerbanner__msg" }, message),
5840
+ /* @__PURE__ */ React15.createElement("span", { className: "tf-checkout-timerbanner__msg" }, message != null ? message : t("timer.completePurchase")),
5644
5841
  /* @__PURE__ */ React15.createElement("span", { className: "tf-checkout-timerbanner__clock" }, clock2(seconds)),
5645
5842
  /* @__PURE__ */ React15.createElement(
5646
5843
  "button",
5647
5844
  {
5648
5845
  type: "button",
5649
5846
  className: "tf-checkout-timerbanner__close",
5650
- "aria-label": "Dismiss",
5847
+ "aria-label": t("common.dismiss"),
5651
5848
  onClick: () => setDismissed(true)
5652
5849
  },
5653
5850
  "\xD7"
@@ -5680,9 +5877,9 @@ var ForgotPasswordForm = ({
5680
5877
  void onSubmit(email);
5681
5878
  };
5682
5879
  if (successMessage) {
5683
- return /* @__PURE__ */ React16.createElement("div", { className: "tf-checkout-auth__form" }, /* @__PURE__ */ React16.createElement("div", { className: "tf-checkout-auth__success", role: "status" }, successMessage), /* @__PURE__ */ React16.createElement(Button, { type: "button", block: true, onClick: () => onBackToLogin(email) }, "Back to log in"));
5880
+ return /* @__PURE__ */ React16.createElement("div", { className: "tf-checkout-auth__form" }, /* @__PURE__ */ React16.createElement("div", { className: "tf-checkout-auth__success", role: "status" }, successMessage), /* @__PURE__ */ React16.createElement(Button, { type: "button", block: true, onClick: () => onBackToLogin(email) }, t("auth.backToLogin")));
5684
5881
  }
5685
- return /* @__PURE__ */ React16.createElement("form", { className: "tf-checkout-auth__form", onSubmit: submit, noValidate: true }, /* @__PURE__ */ React16.createElement("p", { className: "tf-checkout-auth__intro" }, "Enter your email and we\u2019ll send you instructions to reset your password."), error && /* @__PURE__ */ React16.createElement("div", { className: "tf-checkout-auth__alert", role: "alert" }, error), /* @__PURE__ */ React16.createElement(Field, { label: t("auth.email"), error: errors.email }, /* @__PURE__ */ React16.createElement(
5882
+ return /* @__PURE__ */ React16.createElement("form", { className: "tf-checkout-auth__form", onSubmit: submit, noValidate: true }, /* @__PURE__ */ React16.createElement("p", { className: "tf-checkout-auth__intro" }, t("auth.forgotIntro")), error && /* @__PURE__ */ React16.createElement("div", { className: "tf-checkout-auth__alert", role: "alert" }, error), /* @__PURE__ */ React16.createElement(Field, { label: t("auth.email"), error: errors.email }, /* @__PURE__ */ React16.createElement(
5686
5883
  Input,
5687
5884
  {
5688
5885
  type: "email",
@@ -5697,14 +5894,14 @@ var ForgotPasswordForm = ({
5697
5894
  onFieldChange == null ? void 0 : onFieldChange();
5698
5895
  }
5699
5896
  }
5700
- )), /* @__PURE__ */ React16.createElement(Button, { type: "submit", block: true, loading }, "Send reset instructions"), /* @__PURE__ */ React16.createElement(
5897
+ )), /* @__PURE__ */ React16.createElement(Button, { type: "submit", block: true, loading }, t("auth.sendResetInstructions")), /* @__PURE__ */ React16.createElement(
5701
5898
  "button",
5702
5899
  {
5703
5900
  type: "button",
5704
5901
  className: "tf-checkout-auth__text-button tf-checkout-auth__back",
5705
5902
  onClick: () => onBackToLogin(email)
5706
5903
  },
5707
- "Back to log in"
5904
+ t("auth.backToLogin")
5708
5905
  ));
5709
5906
  };
5710
5907
 
@@ -5806,14 +6003,14 @@ var LoginForm = ({
5806
6003
  }
5807
6004
  }
5808
6005
  )
5809
- ), /* @__PURE__ */ React18.createElement(Button, { type: "submit", block: true, loading }, "Login"), allowPasswordReset && onForgotPassword && /* @__PURE__ */ React18.createElement(
6006
+ ), /* @__PURE__ */ React18.createElement(Button, { type: "submit", block: true, loading }, t("auth.logIn")), allowPasswordReset && onForgotPassword && /* @__PURE__ */ React18.createElement(
5810
6007
  "button",
5811
6008
  {
5812
6009
  type: "button",
5813
6010
  className: "tf-checkout-auth__text-button tf-checkout-auth__forgot",
5814
6011
  onClick: () => onForgotPassword(email)
5815
6012
  },
5816
- "Forgot password?"
6013
+ t("auth.forgotPassword")
5817
6014
  ));
5818
6015
  };
5819
6016
 
@@ -6040,7 +6237,7 @@ var RegisterForm = ({
6040
6237
  invalid: Boolean(errors.stateId),
6041
6238
  onChange: (event) => setField("stateId", event.target.value)
6042
6239
  },
6043
- /* @__PURE__ */ React19.createElement("option", { value: "" }, states.length > 0 ? "Select state / region" : "Not required"),
6240
+ /* @__PURE__ */ React19.createElement("option", { value: "" }, states.length > 0 ? t("auth.selectState") : t("auth.notRequired")),
6044
6241
  states.map((state) => /* @__PURE__ */ React19.createElement("option", { key: state.id, value: state.id }, state.name))
6045
6242
  )
6046
6243
  ), /* @__PURE__ */ React19.createElement(
@@ -6134,7 +6331,7 @@ var RegisterForm = ({
6134
6331
  }
6135
6332
  )
6136
6333
  )),
6137
- /* @__PURE__ */ React19.createElement(Button, { type: "submit", block: true, loading }, "Create Account")
6334
+ /* @__PURE__ */ React19.createElement(Button, { type: "submit", block: true, loading }, t("auth.createAccount"))
6138
6335
  );
6139
6336
  };
6140
6337
 
@@ -6173,6 +6370,8 @@ var AuthModal = ({
6173
6370
  const previouslyFocused = useRef4(null);
6174
6371
  const submittingRef = useRef4(auth.isSubmitting);
6175
6372
  submittingRef.current = auth.isSubmitting;
6373
+ const onCloseRef = useRef4(onClose);
6374
+ onCloseRef.current = onClose;
6176
6375
  useEffect7(() => {
6177
6376
  var _a, _b, _c;
6178
6377
  if (!open) return;
@@ -6193,7 +6392,7 @@ var AuthModal = ({
6193
6392
  initialFocus == null ? void 0 : initialFocus.focus();
6194
6393
  const onKeyDown = (event) => {
6195
6394
  var _a2;
6196
- if (event.key === "Escape" && !submittingRef.current) onClose();
6395
+ if (event.key === "Escape" && !submittingRef.current) onCloseRef.current();
6197
6396
  if (event.key !== "Tab") return;
6198
6397
  const elements = focusable();
6199
6398
  if (elements.length === 0) {
@@ -6218,13 +6417,13 @@ var AuthModal = ({
6218
6417
  document.body.style.overflow = previousOverflow;
6219
6418
  (_a2 = previouslyFocused.current) == null ? void 0 : _a2.focus();
6220
6419
  };
6221
- }, [onClose, open]);
6420
+ }, [open]);
6222
6421
  if (!open) return null;
6223
6422
  const closeFromBackdrop = (event) => {
6224
6423
  if (event.target === event.currentTarget && !auth.isSubmitting) onClose();
6225
6424
  };
6226
6425
  const isPasswordReset = auth.view === "forgot-password";
6227
- const title = isPasswordReset ? "Password reset" : "Ticket Fairy account";
6426
+ const title = isPasswordReset ? t("auth.passwordReset") : t("auth.title");
6228
6427
  return /* @__PURE__ */ React20.createElement("div", { className: cx("tf-checkout-auth", className), onMouseDown: closeFromBackdrop }, /* @__PURE__ */ React20.createElement(
6229
6428
  "div",
6230
6429
  {
@@ -6266,7 +6465,7 @@ var AuthModal = ({
6266
6465
  ),
6267
6466
  onClick: () => auth.showLogin(auth.suggestedEmail)
6268
6467
  },
6269
- "Login"
6468
+ t("auth.logIn")
6270
6469
  ),
6271
6470
  /* @__PURE__ */ React20.createElement(
6272
6471
  "button",
@@ -6280,7 +6479,7 @@ var AuthModal = ({
6280
6479
  ),
6281
6480
  onClick: () => auth.showRegister(auth.suggestedEmail)
6282
6481
  },
6283
- "Sign Up"
6482
+ t("auth.signUp")
6284
6483
  )
6285
6484
  ),
6286
6485
  logoUrl && /* @__PURE__ */ React20.createElement("div", { className: "tf-checkout-auth__logo-wrap" }, /* @__PURE__ */ React20.createElement(
@@ -6349,9 +6548,9 @@ var ResetPasswordForm = ({
6349
6548
  const validation = useMemo3(() => {
6350
6549
  if (!submitted) return {};
6351
6550
  return {
6352
- token: token ? "" : "This password-reset link is missing its token.",
6353
- password: password.length < 8 ? "Password must have at least 8 characters." : !/[@$!%*#?&]/.test(password) ? "Password must contain at least one special character." : "",
6354
- confirmation: password !== confirmation ? "Passwords must match." : ""
6551
+ token: token ? "" : t("auth.missingToken"),
6552
+ password: password.length < 8 ? t("auth.passwordTooShort") : !/[@$!%*#?&]/.test(password) ? t("auth.passwordNeedsSpecial") : "",
6553
+ confirmation: password !== confirmation ? t("auth.passwordsMustMatch") : ""
6355
6554
  };
6356
6555
  }, [confirmation, password, submitted, token]);
6357
6556
  const reset = hooks_exports.useResetPassword({
@@ -6368,7 +6567,7 @@ var ResetPasswordForm = ({
6368
6567
  reset.mutate({ token, password, passwordConfirmation: confirmation });
6369
6568
  };
6370
6569
  if (success) {
6371
- return /* @__PURE__ */ React21.createElement("div", { className: "tf-checkout-auth__form" }, /* @__PURE__ */ React21.createElement("div", { className: "tf-checkout-auth__success", role: "status" }, "Your password has been changed. You can now log in."), onBackToLogin && /* @__PURE__ */ React21.createElement(Button, { type: "button", block: true, onClick: onBackToLogin }, "Log in"));
6570
+ return /* @__PURE__ */ React21.createElement("div", { className: "tf-checkout-auth__form" }, /* @__PURE__ */ React21.createElement("div", { className: "tf-checkout-auth__success", role: "status" }, t("auth.passwordChanged")), onBackToLogin && /* @__PURE__ */ React21.createElement(Button, { type: "button", block: true, onClick: onBackToLogin }, t("auth.logIn")));
6372
6571
  }
6373
6572
  return /* @__PURE__ */ React21.createElement("form", { className: "tf-checkout-auth__form", onSubmit: submit, noValidate: true }, /* @__PURE__ */ React21.createElement("h2", { className: "tf-checkout-auth__title" }, t("auth.changePassword")), validation.token && /* @__PURE__ */ React21.createElement("div", { className: "tf-checkout-auth__alert", role: "alert" }, validation.token), reset.error && /* @__PURE__ */ React21.createElement("div", { className: "tf-checkout-auth__alert", role: "alert" }, errorMessage(reset.error)), /* @__PURE__ */ React21.createElement(Field, { label: t("auth.newPassword"), error: validation.password }, /* @__PURE__ */ React21.createElement(
6374
6573
  Input,
@@ -6392,7 +6591,7 @@ var ResetPasswordForm = ({
6392
6591
  invalid: Boolean(validation.confirmation),
6393
6592
  onChange: (event) => setConfirmation(event.target.value)
6394
6593
  }
6395
- )), /* @__PURE__ */ React21.createElement(Button, { type: "submit", block: true, loading: reset.isPending, disabled: !token }, "Submit"));
6594
+ )), /* @__PURE__ */ React21.createElement(Button, { type: "submit", block: true, loading: reset.isPending, disabled: !token }, t("common.submit")));
6396
6595
  };
6397
6596
 
6398
6597
  // src/sections/Tickets.tsx
@@ -6452,7 +6651,7 @@ var Tickets = ({
6452
6651
  eventId,
6453
6652
  title = false,
6454
6653
  onContinue,
6455
- buttonLabel = "Get tickets",
6654
+ buttonLabel,
6456
6655
  timeSlotDates,
6457
6656
  step,
6458
6657
  onSelectSeats,
@@ -6462,7 +6661,9 @@ var Tickets = ({
6462
6661
  className
6463
6662
  }) => {
6464
6663
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
6664
+ const tr = useT();
6465
6665
  const checkout = useCheckoutContext();
6666
+ const buttonText = buttonLabel != null ? buttonLabel : tr("tickets.getTickets");
6466
6667
  const ticketsQuery = hooks_exports.useTicketsWithMeta(eventId);
6467
6668
  const promoMeta = (_a = ticketsQuery.data) == null ? void 0 : _a.promo;
6468
6669
  const showWaitingList = (_c = (_b = ticketsQuery.data) == null ? void 0 : _b.showWaitingList) != null ? _c : false;
@@ -6548,7 +6749,7 @@ var Tickets = ({
6548
6749
  const seatMapRow = (t) => isSeated && !t.allowDirectPurchase;
6549
6750
  const hasSeatMapTickets = tickets.some(seatMapRow);
6550
6751
  const directPurchasable = tickets.filter((t) => !seatMapRow(t));
6551
- const seatCtaLabel = (eventInfo == null ? void 0 : eventInfo.tableMapEnabled) ? "Select on map" : "Select seats";
6752
+ const seatCtaLabel = (eventInfo == null ? void 0 : eventInfo.tableMapEnabled) ? tr("tickets.selectOnMap") : tr("tickets.selectSeats");
6552
6753
  const firstTableIndex = tickets.findIndex((t) => t.isTable);
6553
6754
  const firstTableId = firstTableIndex > 0 && tickets.slice(0, firstTableIndex).some((t) => !t.isTable) ? tickets[firstTableIndex].id : void 0;
6554
6755
  const prime = () => {
@@ -6581,7 +6782,7 @@ var Tickets = ({
6581
6782
  const ticketIndex = tickets.findIndex((candidate) => candidate.id === t.id);
6582
6783
  const previousTicket = ticketIndex > 0 ? tickets[ticketIndex - 1] : void 0;
6583
6784
  const startsNamedGroup = Boolean(t.groupName) && t.groupName !== (previousTicket == null ? void 0 : previousTicket.groupName);
6584
- return /* @__PURE__ */ React22.createElement(Fragment, { key: t.id }, startsNamedGroup ? /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__group" }, t.groupName) : t.id === firstTableId && /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__group" }, "Reserve tables"), /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__row-wrap" }, /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__row" }, /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__info" }, /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__name" }, /* @__PURE__ */ React22.createElement("span", null, t.name), t.descriptionRich && /* @__PURE__ */ React22.createElement(
6785
+ return /* @__PURE__ */ React22.createElement(Fragment, { key: t.id }, startsNamedGroup ? /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__group" }, t.groupName) : t.id === firstTableId && /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__group" }, tr("tickets.reserveTables")), /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__row-wrap" }, /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__row" }, /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__info" }, /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__name" }, /* @__PURE__ */ React22.createElement("span", null, t.name), t.descriptionRich && /* @__PURE__ */ React22.createElement(
6585
6786
  "button",
6586
6787
  {
6587
6788
  type: "button",
@@ -6590,7 +6791,7 @@ var Tickets = ({
6590
6791
  "aria-controls": `ticket-description-${t.id}`,
6591
6792
  onClick: () => setVisibleDescription((current2) => current2 === t.id ? null : t.id)
6592
6793
  },
6593
- visibleDescription === t.id ? "Hide info" : "View info"
6794
+ visibleDescription === t.id ? tr("tickets.hideInfo") : tr("tickets.viewInfo")
6594
6795
  )), /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__price" }, discounted && /* @__PURE__ */ React22.createElement("span", { className: "tf-checkout-tickets__old" }, money(sym, original)), /* @__PURE__ */ React22.createElement(
6595
6796
  "span",
6596
6797
  {
@@ -6600,7 +6801,7 @@ var Tickets = ({
6600
6801
  )
6601
6802
  },
6602
6803
  isFree ? "FREE" : money(sym, t.price)
6603
- ), !isFree && !t.soldOut && /* @__PURE__ */ React22.createElement("span", { className: "tf-checkout-tickets__fees" }, "(", money(sym, t.priceWithFees), " with fees)"), t.depositPercent != null && /* @__PURE__ */ React22.createElement("span", { className: "tf-checkout-tickets__deposit" }, t.depositPercent.toFixed(2), "% DEPOSIT"))), seatMapRow(t) ? null : unavailable ? /* @__PURE__ */ React22.createElement("span", { className: "tf-checkout-tickets__soldout" }, t.soldOut ? "Sold out" : notStarted ? "Sales not started" : "Sales Ended") : /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__qty" }, t.isTable && /* @__PURE__ */ React22.createElement("span", { className: "tf-checkout-tickets__guests" }, "Guests"), /* @__PURE__ */ React22.createElement(
6804
+ ), !isFree && !t.soldOut && /* @__PURE__ */ React22.createElement("span", { className: "tf-checkout-tickets__fees" }, "(", money(sym, t.priceWithFees), " with fees)"), t.depositPercent != null && /* @__PURE__ */ React22.createElement("span", { className: "tf-checkout-tickets__deposit" }, t.depositPercent.toFixed(2), "% DEPOSIT"))), seatMapRow(t) ? null : unavailable ? /* @__PURE__ */ React22.createElement("span", { className: "tf-checkout-tickets__soldout" }, t.soldOut ? tr("tickets.soldOut") : notStarted ? tr("tickets.salesNotStarted") : tr("tickets.salesEnded")) : /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__qty" }, t.isTable && /* @__PURE__ */ React22.createElement("span", { className: "tf-checkout-tickets__guests" }, tr("tickets.guests")), /* @__PURE__ */ React22.createElement(
6604
6805
  QuantitySelect,
6605
6806
  {
6606
6807
  value: (_a2 = qty[t.id]) != null ? _a2 : 0,
@@ -6647,7 +6848,7 @@ var Tickets = ({
6647
6848
  title: title || "",
6648
6849
  pills: listQuery.isFetching && !listQuery.isLoading ? /* @__PURE__ */ React22.createElement(Loader, null) : void 0
6649
6850
  }
6650
- ), listQuery.isLoading && /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__loading" }, /* @__PURE__ */ React22.createElement(Loader, { className: "tf-checkout-tickets__loading-spinner" })), listQuery.error && /* @__PURE__ */ React22.createElement("p", { className: "tf-checkout-error-text" }, listQuery.error.message), isTimeSlot && dates.length > 0 && /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__currency" }, /* @__PURE__ */ React22.createElement("span", { className: "tf-checkout-tickets__currency-label" }, "Date"), /* @__PURE__ */ React22.createElement(
6851
+ ), listQuery.isLoading && /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__loading" }, /* @__PURE__ */ React22.createElement(Loader, { className: "tf-checkout-tickets__loading-spinner" })), listQuery.error && /* @__PURE__ */ React22.createElement("p", { className: "tf-checkout-error-text" }, listQuery.error.message), isTimeSlot && dates.length > 0 && /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__currency" }, /* @__PURE__ */ React22.createElement("span", { className: "tf-checkout-tickets__currency-label" }, tr("common.date")), /* @__PURE__ */ React22.createElement(
6651
6852
  "select",
6652
6853
  {
6653
6854
  className: "tf-checkout-select",
@@ -6658,7 +6859,7 @@ var Tickets = ({
6658
6859
  }
6659
6860
  },
6660
6861
  dates.map((d) => /* @__PURE__ */ React22.createElement("option", { key: d, value: d }, d))
6661
- )), checkout.currency && checkout.currency.available.length > 1 && /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__currency" }, /* @__PURE__ */ React22.createElement("span", { className: "tf-checkout-tickets__currency-label" }, "Currency"), /* @__PURE__ */ React22.createElement(
6862
+ )), checkout.currency && checkout.currency.available.length > 1 && /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__currency" }, /* @__PURE__ */ React22.createElement("span", { className: "tf-checkout-tickets__currency-label" }, tr("common.currency")), /* @__PURE__ */ React22.createElement(
6662
6863
  "select",
6663
6864
  {
6664
6865
  className: "tf-checkout-select",
@@ -6666,7 +6867,7 @@ var Tickets = ({
6666
6867
  onChange: (e) => changeCurrency(e.target.value)
6667
6868
  },
6668
6869
  checkout.currency.available.map((c) => /* @__PURE__ */ React22.createElement("option", { key: c.code, value: c.code }, c.name, " (", c.code, ")"))
6669
- )), isTimeSlot && !slotQuery.isLoading && tickets.length === 0 && slotDate && /* @__PURE__ */ React22.createElement("p", { className: "tf-checkout-note" }, "No sessions available on this date."), isTimeSlot ? timeGroups.map((g) => /* @__PURE__ */ React22.createElement(Fragment, { key: g.time }, g.time && /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__slot-time" }, g.time), g.items.map(renderRow))) : tickets.map(renderRow), showCodeInput && /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__promo" }, !isAccess && !promoOpen ? /* @__PURE__ */ React22.createElement(
6870
+ )), isTimeSlot && !slotQuery.isLoading && tickets.length === 0 && slotDate && /* @__PURE__ */ React22.createElement("p", { className: "tf-checkout-note" }, tr("tickets.noSessions")), isTimeSlot ? timeGroups.map((g) => /* @__PURE__ */ React22.createElement(Fragment, { key: g.time }, g.time && /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__slot-time" }, g.time), g.items.map(renderRow))) : tickets.map(renderRow), showCodeInput && /* @__PURE__ */ React22.createElement("div", { className: "tf-checkout-tickets__promo" }, !isAccess && !promoOpen ? /* @__PURE__ */ React22.createElement(
6670
6871
  "button",
6671
6872
  {
6672
6873
  type: "button",
@@ -6677,7 +6878,7 @@ var Tickets = ({
6677
6878
  ) : /* @__PURE__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement(FieldRow, null, /* @__PURE__ */ React22.createElement(Field, null, /* @__PURE__ */ React22.createElement(
6678
6879
  Input,
6679
6880
  {
6680
- placeholder: isAccess ? "Access code" : "Promo code",
6881
+ placeholder: isAccess ? tr("tickets.accessCode") : tr("tickets.promoCode"),
6681
6882
  value: code,
6682
6883
  onChange: (e) => setCode(e.target.value),
6683
6884
  onKeyDown: (e) => e.key === "Enter" && applyCode()
@@ -6708,7 +6909,7 @@ var Tickets = ({
6708
6909
  loading: checkout.isBusy,
6709
6910
  disabled: checkout.isBusy || selected.length === 0
6710
6911
  },
6711
- checkout.isBusy ? "Reserving\u2026" : selectionIsTable ? "Reserve tables" : buttonLabel
6912
+ checkout.isBusy ? tr("tickets.reserving") : selectionIsTable ? tr("tickets.reserveTables") : buttonText
6712
6913
  ), hasSeatMapTickets && /* @__PURE__ */ React22.createElement(Button, { block: true, onClick: () => onSelectSeats == null ? void 0 : onSelectSeats() }, seatCtaLabel), (error || checkout.error) && /* @__PURE__ */ React22.createElement("p", { className: "tf-checkout-error-text" }, error || checkout.error));
6713
6914
  };
6714
6915
 
@@ -7074,13 +7275,17 @@ var AddOns = ({
7074
7275
  eventId,
7075
7276
  onContinue,
7076
7277
  onSkip,
7077
- buttonLabel = "CONFIRM SELECTION",
7078
- eyebrow = "Get Your Tickets",
7079
- heading = "UPGRADES & ADD-ONS",
7278
+ buttonLabel,
7279
+ eyebrow,
7280
+ heading,
7080
7281
  className
7081
7282
  }) => {
7082
7283
  var _a, _b, _c, _d, _e, _f, _g, _h;
7284
+ const t = useT();
7083
7285
  const checkout = useCheckoutContext();
7286
+ const buttonText = buttonLabel != null ? buttonLabel : t("addons.confirmSelection");
7287
+ const eyebrowText = eyebrow != null ? eyebrow : t("addons.eyebrow");
7288
+ const headingText = heading != null ? heading : t("addons.heading");
7084
7289
  const combined = !onContinue;
7085
7290
  const addonsQuery = hooks_exports.useEventAddons(eventId);
7086
7291
  const all = (_a = addonsQuery.data) != null ? _a : [];
@@ -7110,14 +7315,14 @@ var AddOns = ({
7110
7315
  return ((_a3 = selection[id]) != null ? _a3 : 0) > 0;
7111
7316
  })
7112
7317
  );
7113
- const t = setTimeout(() => {
7318
+ const t2 = setTimeout(() => {
7114
7319
  checkout.setAddonDataCapture(captureForSelected);
7115
7320
  checkout.setAddons(selection).catch((e) => setError(errorMessage(e)));
7116
7321
  }, 500);
7117
- return () => clearTimeout(t);
7322
+ return () => clearTimeout(t2);
7118
7323
  }, [combined, qty, capture]);
7119
7324
  const hasRequired = ((_f = checkout.requiredAddOns) != null ? _f : []).some((a) => a.required);
7120
- const head = /* @__PURE__ */ React24.createElement("div", { className: "tf-checkout-addons__head" }, eyebrow && /* @__PURE__ */ React24.createElement("span", { className: "tf-checkout-addons__eyebrow" }, eyebrow), /* @__PURE__ */ React24.createElement("span", { className: "tf-checkout-addons__heading" }, heading), onSkip && !hasRequired && /* @__PURE__ */ React24.createElement("button", { type: "button", className: "tf-checkout-addons__skip", onClick: onSkip }, "Skip"));
7325
+ const head = /* @__PURE__ */ React24.createElement("div", { className: "tf-checkout-addons__head" }, eyebrowText && /* @__PURE__ */ React24.createElement("span", { className: "tf-checkout-addons__eyebrow" }, eyebrowText), /* @__PURE__ */ React24.createElement("span", { className: "tf-checkout-addons__heading" }, headingText), onSkip && !hasRequired && /* @__PURE__ */ React24.createElement("button", { type: "button", className: "tf-checkout-addons__skip", onClick: onSkip }, "Skip"));
7121
7326
  if (addonsQuery.isLoading) {
7122
7327
  return /* @__PURE__ */ React24.createElement(Card, { className }, head, /* @__PURE__ */ React24.createElement("div", { className: "tf-checkout-section-loader" }, /* @__PURE__ */ React24.createElement(Loader, null)));
7123
7328
  }
@@ -7164,7 +7369,7 @@ var AddOns = ({
7164
7369
  className: "tf-checkout-addons__desc",
7165
7370
  dangerouslySetInnerHTML: { __html: a.description }
7166
7371
  }
7167
- )), soldOut(a) ? /* @__PURE__ */ React24.createElement("span", { className: "tf-checkout-tickets__soldout" }, "Sold out") : /* @__PURE__ */ React24.createElement(
7372
+ )), soldOut(a) ? /* @__PURE__ */ React24.createElement("span", { className: "tf-checkout-tickets__soldout" }, t("tickets.soldOut")) : /* @__PURE__ */ React24.createElement(
7168
7373
  QuantitySelect,
7169
7374
  {
7170
7375
  value: n,
@@ -7195,7 +7400,7 @@ var AddOns = ({
7195
7400
  loading: checkout.isBusy,
7196
7401
  disabled: checkout.isBusy || selectedCount === 0
7197
7402
  },
7198
- checkout.isBusy ? "Updating\u2026" : buttonLabel
7403
+ checkout.isBusy ? t("addons.updating") : buttonText
7199
7404
  ), missing.length > 0 && /* @__PURE__ */ React24.createElement("p", { className: "tf-checkout-note" }, "Required add-on: ", missing.join(", "), "."), (error || checkout.error) && /* @__PURE__ */ React24.createElement("p", { className: "tf-checkout-error-text" }, error || checkout.error));
7200
7405
  };
7201
7406
 
@@ -7219,17 +7424,18 @@ var BillingAddressFields = ({
7219
7424
  setBilling
7220
7425
  }) => {
7221
7426
  var _a, _b, _c, _d, _e;
7427
+ const t = useT();
7222
7428
  const setValue = (key) => (event) => setBilling((current2) => ({ ...current2, [key]: event.target.value }));
7223
- return /* @__PURE__ */ React25.createElement(React25.Fragment, null, /* @__PURE__ */ React25.createElement("div", { className: "tf-checkout-billing__section-label" }, "Billing address *"), /* @__PURE__ */ React25.createElement(
7429
+ return /* @__PURE__ */ React25.createElement(React25.Fragment, null, /* @__PURE__ */ React25.createElement("div", { className: "tf-checkout-billing__section-label" }, t("billing.address")), /* @__PURE__ */ React25.createElement(
7224
7430
  Field,
7225
7431
  {
7226
- error: fieldError("Street address", "Street address is required."),
7432
+ error: fieldError("Street address", t("billing.streetRequired")),
7227
7433
  invalid: Boolean(fieldError("Street address"))
7228
7434
  },
7229
7435
  /* @__PURE__ */ React25.createElement(
7230
7436
  Input,
7231
7437
  {
7232
- placeholder: "Street address *",
7438
+ placeholder: t("billing.streetPlaceholder"),
7233
7439
  autoComplete: "street-address",
7234
7440
  value: (_a = billing.streetAddress) != null ? _a : "",
7235
7441
  required: true,
@@ -7241,13 +7447,13 @@ var BillingAddressFields = ({
7241
7447
  ), /* @__PURE__ */ React25.createElement(FieldRow, null, /* @__PURE__ */ React25.createElement(
7242
7448
  Field,
7243
7449
  {
7244
- error: fieldError("City", "City is required."),
7450
+ error: fieldError("City", t("billing.cityRequired")),
7245
7451
  invalid: Boolean(fieldError("City"))
7246
7452
  },
7247
7453
  /* @__PURE__ */ React25.createElement(
7248
7454
  Input,
7249
7455
  {
7250
- placeholder: "City *",
7456
+ placeholder: t("billing.cityPlaceholder"),
7251
7457
  autoComplete: "address-level2",
7252
7458
  value: (_b = billing.city) != null ? _b : "",
7253
7459
  required: true,
@@ -7259,13 +7465,13 @@ var BillingAddressFields = ({
7259
7465
  ), /* @__PURE__ */ React25.createElement(
7260
7466
  Field,
7261
7467
  {
7262
- error: fieldError("ZIP / postcode", "ZIP / postcode is required."),
7468
+ error: fieldError("ZIP / postcode", t("billing.postcodeRequired")),
7263
7469
  invalid: Boolean(fieldError("ZIP / postcode"))
7264
7470
  },
7265
7471
  /* @__PURE__ */ React25.createElement(
7266
7472
  Input,
7267
7473
  {
7268
- placeholder: "ZIP / Postcode *",
7474
+ placeholder: t("billing.postcodePlaceholder"),
7269
7475
  autoComplete: "postal-code",
7270
7476
  value: (_c = billing.zip) != null ? _c : "",
7271
7477
  required: true,
@@ -7277,14 +7483,14 @@ var BillingAddressFields = ({
7277
7483
  )), /* @__PURE__ */ React25.createElement(FieldRow, null, /* @__PURE__ */ React25.createElement(
7278
7484
  Field,
7279
7485
  {
7280
- error: fieldError("Country", "Country is required."),
7486
+ error: fieldError("Country", t("billing.countryRequired")),
7281
7487
  invalid: Boolean(fieldError("Country"))
7282
7488
  },
7283
7489
  /* @__PURE__ */ React25.createElement(
7284
7490
  Select,
7285
7491
  {
7286
7492
  value: (_d = billing.countryId) != null ? _d : "",
7287
- "aria-label": "Country",
7493
+ "aria-label": t("billing.countryLabel"),
7288
7494
  required: true,
7289
7495
  invalid: Boolean(fieldError("Country")),
7290
7496
  "aria-invalid": Boolean(fieldError("Country")),
@@ -7304,13 +7510,13 @@ var BillingAddressFields = ({
7304
7510
  });
7305
7511
  }
7306
7512
  },
7307
- /* @__PURE__ */ React25.createElement("option", { value: "" }, "\u2014 country * \u2014"),
7513
+ /* @__PURE__ */ React25.createElement("option", { value: "" }, t("billing.countryEmpty")),
7308
7514
  countries.map((country) => /* @__PURE__ */ React25.createElement("option", { key: country.id, value: country.id }, country.name))
7309
7515
  )
7310
7516
  ), /* @__PURE__ */ React25.createElement(
7311
7517
  Field,
7312
7518
  {
7313
- error: fieldError("State / county", "State / county is required."),
7519
+ error: fieldError("State / county", t("billing.stateRequired")),
7314
7520
  invalid: Boolean(fieldError("State / county"))
7315
7521
  },
7316
7522
  /* @__PURE__ */ React25.createElement(
@@ -7318,7 +7524,7 @@ var BillingAddressFields = ({
7318
7524
  {
7319
7525
  value: (_e = billing.stateId) != null ? _e : "",
7320
7526
  disabled: !billing.countryId || states.length === 0,
7321
- "aria-label": "State / region",
7527
+ "aria-label": t("billing.stateLabel"),
7322
7528
  required: states.length > 0,
7323
7529
  invalid: Boolean(fieldError("State / county")),
7324
7530
  "aria-invalid": Boolean(fieldError("State / county")),
@@ -7333,7 +7539,7 @@ var BillingAddressFields = ({
7333
7539
  }));
7334
7540
  }
7335
7541
  },
7336
- /* @__PURE__ */ React25.createElement("option", { value: "" }, "\u2014 state / county", states.length > 0 ? " *" : "", " \u2014"),
7542
+ /* @__PURE__ */ React25.createElement("option", { value: "" }, states.length > 0 ? t("billing.stateEmptyRequired") : t("billing.stateEmpty")),
7337
7543
  states.map((state) => /* @__PURE__ */ React25.createElement("option", { key: state.id, value: state.id }, state.name))
7338
7544
  )
7339
7545
  )));
@@ -7389,6 +7595,19 @@ var BuyerField = ({
7389
7595
  ));
7390
7596
  };
7391
7597
 
7598
+ // src/sections/billing/fieldRules.ts
7599
+ var isBlankPhone = (phone) => !phone || /^\+?\d{0,4}$/.test(phone.trim());
7600
+ var DOB_MIN = "1900-01-01";
7601
+ var todayISO = () => {
7602
+ const now = /* @__PURE__ */ new Date();
7603
+ return [
7604
+ now.getFullYear(),
7605
+ String(now.getMonth() + 1).padStart(2, "0"),
7606
+ String(now.getDate()).padStart(2, "0")
7607
+ ].join("-");
7608
+ };
7609
+ var toDateInputValue = (year, month, day) => year && month && day ? `${year}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}` : void 0;
7610
+
7392
7611
  // src/sections/billing/TicketHoldersCard.tsx
7393
7612
  import React27 from "react";
7394
7613
  import { PhoneInput as PhoneInput2 } from "react-international-phone";
@@ -7400,112 +7619,121 @@ var TicketHoldersCard = ({
7400
7619
  fieldError,
7401
7620
  renderCustomFields,
7402
7621
  patchHolder
7403
- }) => /* @__PURE__ */ React27.createElement(Card, { className: "tf-checkout-billing__holders-card" }, /* @__PURE__ */ React27.createElement(SectionHeader, { title: "Ticket Holders" }), holders.map((holder, index) => {
7404
- const firstNameKey = `Ticket ${index + 1} holder first name`;
7405
- const lastNameKey = `Ticket ${index + 1} holder last name`;
7406
- const emailKey = `Ticket ${index + 1} holder email`;
7407
- const phoneKey = `Ticket ${index + 1} holder phone`;
7408
- return /* @__PURE__ */ React27.createElement("div", { key: index, className: "tf-checkout-billing__holder" }, /* @__PURE__ */ React27.createElement("div", { className: "tf-checkout-billing__holder-title" }, "Ticket ", index + 1), holderNamesRequired && /* @__PURE__ */ React27.createElement(FieldRow, null, /* @__PURE__ */ React27.createElement(
7409
- Field,
7410
- {
7411
- label: "First Name *",
7412
- error: fieldError(firstNameKey, "First name is required."),
7413
- invalid: Boolean(fieldError(firstNameKey))
7414
- },
7415
- /* @__PURE__ */ React27.createElement(
7416
- Input,
7622
+ }) => {
7623
+ const t = useT();
7624
+ return /* @__PURE__ */ React27.createElement(Card, { className: "tf-checkout-billing__holders-card" }, /* @__PURE__ */ React27.createElement(SectionHeader, { title: t("billing.ticketHolders") }), holders.map((holder, index) => {
7625
+ const firstNameKey = `Ticket ${index + 1} holder first name`;
7626
+ const lastNameKey = `Ticket ${index + 1} holder last name`;
7627
+ const emailKey = `Ticket ${index + 1} holder email`;
7628
+ const phoneKey = `Ticket ${index + 1} holder phone`;
7629
+ return /* @__PURE__ */ React27.createElement("div", { key: index, className: "tf-checkout-billing__holder" }, /* @__PURE__ */ React27.createElement("div", { className: "tf-checkout-billing__holder-title" }, t("billing.holderTitle", { number: index + 1 })), holderNamesRequired && /* @__PURE__ */ React27.createElement(FieldRow, null, /* @__PURE__ */ React27.createElement(
7630
+ Field,
7417
7631
  {
7418
- value: holder.firstName,
7419
- required: true,
7420
- invalid: Boolean(fieldError(firstNameKey)),
7421
- "aria-invalid": Boolean(fieldError(firstNameKey)),
7422
- onChange: (event) => patchHolder(index, { firstName: event.target.value })
7423
- }
7424
- )
7425
- ), /* @__PURE__ */ React27.createElement(
7426
- Field,
7427
- {
7428
- label: "Last Name *",
7429
- error: fieldError(lastNameKey, "Last name is required."),
7430
- invalid: Boolean(fieldError(lastNameKey))
7431
- },
7432
- /* @__PURE__ */ React27.createElement(
7433
- Input,
7632
+ label: t("billing.holderFirstName"),
7633
+ error: fieldError(firstNameKey, t("billing.firstNameRequired")),
7634
+ invalid: Boolean(fieldError(firstNameKey))
7635
+ },
7636
+ /* @__PURE__ */ React27.createElement(
7637
+ Input,
7638
+ {
7639
+ value: holder.firstName,
7640
+ required: true,
7641
+ invalid: Boolean(fieldError(firstNameKey)),
7642
+ "aria-invalid": Boolean(fieldError(firstNameKey)),
7643
+ onChange: (event) => patchHolder(index, { firstName: event.target.value })
7644
+ }
7645
+ )
7646
+ ), /* @__PURE__ */ React27.createElement(
7647
+ Field,
7434
7648
  {
7435
- value: holder.lastName,
7436
- required: true,
7437
- invalid: Boolean(fieldError(lastNameKey)),
7438
- "aria-invalid": Boolean(fieldError(lastNameKey)),
7439
- onChange: (event) => patchHolder(index, { lastName: event.target.value })
7440
- }
7441
- )
7442
- )), collectHolderContact && /* @__PURE__ */ React27.createElement(FieldRow, null, /* @__PURE__ */ React27.createElement(
7443
- Field,
7444
- {
7445
- label: "Email Address *",
7446
- error: fieldError(emailKey, "Enter a valid email address."),
7447
- invalid: Boolean(fieldError(emailKey))
7448
- },
7449
- /* @__PURE__ */ React27.createElement(
7450
- Input,
7649
+ label: t("billing.holderLastName"),
7650
+ error: fieldError(lastNameKey, t("billing.lastNameRequired")),
7651
+ invalid: Boolean(fieldError(lastNameKey))
7652
+ },
7653
+ /* @__PURE__ */ React27.createElement(
7654
+ Input,
7655
+ {
7656
+ value: holder.lastName,
7657
+ required: true,
7658
+ invalid: Boolean(fieldError(lastNameKey)),
7659
+ "aria-invalid": Boolean(fieldError(lastNameKey)),
7660
+ onChange: (event) => patchHolder(index, { lastName: event.target.value })
7661
+ }
7662
+ )
7663
+ )), collectHolderContact && /* @__PURE__ */ React27.createElement(FieldRow, null, /* @__PURE__ */ React27.createElement(
7664
+ Field,
7451
7665
  {
7452
- type: "email",
7453
- autoComplete: "email",
7454
- value: holder.email,
7455
- required: true,
7456
- invalid: Boolean(fieldError(emailKey)),
7457
- "aria-invalid": Boolean(fieldError(emailKey)),
7458
- onChange: (event) => patchHolder(index, { email: event.target.value })
7459
- }
7460
- )
7461
- ), /* @__PURE__ */ React27.createElement(
7462
- Field,
7463
- {
7464
- label: "Phone *",
7465
- error: fieldError(phoneKey, "Enter a valid phone number."),
7466
- invalid: Boolean(fieldError(phoneKey))
7467
- },
7468
- /* @__PURE__ */ React27.createElement(
7469
- PhoneInput2,
7666
+ label: t("billing.email"),
7667
+ error: fieldError(emailKey, t("billing.emailInvalid")),
7668
+ invalid: Boolean(fieldError(emailKey))
7669
+ },
7670
+ /* @__PURE__ */ React27.createElement(
7671
+ Input,
7672
+ {
7673
+ type: "email",
7674
+ autoComplete: "email",
7675
+ value: holder.email,
7676
+ required: true,
7677
+ invalid: Boolean(fieldError(emailKey)),
7678
+ "aria-invalid": Boolean(fieldError(emailKey)),
7679
+ onChange: (event) => patchHolder(index, { email: event.target.value })
7680
+ }
7681
+ )
7682
+ ), /* @__PURE__ */ React27.createElement(
7683
+ Field,
7470
7684
  {
7471
- className: "tf-checkout-phone",
7472
- inputClassName: `tf-checkout-input tf-checkout-phone__input${fieldError(phoneKey) ? " tf-checkout-input--invalid" : ""}`,
7473
- defaultCountry: phoneCountry,
7474
- disableDialCodePrefill: true,
7475
- value: holder.phone,
7476
- required: true,
7477
- inputProps: {
7478
- autoComplete: "tel",
7479
- "aria-label": phoneKey,
7480
- "aria-invalid": Boolean(fieldError(phoneKey))
7481
- },
7482
- onChange: (phone) => patchHolder(index, { phone })
7483
- }
7484
- )
7485
- )), renderCustomFields(holder, index));
7486
- }));
7685
+ label: t("billing.phone"),
7686
+ error: fieldError(phoneKey, t("billing.phoneInvalid")),
7687
+ invalid: Boolean(fieldError(phoneKey))
7688
+ },
7689
+ /* @__PURE__ */ React27.createElement(
7690
+ PhoneInput2,
7691
+ {
7692
+ className: "tf-checkout-phone",
7693
+ inputClassName: `tf-checkout-input tf-checkout-phone__input${fieldError(phoneKey) ? " tf-checkout-input--invalid" : ""}`,
7694
+ defaultCountry: phoneCountry,
7695
+ disableDialCodeAndPrefix: true,
7696
+ showDisabledDialCodeAndPrefix: true,
7697
+ disableDialCodePrefill: true,
7698
+ value: holder.phone,
7699
+ required: true,
7700
+ inputProps: {
7701
+ autoComplete: "tel",
7702
+ "aria-label": phoneKey,
7703
+ "aria-invalid": Boolean(fieldError(phoneKey))
7704
+ },
7705
+ onChange: (phone) => patchHolder(index, { phone })
7706
+ }
7707
+ )
7708
+ )), renderCustomFields(holder, index));
7709
+ }));
7710
+ };
7487
7711
 
7488
7712
  // src/sections/BillingInfo.tsx
7489
7713
  var BillingInfo = ({
7490
7714
  eventId,
7491
7715
  onContinue,
7492
- heading = "Billing Information",
7493
- buttonLabel = "Continue to payment",
7716
+ heading,
7717
+ buttonLabel,
7494
7718
  onLogin,
7495
7719
  skipWhenProfileComplete = false,
7496
7720
  requireEmailConfirmation = false,
7497
7721
  collectTicketHolders = false,
7498
7722
  collectHolderContact = false,
7499
- ttfOptInLabel = "Keep me updated about future events from The Ticket Fairy",
7723
+ ttfOptInLabel,
7500
7724
  brandOptInLabel,
7501
7725
  privacyPolicy,
7502
7726
  showPrivacyError = false,
7503
7727
  step,
7504
7728
  className
7505
7729
  }) => {
7506
- 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;
7730
+ 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;
7731
+ const t = useT();
7507
7732
  const checkout = useCheckoutContext();
7508
7733
  const validation = useCheckoutValidation();
7734
+ const headingText = heading != null ? heading : t("billing.heading");
7735
+ const buttonText = buttonLabel != null ? buttonLabel : t("billing.continueToPayment");
7736
+ const ttfOptInText = ttfOptInLabel != null ? ttfOptInLabel : t("billing.ttfOptIn");
7509
7737
  const profile = hooks_exports.useProfile({ retry: false });
7510
7738
  const event = hooks_exports.useEvent(eventId);
7511
7739
  const combined = !onContinue;
@@ -7593,7 +7821,7 @@ var BillingInfo = ({
7593
7821
  lastName: prev.lastName || profileBilling.lastName || "",
7594
7822
  email: prev.email || profileBilling.email || "",
7595
7823
  confirmEmail: prev.confirmEmail || (checkout.isLoggedIn ? profileBilling.email : "") || "",
7596
- phone: prev.phone || profileBilling.phone,
7824
+ phone: (isBlankPhone(prev.phone) ? void 0 : prev.phone) || profileBilling.phone,
7597
7825
  streetAddress: prev.streetAddress || profileBilling.streetAddress,
7598
7826
  city: prev.city || profileBilling.city,
7599
7827
  zip: prev.zip || profileBilling.zip,
@@ -7603,6 +7831,12 @@ var BillingInfo = ({
7603
7831
  const keys = Object.keys(next);
7604
7832
  return keys.every((k) => next[k] === prev[k]) ? prev : next;
7605
7833
  });
7834
+ setDob((prev) => {
7835
+ var _a2;
7836
+ if (prev) return prev;
7837
+ const { dobYear: dobYear2, dobMonth: dobMonth2, dobDay: dobDay2 } = profileBilling;
7838
+ return (_a2 = toDateInputValue(dobYear2, dobMonth2, dobDay2)) != null ? _a2 : prev;
7839
+ });
7606
7840
  }, [profile.data, checkout.isLoggedIn]);
7607
7841
  useEffect11(() => {
7608
7842
  setHolders(
@@ -7640,11 +7874,11 @@ var BillingInfo = ({
7640
7874
  useEffect11(() => {
7641
7875
  const email = billing.email.trim();
7642
7876
  if (checkout.isLoggedIn || !isEmail(email)) return;
7643
- const t = setTimeout(
7877
+ const t2 = setTimeout(
7644
7878
  () => checkout.checkBuyerEmail(email).catch(() => void 0),
7645
7879
  600
7646
7880
  );
7647
- return () => clearTimeout(t);
7881
+ return () => clearTimeout(t2);
7648
7882
  }, [billing.email, checkout.isLoggedIn]);
7649
7883
  const emailTaken = !checkout.isLoggedIn && checkout.existingAccountEmail === billing.email.trim();
7650
7884
  const needsNationality = checkout.buyerFields.some((f) => f.kind === "nationality");
@@ -7684,6 +7918,7 @@ var BillingInfo = ({
7684
7918
  countryDefaultApplied.current = true;
7685
7919
  setBilling((current2) => {
7686
7920
  var _a3;
7921
+ if (current2.countryId) return current2;
7687
7922
  return {
7688
7923
  ...current2,
7689
7924
  countryId: String(preferred.id),
@@ -7724,24 +7959,30 @@ var BillingInfo = ({
7724
7959
  }, [billing.stateId, billing.stateCode, states]);
7725
7960
  const setB = (k) => (e) => setBilling((b) => ({ ...b, [k]: e.target.value }));
7726
7961
  const patchHolder = (i, patch2) => setHolders((hs) => hs.map((h, j) => j === i ? { ...h, ...patch2 } : h));
7962
+ const dobMax = useMemo5(todayISO, []);
7727
7963
  const [dobYear, dobMonth, dobDay] = dob ? dob.split("-").map(Number) : [];
7964
+ const buyerPhone = isBlankPhone(billing.phone) ? void 0 : billing.phone;
7728
7965
  const committedBilling = {
7729
7966
  ...checkout.billing,
7730
7967
  ...billing,
7968
+ phone: buyerPhone,
7731
7969
  stateRequired: gates.showAddress && Boolean(billing.countryId) && states.length > 0,
7732
7970
  dataCapture,
7733
7971
  dobDay,
7734
7972
  dobMonth,
7735
7973
  dobYear
7736
7974
  };
7737
- const committedHolders = holders.map((holder) => ({
7738
- firstName: holderNamesRequired ? holder.firstName : holder.firstName || billing.firstName,
7739
- lastName: holderNamesRequired ? holder.lastName : holder.lastName || billing.lastName,
7740
- email: showHolders && collectHolderContact ? holder.email : holder.email || billing.email,
7741
- phone: showHolders && collectHolderContact ? holder.phone : holder.phone || billing.phone,
7742
- ticketTypeId: holder.ticketTypeId,
7743
- ticketDataCapture: holder.ticketDataCapture
7744
- }));
7975
+ const committedHolders = holders.map((holder) => {
7976
+ const holderPhone = isBlankPhone(holder.phone) ? "" : holder.phone;
7977
+ return {
7978
+ firstName: holderNamesRequired ? holder.firstName : holder.firstName || billing.firstName,
7979
+ lastName: holderNamesRequired ? holder.lastName : holder.lastName || billing.lastName,
7980
+ email: showHolders && collectHolderContact ? holder.email : holder.email || billing.email,
7981
+ phone: showHolders && collectHolderContact ? holderPhone : holderPhone || buyerPhone || "",
7982
+ ticketTypeId: holder.ticketTypeId,
7983
+ ticketDataCapture: holder.ticketDataCapture
7984
+ };
7985
+ });
7745
7986
  const missingDetails = missingCheckoutDetails(
7746
7987
  {
7747
7988
  billing: committedBilling,
@@ -7761,7 +8002,7 @@ var BillingInfo = ({
7761
8002
  const complete = missingDetails.length === 0;
7762
8003
  const showValidation = validation.attempt > 0;
7763
8004
  const missingSet = new Set(missingDetails);
7764
- const fieldError = (key, message = "This field is required.") => showValidation && missingSet.has(key) ? message : void 0;
8005
+ const fieldError = (key, message = t("billing.fieldRequired")) => showValidation && missingSet.has(key) ? message : void 0;
7765
8006
  const dobError = showValidation ? missingDetails.find(
7766
8007
  (detail) => detail === "Date of birth" || detail.startsWith("Age ")
7767
8008
  ) : void 0;
@@ -7769,7 +8010,7 @@ var BillingInfo = ({
7769
8010
  const commit = () => {
7770
8011
  checkout.setBilling(committedBilling);
7771
8012
  checkout.setHolders(committedHolders);
7772
- if (ttfOptInLabel || brandOptInLabel) checkout.setConsent(consent);
8013
+ if (ttfOptInText || brandOptInLabel) checkout.setConsent(consent);
7773
8014
  };
7774
8015
  useEffect11(() => {
7775
8016
  if (combined) commit();
@@ -7791,7 +8032,7 @@ var BillingInfo = ({
7791
8032
  const hasEventSpecificDetails = checkout.buyerFields.length > 0 || checkout.customFields.some((group) => group.fields.length > 0) || showHolders || gates.showDob;
7792
8033
  const skipBilling = skipWhenProfileComplete && checkout.isLoggedIn && profile.isSuccess && complete && !hasEventSpecificDetails;
7793
8034
  if (skipBilling) return null;
7794
- return /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement(Card, { className }, /* @__PURE__ */ React28.createElement(SectionHeader, { step, title: heading }), onLogin && !checkout.isLoggedIn && /* @__PURE__ */ React28.createElement("div", { className: "tf-checkout-billing__login" }, /* @__PURE__ */ React28.createElement("span", null, "Login & skip ahead:"), /* @__PURE__ */ React28.createElement(
8035
+ return /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement(Card, { className }, /* @__PURE__ */ React28.createElement(SectionHeader, { step, title: headingText }), onLogin && !checkout.isLoggedIn && /* @__PURE__ */ React28.createElement("div", { className: "tf-checkout-billing__login" }, /* @__PURE__ */ React28.createElement("span", null, "Login & skip ahead:"), /* @__PURE__ */ React28.createElement(
7795
8036
  "button",
7796
8037
  {
7797
8038
  type: "button",
@@ -7808,7 +8049,7 @@ var BillingInfo = ({
7808
8049
  /* @__PURE__ */ React28.createElement(
7809
8050
  Input,
7810
8051
  {
7811
- placeholder: "First name *",
8052
+ placeholder: t("billing.firstNamePlaceholder"),
7812
8053
  value: billing.firstName,
7813
8054
  required: true,
7814
8055
  invalid: Boolean(fieldError("First name")),
@@ -7825,7 +8066,7 @@ var BillingInfo = ({
7825
8066
  /* @__PURE__ */ React28.createElement(
7826
8067
  Input,
7827
8068
  {
7828
- placeholder: "Last name *",
8069
+ placeholder: t("billing.lastNamePlaceholder"),
7829
8070
  value: billing.lastName,
7830
8071
  required: true,
7831
8072
  invalid: Boolean(fieldError("Last name")),
@@ -7844,7 +8085,7 @@ var BillingInfo = ({
7844
8085
  {
7845
8086
  type: "email",
7846
8087
  autoComplete: "email",
7847
- placeholder: "Email *",
8088
+ placeholder: t("billing.emailPlaceholder"),
7848
8089
  value: billing.email,
7849
8090
  required: true,
7850
8091
  invalid: Boolean(fieldError("Valid email address")),
@@ -7857,7 +8098,7 @@ var BillingInfo = ({
7857
8098
  {
7858
8099
  error: fieldError(
7859
8100
  "Matching email confirmation",
7860
- "Email addresses must match."
8101
+ t("billing.emailMustMatch")
7861
8102
  ),
7862
8103
  invalid: Boolean(fieldError("Matching email confirmation"))
7863
8104
  },
@@ -7866,7 +8107,7 @@ var BillingInfo = ({
7866
8107
  {
7867
8108
  type: "email",
7868
8109
  autoComplete: "email",
7869
- placeholder: "Confirm email *",
8110
+ placeholder: t("billing.confirmEmailPlaceholder"),
7870
8111
  value: (_C = billing.confirmEmail) != null ? _C : "",
7871
8112
  required: true,
7872
8113
  invalid: Boolean(fieldError("Matching email confirmation")),
@@ -7874,15 +8115,15 @@ var BillingInfo = ({
7874
8115
  onChange: setB("confirmEmail")
7875
8116
  }
7876
8117
  )
7877
- )), !showValidation && requireEmailConfirmation && billing.confirmEmail && billing.confirmEmail.trim().toLowerCase() !== billing.email.trim().toLowerCase() && /* @__PURE__ */ React28.createElement("p", { className: "tf-checkout-error-text" }, "The email addresses do not match."), emailTaken && /* @__PURE__ */ React28.createElement("p", { className: "tf-checkout-note tf-checkout-billing__email-taken" }, "This email is already registered.", " ", onLogin ? /* @__PURE__ */ React28.createElement(
8118
+ )), !showValidation && requireEmailConfirmation && billing.confirmEmail && billing.confirmEmail.trim().toLowerCase() !== billing.email.trim().toLowerCase() && /* @__PURE__ */ React28.createElement("p", { className: "tf-checkout-error-text" }, t("billing.emailMismatch")), emailTaken && /* @__PURE__ */ React28.createElement("p", { className: "tf-checkout-note tf-checkout-billing__email-taken" }, t("billing.emailRegistered"), " ", onLogin ? /* @__PURE__ */ React28.createElement(
7878
8119
  "button",
7879
8120
  {
7880
8121
  type: "button",
7881
8122
  className: "tf-checkout-billing__login-link",
7882
8123
  onClick: () => onLogin(billing.email)
7883
8124
  },
7884
- "Log in to autofill your details"
7885
- ) : "Log in to autofill your details."), checkout.buyerFields.map((f) => {
8125
+ t("billing.loginAutofill")
8126
+ ) : t("billing.loginAutofillPlain")), checkout.buyerFields.map((f) => {
7886
8127
  var _a2;
7887
8128
  return /* @__PURE__ */ React28.createElement(
7888
8129
  BuyerField,
@@ -7893,15 +8134,15 @@ var BillingInfo = ({
7893
8134
  onChange: (v) => setBilling((b) => ({ ...b, [f.key]: v })),
7894
8135
  countries,
7895
8136
  error: fieldError(
7896
- f.kind === "nationality" ? "Nationality" : f.kind === "gender" ? "Gender" : "Instagram handle"
8137
+ f.kind === "nationality" ? t("billing.nationality") : f.kind === "gender" ? t("billing.gender") : t("billing.instagramHandle")
7897
8138
  )
7898
8139
  }
7899
8140
  );
7900
8141
  }), gates.showPhone && /* @__PURE__ */ React28.createElement(
7901
8142
  Field,
7902
8143
  {
7903
- label: `Phone${gates.phoneRequired ? " *" : ""}`,
7904
- error: fieldError("Valid phone number", "Enter a valid phone number."),
8144
+ label: gates.phoneRequired ? t("billing.phone") : t("billing.phoneOptional"),
8145
+ error: fieldError("Valid phone number", t("billing.phoneInvalid")),
7905
8146
  invalid: Boolean(fieldError("Valid phone number"))
7906
8147
  },
7907
8148
  /* @__PURE__ */ React28.createElement(
@@ -7910,13 +8151,15 @@ var BillingInfo = ({
7910
8151
  className: "tf-checkout-phone",
7911
8152
  inputClassName: `tf-checkout-input tf-checkout-phone__input${fieldError("Valid phone number") ? " tf-checkout-input--invalid" : ""}`,
7912
8153
  defaultCountry: phoneCountry,
8154
+ disableDialCodeAndPrefix: true,
8155
+ showDisabledDialCodeAndPrefix: true,
7913
8156
  disableDialCodePrefill: true,
7914
8157
  value: (_D = billing.phone) != null ? _D : "",
7915
8158
  required: gates.phoneRequired,
7916
- placeholder: "Phone number",
8159
+ placeholder: t("billing.phonePlaceholder"),
7917
8160
  inputProps: {
7918
8161
  autoComplete: "tel",
7919
- "aria-label": "Phone",
8162
+ "aria-label": t("billing.phoneAria"),
7920
8163
  "aria-invalid": Boolean(fieldError("Valid phone number"))
7921
8164
  },
7922
8165
  onChange: (phone) => setBilling((current2) => ({ ...current2, phone }))
@@ -7925,8 +8168,8 @@ var BillingInfo = ({
7925
8168
  ), gates.showDob && /* @__PURE__ */ React28.createElement(
7926
8169
  Field,
7927
8170
  {
7928
- label: `Date of birth *${gates.minimumAge ? ` (must be ${gates.minimumAge}+)` : ""}`,
7929
- error: dobError === "Date of birth" ? "Date of birth is required." : dobError ? `You must be ${gates.minimumAge} or older.` : void 0,
8171
+ label: gates.minimumAge ? t("billing.dobWithAge", { age: gates.minimumAge }) : t("billing.dob"),
8172
+ error: dobError === "Date of birth" ? t("billing.dobRequired") : dobError ? t("billing.ageMinimum", { age: (_E = gates.minimumAge) != null ? _E : "" }) : void 0,
7930
8173
  invalid: Boolean(dobError)
7931
8174
  },
7932
8175
  /* @__PURE__ */ React28.createElement(
@@ -7935,6 +8178,8 @@ var BillingInfo = ({
7935
8178
  type: "date",
7936
8179
  value: dob,
7937
8180
  required: true,
8181
+ min: DOB_MIN,
8182
+ max: dobMax,
7938
8183
  invalid: Boolean(dobError),
7939
8184
  "aria-invalid": Boolean(dobError),
7940
8185
  onChange: (e) => setDob(e.target.value)
@@ -7975,17 +8220,17 @@ var BillingInfo = ({
7975
8220
  "aria-invalid": (showPrivacyError || showValidation) && !consent.ttfOptIn,
7976
8221
  onChange: (e) => setConsent((c) => ({ ...c, ttfOptIn: e.target.checked })),
7977
8222
  className: "tf-checkout-checkbox--consent",
7978
- label: /* @__PURE__ */ React28.createElement(React28.Fragment, null, "I have read and agree to ", privacyPolicy.brandName, " ", /* @__PURE__ */ React28.createElement("a", { href: privacyPolicy.url, target: "_blank", rel: "noreferrer" }, privacyPolicy.linkLabel || "Privacy Policy."), " *")
8223
+ label: /* @__PURE__ */ React28.createElement(React28.Fragment, null, t("billing.privacyAgree", { brand: privacyPolicy.brandName }), " ", /* @__PURE__ */ React28.createElement("a", { href: privacyPolicy.url, target: "_blank", rel: "noreferrer" }, privacyPolicy.linkLabel || t("billing.privacyLink")), " *")
7979
8224
  }
7980
8225
  ),
7981
- (showPrivacyError || showValidation) && !consent.ttfOptIn && /* @__PURE__ */ React28.createElement("div", { className: "tf-checkout-consent__error" }, "Required")
7982
- ) : ttfOptInLabel ? /* @__PURE__ */ React28.createElement(
8226
+ (showPrivacyError || showValidation) && !consent.ttfOptIn && /* @__PURE__ */ React28.createElement("div", { className: "tf-checkout-consent__error" }, t("common.required"))
8227
+ ) : ttfOptInText ? /* @__PURE__ */ React28.createElement(
7983
8228
  Checkbox,
7984
8229
  {
7985
8230
  checked: consent.ttfOptIn,
7986
8231
  onChange: (e) => setConsent((c) => ({ ...c, ttfOptIn: e.target.checked })),
7987
8232
  className: "tf-checkout-checkbox--consent",
7988
- label: ttfOptInLabel
8233
+ label: ttfOptInText
7989
8234
  }
7990
8235
  ) : null, !combined && /* @__PURE__ */ React28.createElement(React28.Fragment, null, /* @__PURE__ */ React28.createElement(
7991
8236
  Button,
@@ -8000,7 +8245,7 @@ var BillingInfo = ({
8000
8245
  onContinue == null ? void 0 : onContinue();
8001
8246
  }
8002
8247
  },
8003
- buttonLabel
8248
+ buttonText
8004
8249
  ))), showHolders && /* @__PURE__ */ React28.createElement(
8005
8250
  TicketHoldersCard,
8006
8251
  {
@@ -8035,12 +8280,13 @@ import React30, { useEffect as useEffect12, useMemo as useMemo6, useRef as useRe
8035
8280
  import React29 from "react";
8036
8281
  var OrderSummary = ({ eventId, className }) => {
8037
8282
  var _a, _b, _c;
8283
+ const t = useT();
8038
8284
  const checkout = useCheckoutContext();
8039
8285
  const event = hooks_exports.useEvent(eventId);
8040
8286
  const breakdown = checkout.breakdown;
8041
8287
  const detailed = checkout.priceBreakdown;
8042
8288
  if (!breakdown || breakdown.tickets.length === 0) return null;
8043
- return /* @__PURE__ */ React29.createElement(Card, { className: ["tf-checkout-order-summary", className].filter(Boolean).join(" ") }, ((_a = event.data) == null ? void 0 : _a.name) && /* @__PURE__ */ React29.createElement("div", { className: "tf-checkout-order-summary__group" }, /* @__PURE__ */ React29.createElement("div", { className: "tf-checkout-order-summary__label" }, "Event"), /* @__PURE__ */ React29.createElement("div", { className: "tf-checkout-order-summary__event" }, event.data.name)), /* @__PURE__ */ React29.createElement("div", { className: "tf-checkout-order-summary__group" }, /* @__PURE__ */ React29.createElement("div", { className: "tf-checkout-order-summary__label" }, "Your Tickets"), breakdown.tickets.map((ticket, index) => {
8289
+ return /* @__PURE__ */ React29.createElement(Card, { className: ["tf-checkout-order-summary", className].filter(Boolean).join(" ") }, ((_a = event.data) == null ? void 0 : _a.name) && /* @__PURE__ */ React29.createElement("div", { className: "tf-checkout-order-summary__group" }, /* @__PURE__ */ React29.createElement("div", { className: "tf-checkout-order-summary__label" }, t("common.event")), /* @__PURE__ */ React29.createElement("div", { className: "tf-checkout-order-summary__event" }, event.data.name)), /* @__PURE__ */ React29.createElement("div", { className: "tf-checkout-order-summary__group" }, /* @__PURE__ */ React29.createElement("div", { className: "tf-checkout-order-summary__label" }, t("tickets.yourTickets")), breakdown.tickets.map((ticket, index) => {
8044
8290
  var _a2;
8045
8291
  const detail = detailed == null ? void 0 : detailed.tickets[index];
8046
8292
  return /* @__PURE__ */ React29.createElement(
@@ -8049,7 +8295,7 @@ var OrderSummary = ({ eventId, className }) => {
8049
8295
  key: `${ticket.ticketTypeId}-${index}`,
8050
8296
  className: "tf-checkout-order-summary__item"
8051
8297
  },
8052
- /* @__PURE__ */ React29.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"),
8298
+ /* @__PURE__ */ React29.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")),
8053
8299
  (detail == null ? void 0 : detail.line_total) && detail.line_total !== detail.unit_price && /* @__PURE__ */ React29.createElement("div", { className: "tf-checkout-order-summary__fees" }, "(", detail.line_total, " with fees)")
8054
8300
  );
8055
8301
  })), ((_b = detailed == null ? void 0 : detailed.add_ons.length) != null ? _b : 0) > 0 && /* @__PURE__ */ React29.createElement("div", { className: "tf-checkout-order-summary__group" }, /* @__PURE__ */ React29.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__ */ React29.createElement(
@@ -8058,8 +8304,8 @@ var OrderSummary = ({ eventId, className }) => {
8058
8304
  key: `${addOn.name}-${index}`,
8059
8305
  className: "tf-checkout-order-summary__item"
8060
8306
  },
8061
- /* @__PURE__ */ React29.createElement("div", { className: "tf-checkout-order-summary__ticket" }, addOn.quantity, " x ", addOn.name, addOn.show_price ? ` - ${addOn.unit_price} each` : "")
8062
- ))), /* @__PURE__ */ React29.createElement("div", { className: "tf-checkout-order-summary__total" }, /* @__PURE__ */ React29.createElement("div", { className: "tf-checkout-order-summary__label" }, "Total"), /* @__PURE__ */ React29.createElement("div", { className: "tf-checkout-order-summary__amount" }, (_c = detailed == null ? void 0 : detailed.total) != null ? _c : `${breakdown.currencySymbol || `${breakdown.currencyCode} `}${Number(
8307
+ /* @__PURE__ */ React29.createElement("div", { className: "tf-checkout-order-summary__ticket" }, addOn.quantity, " x ", addOn.name, addOn.show_price ? ` - ${addOn.unit_price} ${t("common.each")}` : "")
8308
+ ))), /* @__PURE__ */ React29.createElement("div", { className: "tf-checkout-order-summary__total" }, /* @__PURE__ */ React29.createElement("div", { className: "tf-checkout-order-summary__label" }, t("common.total")), /* @__PURE__ */ React29.createElement("div", { className: "tf-checkout-order-summary__amount" }, (_c = detailed == null ? void 0 : detailed.total) != null ? _c : `${breakdown.currencySymbol || `${breakdown.currencyCode} `}${Number(
8063
8309
  breakdown.total
8064
8310
  ).toFixed(2)}`)));
8065
8311
  };
@@ -8101,7 +8347,8 @@ var Payment = ({
8101
8347
  showTestCardHint = false,
8102
8348
  className
8103
8349
  }) => {
8104
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
8350
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
8351
+ const t = useT();
8105
8352
  const checkout = useCheckoutContext();
8106
8353
  const validation = useCheckoutValidation();
8107
8354
  const [error, setError] = useState16("");
@@ -8123,13 +8370,19 @@ var Payment = ({
8123
8370
  const bd = checkout.breakdown;
8124
8371
  const isFree = bd != null && Number(bd.total) === 0;
8125
8372
  const isXendit = checkout.gateway === "xendit";
8373
+ const serverMethodTypes = (_a = checkout.stripeElementsConfig) == null ? void 0 : _a.paymentMethodTypes;
8374
+ const offersOxxo = Array.isArray(serverMethodTypes) && serverMethodTypes.includes("oxxo");
8126
8375
  const options = useMemo6(() => {
8127
- var _a2, _b2, _c2, _d2;
8376
+ var _a2, _b2, _c2;
8128
8377
  if (isFree || !methods) return [];
8129
8378
  const out = [];
8130
8379
  if (isXendit) {
8131
8380
  if (methods.xenditCard)
8132
- out.push({ id: { kind: "xenditCard" }, value: "xenditCard", label: "Card" });
8381
+ out.push({
8382
+ id: { kind: "xenditCard" },
8383
+ value: "xenditCard",
8384
+ label: t("payment.card")
8385
+ });
8133
8386
  for (const w of methods.xenditEWallets)
8134
8387
  out.push({
8135
8388
  id: { kind: "xenditEWallet", walletKey: w.key },
@@ -8141,23 +8394,23 @@ var Payment = ({
8141
8394
  } else if (checkout.gateway === "razorpay") {
8142
8395
  out.push({ id: { kind: "razorpay" }, value: "razorpay", label: "Razorpay" });
8143
8396
  } else {
8144
- out.push({ id: { kind: "card" }, value: "card", label: "Card" });
8145
- for (const t of (_b2 = checkout.redirectPaymentMethods) != null ? _b2 : []) {
8146
- if (t === "paypal" && methods.paypal) continue;
8397
+ out.push({ id: { kind: "card" }, value: "card", label: t("payment.card") });
8398
+ for (const t2 of (_b2 = checkout.redirectPaymentMethods) != null ? _b2 : []) {
8399
+ if (t2 === "paypal" && methods.paypal) continue;
8147
8400
  out.push({
8148
- id: { kind: "redirect", methodType: t },
8149
- value: `rd:${t}`,
8150
- label: redirectLabel(t)
8401
+ id: { kind: "redirect", methodType: t2 },
8402
+ value: `rd:${t2}`,
8403
+ label: redirectLabel(t2)
8151
8404
  });
8152
8405
  }
8153
8406
  if ((_c2 = checkout.paymentPlan) == null ? void 0 : _c2.available)
8154
8407
  out.push({
8155
8408
  id: { kind: "paymentPlan" },
8156
8409
  value: "paymentPlan",
8157
- label: "Payment plan"
8410
+ label: t("payment.paymentPlan")
8158
8411
  });
8159
- if (((_d2 = checkout.breakdown) == null ? void 0 : _d2.currencyCode) === "MXN")
8160
- out.push({ id: { kind: "oxxo" }, value: "oxxo", label: "OXXO (pay in cash)" });
8412
+ if (offersOxxo)
8413
+ out.push({ id: { kind: "oxxo" }, value: "oxxo", label: t("payment.oxxo") });
8161
8414
  }
8162
8415
  if (methods.paypal)
8163
8416
  out.push({ id: { kind: "paypal" }, value: "paypal", label: "PayPal" });
@@ -8169,7 +8422,7 @@ var Payment = ({
8169
8422
  checkout.gateway,
8170
8423
  checkout.redirectPaymentMethods,
8171
8424
  checkout.paymentPlan,
8172
- checkout.breakdown
8425
+ offersOxxo
8173
8426
  ]);
8174
8427
  useEffect12(() => {
8175
8428
  if (options.length && !options.some((o) => o.value === selected))
@@ -8179,14 +8432,14 @@ var Payment = ({
8179
8432
  const selectedOption = options.find((o) => o.value === selected);
8180
8433
  const isCardSelected = selected === cardValue;
8181
8434
  const isPlanSelected = (selectedOption == null ? void 0 : selectedOption.id.kind) === "paymentPlan";
8182
- const savedLast4 = (_a = checkout.paymentPlan) == null ? void 0 : _a.savedCardLast4;
8435
+ const savedLast4 = (_b = checkout.paymentPlan) == null ? void 0 : _b.savedCardLast4;
8183
8436
  const reuseSavedCard = Boolean(savedLast4) && useSavedCard;
8184
8437
  const usesCardDetails = !isFree && (isCardSelected || isPlanSelected && !reuseSavedCard);
8185
8438
  const cardWidgetReportsItsOwnError = usesCardDetails && !isXendit;
8186
8439
  const hasWallets = Boolean(
8187
- ((_b = checkout.walletAvailability) == null ? void 0 : _b.applePay) || ((_c = checkout.walletAvailability) == null ? void 0 : _c.googlePay)
8440
+ ((_c = checkout.walletAvailability) == null ? void 0 : _c.applePay) || ((_d = checkout.walletAvailability) == null ? void 0 : _d.googlePay)
8188
8441
  );
8189
- const useWalletElement = !isXendit && !isPlanSelected && hasWallets && ((_d = checkout.breakdown) == null ? void 0 : _d.currencyCode) !== "MXN" && Boolean((_e = checkout.stripeElementsConfig) == null ? void 0 : _e.mode);
8442
+ const useWalletElement = !isXendit && !isPlanSelected && hasWallets && ((_e = checkout.breakdown) == null ? void 0 : _e.currencyCode) !== "MXN" && Boolean((_f = checkout.stripeElementsConfig) == null ? void 0 : _f.mode);
8190
8443
  const onlyOption = options.length === 1 ? options[0] : void 0;
8191
8444
  const singleCard = (onlyOption == null ? void 0 : onlyOption.id.kind) === "card" || (onlyOption == null ? void 0 : onlyOption.id.kind) === "xenditCard";
8192
8445
  const b = checkout.billing;
@@ -8203,7 +8456,7 @@ var Payment = ({
8203
8456
  { requireEmailConfirmation, collectTicketHolders, requireHolderContact }
8204
8457
  );
8205
8458
  const billingReady = missingDetails.length === 0;
8206
- const conditions = [...(_f = checkout.conditions) != null ? _f : [], ...additionalConditions];
8459
+ const conditions = [...(_g = checkout.conditions) != null ? _g : [], ...additionalConditions];
8207
8460
  const requiredConditions = conditions.filter((c) => c.isRequired);
8208
8461
  const conditionsOk = requiredConditions.every(
8209
8462
  (c) => {
@@ -8212,10 +8465,10 @@ var Payment = ({
8212
8465
  }
8213
8466
  );
8214
8467
  const extra = selectedOption == null ? void 0 : selectedOption.extra;
8215
- 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()));
8468
+ 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()));
8216
8469
  const privacyOk = !requirePrivacyPolicy || checkout.consent.ttfOptIn;
8217
- const payLabel = isFree ? "Complete Registration" : isPlanSelected ? planConfirmLabel((_k = checkout.paymentPlan) == null ? void 0 : _k.configuration) : "Submit Payment";
8218
- const planTerms = paymentPlanTerms((_l = checkout.paymentPlan) == null ? void 0 : _l.configuration);
8470
+ const payLabel = isFree ? t("payment.completeRegistration") : isPlanSelected ? planConfirmLabel((_l = checkout.paymentPlan) == null ? void 0 : _l.configuration) : t("payment.submitPayment");
8471
+ const planTerms = paymentPlanTerms((_m = checkout.paymentPlan) == null ? void 0 : _m.configuration);
8219
8472
  const finalizing = checkout.status === "placing" || checkout.status === "succeeded";
8220
8473
  const pay = () => {
8221
8474
  setError("");
@@ -8295,15 +8548,15 @@ var Payment = ({
8295
8548
  }
8296
8549
  }
8297
8550
  ) : /* @__PURE__ */ React30.createElement(CardInput, null)
8298
- ), isXendit && cardAreaError && /* @__PURE__ */ React30.createElement("p", { className: "tf-checkout-error-text" }, cardAreaError), showTestCardHint && /* @__PURE__ */ React30.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__ */ React30.createElement("div", { className: "tf-checkout-payment__plan" }, /* @__PURE__ */ React30.createElement("strong", null, planTermsTitle(checkout.paymentPlan.configuration)), planTerms.map((part) => /* @__PURE__ */ React30.createElement("p", { key: part.id, className: "tf-checkout-note" }, part.text))), isPlanSelected && savedLast4 && /* @__PURE__ */ React30.createElement("div", { className: "tf-checkout-payment__plan-savedcard" }, /* @__PURE__ */ React30.createElement("p", { className: "tf-checkout-note" }, "Your payment will proceed with the card ending in", " ", /* @__PURE__ */ React30.createElement("strong", null, "**** ", savedLast4)), /* @__PURE__ */ React30.createElement(
8551
+ ), isXendit && cardAreaError && /* @__PURE__ */ React30.createElement("p", { className: "tf-checkout-error-text" }, cardAreaError), showTestCardHint && /* @__PURE__ */ React30.createElement("p", { className: "tf-checkout-note" }, isXendit ? t("payment.testCardXendit") : t("payment.testCard"))), isPlanSelected && planTerms.length > 0 && /* @__PURE__ */ React30.createElement("div", { className: "tf-checkout-payment__plan" }, /* @__PURE__ */ React30.createElement("strong", null, planTermsTitle(checkout.paymentPlan.configuration)), planTerms.map((part) => /* @__PURE__ */ React30.createElement("p", { key: part.id, className: "tf-checkout-note" }, part.text))), isPlanSelected && savedLast4 && /* @__PURE__ */ React30.createElement("div", { className: "tf-checkout-payment__plan-savedcard" }, /* @__PURE__ */ React30.createElement("p", { className: "tf-checkout-note" }, "Your payment will proceed with the card ending in", " ", /* @__PURE__ */ React30.createElement("strong", null, "**** ", savedLast4)), /* @__PURE__ */ React30.createElement(
8299
8552
  Checkbox,
8300
8553
  {
8301
8554
  checked: useSavedCard,
8302
8555
  onChange: (e) => setUseSavedCard(e.target.checked),
8303
- label: "Use this card"
8556
+ label: t("payment.useThisCard")
8304
8557
  }
8305
8558
  )));
8306
- return /* @__PURE__ */ React30.createElement("div", { className: ["tf-checkout-payment-stack", className].filter(Boolean).join(" ") }, /* @__PURE__ */ React30.createElement(Card, null, /* @__PURE__ */ React30.createElement(SectionHeader, { title: "Payment" }), !isFree && /* @__PURE__ */ React30.createElement(React30.Fragment, null, !singleCard && /* @__PURE__ */ React30.createElement("div", { className: "tf-checkout-payment__label" }, "Payment method"), !methods ? /* @__PURE__ */ React30.createElement("div", { className: "tf-checkout-payment__cardbox" }, /* @__PURE__ */ React30.createElement(Loader, null)) : singleCard ? paymentInput : /* @__PURE__ */ React30.createElement(
8559
+ return /* @__PURE__ */ React30.createElement("div", { className: ["tf-checkout-payment-stack", className].filter(Boolean).join(" ") }, /* @__PURE__ */ React30.createElement(Card, null, /* @__PURE__ */ React30.createElement(SectionHeader, { title: t("payment.title") }), !isFree && /* @__PURE__ */ React30.createElement(React30.Fragment, null, !singleCard && /* @__PURE__ */ React30.createElement("div", { className: "tf-checkout-payment__label" }, t("payment.method")), !methods ? /* @__PURE__ */ React30.createElement("div", { className: "tf-checkout-payment__cardbox" }, /* @__PURE__ */ React30.createElement(Loader, null)) : singleCard ? paymentInput : /* @__PURE__ */ React30.createElement(
8307
8560
  PaymentMethods,
8308
8561
  {
8309
8562
  options,
@@ -8344,7 +8597,7 @@ var Payment = ({
8344
8597
  loading: finalizing,
8345
8598
  disabled: checkout.isBusy || finalizing || !isFree && !methods
8346
8599
  },
8347
- finalizing ? "Placing\u2026" : payLabel
8600
+ finalizing ? t("payment.placing") : payLabel
8348
8601
  )), bottomError && /* @__PURE__ */ React30.createElement("p", { className: "tf-checkout-error-text" }, bottomError));
8349
8602
  };
8350
8603
 
@@ -8391,6 +8644,7 @@ var Confirmation = ({
8391
8644
  children,
8392
8645
  className
8393
8646
  }) => {
8647
+ const t = useT();
8394
8648
  const checkout = useCheckoutContext();
8395
8649
  const order = checkout.order;
8396
8650
  const [copied, setCopied] = useState18(false);
@@ -8424,7 +8678,7 @@ var Confirmation = ({
8424
8678
  () => void 0
8425
8679
  );
8426
8680
  };
8427
- return /* @__PURE__ */ React32.createElement(Card, { className: cx("tf-checkout-confirmation", className) }, /* @__PURE__ */ React32.createElement("span", { className: "tf-checkout-confirmation__check" }, pending ? "\u23F3" : "\u2713"), /* @__PURE__ */ React32.createElement("strong", { className: "tf-checkout-confirmation__title" }, pending ? "Payment pending" : "Your Tickets are Confirmed!"), /* @__PURE__ */ React32.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__ */ React32.createElement("p", { className: "tf-checkout-confirmation__ref" }, "Reference: ", order.orderHash), pending && order.pendingVoucherUrl && /* @__PURE__ */ React32.createElement(
8681
+ return /* @__PURE__ */ React32.createElement(Card, { className: cx("tf-checkout-confirmation", className) }, /* @__PURE__ */ React32.createElement("span", { className: "tf-checkout-confirmation__check" }, pending ? "\u23F3" : "\u2713"), /* @__PURE__ */ React32.createElement("strong", { className: "tf-checkout-confirmation__title" }, pending ? t("confirmation.pending") : t("confirmation.confirmed")), /* @__PURE__ */ React32.createElement("p", { className: "tf-checkout-note" }, pending ? t("confirmation.pendingBody") : order.alreadyPaid ? t("confirmation.alreadyPaid") : t("confirmation.available")), order.orderHash && /* @__PURE__ */ React32.createElement("p", { className: "tf-checkout-confirmation__ref" }, "Reference: ", order.orderHash), pending && order.pendingVoucherUrl && /* @__PURE__ */ React32.createElement(
8428
8682
  "a",
8429
8683
  {
8430
8684
  className: "tf-checkout-button tf-checkout-button--secondary tf-checkout-button--block",
@@ -8440,7 +8694,7 @@ var Confirmation = ({
8440
8694
  href: viewOrderUrl
8441
8695
  },
8442
8696
  "View my tickets"
8443
- ), children, !pending && url && /* @__PURE__ */ React32.createElement("div", { className: "tf-checkout-confirmation__share" }, /* @__PURE__ */ React32.createElement("strong", null, "Your tickets can be cheaper \u2014 or even FREE!"), /* @__PURE__ */ React32.createElement("p", { className: "tf-checkout-note" }, "Invite friends with your link. When they buy, you get rewarded."), /* @__PURE__ */ React32.createElement("div", { className: "tf-checkout-confirmation__share-link" }, /* @__PURE__ */ React32.createElement("input", { className: "tf-checkout-input", readOnly: true, value: url }), /* @__PURE__ */ React32.createElement(Button, { variant: "secondary", onClick: copy }, copied ? "Copied!" : "Copy link")), /* @__PURE__ */ React32.createElement("div", { className: "tf-checkout-confirmation__socials" }, shares.map((s) => /* @__PURE__ */ React32.createElement(
8697
+ ), children, !pending && url && /* @__PURE__ */ React32.createElement("div", { className: "tf-checkout-confirmation__share" }, /* @__PURE__ */ React32.createElement("strong", null, t("referral.cheaperOrFree")), /* @__PURE__ */ React32.createElement("p", { className: "tf-checkout-note" }, "Invite friends with your link. When they buy, you get rewarded."), /* @__PURE__ */ React32.createElement("div", { className: "tf-checkout-confirmation__share-link" }, /* @__PURE__ */ React32.createElement("input", { className: "tf-checkout-input", readOnly: true, value: url }), /* @__PURE__ */ React32.createElement(Button, { variant: "secondary", onClick: copy }, copied ? t("referral.copied") : t("referral.copyLink"))), /* @__PURE__ */ React32.createElement("div", { className: "tf-checkout-confirmation__socials" }, shares.map((s) => /* @__PURE__ */ React32.createElement(
8444
8698
  "a",
8445
8699
  {
8446
8700
  key: s.label,
@@ -8856,32 +9110,41 @@ var EmbeddedCheckout = ({
8856
9110
  locale,
8857
9111
  messages,
8858
9112
  className
8859
- }) => /* @__PURE__ */ React35.createElement(CheckoutProvider, { theme, locale, messages, className }, /* @__PURE__ */ React35.createElement(
8860
- Flow,
9113
+ }) => /* @__PURE__ */ React35.createElement(
9114
+ CheckoutProvider,
8861
9115
  {
8862
- key: eventId,
8863
- eventId,
8864
- onComplete,
8865
- confirmationMode,
8866
- initialView,
8867
- onViewChange,
8868
- autoScroll,
8869
- requireEmailConfirmation,
8870
- collectTicketHolders,
8871
- collectHolderContact,
8872
- onLogin,
8873
- auth,
8874
- skipBillingWhenProfileComplete,
8875
- ttfOptInLabel,
8876
- brandOptInLabel,
8877
- privacyPolicy,
8878
- additionalConditions,
8879
- initialPromoCode,
8880
- referrer,
8881
- readAttributionFromUrl,
8882
- showTestCardHint
8883
- }
8884
- ));
9116
+ theme,
9117
+ locale,
9118
+ messages,
9119
+ className
9120
+ },
9121
+ /* @__PURE__ */ React35.createElement(
9122
+ Flow,
9123
+ {
9124
+ key: eventId,
9125
+ eventId,
9126
+ onComplete,
9127
+ confirmationMode,
9128
+ initialView,
9129
+ onViewChange,
9130
+ autoScroll,
9131
+ requireEmailConfirmation,
9132
+ collectTicketHolders,
9133
+ collectHolderContact,
9134
+ onLogin,
9135
+ auth,
9136
+ skipBillingWhenProfileComplete,
9137
+ ttfOptInLabel,
9138
+ brandOptInLabel,
9139
+ privacyPolicy,
9140
+ additionalConditions,
9141
+ initialPromoCode,
9142
+ referrer,
9143
+ readAttributionFromUrl,
9144
+ showTestCardHint
9145
+ }
9146
+ )
9147
+ );
8885
9148
 
8886
9149
  // src/ResumedCheckout.tsx
8887
9150
  import React36, { useEffect as useEffect16, useRef as useRef11, useState as useState22 } from "react";