@ecomiq/storefront 2.1.4 → 3.0.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.
Files changed (310) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -103
  3. package/dist/account-Dx4e3syi.js +258 -0
  4. package/dist/account-forms-AVk71ko7.js +39 -0
  5. package/dist/account-forms.d.ts +13 -0
  6. package/dist/account.d.ts +240 -0
  7. package/dist/address-defaults-BqjRhS82.js +14 -0
  8. package/dist/address-defaults.d.ts +11 -0
  9. package/dist/analytics/analytics-CG1Qagwl.js +148 -0
  10. package/dist/analytics/analytics.d.ts +1 -0
  11. package/dist/analytics/config-DJr-GRhs.js +62 -0
  12. package/dist/analytics/config.d.ts +22 -0
  13. package/dist/analytics/consent-B13rBpBs.js +57 -0
  14. package/dist/analytics/consent-banner-9QvRRy8v.js +239 -0
  15. package/dist/analytics/consent-banner.d.ts +20 -0
  16. package/dist/analytics/cookies-pLozllyB.js +100 -0
  17. package/dist/analytics/cookies.d.ts +6 -0
  18. package/dist/analytics/destinations-iECrlLIr.js +144 -0
  19. package/dist/analytics/events-Dt81tIp1.js +102 -0
  20. package/dist/analytics/events.d.ts +51 -0
  21. package/dist/analytics/tracker-p4yaoOyk.js +51 -0
  22. package/dist/api-cache-DsuIn5hX.js +159 -0
  23. package/dist/bank-accounts-DlEczQQ5.js +81 -0
  24. package/dist/bank-accounts.d.ts +4 -0
  25. package/dist/captcha-DAqaIx8m.js +117 -0
  26. package/dist/captcha.d.ts +34 -0
  27. package/dist/cart-D7DxZ2lD.js +30 -0
  28. package/dist/cart-actions-Bsub_FFG.js +116 -0
  29. package/dist/cart-actions.d.ts +15 -0
  30. package/dist/cart-drawer-B7PPsR69.js +22 -0
  31. package/dist/cart-drawer.d.ts +9 -0
  32. package/dist/cart-form-y9P1r_EX.js +81 -0
  33. package/dist/cart-form.d.ts +24 -0
  34. package/dist/cart-summary-ur2VWKr-.js +89 -0
  35. package/dist/cart-summary.d.ts +31 -0
  36. package/dist/cart.d.ts +4 -0
  37. package/dist/catalog-7gJ-l5hW.js +67 -0
  38. package/dist/catalog-hooks-B7ZP4wYY.js +312 -0
  39. package/dist/catalog-hooks.d.ts +111 -0
  40. package/dist/catalog.d.ts +5 -0
  41. package/dist/checkout-DVWSXANi.js +474 -0
  42. package/dist/checkout-form-CbOIdENC.js +131 -0
  43. package/dist/checkout-form.d.ts +20 -0
  44. package/dist/checkout.d.ts +86 -0
  45. package/dist/complaint-book-BvwLvfx0.js +117 -0
  46. package/dist/complaint-book.d.ts +62 -0
  47. package/dist/culqi-authentication-BGr20vAJ.js +204 -0
  48. package/dist/culqi-authentication.d.ts +15 -0
  49. package/dist/culqi-checkout-CTXpKgp_.js +55 -0
  50. package/dist/culqi-three-ds-HP3mfrvV.js +33 -0
  51. package/dist/culqi-three-ds.d.ts +29 -0
  52. package/dist/customer-avatar-CJXSDroK.js +12 -0
  53. package/dist/customer-avatar.d.ts +5 -0
  54. package/dist/customer-cookies-DHOgFAMV.js +45 -0
  55. package/dist/customer-csrf-C1oDX-Py.js +17 -0
  56. package/dist/customer-csrf.d.ts +3 -0
  57. package/dist/customer-document-fields-C1K-_DAD.js +70 -0
  58. package/dist/customer-document-fields.d.ts +9 -0
  59. package/dist/customer-login-form-C7AC6vXd.js +144 -0
  60. package/dist/customer-login-form.d.ts +17 -0
  61. package/dist/customer-registration-form-BEm_NEfP.js +93 -0
  62. package/dist/customer-registration-form.d.ts +8 -0
  63. package/dist/document-url-CGsAl5Tf.js +9 -0
  64. package/dist/documents-T1mzc_j8.js +38 -0
  65. package/dist/documents.d.ts +16 -0
  66. package/dist/entries/account.d.ts +11 -0
  67. package/dist/entries/account.js +10 -0
  68. package/dist/entries/analytics.d.ts +6 -0
  69. package/dist/entries/analytics.js +5 -0
  70. package/dist/entries/cart.d.ts +8 -0
  71. package/dist/entries/cart.js +7 -0
  72. package/dist/entries/checkout.d.ts +12 -0
  73. package/dist/entries/checkout.js +11 -0
  74. package/dist/entries/order.d.ts +11 -0
  75. package/dist/entries/order.js +11 -0
  76. package/dist/favicon-YpyhVJ9H.js +28 -0
  77. package/dist/favicon.d.ts +4 -0
  78. package/dist/form-BtQcbXlJ.js +18 -0
  79. package/dist/form-contracts-BNpHaTGJ.js +166 -0
  80. package/dist/form-contracts.d.ts +42 -0
  81. package/dist/form.d.ts +3 -0
  82. package/dist/hidden-CCWtOWKR.js +3 -0
  83. package/dist/hidden.d.ts +4 -0
  84. package/dist/index.d.ts +50 -0
  85. package/dist/index.js +50 -0
  86. package/dist/invoice-fields-BG0HjL6T.js +103 -0
  87. package/dist/invoice-fields.d.ts +39 -0
  88. package/dist/links-kFxBZfdb.js +96 -0
  89. package/dist/links.d.ts +21 -0
  90. package/dist/mercadopago-checkout-DC7RXa8k.js +27 -0
  91. package/dist/mercadopago-dialog-UTQev0MG.js +180 -0
  92. package/dist/mercadopago-dialog.d.ts +21 -0
  93. package/dist/money-DtGOtDri.js +32 -0
  94. package/dist/money.d.ts +1 -0
  95. package/dist/optimistic-cart-BveVOHuh.js +53 -0
  96. package/dist/optimistic-cart.d.ts +16 -0
  97. package/dist/order-display-DTt5WBbc.js +112 -0
  98. package/dist/order-display.d.ts +20 -0
  99. package/dist/order-draft-DxV1Uhm3.js +38 -0
  100. package/dist/order-draft.d.ts +16 -0
  101. package/dist/order-pages-Dm6l5m0m.js +38 -0
  102. package/dist/order-pages.d.ts +12 -0
  103. package/dist/order-payment-continuation-D_d5PGA4.js +212 -0
  104. package/dist/order-payment-continuation.d.ts +10 -0
  105. package/dist/order-payment-in-review-x4gdLFHZ.js +65 -0
  106. package/dist/order-payment-in-review.d.ts +5 -0
  107. package/dist/order-status-BJXLJwxq.js +162 -0
  108. package/dist/order-status.d.ts +89 -0
  109. package/dist/order-view-9IlBg5AF.js +62 -0
  110. package/dist/order-view.d.ts +12 -0
  111. package/dist/page-action-Ctkf4xC6.js +7 -0
  112. package/dist/page-seo-a5FJl8x5.js +262 -0
  113. package/dist/page-seo.d.ts +34 -0
  114. package/dist/pages-Ca_Gt6mq.js +150 -0
  115. package/dist/pages.d.ts +45 -0
  116. package/dist/payment-dialog-frame-B-Q_xQ94.js +57 -0
  117. package/dist/payment-logo-BoPaGJc_.js +46 -0
  118. package/dist/payment-logo-svgs-By9lDTLK.js +20 -0
  119. package/dist/payment-logo.d.ts +11 -0
  120. package/dist/payment-logos-BYvdwYyJ.js +23 -0
  121. package/dist/payment-methods-B8ocTgFZ.js +73 -0
  122. package/dist/payment-methods.d.ts +58 -0
  123. package/dist/payment-return-5cjypwIw.js +7 -0
  124. package/dist/place-CmW4hBWY.js +13 -0
  125. package/dist/place.d.ts +4 -0
  126. package/dist/preview-BiIBif3C.js +427 -0
  127. package/dist/preview-address-Cf0sJ-9p.js +21 -0
  128. package/dist/preview-cart-Dg2CVktS.js +376 -0
  129. package/dist/product-preview-BspMAecJ.js +51 -0
  130. package/dist/product-preview.d.ts +5 -0
  131. package/dist/product-variants-BNDHvs1y.js +46 -0
  132. package/dist/product-variants.d.ts +12 -0
  133. package/dist/public-pages-XtwlaLwt.js +194 -0
  134. package/dist/public-pages.d.ts +67 -0
  135. package/dist/registration-CpDcv8ql.js +91 -0
  136. package/dist/registration.d.ts +12 -0
  137. package/dist/request-security-CRsRMgwj.js +76 -0
  138. package/dist/rich-text-M-Ju8RL4.js +9 -0
  139. package/dist/rich-text.d.ts +5 -0
  140. package/dist/route-text-DcJw2SsK.js +9 -0
  141. package/dist/route-text.d.ts +4 -0
  142. package/dist/section-preview-CmsMl3yu.js +83 -0
  143. package/dist/section-preview.d.ts +12 -0
  144. package/dist/sections/account-addresses.d.ts +18 -0
  145. package/dist/sections/account-addresses.js +375 -0
  146. package/dist/sections/account-order.d.ts +12 -0
  147. package/dist/sections/account-order.js +592 -0
  148. package/dist/sections/account-orders.d.ts +8 -0
  149. package/dist/sections/account-orders.js +359 -0
  150. package/dist/sections/account-profile.d.ts +16 -0
  151. package/dist/sections/account-profile.js +123 -0
  152. package/dist/sections/checkout.d.ts +24 -0
  153. package/dist/sections/checkout.js +963 -0
  154. package/dist/sections/complaint-book.d.ts +8 -0
  155. package/dist/sections/complaint-book.js +538 -0
  156. package/dist/sections/design-system.d.ts +1 -0
  157. package/dist/sections/design-system.js +310 -0
  158. package/dist/sections/draft-invoice.d.ts +20 -0
  159. package/dist/sections/draft-invoice.js +158 -0
  160. package/dist/sections/order-tracking.d.ts +19 -0
  161. package/dist/sections/order-tracking.js +141 -0
  162. package/dist/sections-CNUMWTF_.js +77 -0
  163. package/dist/sections.d.ts +19 -0
  164. package/dist/seo-GpDRhAAA.js +78 -0
  165. package/dist/session-CKvmFJyg.js +379 -0
  166. package/dist/session.d.ts +24 -0
  167. package/dist/settings-B0NO2A6Y.js +78 -0
  168. package/dist/settings.d.ts +51 -0
  169. package/dist/source-marker-DhqSkW7n.js +4 -0
  170. package/dist/sources-B-3JFJfb.js +46 -0
  171. package/dist/sources.d.ts +7 -0
  172. package/dist/store-8Q-_LFrQ.js +152 -0
  173. package/dist/store-contact--hY6CoFb.js +19 -0
  174. package/dist/store-contact.d.ts +6 -0
  175. package/dist/store.d.ts +17 -0
  176. package/dist/storefront-language-DrMjVbmk.js +29 -0
  177. package/dist/storefront-language.d.ts +14 -0
  178. package/dist/storefront-text-D25ae1qf.js +11 -0
  179. package/dist/storefront-text-en-ljjjSS4q.js +1030 -0
  180. package/dist/storefront-text-pt-BtHaJLcp.js +1030 -0
  181. package/dist/storefront-text.d.ts +4 -0
  182. package/dist/stripe-dialog-Ev9s3Z62.js +396 -0
  183. package/dist/stripe-dialog.d.ts +30 -0
  184. package/dist/telemetry-HuZXWBPi.js +114 -0
  185. package/dist/telemetry.d.ts +10 -0
  186. package/dist/templates-CAqoNyTW.js +40 -0
  187. package/dist/templates.d.ts +15 -0
  188. package/dist/urls-CpGQPxvf.js +71 -0
  189. package/dist/urls.d.ts +18 -0
  190. package/dist/use-checkout-CZcxXJXi.js +42 -0
  191. package/dist/use-checkout-payment-9R-zacrJ.js +80 -0
  192. package/dist/use-checkout-payment.d.ts +18 -0
  193. package/dist/use-checkout.d.ts +36 -0
  194. package/dist/use-culqi-checkout-CrjLAipU.js +109 -0
  195. package/dist/use-order-payment-BKIz_IO0.js +45 -0
  196. package/dist/use-order-payment.d.ts +18 -0
  197. package/dist/use-payment-token-CErx-tN-.js +105 -0
  198. package/dist/vite-payment-logos-kziu7wKb.js +27 -0
  199. package/dist/vite-payment-logos.d.ts +24 -0
  200. package/dist/vite-public-assets-DW2fgtVb.js +209 -0
  201. package/dist/vite-public-assets.d.ts +29 -0
  202. package/dist/vite-sections-DTBr0-Kg.js +464 -0
  203. package/dist/vite-sections.d.ts +21 -0
  204. package/dist/vite-theme-ui-BMO-CDi3.js +41 -0
  205. package/dist/vite-theme-ui.d.ts +10 -0
  206. package/dist/vite.d.ts +36 -0
  207. package/dist/vite.js +127 -0
  208. package/dist/voucher-payment-CVFDZ1L8.js +66 -0
  209. package/dist/worker-CNi-gzCu.js +86 -0
  210. package/dist/worker.d.ts +27 -0
  211. package/package.json +100 -76
  212. package/src/sections/account-addresses.tsx +215 -0
  213. package/src/sections/account-order.tsx +424 -0
  214. package/src/sections/account-orders.tsx +259 -0
  215. package/src/sections/account-profile.tsx +70 -0
  216. package/src/sections/checkout.tsx +586 -0
  217. package/src/sections/complaint-book.tsx +325 -0
  218. package/src/sections/design-system.tsx +146 -0
  219. package/src/sections/draft-invoice.tsx +105 -0
  220. package/src/sections/order-tracking.tsx +81 -0
  221. package/src/vite-client.d.ts +4 -0
  222. package/bin/ecomiq.mjs +0 -179
  223. package/public/design-bridge.js +0 -318
  224. package/src/api-proxy.ts +0 -194
  225. package/src/auth/create-storefront-auth.ts +0 -94
  226. package/src/auth/ecomiq-oauth-password-client.ts +0 -26
  227. package/src/auth/ecomiq-oauth-password-constants.ts +0 -24
  228. package/src/auth/ecomiq-oauth-password-plugin.ts +0 -294
  229. package/src/auth/ecomiq-oauth-password-types.ts +0 -24
  230. package/src/auth/ecomiq-storefront-sign-in.ts +0 -44
  231. package/src/auth/env.ts +0 -7
  232. package/src/auth/secure-cookies.ts +0 -23
  233. package/src/auth/storefront-auth-base-url.ts +0 -117
  234. package/src/auth/storefront-auth.ts +0 -7
  235. package/src/cart-session.ts +0 -239
  236. package/src/client.ts +0 -48
  237. package/src/codegen.mjs +0 -801
  238. package/src/components/account/customer-addresses-panel.tsx +0 -678
  239. package/src/components/account/customer-order-detail-panel.tsx +0 -285
  240. package/src/components/account/customer-orders-panel.tsx +0 -192
  241. package/src/components/account/customer-profile-panel.tsx +0 -379
  242. package/src/components/checkout/cart-sync.ts +0 -143
  243. package/src/components/checkout/checkout-contact-section.tsx +0 -76
  244. package/src/components/checkout/checkout-external-update-banner.tsx +0 -15
  245. package/src/components/checkout/checkout-form-controls.tsx +0 -139
  246. package/src/components/checkout/checkout-line-items.tsx +0 -43
  247. package/src/components/checkout/checkout-order-summary.tsx +0 -165
  248. package/src/components/checkout/checkout-payment-section.tsx +0 -212
  249. package/src/components/checkout/checkout-session-view.tsx +0 -564
  250. package/src/components/checkout/checkout-shipping-address-section.tsx +0 -400
  251. package/src/components/checkout/checkout-shipping-section.tsx +0 -98
  252. package/src/components/checkout/checkout-states.tsx +0 -73
  253. package/src/components/checkout/checkout-step-card.tsx +0 -101
  254. package/src/components/checkout/checkout-steps.ts +0 -111
  255. package/src/components/checkout/form-schema.ts +0 -281
  256. package/src/components/checkout/format.ts +0 -15
  257. package/src/components/checkout/index.ts +0 -5
  258. package/src/components/checkout/map-customer-to-checkout.ts +0 -188
  259. package/src/components/checkout/types.ts +0 -41
  260. package/src/components/checkout/use-checkout-customer-prefill.ts +0 -409
  261. package/src/components/checkout/use-checkout-geo.ts +0 -50
  262. package/src/components/checkout/use-checkout-session.ts +0 -640
  263. package/src/components/hero.tsx +0 -291
  264. package/src/config.d.ts +0 -94
  265. package/src/config.mjs +0 -146
  266. package/src/format-money.ts +0 -31
  267. package/src/health.ts +0 -90
  268. package/src/hooks/index.ts +0 -9
  269. package/src/hooks/recently-viewed.ts +0 -125
  270. package/src/index.ts +0 -349
  271. package/src/link.tsx +0 -2
  272. package/src/pages/account/account-page-skeleton.tsx +0 -69
  273. package/src/pages/account/account-page-view.tsx +0 -270
  274. package/src/pages/account/account-shell.tsx +0 -101
  275. package/src/pages/account/parse-account-route.ts +0 -36
  276. package/src/pages/account.tsx +0 -16
  277. package/src/pages/api.$.ts +0 -20
  278. package/src/pages/api.auth.$.ts +0 -16
  279. package/src/pages/checkout.$checkoutId.tsx +0 -60
  280. package/src/pages/checkout.tsx +0 -31
  281. package/src/pages/pages.$pageSlug.tsx +0 -74
  282. package/src/pages/thank-you.tsx +0 -53
  283. package/src/providers/auth.tsx +0 -96
  284. package/src/providers/cart.tsx +0 -275
  285. package/src/providers/ecomiq.ts +0 -137
  286. package/src/providers/index.ts +0 -26
  287. package/src/proxy-api.ts +0 -20
  288. package/src/public-config.ts +0 -24
  289. package/src/review-submission.ts +0 -89
  290. package/src/runtime/context.ts +0 -2
  291. package/src/runtime/default-layout.tsx +0 -64
  292. package/src/runtime/head.ts +0 -149
  293. package/src/runtime/page.tsx +0 -143
  294. package/src/runtime/postcss-browser-stub.mjs +0 -5
  295. package/src/server-config-store.ts +0 -35
  296. package/src/server.ts +0 -286
  297. package/src/styles.css +0 -76
  298. package/src/ui/badge.tsx +0 -32
  299. package/src/ui/button.tsx +0 -31
  300. package/src/ui/card.tsx +0 -31
  301. package/src/ui/carousel.tsx +0 -218
  302. package/src/ui/cn.ts +0 -6
  303. package/src/ui/index.ts +0 -8
  304. package/src/ui/separator.tsx +0 -6
  305. package/src/ui/skeleton.tsx +0 -6
  306. package/src/ui/storefront-error.tsx +0 -49
  307. package/src/utils.ts +0 -36
  308. package/src/vite-inline.mjs +0 -263
  309. package/templates/__root.tsx +0 -83
  310. package/templates/router.tsx +0 -19
