@reblu/site-blocks 0.29.0 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.js CHANGED
@@ -1550,13 +1550,642 @@ function WithdrawalRequestForm({
1550
1550
  }
1551
1551
  );
1552
1552
  }
1553
+
1554
+ // src/components/course-guest-checkout-form.tsx
1555
+ import { useId as useId5, useState as useState9 } from "react";
1556
+ import { cn as cn14 } from "@reblu/site-ui/utils";
1557
+
1558
+ // src/lib/course-guest-checkout.ts
1559
+ function toAcademyCheckoutInvoiceFields(value, overCap, issuesInvoices = true) {
1560
+ if (!issuesInvoices) return {};
1561
+ if (!value.wantsFullInvoice && !overCap) return {};
1562
+ const billing = {
1563
+ billingName: value.billingName.trim(),
1564
+ billingNif: value.billingNif.trim(),
1565
+ billingIdType: value.billingIdType,
1566
+ ...value.billingIdType === "NIF" ? {} : { billingIdCountry: value.billingIdCountry },
1567
+ billingAddress: {
1568
+ street: value.street.trim(),
1569
+ postalCode: value.postalCode.trim(),
1570
+ city: value.city.trim(),
1571
+ country: value.country
1572
+ }
1573
+ };
1574
+ return { ...value.wantsFullInvoice ? { wantsFullInvoice: true } : {}, billing };
1575
+ }
1576
+
1577
+ // src/components/checkout-pay-action.tsx
1578
+ import { cn as cn11 } from "@reblu/site-ui/utils";
1579
+ import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
1580
+ function CheckoutPayAction({
1581
+ label,
1582
+ notice,
1583
+ submitting = false,
1584
+ submittingLabel = "Procesando\u2026",
1585
+ disabled = false,
1586
+ id = "checkout-pay",
1587
+ className,
1588
+ buttonClassName,
1589
+ noticeClassName
1590
+ }) {
1591
+ const noticeId = `${id}-notice`;
1592
+ const isDisabled = submitting || disabled;
1593
+ return /* @__PURE__ */ jsxs9("div", { "data-slot": "checkout-pay-action", className: cn11("space-y-3", className), children: [
1594
+ /* @__PURE__ */ jsx11(
1595
+ "button",
1596
+ {
1597
+ type: "submit",
1598
+ disabled: isDisabled,
1599
+ "aria-busy": submitting || void 0,
1600
+ "aria-describedby": notice ? noticeId : void 0,
1601
+ className: buttonClassName ?? cn11(
1602
+ "flex w-full items-center justify-center gap-2 rounded-xl px-4 py-3 text-base font-semibold transition-all",
1603
+ isDisabled ? "cursor-not-allowed bg-muted text-muted-foreground" : "cursor-pointer bg-primary text-primary-foreground hover:bg-primary/90"
1604
+ ),
1605
+ children: submitting ? submittingLabel : label
1606
+ }
1607
+ ),
1608
+ notice ? /* @__PURE__ */ jsx11("p", { id: noticeId, "data-slot": "checkout-pay-notice", className: noticeClassName ?? "text-sm text-muted-foreground", children: notice }) : null
1609
+ ] });
1610
+ }
1611
+
1612
+ // src/components/checkout-terms-acceptance.tsx
1613
+ import { cn as cn12 } from "@reblu/site-ui/utils";
1614
+ import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
1615
+ function splitTermsLabel(label) {
1616
+ const at = label.indexOf("{terms}");
1617
+ return at === -1 ? [`${label} `, ""] : [label.slice(0, at), label.slice(at + "{terms}".length)];
1618
+ }
1619
+ function CheckoutTermsAcceptance({
1620
+ copy,
1621
+ termsHref,
1622
+ checked,
1623
+ onCheckedChange,
1624
+ error,
1625
+ newTabHint = "(se abre en una pesta\xF1a nueva)",
1626
+ id,
1627
+ className
1628
+ }) {
1629
+ if (!copy.termsVersion) return null;
1630
+ const boxId = id ?? "checkout-terms";
1631
+ const errorId = `${boxId}-error`;
1632
+ const [before, after] = splitTermsLabel(copy.termsCheckboxLabel).map(
1633
+ (part) => part.replaceAll("{tenant}", copy.tenantName)
1634
+ );
1635
+ const newTab = copy.isTermsLinkNewTab;
1636
+ return /* @__PURE__ */ jsxs10("div", { "data-slot": "checkout-terms", className: cn12("space-y-1", className), children: [
1637
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-start gap-3", children: [
1638
+ /* @__PURE__ */ jsx12(
1639
+ "input",
1640
+ {
1641
+ id: boxId,
1642
+ type: "checkbox",
1643
+ required: true,
1644
+ checked,
1645
+ onChange: (e) => onCheckedChange(e.target.checked),
1646
+ "aria-invalid": error ? true : void 0,
1647
+ "aria-describedby": error ? errorId : void 0,
1648
+ className: "mt-0.5 size-5 shrink-0 cursor-pointer accent-primary"
1649
+ }
1650
+ ),
1651
+ /* @__PURE__ */ jsxs10("label", { htmlFor: boxId, className: "text-sm leading-relaxed", children: [
1652
+ before,
1653
+ /* @__PURE__ */ jsxs10(
1654
+ "a",
1655
+ {
1656
+ href: copy.termsLinkUrl ?? termsHref,
1657
+ ...newTab ? { target: "_blank", rel: "noopener noreferrer" } : {},
1658
+ className: "font-medium underline underline-offset-2 hover:text-primary",
1659
+ children: [
1660
+ copy.termsLinkText,
1661
+ newTab ? /* @__PURE__ */ jsxs10(Fragment4, { children: [
1662
+ " ",
1663
+ /* @__PURE__ */ jsx12("span", { className: "sr-only", children: newTabHint })
1664
+ ] }) : null
1665
+ ]
1666
+ }
1667
+ ),
1668
+ after
1669
+ ] })
1670
+ ] }),
1671
+ error ? /* @__PURE__ */ jsx12("p", { id: errorId, className: "pl-8 text-sm text-destructive", children: error }) : null
1672
+ ] });
1673
+ }
1674
+ function toCheckoutTermsFields(copy, accepted) {
1675
+ const version = copy?.termsVersion;
1676
+ return version ? { acceptsTerms: accepted, termsVersionId: version.id } : {};
1677
+ }
1678
+
1679
+ // src/components/full-invoice-fields.tsx
1680
+ import { cn as cn13 } from "@reblu/site-ui/utils";
1681
+ import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
1682
+ var EMPTY_FULL_INVOICE_VALUE = {
1683
+ wantsFullInvoice: false,
1684
+ billingIdType: "NIF",
1685
+ billingIdCountry: "",
1686
+ billingNif: "",
1687
+ billingName: "",
1688
+ street: "",
1689
+ postalCode: "",
1690
+ city: "",
1691
+ country: "ES"
1692
+ };
1693
+ var DEFAULT_LABELS5 = {
1694
+ toggle: "\xBFQuieres factura completa?",
1695
+ underCapNotice: "Para una factura completa necesitas tu NIF/NIE o un documento de identificaci\xF3n. Si no, recibir\xE1s una factura simplificada.",
1696
+ overCapNotice: "El importe del pedido supera el m\xE1ximo de la factura simplificada: para completar la compra, indica tu NIF/NIE o un documento de identificaci\xF3n, tu nombre y tu direcci\xF3n de facturaci\xF3n.",
1697
+ idType: "Tipo de documento",
1698
+ idCountry: "Pa\xEDs que expidi\xF3 el documento",
1699
+ chooseCountry: "Elige un pa\xEDs",
1700
+ spanishNif: "NIF / NIE / CIF",
1701
+ documentNumber: "N\xFAmero de documento",
1702
+ name: "Nombre o raz\xF3n social",
1703
+ street: "Direcci\xF3n",
1704
+ postalCode: "C\xF3digo postal",
1705
+ city: "Ciudad",
1706
+ country: "Pa\xEDs",
1707
+ idTypeOptions: {
1708
+ NIF: "NIF / NIE / CIF (Espa\xF1a)",
1709
+ "02": "NIF-IVA intracomunitario (otro pa\xEDs de la UE)",
1710
+ "03": "Pasaporte",
1711
+ "04": "Documento oficial de identidad de tu pa\xEDs de residencia",
1712
+ "05": "Certificado de residencia",
1713
+ "06": "Otro documento acreditativo"
1714
+ }
1715
+ };
1716
+ var ID_TYPES = ["NIF", "02", "03", "04", "05", "06"];
1717
+ var DEFAULT_INVOICE_COUNTRIES = [
1718
+ { code: "ES", name: "Espa\xF1a" },
1719
+ { code: "DE", name: "Alemania" },
1720
+ { code: "AD", name: "Andorra" },
1721
+ { code: "AR", name: "Argentina" },
1722
+ { code: "AT", name: "Austria" },
1723
+ { code: "BE", name: "B\xE9lgica" },
1724
+ { code: "BG", name: "Bulgaria" },
1725
+ { code: "CY", name: "Chipre" },
1726
+ { code: "CO", name: "Colombia" },
1727
+ { code: "HR", name: "Croacia" },
1728
+ { code: "DK", name: "Dinamarca" },
1729
+ { code: "SK", name: "Eslovaquia" },
1730
+ { code: "SI", name: "Eslovenia" },
1731
+ { code: "US", name: "Estados Unidos" },
1732
+ { code: "EE", name: "Estonia" },
1733
+ { code: "FI", name: "Finlandia" },
1734
+ { code: "FR", name: "Francia" },
1735
+ { code: "GR", name: "Grecia" },
1736
+ { code: "HU", name: "Hungr\xEDa" },
1737
+ { code: "IE", name: "Irlanda" },
1738
+ { code: "IT", name: "Italia" },
1739
+ { code: "LV", name: "Letonia" },
1740
+ { code: "LT", name: "Lituania" },
1741
+ { code: "LU", name: "Luxemburgo" },
1742
+ { code: "MT", name: "Malta" },
1743
+ { code: "MA", name: "Marruecos" },
1744
+ { code: "MX", name: "M\xE9xico" },
1745
+ { code: "NL", name: "Pa\xEDses Bajos" },
1746
+ { code: "PL", name: "Polonia" },
1747
+ { code: "PT", name: "Portugal" },
1748
+ { code: "GB", name: "Reino Unido" },
1749
+ { code: "CZ", name: "Rep\xFAblica Checa" },
1750
+ { code: "RO", name: "Ruman\xEDa" },
1751
+ { code: "SE", name: "Suecia" },
1752
+ { code: "CH", name: "Suiza" },
1753
+ { code: "VE", name: "Venezuela" }
1754
+ ];
1755
+ function isOverSimplifiedInvoiceCap(totalCents, capCents) {
1756
+ return capCents != null && totalCents > capCents;
1757
+ }
1758
+ var FIELD_CLASS3 = "w-full rounded-lg border border-border bg-background px-3 py-2 text-sm focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20";
1759
+ function FullInvoiceFields({
1760
+ value,
1761
+ onChange,
1762
+ overCap,
1763
+ issuesInvoices = true,
1764
+ errors = {},
1765
+ countries = DEFAULT_INVOICE_COUNTRIES,
1766
+ labels,
1767
+ className
1768
+ }) {
1769
+ if (!issuesInvoices) return null;
1770
+ const t = { ...DEFAULT_LABELS5, ...labels };
1771
+ const showFields = value.wantsFullInvoice || overCap;
1772
+ const isSpanishNif = value.billingIdType === "NIF";
1773
+ const set = (key, next) => onChange({ ...value, [key]: next });
1774
+ const error = (key) => errors[key] ? /* @__PURE__ */ jsx13("p", { id: `full-invoice-${key}-error`, className: "text-sm text-destructive", children: errors[key] }) : null;
1775
+ const invalid = (key) => errors[key] ? { "aria-invalid": true, "aria-describedby": `full-invoice-${key}-error` } : {};
1776
+ return /* @__PURE__ */ jsxs11("section", { className: cn13("space-y-4", className), "data-slot": "full-invoice-fields", children: [
1777
+ overCap ? /* @__PURE__ */ jsx13("p", { role: "note", className: "rounded-lg border border-border p-4 text-sm", children: t.overCapNotice }) : /* @__PURE__ */ jsxs11("div", { className: "space-y-1", children: [
1778
+ /* @__PURE__ */ jsxs11("label", { className: "flex items-center gap-2 text-sm font-medium", children: [
1779
+ /* @__PURE__ */ jsx13(
1780
+ "input",
1781
+ {
1782
+ type: "checkbox",
1783
+ checked: value.wantsFullInvoice,
1784
+ onChange: (e) => set("wantsFullInvoice", e.target.checked)
1785
+ }
1786
+ ),
1787
+ t.toggle
1788
+ ] }),
1789
+ /* @__PURE__ */ jsx13("p", { className: "text-sm text-muted-foreground", children: t.underCapNotice })
1790
+ ] }),
1791
+ showFields && /* @__PURE__ */ jsxs11("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: [
1792
+ /* @__PURE__ */ jsxs11("div", { className: "space-y-1", children: [
1793
+ /* @__PURE__ */ jsx13("label", { htmlFor: "full-invoice-id-type", className: "text-sm font-medium", children: t.idType }),
1794
+ /* @__PURE__ */ jsx13(
1795
+ "select",
1796
+ {
1797
+ id: "full-invoice-id-type",
1798
+ className: FIELD_CLASS3,
1799
+ required: true,
1800
+ value: value.billingIdType,
1801
+ onChange: (e) => set("billingIdType", e.target.value),
1802
+ ...invalid("billingIdType"),
1803
+ children: ID_TYPES.map((type) => /* @__PURE__ */ jsx13("option", { value: type, children: t.idTypeOptions[type] }, type))
1804
+ }
1805
+ ),
1806
+ error("billingIdType")
1807
+ ] }),
1808
+ !isSpanishNif && /* @__PURE__ */ jsxs11("div", { className: "space-y-1", children: [
1809
+ /* @__PURE__ */ jsx13("label", { htmlFor: "full-invoice-id-country", className: "text-sm font-medium", children: t.idCountry }),
1810
+ /* @__PURE__ */ jsxs11(
1811
+ "select",
1812
+ {
1813
+ id: "full-invoice-id-country",
1814
+ className: FIELD_CLASS3,
1815
+ required: true,
1816
+ value: value.billingIdCountry,
1817
+ onChange: (e) => set("billingIdCountry", e.target.value),
1818
+ ...invalid("billingIdCountry"),
1819
+ children: [
1820
+ /* @__PURE__ */ jsx13("option", { value: "", disabled: true, children: t.chooseCountry }),
1821
+ countries.map((c) => /* @__PURE__ */ jsx13("option", { value: c.code, children: c.name }, c.code))
1822
+ ]
1823
+ }
1824
+ ),
1825
+ error("billingIdCountry")
1826
+ ] }),
1827
+ /* @__PURE__ */ jsxs11("div", { className: "space-y-1", children: [
1828
+ /* @__PURE__ */ jsx13("label", { htmlFor: "full-invoice-nif", className: "text-sm font-medium", children: isSpanishNif ? t.spanishNif : t.documentNumber }),
1829
+ /* @__PURE__ */ jsx13(
1830
+ "input",
1831
+ {
1832
+ id: "full-invoice-nif",
1833
+ className: FIELD_CLASS3,
1834
+ required: true,
1835
+ value: value.billingNif,
1836
+ onChange: (e) => set("billingNif", e.target.value),
1837
+ ...invalid("billingNif")
1838
+ }
1839
+ ),
1840
+ error("billingNif")
1841
+ ] }),
1842
+ /* @__PURE__ */ jsxs11("div", { className: "space-y-1", children: [
1843
+ /* @__PURE__ */ jsx13("label", { htmlFor: "full-invoice-name", className: "text-sm font-medium", children: t.name }),
1844
+ /* @__PURE__ */ jsx13(
1845
+ "input",
1846
+ {
1847
+ id: "full-invoice-name",
1848
+ className: FIELD_CLASS3,
1849
+ required: true,
1850
+ value: value.billingName,
1851
+ onChange: (e) => set("billingName", e.target.value),
1852
+ ...invalid("billingName")
1853
+ }
1854
+ ),
1855
+ error("billingName")
1856
+ ] }),
1857
+ /* @__PURE__ */ jsxs11("div", { className: "space-y-1 sm:col-span-2", children: [
1858
+ /* @__PURE__ */ jsx13("label", { htmlFor: "full-invoice-street", className: "text-sm font-medium", children: t.street }),
1859
+ /* @__PURE__ */ jsx13(
1860
+ "input",
1861
+ {
1862
+ id: "full-invoice-street",
1863
+ className: FIELD_CLASS3,
1864
+ required: true,
1865
+ value: value.street,
1866
+ onChange: (e) => set("street", e.target.value),
1867
+ ...invalid("address")
1868
+ }
1869
+ )
1870
+ ] }),
1871
+ /* @__PURE__ */ jsxs11("div", { className: "space-y-1", children: [
1872
+ /* @__PURE__ */ jsx13("label", { htmlFor: "full-invoice-postal-code", className: "text-sm font-medium", children: t.postalCode }),
1873
+ /* @__PURE__ */ jsx13(
1874
+ "input",
1875
+ {
1876
+ id: "full-invoice-postal-code",
1877
+ className: FIELD_CLASS3,
1878
+ required: true,
1879
+ value: value.postalCode,
1880
+ onChange: (e) => set("postalCode", e.target.value)
1881
+ }
1882
+ )
1883
+ ] }),
1884
+ /* @__PURE__ */ jsxs11("div", { className: "space-y-1", children: [
1885
+ /* @__PURE__ */ jsx13("label", { htmlFor: "full-invoice-city", className: "text-sm font-medium", children: t.city }),
1886
+ /* @__PURE__ */ jsx13(
1887
+ "input",
1888
+ {
1889
+ id: "full-invoice-city",
1890
+ className: FIELD_CLASS3,
1891
+ required: true,
1892
+ value: value.city,
1893
+ onChange: (e) => set("city", e.target.value)
1894
+ }
1895
+ )
1896
+ ] }),
1897
+ /* @__PURE__ */ jsxs11("div", { className: "space-y-1", children: [
1898
+ /* @__PURE__ */ jsx13("label", { htmlFor: "full-invoice-country", className: "text-sm font-medium", children: t.country }),
1899
+ /* @__PURE__ */ jsx13(
1900
+ "select",
1901
+ {
1902
+ id: "full-invoice-country",
1903
+ className: FIELD_CLASS3,
1904
+ required: true,
1905
+ value: value.country,
1906
+ onChange: (e) => set("country", e.target.value),
1907
+ children: countries.map((c) => /* @__PURE__ */ jsx13("option", { value: c.code, children: c.name }, c.code))
1908
+ }
1909
+ )
1910
+ ] }),
1911
+ /* @__PURE__ */ jsx13("div", { className: "sm:col-span-2", children: error("address") })
1912
+ ] })
1913
+ ] });
1914
+ }
1915
+
1916
+ // src/components/course-guest-checkout-form.tsx
1917
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
1918
+ var DEFAULT_COURSE_GUEST_CHECKOUT_FORM_LABELS = {
1919
+ firstNameLabel: "Nombre",
1920
+ lastNameLabel: "Apellidos",
1921
+ emailLabel: "Email",
1922
+ total: (total) => `Total (impuestos incluidos): ${total}`,
1923
+ submit: "Continuar al pago",
1924
+ submitting: "Procesando\u2026",
1925
+ firstNameRequired: "Indica tu nombre.",
1926
+ lastNameRequired: "Indica tus apellidos.",
1927
+ emailInvalid: "Introduce un email v\xE1lido.",
1928
+ termsRequired: "Para continuar, acepta las condiciones.",
1929
+ consentRequired: "Para continuar, marca esta casilla.",
1930
+ requestRequiredNotice: "Este curso se solicita antes de pagar. Completa la solicitud.",
1931
+ genericError: "No hemos podido iniciar el pago. Int\xE9ntalo de nuevo."
1932
+ };
1933
+ var DEFAULT_COURSE_GUEST_CHECKOUT_ERROR_MESSAGES = {
1934
+ INVALID_INPUT: "Revisa los datos introducidos.",
1935
+ RATE_LIMITED: "Demasiados intentos. Espera unos minutos e int\xE9ntalo de nuevo.",
1936
+ COURSE_NOT_FOUND: "Este curso ya no est\xE1 disponible.",
1937
+ SALES_CLOSED: "Este curso no est\xE1 a la venta en este momento.",
1938
+ ENROLLMENT_REQUEST_REQUIRED: "Este curso se solicita antes de pagar.",
1939
+ INVOICING_NOT_READY: "No se puede completar la compra en este momento. Int\xE9ntalo m\xE1s tarde.",
1940
+ TERMS_NOT_ACCEPTED: "Para continuar, acepta las condiciones.",
1941
+ TERMS_VERSION_CHANGED: "Las condiciones se han actualizado. Recarga la p\xE1gina y vuelve a aceptarlas.",
1942
+ CONSENT_REQUIRED: "Para continuar, marca la casilla del curso.",
1943
+ CONSENT_VERSION_CHANGED: "El texto de la casilla ha cambiado. Recarga la p\xE1gina y vuelve a marcarla.",
1944
+ INVALID_BILLING: "Revisa los datos de facturaci\xF3n."
1945
+ };
1946
+ var EMAIL_PATTERN3 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
1947
+ var FIELD_CLASS4 = "w-full rounded-lg border bg-background px-3 py-2 text-sm transition focus:outline-none focus:ring-2 focus:ring-primary/20";
1948
+ async function postToRoute3(endpoint, input) {
1949
+ try {
1950
+ const res = await fetch(endpoint, {
1951
+ method: "POST",
1952
+ headers: { "Content-Type": "application/json" },
1953
+ body: JSON.stringify(input)
1954
+ });
1955
+ const json = await res.json().catch(() => null);
1956
+ if (res.ok && json?.data) return { ok: true, data: json.data };
1957
+ return {
1958
+ ok: false,
1959
+ status: res.status,
1960
+ ...typeof json?.code === "string" ? { code: json.code } : {},
1961
+ ...json?.details !== void 0 ? { details: json.details } : {}
1962
+ };
1963
+ } catch {
1964
+ return { ok: false, status: 0 };
1965
+ }
1966
+ }
1967
+ function fieldErrorsOf(details) {
1968
+ const errors = details?.fieldErrors;
1969
+ if (typeof errors !== "object" || errors === null) return {};
1970
+ return Object.fromEntries(
1971
+ Object.entries(errors).filter(
1972
+ (entry) => typeof entry[1] === "string"
1973
+ )
1974
+ );
1975
+ }
1976
+ function toInvoiceErrors(fieldErrors) {
1977
+ const out = {};
1978
+ for (const key of ["billingIdType", "billingIdCountry", "billingNif", "billingName"]) {
1979
+ if (fieldErrors[key]) out[key] = fieldErrors[key];
1980
+ }
1981
+ if (fieldErrors.billingAddress) out.address = fieldErrors.billingAddress;
1982
+ return out;
1983
+ }
1984
+ function CourseGuestCheckoutForm({
1985
+ course,
1986
+ copy,
1987
+ termsHref,
1988
+ requestForm,
1989
+ issuesInvoices = true,
1990
+ simplifiedInvoiceCapCents = null,
1991
+ submit,
1992
+ endpoint = "/api/academy/checkout",
1993
+ onRedirect,
1994
+ onError,
1995
+ labels,
1996
+ errorMessages,
1997
+ invoiceLabels,
1998
+ invoiceCountries,
1999
+ currencyCode,
2000
+ locale,
2001
+ className
2002
+ }) {
2003
+ const t = {
2004
+ ...DEFAULT_COURSE_GUEST_CHECKOUT_FORM_LABELS,
2005
+ ...labels
2006
+ };
2007
+ const messages = { ...DEFAULT_COURSE_GUEST_CHECKOUT_ERROR_MESSAGES, ...errorMessages };
2008
+ const id = useId5();
2009
+ const [firstName, setFirstName] = useState9("");
2010
+ const [lastName, setLastName] = useState9("");
2011
+ const [email, setEmail] = useState9("");
2012
+ const [acceptsTerms, setAcceptsTerms] = useState9(false);
2013
+ const [acceptsConsent, setAcceptsConsent] = useState9(false);
2014
+ const [invoice, setInvoice] = useState9(EMPTY_FULL_INVOICE_VALUE);
2015
+ const [errors, setErrors] = useState9({});
2016
+ const [invoiceErrors, setInvoiceErrors] = useState9({});
2017
+ const [formError, setFormError] = useState9(null);
2018
+ const [submitting, setSubmitting] = useState9(false);
2019
+ const [needsRequest, setNeedsRequest] = useState9(false);
2020
+ const consent = course.withdrawalConsent;
2021
+ const hasTerms = Boolean(copy.termsVersion);
2022
+ const overCap = isOverSimplifiedInvoiceCap(course.priceCents, simplifiedInvoiceCapCents);
2023
+ const formattedTotal = formatPrice(course.priceCents, currencyCode, locale);
2024
+ const notice = copy.payNotice ? copy.payNotice.replaceAll("{total}", formattedTotal).replaceAll("{tenant}", copy.tenantName) : null;
2025
+ if (needsRequest) {
2026
+ return /* @__PURE__ */ jsxs12("div", { "data-slot": "course-guest-checkout-request", className: cn14("space-y-4", className), children: [
2027
+ t.requestRequiredNotice ? /* @__PURE__ */ jsx14("p", { className: "text-sm text-muted-foreground", children: t.requestRequiredNotice }) : null,
2028
+ requestForm
2029
+ ] });
2030
+ }
2031
+ async function handleSubmit(event) {
2032
+ event.preventDefault();
2033
+ if (submitting) return;
2034
+ setFormError(null);
2035
+ setInvoiceErrors({});
2036
+ const next = {};
2037
+ if (!firstName.trim()) next.firstName = t.firstNameRequired;
2038
+ if (!lastName.trim()) next.lastName = t.lastNameRequired;
2039
+ if (!EMAIL_PATTERN3.test(email.trim())) next.email = t.emailInvalid;
2040
+ if (hasTerms && !acceptsTerms) next.terms = t.termsRequired;
2041
+ if (consent && !acceptsConsent) next.consent = t.consentRequired;
2042
+ setErrors(next);
2043
+ if (Object.keys(next).length > 0) return;
2044
+ const input = {
2045
+ courseSlug: course.slug,
2046
+ firstName: firstName.trim(),
2047
+ lastName: lastName.trim(),
2048
+ email: email.trim(),
2049
+ ...toCheckoutTermsFields(copy, acceptsTerms),
2050
+ ...consent ? { acceptsWithdrawalWaiver: acceptsConsent, withdrawalWaiverVersion: consent.version } : {},
2051
+ ...toAcademyCheckoutInvoiceFields(invoice, overCap, issuesInvoices)
2052
+ };
2053
+ setSubmitting(true);
2054
+ try {
2055
+ const result = await (submit ?? ((body) => postToRoute3(endpoint, body)))(input).catch(
2056
+ () => ({ ok: false, status: 0 })
2057
+ );
2058
+ if (result.ok) {
2059
+ ;
2060
+ (onRedirect ?? ((url) => window.location.assign(url)))(result.data.url);
2061
+ return;
2062
+ }
2063
+ onError?.(result);
2064
+ if (result.code === "ENROLLMENT_REQUEST_REQUIRED") {
2065
+ setNeedsRequest(true);
2066
+ return;
2067
+ }
2068
+ if (result.code === "INVALID_BILLING")
2069
+ setInvoiceErrors(toInvoiceErrors(fieldErrorsOf(result.details)));
2070
+ const code = result.code;
2071
+ setFormError(code && messages[code] || t.genericError);
2072
+ } finally {
2073
+ setSubmitting(false);
2074
+ }
2075
+ }
2076
+ const fieldError = (field) => errors[field] ? /* @__PURE__ */ jsx14("p", { id: `${id}-${field}-error`, className: "text-xs text-destructive", children: errors[field] }) : null;
2077
+ const invalid = (field) => errors[field] ? { "aria-invalid": true, "aria-describedby": `${id}-${field}-error` } : {};
2078
+ const border = (field) => errors[field] ? "border-destructive" : "border-border";
2079
+ const textField = (field, label, value, onChange, autoComplete) => /* @__PURE__ */ jsxs12("div", { className: "space-y-1", children: [
2080
+ /* @__PURE__ */ jsx14("label", { htmlFor: `${id}-${field}`, className: "text-sm font-medium", children: label }),
2081
+ /* @__PURE__ */ jsx14(
2082
+ "input",
2083
+ {
2084
+ id: `${id}-${field}`,
2085
+ type: field === "email" ? "email" : "text",
2086
+ autoComplete,
2087
+ maxLength: field === "email" ? 254 : 200,
2088
+ value,
2089
+ onChange: (e) => onChange(e.target.value),
2090
+ ...invalid(field),
2091
+ className: cn14(FIELD_CLASS4, border(field))
2092
+ }
2093
+ ),
2094
+ fieldError(field)
2095
+ ] });
2096
+ return /* @__PURE__ */ jsxs12(
2097
+ "form",
2098
+ {
2099
+ noValidate: true,
2100
+ onSubmit: handleSubmit,
2101
+ "data-slot": "course-guest-checkout-form",
2102
+ className: cn14("space-y-6", className),
2103
+ children: [
2104
+ /* @__PURE__ */ jsxs12("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2", children: [
2105
+ textField("firstName", t.firstNameLabel, firstName, setFirstName, "given-name"),
2106
+ textField("lastName", t.lastNameLabel, lastName, setLastName, "family-name"),
2107
+ /* @__PURE__ */ jsx14("div", { className: "sm:col-span-2", children: textField("email", t.emailLabel, email, setEmail, "email") })
2108
+ ] }),
2109
+ /* @__PURE__ */ jsx14(
2110
+ FullInvoiceFields,
2111
+ {
2112
+ value: invoice,
2113
+ onChange: setInvoice,
2114
+ overCap,
2115
+ issuesInvoices,
2116
+ errors: invoiceErrors,
2117
+ countries: invoiceCountries,
2118
+ labels: {
2119
+ ...copy.fullInvoiceCheckboxLabel ? { toggle: copy.fullInvoiceCheckboxLabel } : {},
2120
+ ...copy.fullInvoiceHelpText ? { underCapNotice: copy.fullInvoiceHelpText } : {},
2121
+ ...invoiceLabels
2122
+ }
2123
+ }
2124
+ ),
2125
+ /* @__PURE__ */ jsxs12("div", { className: "space-y-3", children: [
2126
+ /* @__PURE__ */ jsx14(
2127
+ CheckoutTermsAcceptance,
2128
+ {
2129
+ copy,
2130
+ termsHref,
2131
+ checked: acceptsTerms,
2132
+ onCheckedChange: setAcceptsTerms,
2133
+ error: errors.terms,
2134
+ id: `${id}-terms`
2135
+ }
2136
+ ),
2137
+ consent ? /* @__PURE__ */ jsxs12(
2138
+ "div",
2139
+ {
2140
+ "data-slot": "course-guest-checkout-consent",
2141
+ "data-kind": consent.kind,
2142
+ className: "space-y-1",
2143
+ children: [
2144
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-start gap-3", children: [
2145
+ /* @__PURE__ */ jsx14(
2146
+ "input",
2147
+ {
2148
+ id: `${id}-consent`,
2149
+ type: "checkbox",
2150
+ checked: acceptsConsent,
2151
+ onChange: (e) => setAcceptsConsent(e.target.checked),
2152
+ ...invalid("consent"),
2153
+ className: "mt-0.5 size-5 shrink-0 cursor-pointer accent-primary"
2154
+ }
2155
+ ),
2156
+ /* @__PURE__ */ jsx14("label", { htmlFor: `${id}-consent`, className: "text-sm leading-relaxed", children: consent.text })
2157
+ ] }),
2158
+ errors.consent ? /* @__PURE__ */ jsx14("p", { id: `${id}-consent-error`, className: "pl-8 text-sm text-destructive", children: errors.consent }) : null
2159
+ ]
2160
+ }
2161
+ ) : null
2162
+ ] }),
2163
+ /* @__PURE__ */ jsx14("p", { "data-slot": "course-guest-checkout-total", className: "text-base font-semibold", children: t.total(formattedTotal) }),
2164
+ formError ? /* @__PURE__ */ jsx14("p", { role: "alert", className: "text-sm text-destructive", children: formError }) : null,
2165
+ /* @__PURE__ */ jsx14(
2166
+ CheckoutPayAction,
2167
+ {
2168
+ label: copy.continueToPaymentLabel ?? t.submit,
2169
+ notice,
2170
+ submitting,
2171
+ submittingLabel: t.submitting,
2172
+ id: `${id}-pay`
2173
+ }
2174
+ )
2175
+ ]
2176
+ }
2177
+ );
2178
+ }
1553
2179
  export {
1554
2180
  AddToCartButton,
1555
2181
  CartIcon,
1556
2182
  Collection,
2183
+ CourseGuestCheckoutForm,
1557
2184
  CourseSyllabus,
1558
2185
  DATA_REQUEST_FIELD_LIMITS,
1559
2186
  DATA_REQUEST_TYPES,
2187
+ DEFAULT_COURSE_GUEST_CHECKOUT_ERROR_MESSAGES,
2188
+ DEFAULT_COURSE_GUEST_CHECKOUT_FORM_LABELS,
1560
2189
  DEFAULT_COURSE_SYLLABUS_LABELS,
1561
2190
  DEFAULT_DATA_REQUEST_FORM_LABELS,
1562
2191
  DEFAULT_PRODUCT_CAROUSEL_LABELS,