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