@@ -1,139 +0,0 @@
1
- import type { HTMLAttributes } from 'react'
2
- import { cn } from '../../ui'
3
-
4
- export function fieldClass(error?: string) {
5
- return cn(
6
- 'mt-1.5 flex h-11 w-full rounded-md border border-border bg-background px-3 text-sm outline-none placeholder:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring',
7
- error && 'border-destructive',
8
- )
9
- }
10
-
11
- export function FieldError({ message }: { message?: string }) {
12
- if (!message) return null
13
- return <p className="mt-1 text-xs text-destructive">{message}</p>
14
- }
15
-
16
- export function CheckoutTextField({
17
- id,
18
- label,
19
- value,
20
- onChange,
21
- error,
22
- type = 'text',
23
- autoComplete,
24
- inputMode,
25
- placeholder,
26
- }: {
27
- id: string
28
- label: string
29
- value: string
30
- onChange: (value: string) => void
31
- error?: string
32
- type?: string
33
- autoComplete?: string
34
- inputMode?: HTMLAttributes<HTMLInputElement>['inputMode']
35
- placeholder?: string
36
- }) {
37
- return (
38
- <div className="min-w-0">
39
- <label htmlFor={id} className="text-sm font-medium text-foreground">
40
- {label}
41
- </label>
42
- <input
43
- id={id}
44
- type={type}
45
- className={fieldClass(error)}
46
- value={value}
47
- onChange={(e) => onChange(e.target.value)}
48
- autoComplete={autoComplete}
49
- inputMode={inputMode}
50
- placeholder={placeholder}
51
- />
52
- <FieldError message={error} />
53
- </div>
54
- )
55
- }
56
-
57
- export function CheckoutSelectField({
58
- id,
59
- label,
60
- value,
61
- options,
62
- onChange,
63
- error,
64
- placeholder = 'Seleccionar…',
65
- }: {
66
- id: string
67
- label: string
68
- value: string
69
- options: { value: string; label: string }[]
70
- onChange: (value: string) => void
71
- error?: string
72
- placeholder?: string
73
- }) {
74
- return (
75
- <div className="min-w-0">
76
- <label htmlFor={id} className="text-sm font-medium text-foreground">
77
- {label}
78
- </label>
79
- <select
80
- id={id}
81
- className={fieldClass(error)}
82
- value={value}
83
- onChange={(e) => onChange(e.target.value)}
84
- >
85
- <option value="">{placeholder}</option>
86
- {options.map((o) => (
87
- <option key={o.value} value={o.value}>
88
- {o.label}
89
- </option>
90
- ))}
91
- </select>
92
- <FieldError message={error} />
93
- </div>
94
- )
95
- }
96
-
97
- export function CheckoutPhoneField({
98
- id,
99
- label,
100
- value,
101
- dialCode,
102
- error,
103
- onChange,
104
- }: {
105
- id: string
106
- label: string
107
- value: string
108
- dialCode: string
109
- error?: string
110
- onChange: (value: string) => void
111
- }) {
112
- return (
113
- <div className="min-w-0">
114
- <label htmlFor={id} className="text-sm font-medium text-foreground">
115
- {label}
116
- </label>
117
- <div
118
- className={cn(
119
- 'mt-1.5 flex h-11 overflow-hidden rounded-md border bg-background focus-within:ring-2 focus-within:ring-ring',
120
- error ? 'border-destructive' : 'border-border',
121
- )}
122
- >
123
- <span className="flex shrink-0 items-center border-r bg-muted/40 px-3 text-sm text-muted-foreground">
124
- {dialCode}
125
- </span>
126
- <input
127
- id={id}
128
- type="tel"
129
- inputMode="numeric"
130
- autoComplete="tel-national"
131
- className="min-w-0 flex-1 bg-transparent px-3 text-sm outline-none"
132
- value={value}
133
- onChange={(e) => onChange(e.target.value.replace(/\D/g, ''))}
134
- />
135
- </div>
136
- <FieldError message={error} />
137
- </div>
138
- )
139
- }
@@ -1,43 +0,0 @@
1
- import type { StorefrontOrderBump } from '@ecomiq/core'
2
- import { Button } from '../../ui'
3
-
4
- export function CheckoutOrderBumps({
5
- bumps,
6
- money,
7
- busy,
8
- onAdd,
9
- }: {
10
- bumps: StorefrontOrderBump[]
11
- money: (n: number) => string
12
- busy: boolean
13
- onAdd: (bump: StorefrontOrderBump) => void
14
- }) {
15
- if (bumps.length === 0) return null
16
- return (
17
- <section className="space-y-3 rounded-xl border bg-card p-5">
18
- <h2 className="text-lg font-semibold">Agregar al pedido</h2>
19
- {bumps.map((bump) => (
20
- <div key={bump.id} className="flex items-center gap-3">
21
- <div className="size-14 overflow-hidden rounded-md bg-muted">
22
- {bump.imageUrl ? (
23
- <img src={bump.imageUrl} alt="" className="size-full object-cover" />
24
- ) : null}
25
- </div>
26
- <div className="min-w-0 flex-1">
27
- <p className="text-sm font-medium">{bump.productName}</p>
28
- <p className="text-xs text-muted-foreground">{money(bump.offerPrice)}</p>
29
- </div>
30
- <Button
31
- type="button"
32
- size="sm"
33
- variant="outline"
34
- disabled={busy}
35
- onClick={() => onAdd(bump)}
36
- >
37
- {bump.callToAction || 'Agregar'}
38
- </Button>
39
- </div>
40
- ))}
41
- </section>
42
- )
43
- }
@@ -1,165 +0,0 @@
1
- import { Package, Tag } from 'lucide-react'
2
- import type { StorefrontCartItem } from '@ecomiq/core'
3
- import { Button } from '../../ui'
4
- import { fieldClass } from './checkout-form-controls'
5
-
6
- export function CheckoutOrderSummary({
7
- items,
8
- money,
9
- subtotal,
10
- discount,
11
- shipping,
12
- tax,
13
- total,
14
- hasShippingOptions,
15
- couponCode,
16
- couponError,
17
- promotionCodes,
18
- formError,
19
- isSaving,
20
- canSubmit = true,
21
- submitLabel = 'Pagar',
22
- onCouponCodeChange,
23
- onApplyCoupon,
24
- onRemoveCoupon,
25
- }: {
26
- items: StorefrontCartItem[]
27
- money: (value: number) => string
28
- subtotal: number
29
- discount: number
30
- shipping: number
31
- tax: number
32
- total: number
33
- hasShippingOptions: boolean
34
- couponCode: string
35
- couponError: string | null
36
- promotionCodes: string[]
37
- formError: string | null
38
- isSaving: boolean
39
- canSubmit?: boolean
40
- submitLabel?: string
41
- onCouponCodeChange: (value: string) => void
42
- onApplyCoupon: () => void
43
- onRemoveCoupon: (code: string) => void
44
- }) {
45
- return (
46
- <aside className="rounded-xl border bg-card p-5 shadow-sm lg:sticky lg:top-6">
47
- <h2 className="text-lg font-semibold">Resumen</h2>
48
-
49
- <ul className="mt-4 divide-y border-y" aria-label="Productos">
50
- {items.map((item) => (
51
- <SummaryLineItem key={item.id} item={item} money={money} />
52
- ))}
53
- </ul>
54
-
55
- <div className="mt-4 flex gap-2">
56
- <input
57
- className={fieldClass()}
58
- placeholder="Cupón"
59
- value={couponCode}
60
- onChange={(e) => onCouponCodeChange(e.target.value)}
61
- />
62
- <Button type="button" variant="outline" onClick={onApplyCoupon}>
63
- Aplicar
64
- </Button>
65
- </div>
66
- {couponError ? (
67
- <p className="mt-2 text-xs text-destructive">{couponError}</p>
68
- ) : null}
69
- {promotionCodes.length > 0 ? (
70
- <div className="mt-3 flex flex-wrap gap-2">
71
- {promotionCodes.map((code) => (
72
- <button
73
- key={code}
74
- type="button"
75
- className="inline-flex items-center gap-1.5 rounded-md bg-muted px-2 py-1 text-xs font-medium"
76
- onClick={() => onRemoveCoupon(code)}
77
- >
78
- <Tag className="size-3" aria-hidden="true" />
79
- {code} ×
80
- </button>
81
- ))}
82
- </div>
83
- ) : null}
84
-
85
- <dl className="mt-5 space-y-3 text-sm">
86
- <div className="flex justify-between gap-4">
87
- <dt className="text-muted-foreground">Subtotal</dt>
88
- <dd className="tabular-nums">{money(subtotal)}</dd>
89
- </div>
90
- {discount !== 0 ? (
91
- <div className="flex justify-between gap-4 text-primary">
92
- <dt>Descuentos</dt>
93
- <dd className="tabular-nums">-{money(Math.abs(discount))}</dd>
94
- </div>
95
- ) : null}
96
- <div className="flex justify-between gap-4">
97
- <dt className="text-muted-foreground">Envío</dt>
98
- <dd className="tabular-nums">
99
- {hasShippingOptions ? money(shipping) : 'Por calcular'}
100
- </dd>
101
- </div>
102
- {tax !== 0 ? (
103
- <div className="flex justify-between gap-4">
104
- <dt className="text-muted-foreground">Impuestos</dt>
105
- <dd className="tabular-nums">{money(tax)}</dd>
106
- </div>
107
- ) : null}
108
- <div className="flex items-baseline justify-between gap-4 border-t pt-4">
109
- <dt className="font-semibold">Total</dt>
110
- <dd className="text-xl font-semibold tabular-nums">{money(total)}</dd>
111
- </div>
112
- </dl>
113
-
114
- {formError ? (
115
- <p className="mt-4 text-sm text-destructive" role="alert">
116
- {formError}
117
- </p>
118
- ) : null}
119
-
120
- <Button
121
- type="submit"
122
- className="mt-6 w-full"
123
- size="lg"
124
- disabled={isSaving || !canSubmit}
125
- >
126
- {isSaving ? 'Procesando…' : submitLabel}
127
- </Button>
128
- </aside>
129
- )
130
- }
131
-
132
- function SummaryLineItem({
133
- item,
134
- money,
135
- }: {
136
- item: StorefrontCartItem
137
- money: (value: number) => string
138
- }) {
139
- const lineTotal = item.unitPrice * item.quantity
140
- return (
141
- <li className="flex gap-3 py-3">
142
- <div className="flex size-14 shrink-0 items-center justify-center overflow-hidden rounded-md bg-muted">
143
- {item.thumbnail ? (
144
- <img
145
- src={item.thumbnail}
146
- alt=""
147
- width={56}
148
- height={56}
149
- className="size-full object-cover"
150
- />
151
- ) : (
152
- <Package className="size-4 text-muted-foreground" aria-hidden="true" />
153
- )}
154
- </div>
155
- <div className="min-w-0 flex-1">
156
- <p className="text-sm font-medium leading-snug">{item.title}</p>
157
- <div className="mt-0.5 flex flex-wrap gap-x-2 text-xs text-muted-foreground">
158
- <span>Cant. {item.quantity}</span>
159
- {item.variantLabel ? <span>{item.variantLabel}</span> : null}
160
- </div>
161
- </div>
162
- <p className="shrink-0 text-sm font-semibold tabular-nums">{money(lineTotal)}</p>
163
- </li>
164
- )
165
- }
@@ -1,212 +0,0 @@
1
- import {
2
- Banknote,
3
- CreditCard,
4
- Landmark,
5
- Wallet,
6
- } from 'lucide-react'
7
- import type { CartCheckoutResponse, CartPaymentMethod } from '@ecomiq/core'
8
- import { Button, cn } from '../../ui'
9
- import { methodUsesProviderCheckoutUi } from './cart-sync'
10
- import type { CheckoutFieldId } from './form-schema'
11
- import { FieldError } from './checkout-form-controls'
12
- import { paymentRedirectUrl } from './format'
13
-
14
- function paymentIcon(method: CartPaymentMethod) {
15
- const key = `${method.kind} ${method.code} ${method.providerMethodCode ?? ''}`.toLowerCase()
16
- if (key.includes('paypal')) return Wallet
17
- if (key.includes('stripe') || key.includes('card') || key.includes('credit')) return CreditCard
18
- if (key.includes('mercado')) return Wallet
19
- if (method.isManual || key.includes('transfer') || key.includes('cash')) return Landmark
20
- return Banknote
21
- }
22
-
23
- export function CheckoutPaymentSection({
24
- methods,
25
- selectedCode,
26
- fieldError,
27
- checkoutPaymentLoading,
28
- checkoutPaymentError,
29
- checkoutPaymentResponse,
30
- checkoutPaymentMethodCode,
31
- providerPaymentCompleted,
32
- receiptUrl,
33
- receiptError,
34
- onSelect,
35
- onClearError,
36
- onMarkProviderCompleted,
37
- onReceiptFileChange,
38
- }: {
39
- methods: CartPaymentMethod[]
40
- selectedCode: string | null
41
- fieldError?: string
42
- checkoutPaymentLoading: boolean
43
- checkoutPaymentError: string | null
44
- checkoutPaymentResponse: CartCheckoutResponse | null
45
- checkoutPaymentMethodCode: string | null
46
- providerPaymentCompleted: boolean
47
- receiptUrl: string | null
48
- receiptError: string | null
49
- onSelect: (code: string) => void
50
- onClearError: (id: CheckoutFieldId) => void
51
- onMarkProviderCompleted: () => void
52
- onReceiptFileChange: (file: File | null) => void
53
- }) {
54
- return (
55
- <div className="space-y-4">
56
- <div className="space-y-3">
57
- {methods.map((method) => {
58
- const selected = selectedCode === method.code
59
- const Icon = paymentIcon(method)
60
- const usesProviderUi = methodUsesProviderCheckoutUi(method)
61
- const showExpanded = selected
62
-
63
- return (
64
- <div
65
- key={method.code}
66
- className={cn(
67
- 'overflow-hidden rounded-lg border transition-colors',
68
- selected ? 'border-border bg-muted/40' : 'border-border bg-background',
69
- )}
70
- >
71
- <label className="flex cursor-pointer items-center gap-3 px-4 py-3.5">
72
- <input
73
- type="radio"
74
- name="payment"
75
- className="size-4 accent-blue-600"
76
- checked={selected}
77
- onChange={() => {
78
- onClearError('checkout-payment-method')
79
- onSelect(method.code)
80
- }}
81
- />
82
- <span className="min-w-0 flex-1">
83
- <span className="block text-sm font-medium">{method.name}</span>
84
- {method.description ? (
85
- <span className="mt-0.5 block text-xs text-muted-foreground">
86
- {method.description}
87
- </span>
88
- ) : null}
89
- </span>
90
- <Icon className="size-5 shrink-0 text-muted-foreground" aria-hidden="true" />
91
- </label>
92
-
93
- {showExpanded ? (
94
- <div className="space-y-3 border-t px-4 py-4">
95
- {usesProviderUi ? (
96
- <ProviderPaymentPanel
97
- loading={
98
- checkoutPaymentMethodCode === method.code && checkoutPaymentLoading
99
- }
100
- error={
101
- checkoutPaymentMethodCode === method.code
102
- ? checkoutPaymentError
103
- : null
104
- }
105
- response={
106
- checkoutPaymentMethodCode === method.code
107
- ? checkoutPaymentResponse
108
- : null
109
- }
110
- completed={providerPaymentCompleted}
111
- onMarkCompleted={onMarkProviderCompleted}
112
- />
113
- ) : null}
114
-
115
- {method.isManual ? (
116
- <div className="space-y-2">
117
- <p className="text-sm font-medium">Comprobante de pago</p>
118
- <input
119
- type="file"
120
- accept="image/*,application/pdf"
121
- className="block w-full text-sm"
122
- onChange={(e) =>
123
- onReceiptFileChange(e.target.files?.[0] ?? null)
124
- }
125
- />
126
- {receiptError ? (
127
- <p className="text-xs text-destructive">{receiptError}</p>
128
- ) : null}
129
- {receiptUrl ? (
130
- <p className="text-xs text-muted-foreground">Comprobante listo</p>
131
- ) : null}
132
- </div>
133
- ) : null}
134
-
135
- {!usesProviderUi && !method.isManual ? (
136
- <p className="text-xs text-muted-foreground">
137
- Continúa con Pagar para confirmar este método de pago.
138
- </p>
139
- ) : null}
140
- </div>
141
- ) : null}
142
- </div>
143
- )
144
- })}
145
- </div>
146
- <FieldError message={fieldError} />
147
- </div>
148
- )
149
- }
150
-
151
- function ProviderPaymentPanel({
152
- loading,
153
- error,
154
- response,
155
- completed,
156
- onMarkCompleted,
157
- }: {
158
- loading: boolean
159
- error: string | null
160
- response: CartCheckoutResponse | null
161
- completed: boolean
162
- onMarkCompleted: () => void
163
- }) {
164
- if (loading) {
165
- return <p className="text-sm text-muted-foreground">Preparando pasarela de pago…</p>
166
- }
167
- if (error) {
168
- return <p className="text-sm text-destructive">{error}</p>
169
- }
170
- if (!response) {
171
- return (
172
- <p className="text-xs text-muted-foreground">
173
- Completa el pago de forma segura con el proveedor seleccionado.
174
- </p>
175
- )
176
- }
177
-
178
- const url = paymentRedirectUrl(response)
179
- const clientSecret =
180
- response.clientSecret ??
181
- response.intentClientSecret ??
182
- response.payment?.action?.clientSecret
183
-
184
- return (
185
- <div className="space-y-3 text-sm">
186
- {url ? (
187
- <a
188
- href={url}
189
- target="_blank"
190
- rel="noreferrer"
191
- className="font-medium text-primary underline-offset-4 hover:underline"
192
- >
193
- Abrir pasarela de pago
194
- </a>
195
- ) : null}
196
- {clientSecret && !url ? (
197
- <p className="text-muted-foreground">
198
- Sesión de pago lista. Completa el cobro en la pasarela cuando esté disponible.
199
- </p>
200
- ) : null}
201
- {completed ? (
202
- <p className="text-xs text-muted-foreground">
203
- Pago confirmado. Pulsa Pagar para finalizar tu pedido.
204
- </p>
205
- ) : (
206
- <Button type="button" size="sm" variant="outline" onClick={onMarkCompleted}>
207
- Ya completé el pago en la pasarela
208
- </Button>
209
- )}
210
- </div>
211
- )
212
- }