@nextblock-cms/ecom 0.8.6 → 0.8.7

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 (277) hide show
  1. package/index.cjs.js +1 -1
  2. package/index.es.js +136 -533
  3. package/lib/CurrencyProvider.cjs.js +1 -0
  4. package/lib/CurrencyProvider.es.js +99 -0
  5. package/lib/cart-store.cjs.js +1 -0
  6. package/{cart-store.es.js → lib/cart-store.es.js} +13 -13
  7. package/lib/components/AccountNavigationMenu.cjs.js +1 -0
  8. package/lib/components/AccountNavigationMenu.es.js +44 -0
  9. package/lib/components/AddToCartButton.cjs.js +1 -0
  10. package/{AddToCartButton-ffE0DhHu.js → lib/components/AddToCartButton.es.js} +14 -13
  11. package/lib/components/Cart.cjs.js +1 -0
  12. package/lib/components/Cart.es.js +148 -0
  13. package/lib/components/CartDrawer.cjs.js +1 -0
  14. package/{components → lib/components}/CartDrawer.es.js +15 -14
  15. package/{components → lib/components}/CartIcon.cjs.js +1 -1
  16. package/{components → lib/components}/CartIcon.es.js +1 -0
  17. package/lib/components/Checkout.cjs.js +1 -0
  18. package/{components → lib/components}/Checkout.es.js +330 -363
  19. package/lib/components/CouponForm.cjs.js +1 -0
  20. package/lib/components/CouponForm.es.js +136 -0
  21. package/lib/components/CurrencySwitcher.cjs.js +1 -0
  22. package/{components → lib/components}/CurrencySwitcher.es.js +5 -4
  23. package/lib/components/CustomerProfileForm.cjs.js +1 -0
  24. package/lib/components/CustomerProfileForm.es.js +355 -0
  25. package/lib/components/FeaturedProduct.cjs.js +1 -0
  26. package/{components → lib/components}/FeaturedProduct.es.js +9 -8
  27. package/lib/components/InvoiceDocument.cjs.js +1 -0
  28. package/lib/components/InvoiceDocument.es.js +196 -0
  29. package/lib/components/InvoiceViewerShell.cjs.js +29 -0
  30. package/lib/components/InvoiceViewerShell.es.js +100 -0
  31. package/lib/components/ProductCard.cjs.js +1 -0
  32. package/lib/components/ProductCard.es.js +119 -0
  33. package/lib/components/ProductDetailsLayout.cjs.js +1 -0
  34. package/lib/components/ProductDetailsLayout.es.js +361 -0
  35. package/lib/components/ProductGallery.cjs.js +1 -0
  36. package/lib/components/ProductGallery.es.js +41 -0
  37. package/lib/components/ProductGrid.cjs.js +1 -0
  38. package/lib/components/ProductGrid.es.js +19 -0
  39. package/lib/components/ShippingEstimator.cjs.js +1 -0
  40. package/lib/components/ShippingEstimator.es.js +125 -0
  41. package/lib/components/SubscriptionSelector.cjs.js +1 -0
  42. package/lib/components/SubscriptionSelector.es.js +140 -0
  43. package/lib/countries.cjs.js +1 -0
  44. package/lib/countries.es.js +77 -0
  45. package/lib/coupon-server.cjs.js +1 -0
  46. package/{coupon-server-DUKVtyYs.js → lib/coupon-server.es.js} +68 -82
  47. package/lib/coupons.cjs.js +1 -0
  48. package/lib/coupons.es.js +17 -0
  49. package/lib/currency-store.cjs.js +1 -0
  50. package/lib/currency-store.es.js +27 -0
  51. package/lib/currency-sync.cjs.js +1 -0
  52. package/lib/currency-sync.es.js +180 -0
  53. package/lib/customer-addresses.cjs.js +1 -0
  54. package/lib/customer-addresses.es.js +116 -0
  55. package/lib/customer-orders.cjs.js +1 -0
  56. package/lib/customer-orders.es.js +45 -0
  57. package/lib/customer.cjs.js +1 -0
  58. package/{customer-C3xccjUg.js → lib/customer.es.js} +15 -14
  59. package/lib/export-helpers.cjs.js +1 -0
  60. package/lib/export-helpers.es.js +56 -0
  61. package/lib/factory.cjs.js +1 -0
  62. package/lib/factory.es.js +8 -0
  63. package/lib/freemius-coupons.cjs.js +1 -0
  64. package/lib/freemius-coupons.es.js +272 -0
  65. package/lib/freemius-order-sync.cjs.js +1 -0
  66. package/lib/freemius-order-sync.es.js +284 -0
  67. package/lib/inventory-settings.cjs.js +1 -0
  68. package/lib/inventory-settings.es.js +86 -0
  69. package/lib/invoice-server.cjs.js +33 -0
  70. package/lib/invoice-server.es.js +141 -0
  71. package/lib/invoice-ui.cjs.js +1 -0
  72. package/lib/invoice-ui.es.js +71 -0
  73. package/lib/invoice.cjs.js +1 -0
  74. package/lib/invoice.es.js +102 -0
  75. package/lib/order-inventory.cjs.js +61 -0
  76. package/lib/order-inventory.es.js +128 -0
  77. package/lib/order-tax-details.cjs.js +1 -0
  78. package/lib/order-tax-details.es.js +164 -0
  79. package/lib/pages/cms/coupons/CouponEditorForm.cjs.js +1 -0
  80. package/lib/pages/cms/coupons/CouponEditorForm.es.js +189 -0
  81. package/lib/pages/cms/coupons/CouponsPage.cjs.js +5 -0
  82. package/lib/pages/cms/coupons/CouponsPage.es.js +171 -0
  83. package/lib/pages/cms/coupons/CreateCouponDialog.cjs.js +1 -0
  84. package/lib/pages/cms/coupons/CreateCouponDialog.es.js +35 -0
  85. package/lib/pages/cms/coupons/EditCouponPage.cjs.js +1 -0
  86. package/lib/pages/cms/coupons/EditCouponPage.es.js +48 -0
  87. package/lib/pages/cms/coupons/ProductScopePicker.cjs.js +1 -0
  88. package/lib/pages/cms/coupons/ProductScopePicker.es.js +120 -0
  89. package/lib/pages/cms/coupons/actions.cjs.js +1 -0
  90. package/lib/pages/cms/coupons/actions.es.js +128 -0
  91. package/lib/pages/cms/coupons/product-options.cjs.js +1 -0
  92. package/lib/pages/cms/coupons/product-options.es.js +27 -0
  93. package/lib/pages/cms/orders/ExportReportsDialog.cjs.js +1 -0
  94. package/lib/pages/cms/orders/ExportReportsDialog.es.js +130 -0
  95. package/lib/pages/cms/orders/OrderDetailPage.cjs.js +1 -0
  96. package/lib/pages/cms/orders/OrderDetailPage.es.js +137 -0
  97. package/lib/pages/cms/orders/OrderPrintButton.cjs.js +1 -0
  98. package/lib/pages/cms/orders/OrderPrintButton.es.js +22 -0
  99. package/lib/pages/cms/orders/OrderStatusForm.cjs.js +1 -0
  100. package/lib/pages/cms/orders/OrderStatusForm.es.js +71 -0
  101. package/lib/pages/cms/orders/OrdersPage.cjs.js +1 -0
  102. package/lib/pages/cms/orders/OrdersPage.es.js +104 -0
  103. package/lib/pages/cms/orders/actions.cjs.js +7 -0
  104. package/lib/pages/cms/orders/actions.es.js +71 -0
  105. package/lib/pages/cms/orders/export-actions.cjs.js +1 -0
  106. package/lib/pages/cms/orders/export-actions.es.js +27 -0
  107. package/lib/pages/cms/orders/server-actions.cjs.js +1 -0
  108. package/lib/pages/cms/orders/server-actions.es.js +55 -0
  109. package/lib/pages/cms/payments/PaymentsClient.cjs.js +1 -0
  110. package/lib/pages/cms/payments/PaymentsClient.es.js +188 -0
  111. package/lib/pages/cms/payments/PaymentsPage.cjs.js +1 -0
  112. package/lib/pages/cms/payments/PaymentsPage.es.js +29 -0
  113. package/lib/pages/cms/payments/actions.cjs.js +1 -0
  114. package/lib/pages/cms/payments/actions.es.js +23 -0
  115. package/lib/pages/cms/payments/queries.cjs.js +1 -0
  116. package/lib/pages/cms/payments/queries.es.js +30 -0
  117. package/lib/pages/cms/products/ProductsPage.cjs.js +1 -0
  118. package/lib/pages/cms/products/ProductsPage.es.js +46 -0
  119. package/lib/pages/cms/products/_id_/edit/EditProductPage.cjs.js +1 -0
  120. package/lib/pages/cms/products/_id_/edit/EditProductPage.es.js +156 -0
  121. package/lib/pages/cms/products/actions.cjs.js +44 -0
  122. package/lib/pages/cms/products/actions.es.js +175 -0
  123. package/lib/pages/cms/products/attributes/AttributeManagementPage.cjs.js +1 -0
  124. package/lib/pages/cms/products/attributes/AttributeManagementPage.es.js +48 -0
  125. package/lib/pages/cms/products/attributes/components/AttributeManager.cjs.js +1 -0
  126. package/lib/pages/cms/products/attributes/components/AttributeManager.es.js +291 -0
  127. package/lib/pages/cms/products/categories/CategoryManagementPage.cjs.js +1 -0
  128. package/lib/pages/cms/products/categories/CategoryManagementPage.es.js +36 -0
  129. package/lib/pages/cms/products/categories/components/CategoryManager.cjs.js +1 -0
  130. package/lib/pages/cms/products/categories/components/CategoryManager.es.js +263 -0
  131. package/lib/pages/cms/products/components/CopyProductFromLanguage.cjs.js +1 -0
  132. package/lib/pages/cms/products/components/CopyProductFromLanguage.es.js +114 -0
  133. package/lib/pages/cms/products/components/CurrencyPriceFields.cjs.js +1 -0
  134. package/lib/pages/cms/products/components/CurrencyPriceFields.es.js +107 -0
  135. package/lib/pages/cms/products/components/DeleteProductButton.cjs.js +1 -0
  136. package/lib/pages/cms/products/components/DeleteProductButton.es.js +48 -0
  137. package/lib/pages/cms/products/components/FreemiusPricingDashboard.cjs.js +1 -0
  138. package/lib/pages/cms/products/components/FreemiusPricingDashboard.es.js +86 -0
  139. package/lib/pages/cms/products/components/ProductCategorySelector.cjs.js +1 -0
  140. package/lib/pages/cms/products/components/ProductCategorySelector.es.js +160 -0
  141. package/lib/pages/cms/products/components/ProductForm.cjs.js +1 -0
  142. package/lib/pages/cms/products/components/ProductForm.es.js +702 -0
  143. package/lib/pages/cms/products/components/ProductMediaManager.cjs.js +1 -0
  144. package/lib/pages/cms/products/components/ProductMediaManager.es.js +104 -0
  145. package/lib/pages/cms/products/components/ProductsBulkTable.cjs.js +1 -0
  146. package/lib/pages/cms/products/components/ProductsBulkTable.es.js +228 -0
  147. package/lib/pages/cms/products/components/SaleScheduleFields.cjs.js +1 -0
  148. package/lib/pages/cms/products/components/SaleScheduleFields.es.js +137 -0
  149. package/lib/pages/cms/products/components/SyncFreemiusButton.cjs.js +1 -0
  150. package/lib/pages/cms/products/components/SyncFreemiusButton.es.js +36 -0
  151. package/lib/pages/cms/products/components/SyncFreemiusPricingButton.cjs.js +1 -0
  152. package/lib/pages/cms/products/components/SyncFreemiusPricingButton.es.js +40 -0
  153. package/lib/pages/cms/products/components/VariationsEditor.cjs.js +1 -0
  154. package/lib/pages/cms/products/components/VariationsEditor.es.js +408 -0
  155. package/lib/pages/cms/products/inventory/InventoryPage.cjs.js +1 -0
  156. package/lib/pages/cms/products/inventory/InventoryPage.es.js +16 -0
  157. package/lib/pages/cms/products/inventory/InventoryTableClient.cjs.js +2 -0
  158. package/lib/pages/cms/products/inventory/InventoryTableClient.es.js +214 -0
  159. package/lib/pages/cms/products/inventory/actions.cjs.js +3 -0
  160. package/lib/pages/cms/products/inventory/actions.es.js +95 -0
  161. package/lib/pages/cms/products/new/NewProductPage.cjs.js +1 -0
  162. package/lib/pages/cms/products/new/NewProductPage.es.js +76 -0
  163. package/lib/pages/cms/products/product-price-sync.cjs.js +1 -0
  164. package/lib/pages/cms/products/product-price-sync.es.js +98 -0
  165. package/lib/pages/cms/products/server-actions.cjs.js +1 -0
  166. package/lib/pages/cms/products/server-actions.es.js +193 -0
  167. package/lib/pages/cms/shipping/ShippingPage.cjs.js +5 -0
  168. package/lib/pages/cms/shipping/ShippingPage.es.js +211 -0
  169. package/lib/pages/cms/shipping/components/RateForm.cjs.js +1 -0
  170. package/lib/pages/cms/shipping/components/RateForm.es.js +441 -0
  171. package/lib/pages/cms/shipping/components/ZoneForm.cjs.js +1 -0
  172. package/lib/pages/cms/shipping/components/ZoneForm.es.js +228 -0
  173. package/lib/pages/cms/shipping/server-actions.cjs.js +1 -0
  174. package/lib/pages/cms/shipping/server-actions.es.js +159 -0
  175. package/lib/pages/cms/taxes/TaxesPage.cjs.js +1 -0
  176. package/lib/pages/cms/taxes/TaxesPage.es.js +172 -0
  177. package/lib/pages/cms/taxes/actions.cjs.js +1 -0
  178. package/lib/pages/cms/taxes/actions.es.js +57 -0
  179. package/lib/pages/cms/taxes/components/TaxRateForm.cjs.js +1 -0
  180. package/lib/pages/cms/taxes/components/TaxRateForm.es.js +100 -0
  181. package/lib/product-actions.cjs.js +237 -0
  182. package/lib/product-actions.es.js +524 -0
  183. package/lib/product-context.cjs.js +1 -0
  184. package/lib/product-context.es.js +16 -0
  185. package/lib/product-schema.cjs.js +1 -0
  186. package/lib/product-schema.es.js +134 -0
  187. package/lib/providers/freemius.cjs.js +5 -0
  188. package/lib/providers/freemius.es.js +538 -0
  189. package/lib/providers/stripe.cjs.js +1 -0
  190. package/lib/providers/stripe.es.js +473 -0
  191. package/lib/server-actions/coupon-actions.cjs.js +1 -0
  192. package/lib/server-actions/coupon-actions.es.js +23 -0
  193. package/lib/server-actions/customer-actions.cjs.js +1 -0
  194. package/lib/server-actions/customer-actions.es.js +30 -0
  195. package/lib/server-actions/product-actions.cjs.js +1 -0
  196. package/{server-actions → lib/server-actions}/product-actions.es.js +5 -4
  197. package/lib/server-actions/shipping-actions.cjs.js +1 -0
  198. package/{shipping-actions-BnHjlo2q.js → lib/server-actions/shipping-actions.es.js} +9 -7
  199. package/lib/server-actions/tax-actions.cjs.js +1 -0
  200. package/lib/server-actions/tax-actions.es.js +40 -0
  201. package/lib/shared-inventory.cjs.js +15 -0
  202. package/lib/shared-inventory.es.js +171 -0
  203. package/lib/shipping/resolver.cjs.js +7 -0
  204. package/lib/shipping/resolver.es.js +62 -0
  205. package/lib/shipping-rate-currency.cjs.js +1 -0
  206. package/lib/shipping-rate-currency.es.js +72 -0
  207. package/lib/states.cjs.js +1 -0
  208. package/{states-DlHJezQ1.js → lib/states.es.js} +27 -100
  209. package/lib/stripe/checkout.cjs.js +1 -0
  210. package/lib/stripe/checkout.es.js +182 -0
  211. package/lib/stripe/client.cjs.js +1 -0
  212. package/lib/stripe/client.es.js +7 -0
  213. package/lib/stripe/order-sync.cjs.js +1 -0
  214. package/lib/stripe/order-sync.es.js +130 -0
  215. package/lib/stripe/webhooks.cjs.js +1 -0
  216. package/lib/stripe/webhooks.es.js +30 -0
  217. package/lib/tax-calculation.cjs.js +1 -0
  218. package/lib/tax-calculation.es.js +101 -0
  219. package/lib/trials.cjs.js +1 -0
  220. package/{trials-RDcRAZKx.js → lib/trials.es.js} +9 -9
  221. package/{use-cart.es.js → lib/use-cart.es.js} +1 -0
  222. package/lib/zod-config.cjs.js +1 -0
  223. package/lib/zod-config.es.js +6 -0
  224. package/package.json +4 -4
  225. package/server.cjs.js +1 -110
  226. package/server.es.js +178 -6052
  227. package/AddToCartButton-DsSEH9yp.cjs +0 -1
  228. package/CouponForm-BI_5SBHQ.js +0 -152
  229. package/CouponForm-D_uu2bLP.cjs +0 -1
  230. package/CurrencyProvider-Cg-Q6ucj.cjs +0 -1
  231. package/CurrencyProvider-OzlRN96V.js +0 -120
  232. package/CurrencyProvider.cjs.js +0 -1
  233. package/CurrencyProvider.es.js +0 -10
  234. package/ProductDetailsLayout-BxJH_BxR.cjs +0 -1
  235. package/ProductDetailsLayout-Dg8dRTYp.js +0 -530
  236. package/ProductGrid-BdL7iglO.cjs +0 -1
  237. package/ProductGrid-D3AWM8sr.js +0 -130
  238. package/actions-AHmBrS5e.cjs +0 -48
  239. package/actions-j5fuSZX-.js +0 -820
  240. package/cart-store.cjs.js +0 -1
  241. package/components/Cart.cjs.js +0 -1
  242. package/components/Cart.es.js +0 -259
  243. package/components/CartDrawer.cjs.js +0 -1
  244. package/components/Checkout.cjs.js +0 -1
  245. package/components/CurrencySwitcher.cjs.js +0 -1
  246. package/components/FeaturedProduct.cjs.js +0 -1
  247. package/components/ProductDetailsLayout.cjs.js +0 -1
  248. package/components/ProductDetailsLayout.es.js +0 -19
  249. package/components/ProductGrid.cjs.js +0 -1
  250. package/components/ProductGrid.es.js +0 -6
  251. package/coupon-server-C9ySm3I5.cjs +0 -1
  252. package/customer-C-UPvrYN.cjs +0 -1
  253. package/invoice-ui-CAnJPu6n.cjs +0 -29
  254. package/invoice-ui-DtpbTJE1.js +0 -2886
  255. package/product-actions-CONBF8i6.cjs +0 -251
  256. package/product-actions-DjlIWCMH.js +0 -691
  257. package/resolver-Fz_FKsfX.cjs +0 -7
  258. package/resolver-cfrCaHpE.js +0 -128
  259. package/server-actions/product-actions.cjs.js +0 -1
  260. package/shipping-actions-D6zt20gg.cjs +0 -1
  261. package/states-CWYRxV4B.cjs +0 -1
  262. package/tax-calculation-Dab89aHd.js +0 -181
  263. package/tax-calculation-MkDKOEkL.cjs +0 -1
  264. package/trials-DvZaOtNy.cjs +0 -1
  265. /package/{components → lib/components}/SimpleTiptapRenderer.cjs.js +0 -0
  266. /package/{components → lib/components}/SimpleTiptapRenderer.es.js +0 -0
  267. /package/{currency-constants.cjs.js → lib/currency-constants.cjs.js} +0 -0
  268. /package/{currency-constants.es.js → lib/currency-constants.es.js} +0 -0
  269. /package/{currency-rest-client-uolJxUkL.cjs → lib/currency-rest-client.cjs.js} +0 -0
  270. /package/{currency-rest-client-CwoqdgAP.js → lib/currency-rest-client.es.js} +0 -0
  271. /package/{currency.cjs.js → lib/currency.cjs.js} +0 -0
  272. /package/{currency.es.js → lib/currency.es.js} +0 -0
  273. /package/{types.cjs.js → lib/types.cjs.js} +0 -0
  274. /package/{types.es.js → lib/types.es.js} +0 -0
  275. /package/{use-cart.cjs.js → lib/use-cart.cjs.js} +0 -0
  276. /package/{variation-utils.cjs.js → lib/variation-utils.cjs.js} +0 -0
  277. /package/{variation-utils.es.js → lib/variation-utils.es.js} +0 -0
@@ -1,2886 +0,0 @@
1
- import { jsxs as a, jsx as r, Fragment as xe } from "react/jsx-runtime";
2
- import Xe from "next/link";
3
- import { Printer as rr, X as Dt, GripVertical as sr, Image as Be, RefreshCw as nr, ChevronsUpDown as ar, Search as ir, Loader2 as or, Check as cr, AlertCircle as xt, CheckCircle2 as dr, Info as lr } from "lucide-react";
4
- import { Button as yt } from "@nextblock-cms/ui/button";
5
- import jt from "next/image";
6
- import pe, { useState as U, useRef as Fe, useEffect as Q, useMemo as he, useCallback as Ce } from "react";
7
- import { zodResolver as ur } from "@hookform/resolvers/zod";
8
- import { Button as ce, Label as q, Input as j, Badge as ie, Popover as mr, PopoverTrigger as pr, PopoverContent as fr, Checkbox as gr, Select as Ke, SelectTrigger as Je, SelectValue as Ge, SelectContent as He, SelectItem as re } from "@nextblock-cms/ui";
9
- import { z as u } from "zod";
10
- import { useForm as _r } from "react-hook-form";
11
- import { toast as oe } from "sonner";
12
- import { q as hr, a as xr, r as yr } from "./actions-j5fuSZX-.js";
13
- import { extractSelectedTermsByAttribute as br, resolveTermValue as bt, resolveAttributeName as vt, generateVariantDrafts as vr } from "./variation-utils.es.js";
14
- import { normalizeCurrencyRecord as de, convertMinorUnitAmount as ye, normalizeSalePriceMap as Nr, normalizePriceMap as wr } from "./currency.es.js";
15
- import { cn as Ye, normalizeCurrencyCode as be, majorUnitAmountToMinor as ve, minorUnitAmountToMajor as fe } from "@nextblock-cms/utils";
16
- import { getServiceRoleSupabaseClient as Y, createClient as Ne } from "@nextblock-cms/db/server";
17
- import { a as Sr, d as Cr, i as kr } from "./product-actions-DjlIWCMH.js";
18
- import { revalidatePath as w } from "next/cache";
19
- import { redirect as Pr } from "next/navigation";
20
- import { derivePaymentProviderFromProductType as Ir } from "./types.es.js";
21
- const ws = "invoice_settings", qt = {
22
- businessName: "",
23
- email: "",
24
- phone: "",
25
- address: {
26
- line1: "",
27
- line2: "",
28
- city: "",
29
- state: "",
30
- postal_code: "",
31
- country_code: "CA"
32
- },
33
- taxRegistrations: []
34
- };
35
- function G(e) {
36
- return typeof e != "string" ? "" : e.trim();
37
- }
38
- function Ot(e) {
39
- if (!e || typeof e != "object" || Array.isArray(e))
40
- return { ...qt.address };
41
- const t = e;
42
- return {
43
- line1: G(t.line1),
44
- line2: G(t.line2),
45
- city: G(t.city),
46
- state: G(t.state),
47
- postal_code: G(t.postal_code),
48
- country_code: G(t.country_code).toUpperCase() || "CA"
49
- };
50
- }
51
- function Et(e) {
52
- return Array.isArray(e) ? e.map((t) => {
53
- if (!t || typeof t != "object" || Array.isArray(t))
54
- return null;
55
- const n = t, s = G(n.label), i = G(n.value);
56
- return !s && !i ? null : {
57
- label: s,
58
- value: i
59
- };
60
- }).filter((t) => !!t) : [];
61
- }
62
- function Ss(e) {
63
- if (!e || typeof e != "object" || Array.isArray(e))
64
- return { ...qt };
65
- const t = e;
66
- return {
67
- businessName: G(t.business_name ?? t.businessName),
68
- email: G(t.email),
69
- phone: G(t.phone),
70
- address: Ot(t.address),
71
- taxRegistrations: Et(
72
- t.tax_registrations ?? t.taxRegistrations
73
- )
74
- };
75
- }
76
- function Cs(e) {
77
- return {
78
- business_name: G(e.businessName),
79
- email: G(e.email),
80
- phone: G(e.phone),
81
- address: Ot(e.address),
82
- tax_registrations: Et(e.taxRegistrations)
83
- };
84
- }
85
- function se(e, t = "usd", n = "en-US") {
86
- return new Intl.NumberFormat(n, {
87
- style: "currency",
88
- currency: t.toUpperCase()
89
- }).format(e / 100);
90
- }
91
- function Tr(e, t = "en-US") {
92
- if (!e)
93
- return "";
94
- const n = new Date(e);
95
- return Number.isNaN(n.getTime()) ? "" : new Intl.DateTimeFormat(t, {
96
- year: "numeric",
97
- month: "short",
98
- day: "numeric"
99
- }).format(n);
100
- }
101
- function Qe(e) {
102
- if (!e)
103
- return [];
104
- const t = [e.city, e.state, e.postal_code].filter(Boolean).join(", ").replace(", ,", ",").trim();
105
- return [
106
- "company_name" in e && e.company_name || "",
107
- "recipient_name" in e && e.recipient_name || "",
108
- e.line1 || "",
109
- e.line2 || "",
110
- t,
111
- e.country_code || ""
112
- ].filter(Boolean);
113
- }
114
- const Nt = {
115
- gst: "GST",
116
- qst: "QST",
117
- hst: "HST",
118
- pst: "PST",
119
- vat: "VAT",
120
- sales_tax: "Sales Tax",
121
- amusement_tax: "Amusement Tax",
122
- retail_delivery_fee: "Retail Delivery Fee"
123
- };
124
- function nt() {
125
- return (/* @__PURE__ */ new Date()).toISOString();
126
- }
127
- function $e(e) {
128
- const t = e.tax_type?.trim().toLowerCase();
129
- return t && Nt[t] ? Nt[t] : e.display_name || "Tax";
130
- }
131
- function Me(e) {
132
- return typeof e.effective_percentage == "number" ? e.effective_percentage : typeof e.percentage == "number" ? e.percentage : null;
133
- }
134
- function Ze(e) {
135
- return e.jurisdiction ? e.jurisdiction : [e.state, e.country].filter(Boolean).join(", ") || null;
136
- }
137
- function Ar(e) {
138
- return JSON.stringify({
139
- source: e.source,
140
- rate_id: e.rate.id ?? null,
141
- display_name: $e(e.rate),
142
- percentage: Me(e.rate),
143
- jurisdiction: Ze(e.rate),
144
- jurisdiction_level: e.rate.jurisdiction_level ?? null,
145
- country: e.rate.country ?? null,
146
- state: e.rate.state ?? null,
147
- tax_type: e.rate.tax_type ?? null,
148
- inclusive: e.rate.inclusive ?? null
149
- });
150
- }
151
- function Rt(e) {
152
- const t = /* @__PURE__ */ new Map();
153
- for (const n of e) {
154
- const s = Ar(n), i = t.get(s);
155
- if (!i) {
156
- t.set(s, {
157
- ...n,
158
- scope: "aggregate",
159
- line_item_id: null
160
- });
161
- continue;
162
- }
163
- i.amount += n.amount, typeof i.taxable_amount == "number" || typeof n.taxable_amount == "number" ? i.taxable_amount = (typeof i.taxable_amount == "number" ? i.taxable_amount : 0) + (typeof n.taxable_amount == "number" ? n.taxable_amount : 0) : i.taxable_amount = null, i.description !== n.description && (i.description = null), i.taxability_reason !== n.taxability_reason && (i.taxability_reason = null);
164
- }
165
- return [...t.values()].sort((n, s) => {
166
- const i = $e(n.rate).localeCompare($e(s.rate));
167
- return i !== 0 ? i : (Me(n.rate) ?? 0) - (Me(s.rate) ?? 0);
168
- });
169
- }
170
- function ks(e) {
171
- if (!e || typeof e != "object" || Array.isArray(e))
172
- return null;
173
- const t = e;
174
- return typeof t.currency != "string" ? null : {
175
- source: t.source === "manual" || t.source === "stripe_checkout" || t.source === "none" ? t.source : "none",
176
- mode: t.mode === "automatic" ? "automatic" : "manual",
177
- currency: t.currency,
178
- subtotal: typeof t.subtotal == "number" ? t.subtotal : 0,
179
- shipping_total: typeof t.shipping_total == "number" ? t.shipping_total : 0,
180
- tax_total: typeof t.tax_total == "number" ? t.tax_total : 0,
181
- total: typeof t.total == "number" ? t.total : 0,
182
- is_finalized: !!t.is_finalized,
183
- lines: Array.isArray(t.lines) ? Rt(t.lines) : [],
184
- updated_at: typeof t.updated_at == "string" ? t.updated_at : nt()
185
- };
186
- }
187
- function Ps(e) {
188
- const t = e.currency || "usd", n = e.calculation.mode === "manual" && !e.calculation.isPendingExternalCalculation;
189
- return {
190
- source: e.calculation.enabled && e.calculation.mode === "manual" ? "manual" : e.calculation.mode === "automatic" ? "stripe_checkout" : "none",
191
- mode: e.calculation.mode,
192
- currency: t,
193
- subtotal: e.subtotal,
194
- shipping_total: e.shippingTotal,
195
- tax_total: e.calculation.amount,
196
- total: e.total,
197
- is_finalized: n,
198
- lines: e.calculation.enabled && e.calculation.mode === "manual" ? e.calculation.lines.map((s) => ({
199
- scope: "aggregate",
200
- source: "manual",
201
- amount: s.amount,
202
- taxable_amount: e.calculation.taxableSubtotal,
203
- description: s.name,
204
- rate: {
205
- id: s.id ?? null,
206
- display_name: s.name,
207
- percentage: s.rate,
208
- country: s.country_code,
209
- state: s.state_code ?? null
210
- }
211
- })) : [],
212
- updated_at: nt()
213
- };
214
- }
215
- function wt(e) {
216
- return {
217
- id: e.id,
218
- display_name: e.display_name,
219
- percentage: e.percentage,
220
- effective_percentage: e.effective_percentage,
221
- jurisdiction: e.jurisdiction,
222
- jurisdiction_level: e.jurisdiction_level,
223
- country: e.country,
224
- state: e.state,
225
- tax_type: e.tax_type,
226
- inclusive: e.inclusive,
227
- description: e.description
228
- };
229
- }
230
- function Is(e) {
231
- const t = e.currency || e.session.currency || "usd", n = typeof e.session.amount_total == "number" ? e.session.amount_total : 0, s = e.session.total_details?.amount_tax ?? 0, i = [];
232
- for (const l of e.lineItems)
233
- for (const o of l.taxes || [])
234
- i.push({
235
- scope: "line_item",
236
- source: "stripe_checkout",
237
- amount: o.amount,
238
- taxable_amount: o.taxable_amount,
239
- description: l.description || void 0,
240
- line_item_id: l.id,
241
- taxability_reason: o.taxability_reason,
242
- rate: wt(o.rate)
243
- });
244
- if (i.length === 0)
245
- for (const l of e.session.total_details?.breakdown?.taxes || [])
246
- i.push({
247
- scope: "aggregate",
248
- source: "stripe_checkout",
249
- amount: l.amount,
250
- taxable_amount: l.taxable_amount,
251
- description: l.rate.display_name,
252
- taxability_reason: l.taxability_reason,
253
- rate: wt(l.rate)
254
- });
255
- const c = Rt(i);
256
- return {
257
- source: s > 0 || c.length > 0 ? "stripe_checkout" : "none",
258
- mode: e.fallbackMode === "manual" ? "manual" : "automatic",
259
- currency: t,
260
- subtotal: e.subtotal,
261
- shipping_total: e.shippingTotal,
262
- tax_total: s,
263
- total: n,
264
- is_finalized: !0,
265
- lines: c,
266
- updated_at: nt()
267
- };
268
- }
269
- function Fr({
270
- data: e,
271
- labels: t,
272
- locale: n = "en-US",
273
- className: s = ""
274
- }) {
275
- const i = Qe(e.settings.address), c = Qe(e.order.customer_details?.billing), l = Qe(e.order.customer_details?.shipping);
276
- return /* @__PURE__ */ a(
277
- "section",
278
- {
279
- className: `rounded-2xl border bg-white text-slate-900 shadow-sm print:rounded-none print:border-0 print:text-[10px] print:shadow-none ${s}`,
280
- children: [
281
- /* @__PURE__ */ r("div", { className: "border-b px-6 py-6 print:px-0", children: /* @__PURE__ */ a("div", { className: "grid gap-6 md:grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] md:items-start print:grid-cols-[minmax(0,1fr)_72px_280px] print:items-start print:gap-4", children: [
282
- /* @__PURE__ */ a("div", { className: "order-2 max-w-md space-y-4 print:order-none print:max-w-none print:space-y-2 md:order-none", children: [
283
- /* @__PURE__ */ a("div", { className: "space-y-1 text-sm print:text-[10px]", children: [
284
- /* @__PURE__ */ r("p", { className: "text-xs font-semibold uppercase tracking-[0.2em] text-slate-500", children: t.from }),
285
- e.settings.businessName ? /* @__PURE__ */ r("p", { className: "text-base font-semibold", children: e.settings.businessName }) : null,
286
- i.map((o, x) => /* @__PURE__ */ r("p", { children: o }, `seller-${x}-${o}`)),
287
- e.settings.email ? /* @__PURE__ */ r("p", { children: e.settings.email }) : null,
288
- e.settings.phone ? /* @__PURE__ */ r("p", { children: e.settings.phone }) : null
289
- ] }),
290
- e.settings.taxRegistrations.length > 0 ? /* @__PURE__ */ a("div", { className: "rounded-xl border bg-slate-50 px-4 py-3 text-sm print:px-3 print:py-2 print:text-[10px]", children: [
291
- /* @__PURE__ */ r("p", { className: "mb-2 font-semibold", children: t.taxRegistrations }),
292
- /* @__PURE__ */ r("div", { className: "space-y-1", children: e.settings.taxRegistrations.map((o, x) => /* @__PURE__ */ a("p", { children: [
293
- /* @__PURE__ */ r("span", { className: "font-medium", children: o.label }),
294
- o.label && o.value ? ": " : "",
295
- o.value
296
- ] }, `${o.label}-${o.value}-${x}`)) })
297
- ] }) : null
298
- ] }),
299
- /* @__PURE__ */ r("div", { className: "order-1 flex justify-center md:order-none md:pt-2 print:order-none print:pt-1", children: e.logo?.url ? /* @__PURE__ */ r(
300
- jt,
301
- {
302
- src: e.logo.url,
303
- alt: e.logo.name || e.settings.businessName || "Logo",
304
- className: "mx-auto h-24 w-auto object-contain print:h-14",
305
- width: e.logo.width || 320,
306
- height: e.logo.height || 120
307
- }
308
- ) : null }),
309
- /* @__PURE__ */ r("div", { className: "order-3 flex justify-start md:order-none md:justify-end print:order-none", children: /* @__PURE__ */ a("div", { className: "w-full max-w-[380px] rounded-2xl bg-slate-950 px-5 py-5 text-white print:max-w-none print:border print:border-slate-300 print:bg-white print:px-3 print:py-3 print:text-[10px] print:text-slate-950", children: [
310
- /* @__PURE__ */ r("p", { className: "text-xs uppercase tracking-[0.2em] text-white/70 print:text-slate-500", children: t.invoice }),
311
- /* @__PURE__ */ a("div", { className: "mt-4 space-y-3 text-sm print:mt-3 print:space-y-2 print:text-[10px]", children: [
312
- /* @__PURE__ */ r(
313
- ke,
314
- {
315
- label: t.invoiceNumber,
316
- value: e.order.invoice_number || "--"
317
- }
318
- ),
319
- /* @__PURE__ */ r(ke, { label: t.orderNumber, value: e.order.id }),
320
- /* @__PURE__ */ r(
321
- ke,
322
- {
323
- label: t.paidOn,
324
- value: Tr(e.order.paid_at || e.order.created_at, n) || "--"
325
- }
326
- ),
327
- /* @__PURE__ */ r(ke, { label: t.status, value: e.order.status })
328
- ] })
329
- ] }) })
330
- ] }) }),
331
- /* @__PURE__ */ a("div", { className: "grid gap-4 border-b px-6 py-6 md:grid-cols-2 print:grid-cols-2 print:gap-3 print:px-0 print:py-3", children: [
332
- /* @__PURE__ */ r(St, { title: t.billTo, lines: c }),
333
- /* @__PURE__ */ r(St, { title: t.shipTo, lines: l })
334
- ] }),
335
- /* @__PURE__ */ a("div", { className: "px-6 py-6 print:px-0 print:py-3", children: [
336
- /* @__PURE__ */ r("div", { className: "overflow-hidden rounded-2xl border", children: /* @__PURE__ */ a("table", { className: "w-full border-collapse text-sm print:table-fixed print:text-[9px]", children: [
337
- /* @__PURE__ */ r("thead", { className: "bg-slate-50", children: /* @__PURE__ */ a("tr", { children: [
338
- /* @__PURE__ */ r("th", { className: "px-4 py-3 text-left font-semibold print:w-[22%] print:px-2 print:py-1.5", children: t.item }),
339
- /* @__PURE__ */ r("th", { className: "px-4 py-3 text-left font-semibold print:w-[38%] print:px-2 print:py-1.5", children: t.details }),
340
- /* @__PURE__ */ r("th", { className: "px-4 py-3 text-right font-semibold print:w-[10%] print:px-2 print:py-1.5", children: t.quantity }),
341
- /* @__PURE__ */ r("th", { className: "px-4 py-3 text-right font-semibold print:w-[15%] print:px-2 print:py-1.5", children: t.price }),
342
- /* @__PURE__ */ r("th", { className: "px-4 py-3 text-right font-semibold print:w-[15%] print:px-2 print:py-1.5", children: t.amount })
343
- ] }) }),
344
- /* @__PURE__ */ r("tbody", { children: e.order.items.map((o) => /* @__PURE__ */ a("tr", { className: "border-t", children: [
345
- /* @__PURE__ */ r("td", { className: "px-4 py-4 font-medium print:px-2 print:py-1.5", children: o.title }),
346
- /* @__PURE__ */ r("td", { className: "px-4 py-4 text-slate-600 print:px-2 print:py-1.5", children: o.description || "--" }),
347
- /* @__PURE__ */ r("td", { className: "px-4 py-4 text-right print:px-2 print:py-1.5", children: o.quantity }),
348
- /* @__PURE__ */ r("td", { className: "px-4 py-4 text-right print:px-2 print:py-1.5", children: se(o.unit_amount, e.order.currency, n) }),
349
- /* @__PURE__ */ r("td", { className: "px-4 py-4 text-right font-medium print:px-2 print:py-1.5", children: se(o.total_amount, e.order.currency, n) })
350
- ] }, o.id)) })
351
- ] }) }),
352
- /* @__PURE__ */ a("div", { className: "mt-6 grid gap-6 md:grid-cols-[minmax(0,1fr)_320px] print:mt-4 print:grid-cols-[minmax(0,1fr)_220px] print:items-start print:gap-4", children: [
353
- /* @__PURE__ */ r("div", { children: e.order.tax_details?.lines?.length ? /* @__PURE__ */ a("div", { className: "rounded-xl border bg-slate-50 px-5 py-4 print:break-inside-avoid print:px-3 print:py-2.5 print:text-[10px]", children: [
354
- /* @__PURE__ */ r("p", { className: "mb-3 font-semibold", children: t.taxBreakdown }),
355
- /* @__PURE__ */ r("div", { className: "space-y-3 text-sm print:space-y-2 print:text-[10px]", children: e.order.tax_details.lines.map((o, x) => {
356
- const b = Me(o.rate);
357
- return /* @__PURE__ */ a(
358
- "div",
359
- {
360
- className: "flex items-start justify-between gap-4",
361
- children: [
362
- /* @__PURE__ */ a("div", { children: [
363
- /* @__PURE__ */ a("p", { className: "font-medium", children: [
364
- $e(o.rate),
365
- typeof b == "number" ? ` - ${b.toFixed(4)}%` : ""
366
- ] }),
367
- Ze(o.rate) ? /* @__PURE__ */ r("p", { className: "text-xs text-slate-500 print:text-[9px]", children: Ze(o.rate) }) : null
368
- ] }),
369
- /* @__PURE__ */ r("span", { children: se(o.amount, e.order.currency, n) })
370
- ]
371
- },
372
- `${o.rate.display_name}-${o.description || "tax"}-${x}`
373
- );
374
- }) })
375
- ] }) : null }),
376
- /* @__PURE__ */ a("div", { className: "rounded-xl border bg-slate-950 px-5 py-5 text-sm text-white print:break-inside-avoid print:border-slate-300 print:bg-white print:px-3 print:py-3 print:text-[10px] print:text-slate-950", children: [
377
- /* @__PURE__ */ a("div", { className: "space-y-3 print:space-y-2", children: [
378
- /* @__PURE__ */ r(
379
- _e,
380
- {
381
- label: t.subtotal,
382
- value: se(e.order.subtotal, e.order.currency, n)
383
- }
384
- ),
385
- e.order.discount_total > 0 ? /* @__PURE__ */ r(
386
- _e,
387
- {
388
- label: e.order.coupon_code ? `${t.discount} (${e.order.coupon_code})` : t.discount,
389
- value: `-${se(
390
- e.order.discount_total,
391
- e.order.currency,
392
- n
393
- )}`
394
- }
395
- ) : null,
396
- /* @__PURE__ */ r(
397
- _e,
398
- {
399
- label: t.shipping,
400
- value: se(
401
- e.order.shipping_total,
402
- e.order.currency,
403
- n
404
- )
405
- }
406
- ),
407
- /* @__PURE__ */ r(
408
- _e,
409
- {
410
- label: t.tax,
411
- value: se(e.order.tax_total, e.order.currency, n)
412
- }
413
- )
414
- ] }),
415
- /* @__PURE__ */ r("div", { className: "mt-4 border-t border-white/15 pt-4 print:mt-3 print:border-slate-300 print:pt-3", children: /* @__PURE__ */ r(
416
- _e,
417
- {
418
- label: t.total,
419
- value: se(e.order.total, e.order.currency, n),
420
- strong: !0
421
- }
422
- ) })
423
- ] })
424
- ] })
425
- ] })
426
- ]
427
- }
428
- );
429
- }
430
- function St({ title: e, lines: t }) {
431
- return /* @__PURE__ */ a("div", { className: "rounded-xl border bg-slate-50 px-5 py-4 print:break-inside-avoid print:px-3 print:py-2.5 print:text-[10px]", children: [
432
- /* @__PURE__ */ r("p", { className: "mb-3 text-xs font-semibold uppercase tracking-[0.2em] text-slate-500", children: e }),
433
- t.length ? /* @__PURE__ */ r("div", { className: "space-y-1 text-sm print:text-[10px]", children: t.map((n, s) => /* @__PURE__ */ r("p", { children: n }, `${e}-${s}-${n}`)) }) : /* @__PURE__ */ r("p", { className: "text-sm text-slate-500", children: "--" })
434
- ] });
435
- }
436
- function ke({ label: e, value: t }) {
437
- return /* @__PURE__ */ a("div", { className: "flex items-center justify-between gap-4", children: [
438
- /* @__PURE__ */ r("span", { className: "text-white/70 print:text-[9px] print:text-slate-500", children: e }),
439
- /* @__PURE__ */ r("span", { className: "text-right font-medium", children: t })
440
- ] });
441
- }
442
- function _e({
443
- label: e,
444
- value: t,
445
- strong: n = !1
446
- }) {
447
- return /* @__PURE__ */ a("div", { className: "flex items-center justify-between gap-4", children: [
448
- /* @__PURE__ */ r(
449
- "span",
450
- {
451
- className: n ? "text-base font-semibold print:text-sm" : "text-white/75 print:text-[9px] print:text-slate-500",
452
- children: e
453
- }
454
- ),
455
- /* @__PURE__ */ r("span", { className: n ? "text-lg font-semibold print:text-base" : "font-medium", children: t })
456
- ] });
457
- }
458
- function Ts({
459
- invoice: e,
460
- labels: t,
461
- locale: n,
462
- title: s,
463
- description: i,
464
- printLabel: c,
465
- headerVisual: l,
466
- action: o,
467
- loading: x = !1,
468
- loadingMessage: b,
469
- error: S,
470
- emptyMessage: $,
471
- className: y = "",
472
- showHeader: _ = !0
473
- }) {
474
- return /* @__PURE__ */ a(xe, { children: [
475
- /* @__PURE__ */ r("style", { children: `
476
- @media print {
477
- @page {
478
- size: portrait;
479
- margin: 12mm;
480
- }
481
-
482
- body {
483
- background: white !important;
484
- }
485
-
486
- body * {
487
- visibility: hidden;
488
- }
489
-
490
- [data-print-invoice-root],
491
- [data-print-invoice-root] * {
492
- visibility: visible;
493
- }
494
-
495
- [data-print-invoice-root] {
496
- position: absolute;
497
- inset: 0;
498
- width: 100%;
499
- margin: 0;
500
- padding: 0;
501
- }
502
- }
503
- ` }),
504
- /* @__PURE__ */ a(
505
- "div",
506
- {
507
- className: `mx-auto max-w-6xl px-4 py-10 md:px-6 print:max-w-none print:px-0 print:py-0 ${y}`,
508
- children: [
509
- _ ? /* @__PURE__ */ a("div", { className: "mb-6 flex flex-col gap-4 md:flex-row md:items-center md:justify-between print:hidden", children: [
510
- /* @__PURE__ */ a("div", { className: "flex items-center gap-4", children: [
511
- l ? /* @__PURE__ */ r("div", { className: "shrink-0", children: l }) : null,
512
- /* @__PURE__ */ a("div", { children: [
513
- /* @__PURE__ */ r("h1", { className: "text-3xl font-bold", children: s }),
514
- i ? /* @__PURE__ */ r("p", { className: "text-sm text-muted-foreground", children: i }) : null
515
- ] })
516
- ] }),
517
- /* @__PURE__ */ a("div", { className: "flex flex-wrap items-center gap-3", children: [
518
- /* @__PURE__ */ a(
519
- yt,
520
- {
521
- type: "button",
522
- variant: "outline",
523
- onClick: () => window.print(),
524
- disabled: !e,
525
- children: [
526
- /* @__PURE__ */ r(rr, { className: "mr-2 h-4 w-4" }),
527
- c
528
- ]
529
- }
530
- ),
531
- o ? /* @__PURE__ */ r(yt, { asChild: !0, variant: o.variant || "default", children: /* @__PURE__ */ r(Xe, { href: o.href, children: o.label }) }) : null
532
- ] })
533
- ] }) : null,
534
- x ? /* @__PURE__ */ r("div", { className: "mb-6 flex items-center justify-center gap-3 rounded-2xl border bg-background px-5 py-4 text-sm text-muted-foreground print:hidden", children: b }) : null,
535
- S ? /* @__PURE__ */ r("div", { className: "mb-6 rounded-2xl border border-amber-200 bg-amber-50 px-5 py-4 text-sm text-amber-700 print:hidden", children: S }) : null,
536
- e ? /* @__PURE__ */ r("div", { "data-print-invoice-root": !0, children: /* @__PURE__ */ r(
537
- Fr,
538
- {
539
- data: e,
540
- labels: t,
541
- locale: n
542
- }
543
- ) }) : !x && !S ? /* @__PURE__ */ r("div", { className: "rounded-2xl border bg-background px-6 py-12 text-center text-muted-foreground print:hidden", children: $ }) : null
544
- ]
545
- }
546
- )
547
- ] });
548
- }
549
- u.config({ jitless: !0 });
550
- const $r = u.enum(["physical", "digital"]).or(u.literal("")).refine((e) => e !== "", {
551
- message: "Product type is required"
552
- }).transform((e) => e), Vt = u.record(
553
- u.string().regex(/^[A-Z]{3}$/, "Currency code must be ISO 4217"),
554
- u.coerce.number().min(0, "Prices must be non-negative")
555
- ), zt = u.record(
556
- u.string().regex(/^[A-Z]{3}$/, "Currency code must be ISO 4217"),
557
- u.coerce.number().min(0, "Sale prices must be non-negative").nullable()
558
- ), De = u.string().trim().refine((e) => e === "" || !Number.isNaN(Date.parse(e)), {
559
- message: "Must be a valid date and time"
560
- }).transform((e) => e === "" ? null : e).nullable().optional();
561
- function Ut(e, t) {
562
- if (!e || !t)
563
- return !0;
564
- const n = Date.parse(e), s = Date.parse(t);
565
- return Number.isNaN(n) || Number.isNaN(s) ? !0 : n < s;
566
- }
567
- const Mr = u.object({
568
- attribute_id: u.string().uuid(),
569
- attribute_name: u.string(),
570
- term_id: u.string().uuid(),
571
- term_value: u.string(),
572
- term_slug: u.string().optional()
573
- }), Dr = u.object({
574
- id: u.string().uuid().optional(),
575
- combination_key: u.string().min(1),
576
- sku: u.string().min(1, "Variant SKU is required"),
577
- upc: u.string().optional().nullable(),
578
- price: u.coerce.number().min(0, "Variant price must be non-negative"),
579
- prices: Vt.default({}),
580
- sale_price: u.coerce.number().min(0, "Variant sale price must be non-negative").optional().nullable(),
581
- sale_prices: zt.default({}),
582
- sale_start_at: De,
583
- sale_end_at: De,
584
- stock_quantity: u.coerce.number().int().min(0, "Variant stock must be a non-negative integer"),
585
- main_media_id: u.string().uuid().optional().nullable(),
586
- main_image_url: u.string().optional().nullable(),
587
- attribute_term_ids: u.array(u.string().uuid()).min(1),
588
- selected_options: u.array(Mr).min(1),
589
- label: u.string().min(1)
590
- }).refine(
591
- (e) => e.sale_price === null || e.sale_price === void 0 || e.sale_price <= e.price,
592
- {
593
- message: "Variant sale price cannot exceed the regular price",
594
- path: ["sale_price"]
595
- }
596
- ).refine(
597
- (e) => Object.entries(e.sale_prices || {}).every(([t, n]) => {
598
- if (n == null)
599
- return !0;
600
- const s = e.prices?.[t];
601
- return typeof s == "number" ? n <= s : !0;
602
- }),
603
- {
604
- message: "Variant sale prices cannot exceed regular prices",
605
- path: ["sale_prices"]
606
- }
607
- ).refine(
608
- (e) => Ut(e.sale_start_at, e.sale_end_at),
609
- {
610
- message: "Sale end must be after the sale start",
611
- path: ["sale_end_at"]
612
- }
613
- ), jr = u.object({
614
- attribute_id: u.string().uuid(),
615
- term_ids: u.array(u.string().uuid())
616
- }), qr = u.object({
617
- product_type: $r,
618
- payment_provider: u.enum(["stripe", "freemius"]),
619
- title: u.string().min(1, "Title is required"),
620
- slug: u.string().min(1, "Slug is required").regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "Slug must be lowercase alphanumeric with hyphens"),
621
- sku: u.string().min(1, "SKU is required"),
622
- upc: u.string().optional().nullable(),
623
- price: u.coerce.number().min(0, "Price must be non-negative"),
624
- prices: Vt.default({}),
625
- sale_price: u.coerce.number().min(0, "Sale price must be non-negative").optional().nullable(),
626
- sale_prices: zt.default({}),
627
- sale_start_at: De,
628
- sale_end_at: De,
629
- stock: u.coerce.number().int().min(0, "Stock must be a non-negative integer"),
630
- meta_title: u.string().optional().nullable(),
631
- meta_description: u.string().optional().nullable(),
632
- short_description: u.string().optional(),
633
- description_json: u.any().optional(),
634
- // Using any for Tiptap JSON structure
635
- freemius_plan_id: u.string().optional(),
636
- // ID from Freemius Dashboard
637
- freemius_product_id: u.string().optional(),
638
- // Product or App ID from Freemius Dashboard
639
- trial_period_days: u.coerce.number().int().min(0, "Trial period must be zero or greater").default(0),
640
- trial_requires_payment_method: u.boolean().default(!1),
641
- media_id: u.string().optional(),
642
- // For the main product image (backward compat or single select)
643
- product_media: u.array(u.object({
644
- media_id: u.string()
645
- // We can sort based on index in this array, or explicit sort_order from UI
646
- })).optional(),
647
- category_ids: u.array(u.string().uuid()).optional(),
648
- is_taxable: u.boolean(),
649
- status: u.enum(["draft", "active", "archived"]),
650
- language_id: u.coerce.number().int().min(1, "Language is required"),
651
- translation_group_id: u.string().uuid().optional().or(u.literal("")).transform((e) => e === "" ? void 0 : e),
652
- explicitly_removed_media_ids: u.array(u.string()).optional(),
653
- variation_attributes: u.array(jr).optional(),
654
- variants: u.array(Dr).optional()
655
- }).refine(
656
- (e) => e.sale_price === null || e.sale_price === void 0 || e.sale_price <= e.price,
657
- {
658
- message: "Sale price cannot exceed the regular price",
659
- path: ["sale_price"]
660
- }
661
- ).refine(
662
- (e) => Object.entries(e.sale_prices || {}).every(([t, n]) => {
663
- if (n == null)
664
- return !0;
665
- const s = e.prices?.[t];
666
- return typeof s == "number" ? n <= s : !0;
667
- }),
668
- {
669
- message: "Sale prices cannot exceed regular prices",
670
- path: ["sale_prices"]
671
- }
672
- ).refine(
673
- (e) => Ut(e.sale_start_at, e.sale_end_at),
674
- {
675
- message: "Sale end must be after the sale start",
676
- path: ["sale_end_at"]
677
- }
678
- ), Ct = process.env.NEXT_PUBLIC_R2_BASE_URL || "", kt = (e) => e ? e.startsWith("http") || !Ct ? e : `${Ct.replace(/\/+$/, "")}/${e.replace(/^\/+/, "")}` : "", Or = ({ initialMedia: e, onUpdate: t, mediaPickerNode: n }) => {
679
- const [s, i] = U(e), c = Fe(null), l = Fe(null);
680
- Q(() => {
681
- i(e);
682
- }, [e]);
683
- const o = (_, f) => {
684
- c.current = f, _.dataTransfer.effectAllowed = "move";
685
- }, x = (_, f) => {
686
- l.current = f, _.preventDefault();
687
- }, b = (_) => {
688
- _.preventDefault();
689
- }, S = (_) => {
690
- if (_.preventDefault(), c.current === null || l.current === null) return;
691
- const f = [...s], N = f[c.current];
692
- f.splice(c.current, 1), f.splice(l.current, 0, N), c.current = null, l.current = null;
693
- const M = f.map((H, P) => ({
694
- ...H,
695
- sort_order: P
696
- }));
697
- i(M), t(M);
698
- }, $ = (_) => {
699
- if (!_ || s.some((M) => M.media_id === _.id))
700
- return;
701
- const f = {
702
- id: `temp-${Date.now()}`,
703
- // Temp ID
704
- media_id: _.id,
705
- file_path: _.file_path || _.object_key,
706
- alt: _.description || _.file_name || "",
707
- sort_order: s.length,
708
- isNew: !0
709
- }, N = [...s, f];
710
- i(N), t(N);
711
- }, y = (_) => {
712
- const N = s.filter((M, H) => H !== _).map((M, H) => ({ ...M, sort_order: H }));
713
- i(N), t(N);
714
- };
715
- return /* @__PURE__ */ a("div", { className: "space-y-4", children: [
716
- /* @__PURE__ */ a("div", { className: "grid grid-cols-3 sm:grid-cols-4 md:grid-cols-5 lg:grid-cols-6 gap-4", children: [
717
- s.map((_, f) => /* @__PURE__ */ a(
718
- "div",
719
- {
720
- className: "group relative aspect-square bg-muted/40 rounded-lg border overflow-hidden cursor-move transition-all hover:shadow-md",
721
- draggable: !0,
722
- onDragStart: (N) => o(N, f),
723
- onDragEnter: (N) => x(N, f),
724
- onDragOver: b,
725
- onDrop: S,
726
- children: [
727
- f === 0 && /* @__PURE__ */ r("div", { className: "absolute top-2 left-2 z-10 bg-primary text-primary-foreground text-[10px] font-bold px-2 py-0.5 rounded shadow-sm", children: "MAIN" }),
728
- /* @__PURE__ */ r(
729
- "button",
730
- {
731
- type: "button",
732
- onClick: () => y(f),
733
- className: "absolute top-1 right-1 z-20 p-1 bg-destructive/90 text-destructive-foreground rounded-full opacity-0 group-hover:opacity-100 transition-opacity",
734
- children: /* @__PURE__ */ r(Dt, { className: "w-3 h-3" })
735
- }
736
- ),
737
- /* @__PURE__ */ r("div", { className: "absolute inset-0 bg-black/0 group-hover:bg-black/5 transition-colors pointer-events-none" }),
738
- /* @__PURE__ */ r("div", { className: "absolute bottom-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity", children: /* @__PURE__ */ r(sr, { className: "w-4 h-4 text-white drop-shadow-md" }) }),
739
- kt(_.file_path) ? /* @__PURE__ */ r(
740
- jt,
741
- {
742
- src: kt(_.file_path),
743
- alt: _.alt,
744
- fill: !0,
745
- className: "object-cover",
746
- sizes: "(max-width: 768px) 50vw, 33vw"
747
- }
748
- ) : /* @__PURE__ */ r("div", { className: "flex h-full w-full items-center justify-center text-muted-foreground", children: /* @__PURE__ */ r(Be, { className: "w-8 h-8 opacity-30" }) })
749
- ]
750
- },
751
- _.id
752
- )),
753
- n ? pe.cloneElement(n, {
754
- onSelect: $,
755
- children: /* @__PURE__ */ a(
756
- "button",
757
- {
758
- type: "button",
759
- className: "group relative aspect-square flex flex-col items-center justify-center border-2 border-dashed rounded-lg bg-muted/10 text-muted-foreground hover:bg-muted/20 hover:border-muted-foreground/50 transition-all focus:outline-none focus:ring-2 focus:ring-primary",
760
- children: [
761
- /* @__PURE__ */ r(Be, { className: "w-8 h-8 mb-2 opacity-50 group-hover:opacity-75 transition-opacity" }),
762
- /* @__PURE__ */ r("span", { className: "text-sm font-medium", children: "Add Image" })
763
- ]
764
- }
765
- )
766
- }) : /* @__PURE__ */ a("div", { className: "relative aspect-square flex flex-col items-center justify-center border-2 border-dashed rounded-lg bg-muted/10 text-muted-foreground", children: [
767
- /* @__PURE__ */ r(Be, { className: "w-8 h-8 mb-2 opacity-30" }),
768
- /* @__PURE__ */ r("span", { className: "text-xs text-center px-2", children: "Media Picker not injected" })
769
- ] })
770
- ] }),
771
- /* @__PURE__ */ r("p", { className: "text-xs text-muted-foreground", children: "Drag and drop images to reorder. The first image will be used as the main product image." })
772
- ] });
773
- };
774
- function Er({ productId: e }) {
775
- const [t, n] = U(!1);
776
- return /* @__PURE__ */ a(
777
- ce,
778
- {
779
- variant: "outline",
780
- onClick: async () => {
781
- if (!e) {
782
- oe.error("Product ID is missing");
783
- return;
784
- }
785
- n(!0);
786
- try {
787
- const i = await hr(e);
788
- i.error ? oe.error(i.error) : oe.success("Pricing sync complete!");
789
- } catch (i) {
790
- oe.error(i.message || "An unexpected error occurred during sync");
791
- } finally {
792
- n(!1);
793
- }
794
- },
795
- disabled: t,
796
- className: "gap-2",
797
- children: [
798
- /* @__PURE__ */ r(nr, { className: `w-4 h-4 ${t ? "animate-spin" : ""}` }),
799
- t ? "Syncing..." : "Sync Prices from Freemius"
800
- ]
801
- }
802
- );
803
- }
804
- function We({
805
- idPrefix: e = "currency",
806
- currencies: t,
807
- prices: n,
808
- salePrices: s,
809
- managedCurrencyCodes: i = [],
810
- onPriceChange: c,
811
- onSalePriceChange: l,
812
- readOnly: o = !1,
813
- helperText: x,
814
- trailing: b
815
- }) {
816
- const S = t.find((y) => y.is_default) ?? t[0], $ = new Set(i);
817
- return S ? /* @__PURE__ */ a("div", { className: "flex flex-col gap-2", children: [
818
- x && /* @__PURE__ */ r("p", { className: "text-xs text-muted-foreground bg-muted/20 p-2 rounded-md border", children: x }),
819
- /* @__PURE__ */ r("div", { className: "divide-y divide-muted/50", children: t.map((y) => {
820
- const _ = de(y), f = _.is_default !== !0 && $.has(_.code), N = o || f;
821
- return /* @__PURE__ */ a(
822
- "div",
823
- {
824
- className: "flex flex-wrap items-stretch gap-4 py-3 first:pt-0 last:pb-0",
825
- children: [
826
- /* @__PURE__ */ a("div", { className: "flex items-center gap-2 w-[160px] shrink-0 self-stretch border-r border-border/50 pr-4", children: [
827
- /* @__PURE__ */ r("span", { className: "text-sm font-black tracking-tighter text-foreground", children: _.code }),
828
- /* @__PURE__ */ r("span", { className: "text-[11px] text-muted-foreground font-medium", children: _.symbol }),
829
- _.is_default ? /* @__PURE__ */ r("span", { className: "text-[9px] uppercase font-bold bg-primary/10 text-primary px-1.5 py-0.5 rounded tracking-widest leading-none", children: "Default" }) : f ? /* @__PURE__ */ r("span", { className: "text-[9px] uppercase font-bold bg-muted text-muted-foreground px-1.5 py-0.5 rounded tracking-widest leading-none", children: "Auto" }) : null,
830
- !_.is_default && /* @__PURE__ */ a("span", { className: "text-[9px] text-muted-foreground/80 font-medium tracking-wide leading-none ml-auto", children: [
831
- "x",
832
- _.exchange_rate
833
- ] })
834
- ] }),
835
- /* @__PURE__ */ a("div", { className: "grid flex-1 grid-cols-2 items-end gap-3 sm:grid-cols-4", children: [
836
- /* @__PURE__ */ a("div", { className: "min-w-0 space-y-1", children: [
837
- /* @__PURE__ */ r(
838
- q,
839
- {
840
- htmlFor: `${e}-price-${_.code}`,
841
- className: "block text-[10px] uppercase font-bold text-muted-foreground tracking-widest",
842
- children: "Price"
843
- }
844
- ),
845
- /* @__PURE__ */ a("div", { className: "relative", children: [
846
- /* @__PURE__ */ r("span", { className: "absolute left-2.5 top-1/2 -translate-y-1/2 text-xs text-muted-foreground font-bold pointer-events-none", children: _.symbol }),
847
- /* @__PURE__ */ r(
848
- j,
849
- {
850
- id: `${e}-price-${_.code}`,
851
- type: "number",
852
- step: "0.01",
853
- min: "0",
854
- value: n[_.code] ?? "",
855
- disabled: N,
856
- className: "h-8 w-full text-sm pl-6",
857
- onChange: (M) => c(
858
- _.code,
859
- Number(M.target.value || 0)
860
- )
861
- }
862
- )
863
- ] })
864
- ] }),
865
- /* @__PURE__ */ a("div", { className: "min-w-0 space-y-1", children: [
866
- /* @__PURE__ */ r(
867
- q,
868
- {
869
- htmlFor: `${e}-sale-price-${_.code}`,
870
- className: "block text-[10px] uppercase font-bold text-muted-foreground tracking-widest",
871
- children: "Sale"
872
- }
873
- ),
874
- /* @__PURE__ */ a("div", { className: "relative", children: [
875
- /* @__PURE__ */ r("span", { className: "absolute left-2.5 top-1/2 -translate-y-1/2 text-xs text-muted-foreground font-bold pointer-events-none", children: _.symbol }),
876
- /* @__PURE__ */ r(
877
- j,
878
- {
879
- id: `${e}-sale-price-${_.code}`,
880
- type: "number",
881
- step: "0.01",
882
- min: "0",
883
- value: s[_.code] ?? "",
884
- disabled: N,
885
- placeholder: f ? "Auto" : "—",
886
- className: "h-8 w-full text-sm pl-6",
887
- onChange: (M) => l(
888
- _.code,
889
- M.target.value === "" ? null : Number(M.target.value)
890
- )
891
- }
892
- )
893
- ] })
894
- ] }),
895
- b && _.is_default ? b : null
896
- ] })
897
- ]
898
- },
899
- _.code
900
- );
901
- }) })
902
- ] }) : null;
903
- }
904
- const Pe = (e) => String(e).padStart(2, "0");
905
- function Ie(e) {
906
- if (!e)
907
- return "";
908
- const t = new Date(e);
909
- return Number.isNaN(t.getTime()) ? "" : `${t.getFullYear()}-${Pe(t.getMonth() + 1)}-${Pe(
910
- t.getDate()
911
- )}T${Pe(t.getHours())}:${Pe(t.getMinutes())}`;
912
- }
913
- function Te(e) {
914
- if (!e)
915
- return null;
916
- const t = new Date(e);
917
- return Number.isNaN(t.getTime()) ? null : t.toISOString();
918
- }
919
- function et({
920
- idPrefix: e = "product",
921
- startAt: t,
922
- endAt: n,
923
- onChange: s,
924
- error: i,
925
- disabled: c,
926
- description: l,
927
- dense: o,
928
- bare: x
929
- }) {
930
- const b = Intl.DateTimeFormat().resolvedOptions().timeZone, S = Ye("h-7 text-xs", o || x ? "w-[150px]" : "w-[160px] sm:w-[180px]"), $ = /* @__PURE__ */ a(xe, { children: [
931
- /* @__PURE__ */ r(
932
- q,
933
- {
934
- htmlFor: `${e}-sale-start-at`,
935
- className: "text-[10px] uppercase tracking-wider text-muted-foreground",
936
- children: "Starts"
937
- }
938
- ),
939
- /* @__PURE__ */ r(
940
- j,
941
- {
942
- id: `${e}-sale-start-at`,
943
- type: "datetime-local",
944
- value: Ie(t),
945
- disabled: c,
946
- onChange: (y) => s("sale_start_at", Te(y.target.value)),
947
- className: S
948
- }
949
- ),
950
- /* @__PURE__ */ r("span", { className: "text-xs text-muted-foreground", children: "→" }),
951
- /* @__PURE__ */ r(
952
- q,
953
- {
954
- htmlFor: `${e}-sale-end-at`,
955
- className: "text-[10px] uppercase tracking-wider text-muted-foreground",
956
- children: "Ends"
957
- }
958
- ),
959
- /* @__PURE__ */ r(
960
- j,
961
- {
962
- id: `${e}-sale-end-at`,
963
- type: "datetime-local",
964
- value: Ie(n),
965
- disabled: c,
966
- onChange: (y) => s("sale_end_at", Te(y.target.value)),
967
- className: S
968
- }
969
- )
970
- ] });
971
- return x ? /* @__PURE__ */ a(xe, { children: [
972
- /* @__PURE__ */ a("div", { className: "min-w-0 space-y-1", children: [
973
- /* @__PURE__ */ r(
974
- q,
975
- {
976
- htmlFor: `${e}-sale-start-at`,
977
- className: "block text-[10px] uppercase font-bold tracking-widest text-muted-foreground",
978
- children: "Starts"
979
- }
980
- ),
981
- /* @__PURE__ */ r(
982
- j,
983
- {
984
- id: `${e}-sale-start-at`,
985
- type: "datetime-local",
986
- value: Ie(t),
987
- disabled: c,
988
- onChange: (y) => s("sale_start_at", Te(y.target.value)),
989
- className: "h-8 w-full text-xs"
990
- }
991
- )
992
- ] }),
993
- /* @__PURE__ */ a("div", { className: "min-w-0 space-y-1", children: [
994
- /* @__PURE__ */ r(
995
- q,
996
- {
997
- htmlFor: `${e}-sale-end-at`,
998
- className: "block text-[10px] uppercase font-bold tracking-widest text-muted-foreground",
999
- children: "Ends"
1000
- }
1001
- ),
1002
- /* @__PURE__ */ r(
1003
- j,
1004
- {
1005
- id: `${e}-sale-end-at`,
1006
- type: "datetime-local",
1007
- value: Ie(n),
1008
- disabled: c,
1009
- onChange: (y) => s("sale_end_at", Te(y.target.value)),
1010
- className: "h-8 w-full text-xs"
1011
- }
1012
- ),
1013
- i ? /* @__PURE__ */ r("p", { className: "mt-0.5 text-[10px] text-destructive", children: i }) : null
1014
- ] })
1015
- ] }) : /* @__PURE__ */ a(
1016
- "div",
1017
- {
1018
- className: Ye("rounded border border-dashed bg-muted/5 space-y-1", o ? "p-1.5" : "p-2"),
1019
- children: [
1020
- /* @__PURE__ */ a("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1.5", children: [
1021
- /* @__PURE__ */ r("span", { className: "shrink-0 text-[11px] font-bold uppercase tracking-wider text-muted-foreground", children: "Sale window" }),
1022
- $,
1023
- /* @__PURE__ */ a("span", { className: "ml-auto text-[10px] text-muted-foreground", children: [
1024
- b || "local time",
1025
- " · empty = always on"
1026
- ] })
1027
- ] }),
1028
- l && !o ? /* @__PURE__ */ r("p", { className: "text-[10px] leading-snug text-muted-foreground", children: l }) : null,
1029
- i ? /* @__PURE__ */ r("p", { className: "text-[11px] text-destructive", children: i }) : null
1030
- ]
1031
- }
1032
- );
1033
- }
1034
- function tt(e) {
1035
- return Object.entries(e || {}).reduce(
1036
- (t, [n, s]) => (typeof s == "number" && Number.isFinite(s) && s >= 0 ? t[be(n)] = s : s === null && (t[be(n)] = null), t),
1037
- {}
1038
- );
1039
- }
1040
- function rt(e) {
1041
- const t = de(e);
1042
- return t.is_default !== !0 && t.auto_sync_product_prices === !0;
1043
- }
1044
- function at(e) {
1045
- return e.map((t) => de(t)).filter((t) => rt(t)).map((t) => t.code);
1046
- }
1047
- function je(e, t) {
1048
- const n = new Set(at(t)), s = tt(e);
1049
- return Object.entries(s).reduce(
1050
- (i, [c, l]) => (n.has(c) || (i[c] = l), i),
1051
- {}
1052
- );
1053
- }
1054
- function Pt(e) {
1055
- const { baseAmount: t, defaultCurrencyCode: n, targetCurrencyCode: s, currencies: i } = e;
1056
- if (typeof t != "number" || !Number.isFinite(t) || t < 0)
1057
- return null;
1058
- const c = ye({
1059
- amount: ve(t, n),
1060
- fromCurrencyCode: n,
1061
- toCurrencyCode: s,
1062
- currencies: i,
1063
- applyRounding: !0
1064
- });
1065
- return fe(c, s);
1066
- }
1067
- function Lt(e) {
1068
- const { currencies: t, fallbackPrice: n, fallbackSalePrice: s } = e, i = tt(e.prices), c = tt(e.salePrices), l = t.find((y) => y.is_default) ?? t[0];
1069
- if (!l)
1070
- return {
1071
- prices: i,
1072
- salePrices: c
1073
- };
1074
- const o = be(l.code), x = i[o] ?? (typeof n == "number" ? n : null), b = c[o] ?? (typeof s == "number" ? s : null), S = t.reduce((y, _) => {
1075
- const f = de(_);
1076
- return rt(f) ? (y[f.code] = Pt({
1077
- baseAmount: x,
1078
- defaultCurrencyCode: o,
1079
- targetCurrencyCode: f.code,
1080
- currencies: t
1081
- }), y) : (y[f.code] = i[f.code] ?? (f.code === o ? x : void 0), y);
1082
- }, {}), $ = t.reduce((y, _) => {
1083
- const f = de(_);
1084
- return rt(f) ? (y[f.code] = Pt({
1085
- baseAmount: b,
1086
- defaultCurrencyCode: o,
1087
- targetCurrencyCode: f.code,
1088
- currencies: t
1089
- }), y) : (y[f.code] = c[f.code] ?? (f.code === o ? b : void 0), y);
1090
- }, {});
1091
- return {
1092
- prices: S,
1093
- salePrices: $
1094
- };
1095
- }
1096
- function Rr(e, t) {
1097
- const n = t.find((l) => l.is_default) ?? t[0], s = n ? be(n.code) : "USD", i = je(e.prices, t), c = je(e.sale_prices, t);
1098
- return {
1099
- ...e,
1100
- price: typeof i[s] == "number" ? i[s] : e.price,
1101
- prices: i,
1102
- sale_price: typeof c[s] == "number" ? c[s] : e.sale_price ?? null,
1103
- sale_prices: c
1104
- };
1105
- }
1106
- function st(e, t) {
1107
- return e?.map(
1108
- (n) => Rr(n, t)
1109
- ) || [];
1110
- }
1111
- function qe(e, t) {
1112
- const n = t.find((l) => l.is_default) ?? t[0], s = n ? be(n.code) : "USD", i = je(e.prices, t), c = je(e.sale_prices, t);
1113
- return {
1114
- ...e,
1115
- price: typeof i[s] == "number" ? i[s] : e.price,
1116
- prices: i,
1117
- sale_price: typeof c[s] == "number" ? c[s] : e.sale_price ?? null,
1118
- sale_prices: c,
1119
- variants: st(e.variants, t)
1120
- };
1121
- }
1122
- const It = process.env.NEXT_PUBLIC_R2_BASE_URL || "", Tt = process.env.NEXT_PUBLIC_SUPABASE_URL || "", Vr = (e) => e.startsWith("http") ? e : It ? `${It.replace(/\/+$/, "")}/${e.replace(/^\/+/, "")}` : Tt ? `${Tt.replace(/\/+$/, "")}/storage/v1/object/public/media/${e.replace(/^\/+/, "")}` : e;
1123
- function At(e, t = "USD") {
1124
- return new Intl.NumberFormat("en-US", {
1125
- style: "currency",
1126
- currency: t
1127
- }).format(e);
1128
- }
1129
- function zr(e) {
1130
- return Object.entries(e).filter(([, t]) => t.length > 0).map(([t, n]) => ({ attribute_id: t, term_ids: n }));
1131
- }
1132
- function Ur({
1133
- globalAttributes: e,
1134
- currentLanguageCode: t,
1135
- baseSku: n,
1136
- basePrice: s,
1137
- basePrices: i,
1138
- baseSalePrice: c,
1139
- baseSalePrices: l,
1140
- currencies: o,
1141
- availableVariantImages: x = [],
1142
- initialVariationAttributes: b,
1143
- initialVariants: S,
1144
- onChange: $
1145
- }) {
1146
- const [y, _] = U(() => b && b.length > 0 ? b.reduce((d, g) => (d[g.attribute_id] = g.term_ids, d), {}) : br(S || [])), [f, N] = U(
1147
- st(
1148
- S || [],
1149
- o
1150
- )
1151
- ), M = he(
1152
- () => e.map((d) => ({
1153
- attribute_id: d.id,
1154
- attribute_name: vt(d, t),
1155
- terms: d.terms.filter((g) => (y[d.id] || []).includes(g.id)).map((g) => ({
1156
- ...g,
1157
- value: bt(g, t)
1158
- }))
1159
- })).filter((d) => d.terms.length > 0),
1160
- [t, e, y]
1161
- );
1162
- Q(() => {
1163
- if (M.length === 0) {
1164
- N([]);
1165
- return;
1166
- }
1167
- N(
1168
- (d) => st(
1169
- vr({
1170
- baseSku: n,
1171
- basePrice: s,
1172
- basePrices: wr(i),
1173
- baseSalePrice: c,
1174
- baseSalePrices: Nr(l),
1175
- selectedAttributes: M,
1176
- previousVariants: d
1177
- }),
1178
- o
1179
- )
1180
- );
1181
- }, [s, i, c, l, n, o, M]), Q(() => {
1182
- $({
1183
- variationAttributes: zr(y),
1184
- variants: f
1185
- });
1186
- }, [$, y, f]);
1187
- const H = f.reduce(
1188
- (d, g) => d + (g.stock_quantity || 0),
1189
- 0
1190
- ), P = o.find((d) => d.is_default) ?? o[0], p = he(
1191
- () => at(o),
1192
- [o]
1193
- ), A = (d, g) => {
1194
- _((h) => {
1195
- const C = new Set(h[d] || []);
1196
- return C.has(g) ? C.delete(g) : C.add(g), {
1197
- ...h,
1198
- [d]: [...C]
1199
- };
1200
- });
1201
- }, X = (d, g, h) => {
1202
- N(
1203
- (C) => C.map((I) => {
1204
- if (I.combination_key !== d)
1205
- return I;
1206
- if (g === "sku")
1207
- return {
1208
- ...I,
1209
- sku: h
1210
- };
1211
- if (g === "upc")
1212
- return {
1213
- ...I,
1214
- upc: h
1215
- };
1216
- if (g === "sale_price" && h === "")
1217
- return {
1218
- ...I,
1219
- sale_price: null
1220
- };
1221
- if (g === "prices" || g === "sale_prices")
1222
- return I;
1223
- const L = h === "" ? 0 : Number(h);
1224
- return {
1225
- ...I,
1226
- [g]: Number.isFinite(L) ? L : 0
1227
- };
1228
- })
1229
- );
1230
- }, D = (d, g, h) => {
1231
- N(
1232
- (C) => C.map(
1233
- (I) => I.combination_key === d ? { ...I, [g]: h } : I
1234
- )
1235
- );
1236
- }, le = (d, g, h, C) => {
1237
- const I = o.find((L) => L.is_default) ?? o[0];
1238
- N(
1239
- (L) => L.map((V) => {
1240
- if (V.combination_key !== d)
1241
- return V;
1242
- const B = {
1243
- ...h === "prices" ? V.prices : V.sale_prices,
1244
- [g]: C
1245
- };
1246
- return {
1247
- ...V,
1248
- [h]: B,
1249
- ...g === I?.code ? h === "prices" ? { price: C ?? 0 } : { sale_price: C } : {}
1250
- };
1251
- })
1252
- );
1253
- }, v = (d) => {
1254
- const g = o.find((C) => C.is_default) ?? o[0], h = new Set(p);
1255
- g && N(
1256
- (C) => C.map((I) => {
1257
- if (I.combination_key !== d)
1258
- return I;
1259
- const L = o.reduce((B, O) => {
1260
- if (O.code !== g.code && h.has(O.code))
1261
- return B;
1262
- const ue = ye({
1263
- amount: ve(I.price, g.code),
1264
- fromCurrencyCode: g.code,
1265
- toCurrencyCode: O.code,
1266
- currencies: o,
1267
- applyRounding: !0
1268
- });
1269
- return B[O.code] = fe(ue, O.code), B;
1270
- }, {}), V = o.reduce(
1271
- (B, O) => {
1272
- if (O.code !== g.code && h.has(O.code))
1273
- return B;
1274
- if (typeof I.sale_price != "number")
1275
- return B[O.code] = null, B;
1276
- const ue = ye({
1277
- amount: ve(I.sale_price, g.code),
1278
- fromCurrencyCode: g.code,
1279
- toCurrencyCode: O.code,
1280
- currencies: o,
1281
- applyRounding: !0
1282
- });
1283
- return B[O.code] = fe(ue, O.code), B;
1284
- },
1285
- {}
1286
- );
1287
- return {
1288
- ...I,
1289
- prices: L,
1290
- sale_prices: V
1291
- };
1292
- })
1293
- );
1294
- }, we = (d, g) => {
1295
- const h = x.find((L) => L.media_id === g);
1296
- if (!h)
1297
- return;
1298
- const C = h.file_path, I = Vr(C);
1299
- N(
1300
- (L) => L.map(
1301
- (V) => V.combination_key === d ? {
1302
- ...V,
1303
- main_media_id: h.media_id,
1304
- main_image_url: I
1305
- } : V
1306
- )
1307
- );
1308
- }, F = (d) => {
1309
- N(
1310
- (g) => g.map(
1311
- (h) => h.combination_key === d ? {
1312
- ...h,
1313
- main_media_id: null,
1314
- main_image_url: null
1315
- } : h
1316
- )
1317
- );
1318
- };
1319
- return e.length === 0 ? /* @__PURE__ */ a("div", { className: "rounded-lg border border-dashed p-6 text-sm text-muted-foreground", children: [
1320
- "No global attributes have been created yet. Create them first in",
1321
- " ",
1322
- /* @__PURE__ */ r(Xe, { href: "/cms/products/attributes", className: "font-medium text-primary underline-offset-4 hover:underline", children: "Attribute Management" }),
1323
- "."
1324
- ] }) : /* @__PURE__ */ a("div", { className: "space-y-3", children: [
1325
- /* @__PURE__ */ a("div", { className: "space-y-2", children: [
1326
- /* @__PURE__ */ a("div", { className: "flex items-center justify-between gap-3", children: [
1327
- /* @__PURE__ */ a("div", { className: "flex items-center gap-3", children: [
1328
- /* @__PURE__ */ r("span", { className: "text-xs uppercase font-bold text-muted-foreground tracking-wider leading-none", children: "Attributes" }),
1329
- /* @__PURE__ */ a(ie, { variant: "outline", className: "text-[10px] px-1.5 h-4", children: [
1330
- f.length,
1331
- " variants"
1332
- ] }),
1333
- /* @__PURE__ */ a(ie, { variant: "secondary", className: "text-[10px] px-1.5 h-4", children: [
1334
- "Stock: ",
1335
- H
1336
- ] })
1337
- ] }),
1338
- /* @__PURE__ */ r(ce, { asChild: !0, variant: "outline", size: "sm", className: "h-7 text-xs px-3", children: /* @__PURE__ */ r(Xe, { href: "/cms/products/attributes", children: "Manage" }) })
1339
- ] }),
1340
- /* @__PURE__ */ r("div", { className: "grid gap-2 lg:grid-cols-2", children: e.map((d) => {
1341
- const g = y[d.id] || [];
1342
- return /* @__PURE__ */ a("div", { className: "flex items-center gap-3 rounded border p-2.5", children: [
1343
- /* @__PURE__ */ a("div", { className: "shrink-0 w-[100px]", children: [
1344
- /* @__PURE__ */ r("span", { className: "text-sm font-bold block leading-tight", children: vt(d, t) }),
1345
- /* @__PURE__ */ a("span", { className: "text-[10px] text-muted-foreground leading-none", children: [
1346
- g.length,
1347
- " selected"
1348
- ] })
1349
- ] }),
1350
- /* @__PURE__ */ r("div", { className: "flex flex-wrap gap-1.5 flex-1", children: d.terms.map((h) => {
1351
- const C = g.includes(h.id);
1352
- return /* @__PURE__ */ r(
1353
- "button",
1354
- {
1355
- type: "button",
1356
- onClick: () => A(d.id, h.id),
1357
- className: `rounded-full border px-2.5 py-0.5 text-[11px] font-medium transition-colors ${C ? "border-primary bg-primary/10 text-primary" : "border-border bg-background text-foreground hover:border-primary/40"}`,
1358
- children: bt(h, t)
1359
- },
1360
- h.id
1361
- );
1362
- }) })
1363
- ] }, d.id);
1364
- }) })
1365
- ] }),
1366
- f.length === 0 ? /* @__PURE__ */ r("div", { className: "rounded border border-dashed p-3 text-xs text-muted-foreground text-center", children: "Select terms above to generate variations." }) : /* @__PURE__ */ r("div", { className: "space-y-2", children: f.map((d) => {
1367
- const g = Lt({
1368
- currencies: o,
1369
- prices: d.prices || {},
1370
- salePrices: d.sale_prices || {},
1371
- fallbackPrice: d.price,
1372
- fallbackSalePrice: d.sale_price
1373
- });
1374
- return /* @__PURE__ */ a("div", { className: "rounded border p-3 space-y-2", children: [
1375
- /* @__PURE__ */ a("div", { className: "flex items-center justify-between gap-3", children: [
1376
- /* @__PURE__ */ a("div", { className: "flex items-center gap-2", children: [
1377
- /* @__PURE__ */ r("span", { className: "text-sm font-bold", children: d.label }),
1378
- /* @__PURE__ */ r("span", { className: "text-xs text-muted-foreground", children: d.selected_options.map((h) => `${h.attribute_name}: ${h.term_value}`).join(" · ") })
1379
- ] }),
1380
- /* @__PURE__ */ a("div", { className: "flex items-center gap-3 text-xs text-muted-foreground", children: [
1381
- /* @__PURE__ */ a("span", { children: [
1382
- "Reg: ",
1383
- At(d.price, P?.code || "USD")
1384
- ] }),
1385
- /* @__PURE__ */ a("span", { children: [
1386
- "Sale:",
1387
- " ",
1388
- d.sale_price !== null && d.sale_price !== void 0 ? At(d.sale_price, P?.code || "USD") : "—"
1389
- ] })
1390
- ] })
1391
- ] }),
1392
- /* @__PURE__ */ a("div", { className: "grid grid-cols-3 gap-2.5", children: [
1393
- /* @__PURE__ */ a("div", { className: "flex items-center gap-2", children: [
1394
- /* @__PURE__ */ r(q, { htmlFor: `variant-sku-${d.combination_key}`, className: "text-xs uppercase font-bold text-muted-foreground tracking-wider shrink-0", children: "SKU" }),
1395
- /* @__PURE__ */ r(
1396
- j,
1397
- {
1398
- id: `variant-sku-${d.combination_key}`,
1399
- value: d.sku,
1400
- onChange: (h) => X(d.combination_key, "sku", h.target.value),
1401
- placeholder: "SKU",
1402
- className: "h-8 text-sm font-mono"
1403
- }
1404
- )
1405
- ] }),
1406
- /* @__PURE__ */ a("div", { className: "flex items-center gap-2", children: [
1407
- /* @__PURE__ */ r(q, { htmlFor: `variant-upc-${d.combination_key}`, className: "text-xs uppercase font-bold text-muted-foreground tracking-wider shrink-0", children: "UPC" }),
1408
- /* @__PURE__ */ r(
1409
- j,
1410
- {
1411
- id: `variant-upc-${d.combination_key}`,
1412
- value: d.upc ?? "",
1413
- onChange: (h) => X(d.combination_key, "upc", h.target.value),
1414
- placeholder: "—",
1415
- className: "h-8 text-sm font-mono"
1416
- }
1417
- )
1418
- ] }),
1419
- /* @__PURE__ */ a("div", { className: "flex items-center gap-2", children: [
1420
- /* @__PURE__ */ r(q, { htmlFor: `variant-stock-${d.combination_key}`, className: "text-xs uppercase font-bold text-muted-foreground tracking-wider shrink-0", children: "Qty" }),
1421
- /* @__PURE__ */ r(
1422
- j,
1423
- {
1424
- id: `variant-stock-${d.combination_key}`,
1425
- type: "number",
1426
- min: "0",
1427
- value: d.stock_quantity,
1428
- onChange: (h) => X(
1429
- d.combination_key,
1430
- "stock_quantity",
1431
- h.target.value
1432
- ),
1433
- className: "h-8 text-sm font-mono w-20"
1434
- }
1435
- )
1436
- ] })
1437
- ] }),
1438
- /* @__PURE__ */ r(
1439
- We,
1440
- {
1441
- idPrefix: `variant-${d.combination_key}`,
1442
- currencies: o,
1443
- prices: g.prices,
1444
- salePrices: g.salePrices,
1445
- managedCurrencyCodes: p,
1446
- onPriceChange: (h, C) => le(
1447
- d.combination_key,
1448
- h,
1449
- "prices",
1450
- C
1451
- ),
1452
- onSalePriceChange: (h, C) => le(
1453
- d.combination_key,
1454
- h,
1455
- "sale_prices",
1456
- C
1457
- ),
1458
- onAutoFill: () => v(d.combination_key),
1459
- helperText: p.length > 0 ? `Store-managed currencies derive from ${P?.code || "the base currency"}.` : void 0,
1460
- trailing: /* @__PURE__ */ r(
1461
- et,
1462
- {
1463
- idPrefix: `variant-${d.combination_key}`,
1464
- startAt: d.sale_start_at,
1465
- endAt: d.sale_end_at,
1466
- onChange: (h, C) => D(d.combination_key, h, C),
1467
- bare: !0
1468
- }
1469
- )
1470
- }
1471
- ),
1472
- /* @__PURE__ */ a("div", { className: "flex items-center gap-3 pt-1.5 border-t border-muted/30", children: [
1473
- d.main_image_url && /* @__PURE__ */ r("div", { className: "h-9 w-9 overflow-hidden rounded border bg-background shrink-0", children: /* @__PURE__ */ r(
1474
- "img",
1475
- {
1476
- src: d.main_image_url,
1477
- alt: `${d.label} image`,
1478
- className: "h-full w-full object-cover"
1479
- }
1480
- ) }),
1481
- /* @__PURE__ */ r("span", { className: "text-xs uppercase font-bold text-muted-foreground tracking-wider shrink-0", children: "Image" }),
1482
- x.length > 0 ? /* @__PURE__ */ a(
1483
- "select",
1484
- {
1485
- className: "flex h-8 rounded-md border border-input bg-background px-2 py-1 text-sm min-w-[180px]",
1486
- value: d.main_media_id ?? "",
1487
- onChange: (h) => {
1488
- if (!h.target.value) {
1489
- F(d.combination_key);
1490
- return;
1491
- }
1492
- we(d.combination_key, h.target.value);
1493
- },
1494
- children: [
1495
- /* @__PURE__ */ r("option", { value: "", children: "Use parent image" }),
1496
- x.map((h, C) => /* @__PURE__ */ r("option", { value: h.media_id, children: h.alt?.trim() || `Gallery image ${C + 1}` }, h.media_id))
1497
- ]
1498
- }
1499
- ) : /* @__PURE__ */ r("span", { className: "text-xs text-muted-foreground", children: "Add gallery images first." }),
1500
- d.main_media_id && /* @__PURE__ */ r(
1501
- ce,
1502
- {
1503
- type: "button",
1504
- variant: "ghost",
1505
- size: "sm",
1506
- className: "h-7 text-xs px-2 text-muted-foreground hover:text-destructive",
1507
- onClick: () => F(d.combination_key),
1508
- children: "Remove"
1509
- }
1510
- )
1511
- ] })
1512
- ] }, d.combination_key);
1513
- }) })
1514
- ] });
1515
- }
1516
- function Ft(e) {
1517
- if (!e)
1518
- return null;
1519
- const t = new Date(e);
1520
- return Number.isNaN(t.getTime()) ? e : t.toISOString().replace("T", " ").replace(/\.\d{3}Z$/, "");
1521
- }
1522
- function Lr(e) {
1523
- return e === "percent" ? "percentage" : "dollar";
1524
- }
1525
- function Br(e) {
1526
- return xr(e).apiKey || yr("FREEMIUS_API_KEY");
1527
- }
1528
- async function it(e) {
1529
- const t = Br(e.productId);
1530
- if (!t)
1531
- throw new Error(
1532
- `Missing Freemius API bearer token for product ${e.productId}. Set FREEMIUS_API_KEY or FREEMIUS_CHECKOUT_PRODUCTS_JSON[${e.productId}].apiKey.`
1533
- );
1534
- const n = e.couponId ? `/${e.couponId}` : "", s = await fetch(
1535
- `https://api.freemius.com/v1/products/${e.productId}/coupons${n}.json`,
1536
- {
1537
- method: e.method,
1538
- headers: {
1539
- Authorization: `Bearer ${t}`,
1540
- "Content-Type": "application/json",
1541
- Accept: "application/json"
1542
- },
1543
- body: e.method === "DELETE" ? void 0 : JSON.stringify(e.body || {})
1544
- }
1545
- ), i = await s.text(), c = i ? JSON.parse(i) : null;
1546
- if (!s.ok)
1547
- throw new Error(
1548
- c?.message || c?.error?.message || `Freemius coupon request failed with ${s.status}`
1549
- );
1550
- return c;
1551
- }
1552
- function Bt(e, t) {
1553
- return {
1554
- code: e.code,
1555
- discount: e.discount_type === "fixed" ? fe(e.discount_amount, "USD") : e.discount_amount,
1556
- discount_type: Lr(e.discount_type),
1557
- plans: t.planIds.length > 0 ? t.planIds.join(",") : null,
1558
- licenses: null,
1559
- billing_cycles: null,
1560
- start_date: Ft(e.starts_at),
1561
- end_date: Ft(e.ends_at),
1562
- redemptions_limit: e.redemption_limit ?? null,
1563
- has_renewals_discount: !1,
1564
- has_addons_discount: !1,
1565
- is_one_per_user: !1,
1566
- is_active: e.is_active,
1567
- user_type: "all"
1568
- };
1569
- }
1570
- async function Kr(e, t) {
1571
- if (t.provider_scope === "stripe")
1572
- return [];
1573
- const { data: n, error: s } = await e.from("coupon_products").select("product_id").eq("coupon_id", t.id);
1574
- if (s)
1575
- throw new Error(s.message);
1576
- const i = (n || []).map((b) => b.product_id);
1577
- let c = e.from("products").select("id, freemius_product_id, freemius_plan_id").eq("payment_provider", "freemius").not("freemius_product_id", "is", null);
1578
- i.length > 0 && (c = c.in("id", i));
1579
- const { data: l, error: o } = await c;
1580
- if (o)
1581
- throw new Error(o.message);
1582
- const x = /* @__PURE__ */ new Map();
1583
- for (const b of l || []) {
1584
- const S = String(b.freemius_product_id || "").trim();
1585
- if (!S)
1586
- continue;
1587
- const $ = x.get(S) ?? {
1588
- freemiusProductId: S,
1589
- productId: b.id,
1590
- planIds: []
1591
- };
1592
- i.length > 0 && b.freemius_plan_id && $.planIds.push(String(b.freemius_plan_id)), x.set(S, $);
1593
- }
1594
- return [...x.values()].map((b) => ({
1595
- ...b,
1596
- planIds: [...new Set(b.planIds)]
1597
- }));
1598
- }
1599
- async function Jr(e, t) {
1600
- const { data: n } = await e.from("coupon_freemius_mappings").select("sync_status, sync_error").eq("coupon_id", t), s = n || [];
1601
- if (s.length === 0) {
1602
- await e.from("coupons").update({
1603
- freemius_sync_status: "not_required",
1604
- freemius_sync_error: null
1605
- }).eq("id", t);
1606
- return;
1607
- }
1608
- const i = s.find((c) => c.sync_status === "failed");
1609
- await e.from("coupons").update({
1610
- freemius_sync_status: i ? "failed" : "synced",
1611
- freemius_sync_error: i?.sync_error ?? null
1612
- }).eq("id", t);
1613
- }
1614
- async function As(e) {
1615
- const { data: t, error: n } = await e.client.from("coupons").select(
1616
- "id, code, name, internal_note, provider_scope, discount_type, discount_amount, is_active, starts_at, ends_at, redemption_limit"
1617
- ).eq("id", e.couponId).single();
1618
- if (n || !t)
1619
- return {
1620
- success: !1,
1621
- error: n?.message || "Coupon not found"
1622
- };
1623
- const s = t, i = await Kr(e.client, s);
1624
- await e.client.from("coupons").update({
1625
- freemius_sync_status: i.length > 0 ? "pending" : "not_required",
1626
- freemius_sync_error: null
1627
- }).eq("id", s.id);
1628
- for (const c of i) {
1629
- const { data: l } = await e.client.from("coupon_freemius_mappings").select("id, freemius_coupon_id").eq("coupon_id", s.id).eq("freemius_product_id", c.freemiusProductId).maybeSingle(), o = Bt(s, c);
1630
- try {
1631
- const x = await it({
1632
- productId: c.freemiusProductId,
1633
- method: l?.freemius_coupon_id ? "PUT" : "POST",
1634
- couponId: l?.freemius_coupon_id ?? null,
1635
- body: o
1636
- }), b = x?.coupon ?? x;
1637
- await e.client.from("coupon_freemius_mappings").upsert(
1638
- {
1639
- id: l?.id,
1640
- coupon_id: s.id,
1641
- product_id: c.productId,
1642
- freemius_product_id: c.freemiusProductId,
1643
- freemius_coupon_id: b?.id ? String(b.id) : l?.freemius_coupon_id ?? null,
1644
- freemius_coupon_code: s.code,
1645
- sync_status: "synced",
1646
- sync_error: null,
1647
- remote_payload: x,
1648
- last_synced_at: (/* @__PURE__ */ new Date()).toISOString()
1649
- },
1650
- { onConflict: "coupon_id,freemius_product_id" }
1651
- );
1652
- } catch (x) {
1653
- await e.client.from("coupon_freemius_mappings").upsert(
1654
- {
1655
- id: l?.id,
1656
- coupon_id: s.id,
1657
- product_id: c.productId,
1658
- freemius_product_id: c.freemiusProductId,
1659
- freemius_coupon_id: l?.freemius_coupon_id ?? null,
1660
- freemius_coupon_code: s.code,
1661
- sync_status: "failed",
1662
- sync_error: x.message || "Freemius sync failed",
1663
- last_synced_at: (/* @__PURE__ */ new Date()).toISOString()
1664
- },
1665
- { onConflict: "coupon_id,freemius_product_id" }
1666
- );
1667
- }
1668
- }
1669
- return await Jr(e.client, s.id), {
1670
- success: !0,
1671
- targetCount: i.length
1672
- };
1673
- }
1674
- function Gr(e) {
1675
- const t = (e.sku || "").toUpperCase().replace(/[^A-Z0-9]/g, "");
1676
- return t ? `SALE${t}`.slice(0, 32) : `SALE${e.productId.replace(/[^A-Za-z0-9]/g, "").toUpperCase()}`.slice(0, 32);
1677
- }
1678
- function Hr(e, t) {
1679
- if (typeof e != "number" || e <= 0 || typeof t != "number" || t < 0 || t >= e)
1680
- return null;
1681
- const n = Math.round((1 - t / e) * 100);
1682
- return n <= 0 || n > 100 ? null : n;
1683
- }
1684
- async function Qr(e) {
1685
- const { data: t, error: n } = await e.client.from("products").select(
1686
- "id, sku, price, sale_price, sale_start_at, sale_end_at, payment_provider, freemius_product_id, freemius_plan_id"
1687
- ).eq("id", e.productId).maybeSingle();
1688
- if (n || !t)
1689
- return { success: !1, error: n?.message || "Product not found" };
1690
- const s = t, i = String(s.freemius_product_id || "").trim();
1691
- if (s.payment_provider !== "freemius" || !i)
1692
- return { success: !0, skipped: !0, reason: "not_a_freemius_product" };
1693
- const c = Hr(s.price, s.sale_price), l = c !== null, { data: o } = await e.client.from("product_freemius_sale_coupons").select("id, freemius_coupon_id, freemius_coupon_code, discount_percent, is_active").eq("product_id", s.id).maybeSingle();
1694
- if (!l && !o?.freemius_coupon_id)
1695
- return o?.id && await e.client.from("product_freemius_sale_coupons").update({ is_active: !1, updated_at: (/* @__PURE__ */ new Date()).toISOString() }).eq("id", o.id), { success: !0, active: !1 };
1696
- const x = o?.freemius_coupon_code || Gr({ sku: s.sku, productId: s.id }), b = s.freemius_plan_id ? [String(s.freemius_plan_id)] : [], S = c ?? o?.discount_percent ?? 1, $ = {
1697
- id: s.id,
1698
- code: x,
1699
- name: `Scheduled sale ${s.sku || s.id}`,
1700
- discount_type: "percent",
1701
- discount_amount: S,
1702
- is_active: l,
1703
- starts_at: s.sale_start_at,
1704
- ends_at: s.sale_end_at,
1705
- redemption_limit: null
1706
- }, y = {
1707
- productId: s.id,
1708
- planIds: b
1709
- }, _ = Bt($, y);
1710
- try {
1711
- const f = await it({
1712
- productId: i,
1713
- method: o?.freemius_coupon_id ? "PUT" : "POST",
1714
- couponId: o?.freemius_coupon_id ?? null,
1715
- body: _
1716
- }), N = f?.coupon ?? f;
1717
- return await e.client.from("product_freemius_sale_coupons").upsert(
1718
- {
1719
- id: o?.id,
1720
- product_id: s.id,
1721
- freemius_product_id: i,
1722
- freemius_plan_id: s.freemius_plan_id ? String(s.freemius_plan_id) : null,
1723
- freemius_coupon_id: N?.id ? String(N.id) : o?.freemius_coupon_id ?? null,
1724
- freemius_coupon_code: x,
1725
- discount_percent: c,
1726
- starts_at: s.sale_start_at,
1727
- ends_at: s.sale_end_at,
1728
- is_active: l,
1729
- sync_status: "synced",
1730
- sync_error: null,
1731
- remote_payload: f,
1732
- last_synced_at: (/* @__PURE__ */ new Date()).toISOString()
1733
- },
1734
- { onConflict: "product_id" }
1735
- ), { success: !0, active: l, code: x };
1736
- } catch (f) {
1737
- return await e.client.from("product_freemius_sale_coupons").upsert(
1738
- {
1739
- id: o?.id,
1740
- product_id: s.id,
1741
- freemius_product_id: i,
1742
- freemius_plan_id: s.freemius_plan_id ? String(s.freemius_plan_id) : null,
1743
- freemius_coupon_id: o?.freemius_coupon_id ?? null,
1744
- freemius_coupon_code: x,
1745
- discount_percent: c,
1746
- starts_at: s.sale_start_at,
1747
- ends_at: s.sale_end_at,
1748
- is_active: l,
1749
- sync_status: "failed",
1750
- sync_error: f.message || "Freemius sale coupon sync failed",
1751
- last_synced_at: (/* @__PURE__ */ new Date()).toISOString()
1752
- },
1753
- { onConflict: "product_id" }
1754
- ), {
1755
- success: !1,
1756
- error: f.message || "Freemius sale coupon sync failed"
1757
- };
1758
- }
1759
- }
1760
- async function Fs(e) {
1761
- const { data: t } = await e.client.from("coupon_freemius_mappings").select("id, freemius_product_id, freemius_coupon_id").eq("coupon_id", e.couponId).not("freemius_coupon_id", "is", null);
1762
- for (const n of t || [])
1763
- try {
1764
- await it({
1765
- productId: n.freemius_product_id,
1766
- couponId: n.freemius_coupon_id,
1767
- method: "DELETE"
1768
- }), await e.client.from("coupon_freemius_mappings").update({
1769
- sync_status: "deleted",
1770
- sync_error: null,
1771
- updated_at: (/* @__PURE__ */ new Date()).toISOString()
1772
- }).eq("id", n.id);
1773
- } catch (s) {
1774
- await e.client.from("coupon_freemius_mappings").update({
1775
- sync_status: "failed",
1776
- sync_error: s.message || "Freemius delete failed",
1777
- updated_at: (/* @__PURE__ */ new Date()).toISOString()
1778
- }).eq("id", n.id);
1779
- }
1780
- }
1781
- function Oe(e) {
1782
- return e.toLowerCase().trim().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/-+/g, "-").replace(/^-|-$/g, "");
1783
- }
1784
- async function $s(e) {
1785
- const t = Ne(), { data: n } = await t.from("currencies").select(
1786
- "code, symbol, exchange_rate, is_default, is_active, auto_sync_product_prices, auto_update_exchange_rate, exchange_rate_source, exchange_rate_updated_at, rounding_mode, rounding_increment, rounding_charm_amount"
1787
- ).eq("is_active", !0).order("code", { ascending: !0 }), s = qe(
1788
- e,
1789
- (n || []).map((c) => de(c))
1790
- ), i = await Sr(t, s);
1791
- if (s.payment_provider === "freemius" && i?.id)
1792
- try {
1793
- await Qr({
1794
- productId: i.id,
1795
- client: Y()
1796
- });
1797
- } catch (c) {
1798
- console.error("Failed to sync Freemius sale coupon on create:", c);
1799
- }
1800
- w("/cms/products"), Pr("/cms/products");
1801
- }
1802
- async function Ms(e, t) {
1803
- const n = Ne(), { data: { user: s } } = await n.auth.getUser();
1804
- if (!s)
1805
- throw new Error("User not authenticated.");
1806
- const { data: i } = await n.from("currencies").select(
1807
- "code, symbol, exchange_rate, is_default, is_active, auto_sync_product_prices, auto_update_exchange_rate, exchange_rate_source, exchange_rate_updated_at, rounding_mode, rounding_increment, rounding_charm_amount"
1808
- ).eq("is_active", !0).order("code", { ascending: !0 }), c = qe(
1809
- t,
1810
- (i || []).map((o) => de(o))
1811
- ), { error: l } = await n.from("product_drafts").upsert(
1812
- {
1813
- product_id: e,
1814
- author_id: s.id,
1815
- meta: c,
1816
- updated_at: (/* @__PURE__ */ new Date()).toISOString()
1817
- },
1818
- { onConflict: "product_id" }
1819
- );
1820
- if (l)
1821
- throw new Error(`Failed to save product draft: ${l.message}`);
1822
- return { success: !0 };
1823
- }
1824
- async function Ds(e) {
1825
- const t = Ne();
1826
- await Cr(t, e), w("/cms/products");
1827
- }
1828
- function Kt(e) {
1829
- return Array.from(
1830
- new Set(
1831
- e.map((t) => t.trim()).filter(Boolean)
1832
- )
1833
- );
1834
- }
1835
- async function js(e) {
1836
- const t = Kt(e);
1837
- if (t.length === 0)
1838
- return { success: !1, error: "Select at least one product." };
1839
- const n = Ne(), { error: s } = await n.from("products").delete().in("id", t);
1840
- return s ? { success: !1, error: s.message } : (w("/cms/products"), { success: !0, count: t.length });
1841
- }
1842
- async function qs(e) {
1843
- const t = Kt(e);
1844
- if (t.length === 0)
1845
- return { success: !1, error: "Select at least one product." };
1846
- const n = Ne(), { error: s } = await n.from("products").update({
1847
- status: "draft",
1848
- updated_at: (/* @__PURE__ */ new Date()).toISOString()
1849
- }).in("id", t);
1850
- return s ? { success: !1, error: s.message } : (w("/cms/products"), { success: !0, count: t.length });
1851
- }
1852
- async function Os(e) {
1853
- const t = Y(), n = e.name.trim(), s = Oe(e.slug?.trim() || e.name);
1854
- if (!n || !s)
1855
- return { success: !1, error: "Attribute name is required." };
1856
- const { error: i } = await t.from("product_attributes").insert({
1857
- name: n,
1858
- slug: s
1859
- });
1860
- return i ? { success: !1, error: i.message } : (w("/cms/products/attributes"), w("/cms/products/new"), w("/cms/products"), { success: !0 });
1861
- }
1862
- async function Es(e) {
1863
- const t = Y(), { error: n } = await t.from("product_attributes").delete().eq("id", e);
1864
- return n ? { success: !1, error: n.message } : (w("/cms/products/attributes"), w("/cms/products/new"), w("/cms/products"), { success: !0 });
1865
- }
1866
- async function Rs(e) {
1867
- const t = Y(), n = e.value.trim(), s = Oe(e.slug?.trim() || e.value);
1868
- if (!n || !s)
1869
- return { success: !1, error: "Term value is required." };
1870
- const { data: i } = await t.from("product_attribute_terms").select("sort_order").eq("attribute_id", e.attributeId).order("sort_order", { ascending: !1 }).limit(1), c = typeof i?.[0]?.sort_order == "number" ? i[0].sort_order + 1 : 0, { error: l } = await t.from("product_attribute_terms").insert({
1871
- attribute_id: e.attributeId,
1872
- value: n,
1873
- slug: s,
1874
- sort_order: c
1875
- });
1876
- return l ? { success: !1, error: l.message } : (w("/cms/products/attributes"), w("/cms/products/new"), w("/cms/products"), { success: !0 });
1877
- }
1878
- async function Vs(e) {
1879
- const t = Y();
1880
- for (const [n, s] of e.orderedTermIds.entries()) {
1881
- const { error: i } = await t.from("product_attribute_terms").update({
1882
- sort_order: n,
1883
- updated_at: (/* @__PURE__ */ new Date()).toISOString()
1884
- }).eq("id", s).eq("attribute_id", e.attributeId);
1885
- if (i)
1886
- return { success: !1, error: i.message };
1887
- }
1888
- return w("/cms/products/attributes"), w("/cms/products/new"), w("/cms/products"), { success: !0 };
1889
- }
1890
- async function zs(e) {
1891
- const t = Y(), { error: n } = await t.from("product_attributes").update({
1892
- name_translations: e.nameTranslations,
1893
- updated_at: (/* @__PURE__ */ new Date()).toISOString()
1894
- }).eq("id", e.attributeId);
1895
- if (n)
1896
- return { success: !1, error: n.message };
1897
- for (const s of e.termTranslations) {
1898
- const { error: i } = await t.from("product_attribute_terms").update({
1899
- value_translations: s.valueTranslations,
1900
- updated_at: (/* @__PURE__ */ new Date()).toISOString()
1901
- }).eq("id", s.termId).eq("attribute_id", e.attributeId);
1902
- if (i)
1903
- return { success: !1, error: i.message };
1904
- }
1905
- return w("/cms/products/attributes"), w("/cms/products/new"), w("/cms/products"), { success: !0 };
1906
- }
1907
- async function Us(e) {
1908
- const t = Y(), { error: n } = await t.from("product_attribute_terms").delete().eq("id", e);
1909
- return n ? { success: !1, error: n.message } : (w("/cms/products/attributes"), w("/cms/products/new"), w("/cms/products"), { success: !0 });
1910
- }
1911
- async function Xr(e) {
1912
- const t = Y(), n = e.name.trim(), s = Oe(e.slug?.trim() || e.name);
1913
- if (!n || !s)
1914
- return { success: !1, error: "Category name is required." };
1915
- const { data: i, error: c } = await t.from("categories").insert({
1916
- name: n,
1917
- slug: s,
1918
- description: e.description?.trim() || null,
1919
- name_translations: e.nameTranslations || {},
1920
- description_translations: e.descriptionTranslations || {}
1921
- }).select().single();
1922
- return c ? { success: !1, error: c.message } : (w("/cms/products/categories"), w("/cms/products/new"), w("/cms/products"), { success: !0, category: i });
1923
- }
1924
- async function Ls(e, t) {
1925
- const n = Y(), s = t.name.trim(), i = Oe(t.slug?.trim() || t.name);
1926
- if (!s || !i)
1927
- return { success: !1, error: "Category name is required." };
1928
- const { error: c } = await n.from("categories").update({
1929
- name: s,
1930
- slug: i,
1931
- description: t.description?.trim() || null,
1932
- name_translations: t.nameTranslations || {},
1933
- description_translations: t.descriptionTranslations || {}
1934
- }).eq("id", e);
1935
- return c ? { success: !1, error: c.message } : (w("/cms/products/categories"), w("/cms/products/new"), w("/cms/products"), { success: !0 });
1936
- }
1937
- async function Bs(e) {
1938
- const t = Y(), { error: n } = await t.from("categories").delete().eq("id", e);
1939
- return n ? { success: !1, error: n.message } : (w("/cms/products/categories"), w("/cms/products/new"), w("/cms/products"), { success: !0 });
1940
- }
1941
- async function Ks(e, t) {
1942
- const n = Y();
1943
- try {
1944
- return await kr(n, e, t), w("/cms/products"), w(`/cms/products/${e}/edit`), { success: !0 };
1945
- } catch (s) {
1946
- return { success: !1, error: s.message };
1947
- }
1948
- }
1949
- function Yr({
1950
- categories: e = [],
1951
- selectedIds: t = [],
1952
- onChange: n,
1953
- placeholder: s = "Select categories..."
1954
- }) {
1955
- const [i, c] = U(!1), [l, o] = U(""), [x, b] = U(e), [S, $] = U(!1);
1956
- Q(() => {
1957
- b(e);
1958
- }, [e]);
1959
- const y = he(() => x.filter((p) => t.includes(p.id)), [x, t]), _ = he(() => {
1960
- if (!l) return x;
1961
- const p = l.toLowerCase();
1962
- return x.filter(
1963
- (A) => A.name.toLowerCase().includes(p) || A.slug.toLowerCase().includes(p)
1964
- );
1965
- }, [x, l]), f = l.trim(), N = he(() => {
1966
- if (!f) return !1;
1967
- const p = f.toLowerCase();
1968
- return !x.some((A) => A.name.toLowerCase() === p);
1969
- }, [x, f]), M = async () => {
1970
- if (f) {
1971
- $(!0);
1972
- try {
1973
- const p = await Xr({ name: f });
1974
- if (p.success && p.category) {
1975
- const A = {
1976
- id: p.category.id,
1977
- name: p.category.name,
1978
- slug: p.category.slug
1979
- };
1980
- b((X) => [...X, A]), n([...t, A.id]), o(""), oe.success(`Category "${A.name}" created successfully.`);
1981
- } else
1982
- oe.error(p.error || "Failed to create category.");
1983
- } catch (p) {
1984
- oe.error(p.message || "An error occurred while creating category.");
1985
- } finally {
1986
- $(!1);
1987
- }
1988
- }
1989
- }, H = (p) => {
1990
- const A = t.includes(p) ? t.filter((X) => X !== p) : [...t, p];
1991
- n(A);
1992
- }, P = (p, A) => {
1993
- A.stopPropagation(), n(t.filter((X) => X !== p));
1994
- };
1995
- return /* @__PURE__ */ a("div", { className: "space-y-2", children: [
1996
- /* @__PURE__ */ r("div", { className: "flex flex-wrap gap-1.5 min-h-[32px] p-1 border rounded-md bg-background focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2", children: y.length === 0 ? /* @__PURE__ */ r("span", { className: "text-xs text-muted-foreground self-center px-2 py-1 select-none", children: "No categories selected." }) : y.map((p) => /* @__PURE__ */ a(
1997
- ie,
1998
- {
1999
- variant: "secondary",
2000
- className: "pl-2 pr-1.5 py-0.5 text-xs flex items-center gap-1 bg-amber-500/10 text-amber-800 dark:text-amber-300 border border-amber-500/20 rounded-full",
2001
- children: [
2002
- p.name,
2003
- /* @__PURE__ */ r(
2004
- "button",
2005
- {
2006
- type: "button",
2007
- onClick: (A) => P(p.id, A),
2008
- className: "rounded-full p-0.5 text-muted-foreground hover:bg-amber-500/20 hover:text-amber-950 dark:hover:text-amber-50 transition-colors cursor-pointer",
2009
- "aria-label": `Remove ${p.name}`,
2010
- children: /* @__PURE__ */ r(Dt, { className: "h-3 w-3" })
2011
- }
2012
- )
2013
- ]
2014
- },
2015
- p.id
2016
- )) }),
2017
- /* @__PURE__ */ a(mr, { open: i, onOpenChange: c, children: [
2018
- /* @__PURE__ */ r(pr, { asChild: !0, children: /* @__PURE__ */ a(
2019
- ce,
2020
- {
2021
- variant: "outline",
2022
- role: "combobox",
2023
- "aria-expanded": i,
2024
- className: "w-full justify-between h-8 text-xs font-normal",
2025
- children: [
2026
- /* @__PURE__ */ r("span", { className: "truncate", children: t.length > 0 ? `${t.length} categor${t.length === 1 ? "y" : "ies"} selected` : s }),
2027
- /* @__PURE__ */ r(ar, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })
2028
- ]
2029
- }
2030
- ) }),
2031
- /* @__PURE__ */ a(fr, { className: "w-[--radix-popover-trigger-width] p-0", align: "start", children: [
2032
- /* @__PURE__ */ a("div", { className: "flex items-center border-b px-3", children: [
2033
- /* @__PURE__ */ r(ir, { className: "mr-2 h-4 w-4 shrink-0 opacity-50" }),
2034
- /* @__PURE__ */ r(
2035
- j,
2036
- {
2037
- className: "flex h-9 w-full rounded-md bg-transparent py-2 text-xs outline-none border-0 focus-visible:ring-0 focus-visible:ring-offset-0",
2038
- placeholder: "Search categories...",
2039
- value: l,
2040
- onChange: (p) => o(p.target.value)
2041
- }
2042
- )
2043
- ] }),
2044
- N && /* @__PURE__ */ r("div", { className: "border-b border-border/50 p-1", children: /* @__PURE__ */ a(
2045
- ce,
2046
- {
2047
- type: "button",
2048
- variant: "ghost",
2049
- size: "sm",
2050
- className: "w-full justify-start text-xs h-8 text-amber-600 dark:text-amber-400 hover:text-amber-700 hover:bg-amber-500/10 cursor-pointer",
2051
- onClick: M,
2052
- disabled: S,
2053
- children: [
2054
- S ? /* @__PURE__ */ r(or, { className: "mr-2 h-3 w-3 animate-spin" }) : /* @__PURE__ */ r("span", { className: "font-bold mr-1.5", children: "+" }),
2055
- 'Create category "',
2056
- f,
2057
- '"'
2058
- ]
2059
- }
2060
- ) }),
2061
- /* @__PURE__ */ r("div", { className: "max-h-60 overflow-y-auto p-1", children: _.length === 0 ? /* @__PURE__ */ r("p", { className: "py-4 text-center text-xs text-muted-foreground", children: "No categories found." }) : /* @__PURE__ */ r("div", { className: "flex flex-col gap-0.5", children: _.map((p) => {
2062
- const A = t.includes(p.id);
2063
- return /* @__PURE__ */ a(
2064
- "div",
2065
- {
2066
- onClick: () => H(p.id),
2067
- className: Ye(
2068
- "relative flex w-full cursor-pointer select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-xs outline-none hover:bg-accent hover:text-accent-foreground text-left transition-colors",
2069
- A && "bg-accent/40 font-medium"
2070
- ),
2071
- children: [
2072
- /* @__PURE__ */ r("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center pointer-events-none", children: /* @__PURE__ */ r(
2073
- gr,
2074
- {
2075
- checked: A,
2076
- tabIndex: -1,
2077
- "aria-label": `Toggle ${p.name}`,
2078
- className: "h-3.5 w-3.5"
2079
- }
2080
- ) }),
2081
- /* @__PURE__ */ a("span", { className: "flex flex-col", children: [
2082
- /* @__PURE__ */ r("span", { children: p.name }),
2083
- /* @__PURE__ */ a("span", { className: "font-mono text-[9px] text-muted-foreground leading-none", children: [
2084
- "/",
2085
- p.slug
2086
- ] })
2087
- ] }),
2088
- A && /* @__PURE__ */ r("span", { className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ r(cr, { className: "h-3.5 w-3.5 text-primary" }) })
2089
- ]
2090
- },
2091
- p.id
2092
- );
2093
- }) }) })
2094
- ] })
2095
- ] })
2096
- ] });
2097
- }
2098
- function Ae({ title: e, description: t, action: n, children: s, hideHeader: i }) {
2099
- return /* @__PURE__ */ a("section", { className: "rounded-lg border bg-card p-3 shadow-sm space-y-3", children: [
2100
- !i && /* @__PURE__ */ a("div", { className: "flex items-start justify-between gap-4 flex-wrap border-b border-muted/50 pb-2 mb-1", children: [
2101
- /* @__PURE__ */ a("div", { className: "space-y-0.5", children: [
2102
- /* @__PURE__ */ r("h2", { className: "text-sm font-bold tracking-tight", children: e }),
2103
- t ? /* @__PURE__ */ r("p", { className: "text-[11px] text-muted-foreground leading-none", children: t }) : null
2104
- ] }),
2105
- n
2106
- ] }),
2107
- /* @__PURE__ */ r("div", { className: i ? "" : "pt-1", children: s })
2108
- ] });
2109
- }
2110
- function Zr(e, t, n) {
2111
- const s = t ? Number.parseInt(t, 10) : void 0;
2112
- return e?.language_id || (Number.isFinite(s) ? s : void 0) || n.find((i) => i.is_default)?.id || n[0]?.id || 1;
2113
- }
2114
- function $t(e, t, n, s, i) {
2115
- const l = (s.find((y) => y.is_default) ?? s[0])?.code || "USD", o = e?.prices && Object.keys(e.prices).length > 0 ? e.prices : {
2116
- [l]: typeof e?.price == "number" ? e.price / 100 : 0
2117
- }, x = e?.sale_prices && Object.keys(e.sale_prices).length > 0 ? e.sale_prices : typeof e?.sale_price == "number" ? {
2118
- [l]: e.sale_price / 100
2119
- } : {}, b = e?.product_type || "", S = e?.payment_provider || (e?.product_type ? Ir(e.product_type) : "stripe");
2120
- return {
2121
- ...qe({
2122
- product_type: b || "physical",
2123
- payment_provider: S,
2124
- title: e?.title || "",
2125
- slug: e?.slug || "",
2126
- sku: e?.sku || "",
2127
- upc: e?.upc || "",
2128
- is_taxable: e?.is_taxable ?? !0,
2129
- price: typeof e?.price == "number" ? e.price / 100 : 0,
2130
- prices: o,
2131
- sale_price: typeof e?.sale_price == "number" ? e.sale_price / 100 : null,
2132
- sale_prices: x,
2133
- stock: e?.stock || 0,
2134
- meta_title: e?.meta_title || "",
2135
- meta_description: e?.meta_description || "",
2136
- short_description: e?.short_description || "",
2137
- description_json: e?.description_json || {
2138
- type: "doc",
2139
- content: [{ type: "paragraph" }]
2140
- },
2141
- freemius_product_id: e?.freemius_product_id || "",
2142
- freemius_plan_id: e?.freemius_plan_id || "",
2143
- trial_period_days: e?.trial_period_days ?? 0,
2144
- trial_requires_payment_method: e?.trial_requires_payment_method ?? !1,
2145
- status: e?.status || "draft",
2146
- language_id: Zr(
2147
- e,
2148
- t,
2149
- n
2150
- ),
2151
- translation_group_id: e?.translation_group_id || i || void 0,
2152
- product_media: e?.product_media?.map((y) => ({
2153
- media_id: y.media_id
2154
- })) || [],
2155
- category_ids: e?.category_ids || [],
2156
- variation_attributes: e?.variation_attributes || [],
2157
- variants: e?.variants?.map((y) => ({
2158
- ...y,
2159
- prices: y.prices || {},
2160
- sale_prices: y.sale_prices || {}
2161
- })) || []
2162
- }, s),
2163
- product_type: b,
2164
- payment_provider: S
2165
- };
2166
- }
2167
- function Mt(e) {
2168
- return e ? e.map((t) => ({
2169
- id: t.id || t.media_id,
2170
- media_id: t.media_id,
2171
- file_path: t.media?.file_path || t.media?.object_key || "",
2172
- alt: t.media?.alt_text || "",
2173
- sort_order: t.sort_order ?? 0
2174
- })).sort((t, n) => t.sort_order - n.sort_order) : [];
2175
- }
2176
- function Wr(e) {
2177
- return e.map((t) => ({ media_id: t.media_id }));
2178
- }
2179
- function es(e) {
2180
- return e.map((t) => ({
2181
- media_id: t.media_id,
2182
- file_path: t.file_path,
2183
- alt: t.alt
2184
- }));
2185
- }
2186
- const ts = (e) => e.toString().toLowerCase().trim().replace(/\s+/g, "-").replace(/[^\w-]+/g, "").replace(/--+/g, "-").replace(/^-+/, "").replace(/-+$/, "");
2187
- function Js({
2188
- initialData: e,
2189
- isEdit: t = !1,
2190
- mediaPickerNode: n,
2191
- availableLanguagesProp: s,
2192
- globalAttributesProp: i,
2193
- currenciesProp: c,
2194
- translationGroupId: l,
2195
- targetLanguageId: o,
2196
- freemiusDashboardNode: x,
2197
- enabledProviders: b,
2198
- configStatus: S,
2199
- createAction: $,
2200
- updateAction: y,
2201
- availableCategoriesProp: _ = []
2202
- }) {
2203
- const [f, N] = U(!1), [M, H] = U(() => !!e?.variants?.length), P = pe.useMemo(
2204
- () => c.filter((m) => m.is_active !== !1).sort((m, k) => m.is_default !== k.is_default ? m.is_default ? -1 : 1 : m.code.localeCompare(k.code)),
2205
- [c]
2206
- ), p = pe.useMemo(
2207
- () => P.find((m) => m.is_default) ?? P[0],
2208
- [P]
2209
- ), A = pe.useMemo(
2210
- () => at(P),
2211
- [P]
2212
- ), X = _r({
2213
- resolver: ur(qr),
2214
- defaultValues: $t(
2215
- e,
2216
- o,
2217
- s,
2218
- P,
2219
- l
2220
- )
2221
- }), {
2222
- register: D,
2223
- handleSubmit: le,
2224
- setValue: v,
2225
- reset: we,
2226
- watch: F,
2227
- setError: d,
2228
- formState: { errors: g, dirtyFields: h }
2229
- } = X, C = Fe(!0), I = Fe(null), [L, V] = U(!1), [B, O] = U(null), [ue, Jt] = U(null), Ee = F(), ot = X.formState.isDirty;
2230
- Q(() => {
2231
- if (!t) return;
2232
- if (C.current) {
2233
- C.current = !1, I.current = JSON.stringify(Ee);
2234
- return;
2235
- }
2236
- if (!ot) return;
2237
- const m = JSON.stringify(Ee);
2238
- if (m === I.current) return;
2239
- const k = setTimeout(() => {
2240
- f || (I.current = m, le(ht)());
2241
- }, 1e3);
2242
- return () => clearTimeout(k);
2243
- }, [Ee, t, ot, f, le]);
2244
- const ct = F("title"), ge = F("product_type"), z = ge === "digital" ? "freemius" : ge === "physical" ? "stripe" : void 0, Z = ge === "physical", dt = ge === "digital", Re = z ? b[z] : !1, Ve = z ? S[z].hasKeys : !1, Gt = !!F("freemius_product_id"), lt = Number(F("trial_period_days") || 0), ut = !!F("trial_requires_payment_method"), Ht = F("variants") || [], ne = F("price"), me = F("sale_price"), W = F("prices") || {}, ae = F("sale_prices") || {}, ee = (Ht?.length || 0) > 0, Qt = F("language_id"), Xt = s.find((m) => m.id === Qt)?.code || s.find((m) => m.is_default)?.code || s[0]?.code, Se = pe.useMemo(
2245
- () => Lt({
2246
- currencies: P,
2247
- prices: W,
2248
- salePrices: ae,
2249
- fallbackPrice: ne,
2250
- fallbackSalePrice: me
2251
- }),
2252
- [ne, me, P, W, ae]
2253
- ), Yt = pe.useMemo(
2254
- () => e?.variants?.map((m) => ({
2255
- ...m,
2256
- prices: m.prices || {},
2257
- sale_prices: m.sale_prices || {}
2258
- })),
2259
- [e?.variants]
2260
- );
2261
- Q(() => {
2262
- if (h.title && !t) {
2263
- const m = ts(ct);
2264
- v("slug", m, { shouldValidate: !0 });
2265
- }
2266
- }, [ct, h.title, v, t]);
2267
- const [ze, mt] = U(
2268
- () => Mt(e?.product_media)
2269
- ), [Ue, pt] = U(/* @__PURE__ */ new Set());
2270
- Q(() => {
2271
- we(
2272
- $t(
2273
- e,
2274
- o,
2275
- s,
2276
- P,
2277
- l
2278
- )
2279
- ), mt(Mt(e?.product_media)), pt(/* @__PURE__ */ new Set()), H(!!e?.variants?.length);
2280
- }, [
2281
- s,
2282
- P,
2283
- e,
2284
- we,
2285
- o,
2286
- l
2287
- ]);
2288
- const Zt = (m) => {
2289
- const k = new Set(m.map((R) => R.id)), E = ze.filter((R) => !k.has(R.id)), K = new Set(Ue);
2290
- E.forEach((R) => {
2291
- R.media_id && K.add(R.media_id);
2292
- }), pt(K), mt(m), v("product_media", Wr(m), { shouldDirty: !0 }), v("explicitly_removed_media_ids", Array.from(K), {
2293
- shouldDirty: !0
2294
- });
2295
- };
2296
- Q(() => {
2297
- v("explicitly_removed_media_ids", Array.from(Ue));
2298
- }, [Ue, v]), Q(() => {
2299
- ee && H(!0);
2300
- }, [ee]), Q(() => {
2301
- D("is_taxable"), D("price"), D("sale_price"), D("payment_provider"), D("trial_requires_payment_method");
2302
- }, [D]), Q(() => {
2303
- if (!dt) {
2304
- v("trial_period_days", 0, { shouldDirty: !1, shouldValidate: !0 }), v("trial_requires_payment_method", !1, {
2305
- shouldDirty: !1,
2306
- shouldValidate: !0
2307
- });
2308
- return;
2309
- }
2310
- lt <= 0 && v("trial_requires_payment_method", !1, {
2311
- shouldDirty: !1,
2312
- shouldValidate: !0
2313
- });
2314
- }, [dt, v, lt]), Q(() => {
2315
- z && v("payment_provider", z, {
2316
- shouldDirty: !1,
2317
- shouldValidate: !0
2318
- });
2319
- }, [z, v]), Q(() => {
2320
- p && W[p.code] === void 0 && v(
2321
- "prices",
2322
- {
2323
- ...W,
2324
- [p.code]: ne || 0
2325
- },
2326
- { shouldDirty: !1 }
2327
- );
2328
- }, [ne, p, W, v]);
2329
- const ft = Ce(
2330
- (m, k) => {
2331
- const E = {
2332
- ...W,
2333
- [m]: k
2334
- };
2335
- v("prices", E, { shouldDirty: !0, shouldValidate: !0 }), m === p?.code && v("price", k, { shouldDirty: !0, shouldValidate: !0 });
2336
- },
2337
- [p?.code, W, v]
2338
- ), gt = Ce(
2339
- (m, k) => {
2340
- const E = {
2341
- ...ae,
2342
- [m]: k
2343
- };
2344
- v("sale_prices", E, {
2345
- shouldDirty: !0,
2346
- shouldValidate: !0
2347
- }), m === p?.code && v("sale_price", k, { shouldDirty: !0, shouldValidate: !0 });
2348
- },
2349
- [p?.code, ae, v]
2350
- ), _t = Ce(() => {
2351
- if (!p)
2352
- return;
2353
- const m = new Set(A), k = W[p.code] ?? ne ?? 0, E = ae[p.code] ?? me ?? null, K = P.reduce((te, J) => {
2354
- if (J.code !== p.code && m.has(J.code))
2355
- return te;
2356
- const Le = ye({
2357
- amount: ve(k, p.code),
2358
- fromCurrencyCode: p.code,
2359
- toCurrencyCode: J.code,
2360
- currencies: P,
2361
- applyRounding: !0
2362
- });
2363
- return te[J.code] = fe(Le, J.code), te;
2364
- }, {}), R = P.reduce(
2365
- (te, J) => {
2366
- if (J.code !== p.code && m.has(J.code))
2367
- return te;
2368
- if (typeof E != "number")
2369
- return (J.code === p.code || !m.has(J.code)) && (te[J.code] = null), te;
2370
- const Le = ye({
2371
- amount: ve(E, p.code),
2372
- fromCurrencyCode: p.code,
2373
- toCurrencyCode: J.code,
2374
- currencies: P,
2375
- applyRounding: !0
2376
- });
2377
- return te[J.code] = fe(Le, J.code), te;
2378
- },
2379
- {}
2380
- );
2381
- v("prices", K, { shouldDirty: !0, shouldValidate: !0 }), v("sale_prices", R, {
2382
- shouldDirty: !0,
2383
- shouldValidate: !0
2384
- }), v("price", K[p.code] ?? k, {
2385
- shouldDirty: !0,
2386
- shouldValidate: !0
2387
- }), v("sale_price", R[p.code] ?? null, {
2388
- shouldDirty: !0,
2389
- shouldValidate: !0
2390
- });
2391
- }, [
2392
- P,
2393
- p,
2394
- W,
2395
- ae,
2396
- v,
2397
- A,
2398
- ne,
2399
- me
2400
- ]), Wt = Ce(
2401
- ({
2402
- variationAttributes: m,
2403
- variants: k
2404
- }) => {
2405
- v("variation_attributes", m, { shouldDirty: !0 }), v("variants", k, { shouldDirty: !0, shouldValidate: !0 });
2406
- },
2407
- [v]
2408
- ), ht = async (m) => {
2409
- N(!0), V(!0), O(null);
2410
- try {
2411
- if (!z) {
2412
- const R = "Select whether this product is physical or digital before saving.";
2413
- d("product_type", {
2414
- type: "manual",
2415
- message: R
2416
- }), t ? O(R) : alert(R), N(!1), V(!1);
2417
- return;
2418
- }
2419
- if (m.status === "active" && (!Re || !Ve)) {
2420
- const R = `${z === "stripe" ? "Stripe" : "Freemius"} must be enabled and fully configured before this product can be published.`;
2421
- d("product_type", {
2422
- type: "manual",
2423
- message: R
2424
- }), t ? O(R) : alert(R), N(!1), V(!1);
2425
- return;
2426
- }
2427
- const k = Z ? 0 : Math.max(0, Number(m.trial_period_days || 0)), E = {
2428
- ...m,
2429
- product_type: m.product_type,
2430
- payment_provider: z,
2431
- freemius_product_id: Z ? "" : m.freemius_product_id,
2432
- freemius_plan_id: Z ? "" : m.freemius_plan_id,
2433
- trial_period_days: k,
2434
- trial_requires_payment_method: !Z && k > 0 ? m.trial_requires_payment_method : !1,
2435
- upc: Z ? m.upc : null,
2436
- is_taxable: Z ? m.is_taxable : !1,
2437
- variation_attributes: Z ? m.variation_attributes : [],
2438
- variants: Z ? m.variants : []
2439
- }, K = qe(
2440
- E,
2441
- P
2442
- );
2443
- if (t && y)
2444
- await y(K), Jt(/* @__PURE__ */ new Date());
2445
- else if ($)
2446
- await $(K);
2447
- else
2448
- throw new Error("Product form action is not configured.");
2449
- } catch (k) {
2450
- if (console.error(k), k.message === "NEXT_REDIRECT")
2451
- return;
2452
- let E = k.message || "An error occurred while saving.";
2453
- if (k.code === "23505") {
2454
- const K = k.message?.toLowerCase() || "";
2455
- K.includes("products_slug_key") || K.includes("slug") ? (E = "This slug is already in use. Please choose another one.", d("slug", {
2456
- type: "manual",
2457
- message: E
2458
- })) : (K.includes("products_sku_key") || K.includes("sku")) && (E = "This SKU is already in use.", d("sku", {
2459
- type: "manual",
2460
- message: E
2461
- }));
2462
- }
2463
- t ? O(E) : alert(E);
2464
- } finally {
2465
- N(!1), V(!1);
2466
- }
2467
- }, er = ee ? "bg-muted/60 text-muted-foreground opacity-70" : "", tr = es(ze);
2468
- return /* @__PURE__ */ a("form", { onSubmit: le(ht), className: "space-y-2.5 pb-4", children: [
2469
- /* @__PURE__ */ r("input", { type: "hidden", ...D("translation_group_id") }),
2470
- /* @__PURE__ */ r("input", { type: "hidden", ...D("payment_provider") }),
2471
- /* @__PURE__ */ a("div", { className: "space-y-2.5 w-full", children: [
2472
- /* @__PURE__ */ a("div", { className: "rounded-lg border bg-card p-2.5 px-4 shadow-sm flex items-center justify-between gap-3 flex-wrap", children: [
2473
- /* @__PURE__ */ a("div", { className: "flex items-center gap-6", children: [
2474
- /* @__PURE__ */ a("div", { className: "flex h-9 items-center gap-2", children: [
2475
- /* @__PURE__ */ r("span", { className: "text-sm font-bold whitespace-nowrap leading-none pt-0.5", children: "Product Type" }),
2476
- g.product_type && /* @__PURE__ */ r(xt, { className: "h-4 w-4 text-destructive" })
2477
- ] }),
2478
- /* @__PURE__ */ r("div", { className: "flex h-9 items-center", children: /* @__PURE__ */ a(
2479
- Ke,
2480
- {
2481
- onValueChange: (m) => v("product_type", m, {
2482
- shouldDirty: !0,
2483
- shouldValidate: !0
2484
- }),
2485
- value: ge || void 0,
2486
- children: [
2487
- /* @__PURE__ */ r(Je, { className: "w-[160px] h-9 text-xs", children: /* @__PURE__ */ r(Ge, { placeholder: "Select Type" }) }),
2488
- /* @__PURE__ */ a(He, { children: [
2489
- /* @__PURE__ */ r(re, { value: "physical", children: "Physical Product" }),
2490
- /* @__PURE__ */ r(re, { value: "digital", children: "Digital Product" })
2491
- ] })
2492
- ]
2493
- }
2494
- ) })
2495
- ] }),
2496
- /* @__PURE__ */ a("div", { className: "flex items-center gap-6", children: [
2497
- /* @__PURE__ */ a("div", { className: "flex h-9 items-center gap-3", children: [
2498
- /* @__PURE__ */ r("span", { className: "text-[11px] font-semibold text-muted-foreground uppercase tracking-wider leading-none", children: "Payment Provider" }),
2499
- /* @__PURE__ */ r(ie, { variant: "outline", className: "text-xs py-1 font-bold bg-muted/30 leading-none", children: z ? z === "stripe" ? "Stripe" : "Freemius" : "—" })
2500
- ] }),
2501
- z && /* @__PURE__ */ r("div", { className: "flex h-9 items-center gap-2", children: Re && Ve ? /* @__PURE__ */ a("span", { className: "flex items-center gap-1.5 text-emerald-600 text-[10px] font-bold bg-emerald-50 px-2 py-1 rounded-full border border-emerald-100 uppercase leading-none", children: [
2502
- /* @__PURE__ */ r(dr, { className: "h-3 w-3" }),
2503
- "Ready"
2504
- ] }) : /* @__PURE__ */ a("span", { className: "flex items-center gap-1.5 text-amber-600 text-[10px] font-bold bg-amber-50 px-2 py-1 rounded-full border border-amber-100 uppercase leading-none", children: [
2505
- /* @__PURE__ */ r(xt, { className: "h-3 w-3" }),
2506
- Re ? "Keys Missing" : "Disabled"
2507
- ] }) }),
2508
- !Ve && z && S[z].missing.length > 0 && /* @__PURE__ */ a("div", { className: "hidden xl:flex h-9 items-center gap-1 text-[10px] text-muted-foreground bg-muted/50 px-2 py-1 rounded border border-dashed leading-none", children: [
2509
- /* @__PURE__ */ r(lr, { className: "h-3 w-3" }),
2510
- "Missing: ",
2511
- S[z].missing.join(", ")
2512
- ] })
2513
- ] })
2514
- ] }),
2515
- /* @__PURE__ */ a(
2516
- Ae,
2517
- {
2518
- title: "Product Information",
2519
- hideHeader: !0,
2520
- children: [
2521
- t && /* @__PURE__ */ a("div", { className: "flex items-center justify-between text-xs text-muted-foreground pb-2 border-b border-border/40 mb-2.5", children: [
2522
- /* @__PURE__ */ r("span", { className: "font-semibold text-[11px] uppercase tracking-wider text-muted-foreground/80", children: "Product Settings" }),
2523
- /* @__PURE__ */ r("div", { className: "flex items-center gap-1.5 min-h-[16px]", children: L ? /* @__PURE__ */ a(xe, { children: [
2524
- /* @__PURE__ */ a("div", { className: "relative flex h-2 w-2", children: [
2525
- /* @__PURE__ */ r("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-amber-400 opacity-75" }),
2526
- /* @__PURE__ */ r("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-amber-500" })
2527
- ] }),
2528
- /* @__PURE__ */ r("span", { className: "text-amber-600 dark:text-amber-400 font-medium", children: "Autosaving settings..." })
2529
- ] }) : B ? /* @__PURE__ */ a("span", { className: "text-red-500 font-medium", children: [
2530
- "Error saving settings: ",
2531
- B
2532
- ] }) : ue ? /* @__PURE__ */ a("span", { className: "text-emerald-600 dark:text-emerald-400 font-medium", children: [
2533
- "Settings autosaved at ",
2534
- ue.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" })
2535
- ] }) : /* @__PURE__ */ r("span", { className: "text-muted-foreground/60", children: "Settings autosave in draft mode" }) })
2536
- ] }),
2537
- /* @__PURE__ */ a("div", { className: "grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-2.5", children: [
2538
- /* @__PURE__ */ a("div", { className: "col-span-2 space-y-1", children: [
2539
- /* @__PURE__ */ r(q, { htmlFor: "title", className: "text-xs uppercase font-bold text-muted-foreground tracking-wider leading-none", children: "Title" }),
2540
- /* @__PURE__ */ r(j, { id: "title", placeholder: "Product title", ...D("title"), className: "h-8 text-sm" }),
2541
- g.title && /* @__PURE__ */ r("p", { className: "text-destructive text-[11px] leading-none", children: g.title.message })
2542
- ] }),
2543
- /* @__PURE__ */ a("div", { className: "col-span-2 space-y-1", children: [
2544
- /* @__PURE__ */ r(q, { htmlFor: "slug", className: "text-xs uppercase font-bold text-muted-foreground tracking-wider leading-none", children: "Slug" }),
2545
- /* @__PURE__ */ r(j, { id: "slug", placeholder: "product-slug", ...D("slug"), className: "h-8 text-sm" }),
2546
- g.slug && /* @__PURE__ */ r("p", { className: "text-destructive text-[11px] leading-none", children: g.slug.message })
2547
- ] }),
2548
- /* @__PURE__ */ a("div", { className: "col-span-1 space-y-1", children: [
2549
- /* @__PURE__ */ r(q, { htmlFor: "sku", className: "text-xs uppercase font-bold text-muted-foreground tracking-wider leading-none", children: "SKU" }),
2550
- /* @__PURE__ */ r(j, { id: "sku", placeholder: "SKU", ...D("sku"), className: "h-8 text-sm font-mono" }),
2551
- g.sku && /* @__PURE__ */ r("p", { className: "text-destructive text-[11px] leading-none", children: g.sku.message })
2552
- ] }),
2553
- /* @__PURE__ */ a("div", { className: "col-span-1 space-y-1", children: [
2554
- /* @__PURE__ */ r(q, { htmlFor: "upc_ean", className: "text-xs uppercase font-bold text-muted-foreground tracking-wider leading-none", children: "UPC / EAN" }),
2555
- /* @__PURE__ */ r(j, { id: "upc_ean", placeholder: "000000000", ...D("upc"), className: "h-8 text-sm font-mono", readOnly: ee })
2556
- ] })
2557
- ] }),
2558
- /* @__PURE__ */ a("div", { className: "grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-2.5 mt-2", children: [
2559
- /* @__PURE__ */ a("div", { className: "lg:col-span-2 col-span-2 space-y-1", children: [
2560
- /* @__PURE__ */ r(q, { htmlFor: "meta_title", className: "text-xs uppercase font-bold text-muted-foreground tracking-wider leading-none", children: "Meta Title" }),
2561
- /* @__PURE__ */ r(j, { id: "meta_title", ...D("meta_title"), placeholder: "SEO page title (50-60 chars)", className: "h-8 text-sm" })
2562
- ] }),
2563
- /* @__PURE__ */ a("div", { className: `lg:col-span-${t ? "3" : "4"} col-span-2 space-y-1`, children: [
2564
- /* @__PURE__ */ r(q, { htmlFor: "meta_description", className: "text-xs uppercase font-bold text-muted-foreground tracking-wider leading-none", children: "Meta Description" }),
2565
- /* @__PURE__ */ r(j, { id: "meta_description", ...D("meta_description"), placeholder: "SEO description (150-160 chars)", className: "h-8 text-sm" })
2566
- ] }),
2567
- t && /* @__PURE__ */ a("div", { className: "lg:col-span-1 col-span-2 space-y-1", children: [
2568
- /* @__PURE__ */ r(q, { htmlFor: "status", className: "text-xs uppercase font-bold text-muted-foreground tracking-wider leading-none", children: "Status" }),
2569
- /* @__PURE__ */ a(Ke, { onValueChange: (m) => v("status", m, { shouldDirty: !0 }), value: F("status"), children: [
2570
- /* @__PURE__ */ r(Je, { className: "h-8 text-xs", children: /* @__PURE__ */ r(Ge, { placeholder: "Status" }) }),
2571
- /* @__PURE__ */ a(He, { children: [
2572
- /* @__PURE__ */ r(re, { value: "draft", children: "Draft" }),
2573
- /* @__PURE__ */ r(re, { value: "active", children: "Active" }),
2574
- /* @__PURE__ */ r(re, { value: "archived", children: "Archived" })
2575
- ] })
2576
- ] })
2577
- ] })
2578
- ] })
2579
- ]
2580
- }
2581
- ),
2582
- /* @__PURE__ */ r(
2583
- Ae,
2584
- {
2585
- title: "Product Categories",
2586
- description: "Assign this product to one or more categories.",
2587
- children: /* @__PURE__ */ r(
2588
- Yr,
2589
- {
2590
- categories: _,
2591
- selectedIds: F("category_ids") || [],
2592
- onChange: (m) => v("category_ids", m, { shouldDirty: !0, shouldValidate: !0 })
2593
- }
2594
- )
2595
- }
2596
- ),
2597
- /* @__PURE__ */ a("section", { className: "rounded-lg border bg-card p-3 shadow-sm space-y-3", children: [
2598
- Z && /* @__PURE__ */ a("div", { className: "flex items-center justify-between gap-4 flex-wrap border-b border-muted/50 pb-2", children: [
2599
- /* @__PURE__ */ r("div", { className: "flex items-center gap-4", children: /* @__PURE__ */ a("div", { className: "space-y-0.5", children: [
2600
- /* @__PURE__ */ r("h2", { className: "text-sm font-bold tracking-tight", children: "Pricing & Inventory" }),
2601
- /* @__PURE__ */ r("p", { className: "text-[11px] text-muted-foreground leading-none", children: "Manage simple or variant pricing." })
2602
- ] }) }),
2603
- /* @__PURE__ */ a("div", { className: "flex items-center gap-3", children: [
2604
- /* @__PURE__ */ a("div", { className: "flex items-center gap-2 bg-muted/40 rounded-md px-2.5 py-1.5", children: [
2605
- /* @__PURE__ */ r("span", { className: "text-xs uppercase font-bold text-muted-foreground tracking-wider leading-none", children: "Stock" }),
2606
- /* @__PURE__ */ r(
2607
- j,
2608
- {
2609
- id: "stock",
2610
- type: "number",
2611
- min: "0",
2612
- ...D("stock", { valueAsNumber: !0 }),
2613
- placeholder: "0",
2614
- readOnly: ee,
2615
- className: `${er} h-8 w-20 text-sm text-center font-mono bg-background`
2616
- }
2617
- )
2618
- ] }),
2619
- ee ? /* @__PURE__ */ r(ie, { variant: "secondary", className: "text-[11px] py-0 px-2 h-5", children: "Variant pricing" }) : null
2620
- ] })
2621
- ] }),
2622
- Z ? /* @__PURE__ */ a("div", { className: "space-y-3", children: [
2623
- /* @__PURE__ */ a("div", { className: "w-full", children: [
2624
- /* @__PURE__ */ r(
2625
- We,
2626
- {
2627
- idPrefix: "product",
2628
- currencies: P,
2629
- prices: Se.prices,
2630
- salePrices: Se.salePrices,
2631
- managedCurrencyCodes: A,
2632
- onPriceChange: ft,
2633
- onSalePriceChange: gt,
2634
- onAutoFill: _t,
2635
- readOnly: ee,
2636
- helperText: ee ? "Parent prices stay as a fallback, but active variants define the live shopper price." : void 0,
2637
- trailing: /* @__PURE__ */ r(
2638
- et,
2639
- {
2640
- idPrefix: "product",
2641
- startAt: F("sale_start_at"),
2642
- endAt: F("sale_end_at"),
2643
- onChange: (m, k) => v(m, k, { shouldDirty: !0, shouldValidate: !0 }),
2644
- error: g.sale_end_at?.message,
2645
- bare: !0
2646
- }
2647
- )
2648
- }
2649
- ),
2650
- g.price && /* @__PURE__ */ r("p", { className: "text-destructive text-sm mt-1", children: g.price.message }),
2651
- g.sale_price && /* @__PURE__ */ r("p", { className: "text-destructive text-sm mt-1", children: g.sale_price.message }),
2652
- g.stock && /* @__PURE__ */ r("p", { className: "text-destructive text-[10px] font-medium leading-none mt-1", children: g.stock.message })
2653
- ] }),
2654
- /* @__PURE__ */ a("div", { className: "flex items-center justify-between gap-3 rounded border border-dashed p-2.5 bg-muted/5", children: [
2655
- /* @__PURE__ */ r("span", { className: "text-xs font-bold uppercase tracking-wider text-muted-foreground", children: ee ? "Variations Active" : "Variations" }),
2656
- /* @__PURE__ */ r(
2657
- ce,
2658
- {
2659
- type: "button",
2660
- variant: M ? "outline" : "default",
2661
- onClick: () => H((m) => !m),
2662
- size: "sm",
2663
- className: "h-7 text-xs px-3",
2664
- children: M ? "Hide" : "Manage"
2665
- }
2666
- )
2667
- ] }),
2668
- M && /* @__PURE__ */ r("div", { className: "border-t pt-3", children: /* @__PURE__ */ r(
2669
- Ur,
2670
- {
2671
- globalAttributes: i,
2672
- currentLanguageCode: Xt,
2673
- baseSku: F("sku") || "",
2674
- basePrice: ne || 0,
2675
- basePrices: W,
2676
- baseSalePrice: typeof me == "number" ? me : null,
2677
- baseSalePrices: ae,
2678
- currencies: P,
2679
- availableVariantImages: tr,
2680
- initialVariationAttributes: e?.variation_attributes,
2681
- initialVariants: Yt,
2682
- onChange: Wt
2683
- }
2684
- ) })
2685
- ] }) : /* @__PURE__ */ a(xe, { children: [
2686
- /* @__PURE__ */ a("div", { className: "space-y-4", children: [
2687
- /* @__PURE__ */ a("div", { className: "flex items-end gap-4 w-full", children: [
2688
- /* @__PURE__ */ a("div", { className: "flex-1", children: [
2689
- /* @__PURE__ */ r(q, { htmlFor: "freemius_product_id", className: "text-[11px] uppercase tracking-wider text-muted-foreground font-bold mb-1.5 block", children: "Freemius Product ID" }),
2690
- /* @__PURE__ */ r(j, { id: "freemius_product_id", ...D("freemius_product_id"), className: "h-9" })
2691
- ] }),
2692
- /* @__PURE__ */ a("div", { className: "flex-1", children: [
2693
- /* @__PURE__ */ r(q, { htmlFor: "freemius_plan_id", className: "text-[11px] uppercase tracking-wider text-muted-foreground font-bold mb-1.5 block", children: "Freemius Plan ID" }),
2694
- /* @__PURE__ */ r(j, { id: "freemius_plan_id", ...D("freemius_plan_id"), className: "h-9" })
2695
- ] }),
2696
- Gt ? /* @__PURE__ */ r(Er, { productId: F("freemius_product_id") }) : null
2697
- ] }),
2698
- /* @__PURE__ */ a("div", { className: "bg-muted/10 border rounded-md overflow-hidden", children: [
2699
- /* @__PURE__ */ a("div", { className: "flex flex-wrap items-center gap-6 bg-muted/20 border-b p-2.5 px-4", children: [
2700
- /* @__PURE__ */ a("div", { className: "flex items-center gap-2", children: [
2701
- /* @__PURE__ */ r("span", { className: "text-[11px] font-bold uppercase tracking-wider text-muted-foreground", children: "Free Trial" }),
2702
- /* @__PURE__ */ a(ie, { variant: "outline", className: "font-mono text-xs shadow-sm bg-background", children: [
2703
- String(F("trial_period_days") || 0),
2704
- " Days"
2705
- ] })
2706
- ] }),
2707
- /* @__PURE__ */ a("div", { className: "flex items-center gap-2", children: [
2708
- /* @__PURE__ */ r("span", { className: "text-[11px] font-bold uppercase tracking-wider text-muted-foreground", children: "Card Required" }),
2709
- /* @__PURE__ */ r(ie, { variant: ut ? "default" : "secondary", className: "text-xs shadow-sm", children: ut ? "Yes" : "No" })
2710
- ] }),
2711
- /* @__PURE__ */ r("span", { className: "text-[10px] text-muted-foreground ml-auto", children: "Managed in Freemius dashboard" }),
2712
- /* @__PURE__ */ r("input", { type: "hidden", ...D("trial_period_days", { valueAsNumber: !0 }) })
2713
- ] }),
2714
- /* @__PURE__ */ a("div", { className: "w-full p-4 pt-3 space-y-2", children: [
2715
- /* @__PURE__ */ r(
2716
- We,
2717
- {
2718
- idPrefix: "product",
2719
- currencies: P,
2720
- prices: Se.prices,
2721
- salePrices: Se.salePrices,
2722
- managedCurrencyCodes: A,
2723
- onPriceChange: ft,
2724
- onSalePriceChange: gt,
2725
- onAutoFill: _t,
2726
- readOnly: !0,
2727
- trailing: /* @__PURE__ */ r(
2728
- et,
2729
- {
2730
- idPrefix: "product",
2731
- startAt: F("sale_start_at"),
2732
- endAt: F("sale_end_at"),
2733
- onChange: (m, k) => v(m, k, { shouldDirty: !0, shouldValidate: !0 }),
2734
- error: g.sale_end_at?.message,
2735
- bare: !0
2736
- }
2737
- )
2738
- }
2739
- ),
2740
- /* @__PURE__ */ r("p", { className: "text-[10px] leading-snug text-muted-foreground", children: "Scheduling a sale on a Freemius product generates a time-bounded Freemius coupon so the discount is enforced at Freemius checkout." })
2741
- ] })
2742
- ] })
2743
- ] }),
2744
- x && /* @__PURE__ */ r("div", { className: "pt-2 border-t", children: x })
2745
- ] })
2746
- ] }),
2747
- /* @__PURE__ */ r(Ae, { title: "Product Description", hideHeader: !0, children: /* @__PURE__ */ r("div", { className: "space-y-2", children: /* @__PURE__ */ a("div", { className: "space-y-1", children: [
2748
- /* @__PURE__ */ r(q, { htmlFor: "short_description", className: "text-xs uppercase font-bold text-muted-foreground tracking-wider leading-none", children: "Short Description" }),
2749
- /* @__PURE__ */ r(j, { id: "short_description", ...D("short_description"), placeholder: "Brief summary for product cards...", className: "h-8 text-sm" })
2750
- ] }) }) }),
2751
- /* @__PURE__ */ a(Ae, { title: "Media Gallery", description: "Drag to reorder. First image is the hero.", children: [
2752
- /* @__PURE__ */ r(
2753
- Or,
2754
- {
2755
- initialMedia: ze,
2756
- onUpdate: Zt,
2757
- mediaPickerNode: n
2758
- }
2759
- ),
2760
- /* @__PURE__ */ r("input", { type: "hidden", ...D("product_media") })
2761
- ] }),
2762
- !t && /* @__PURE__ */ a("div", { className: "rounded-lg border bg-card p-3 px-4 shadow-sm flex items-center justify-between gap-3 flex-wrap", children: [
2763
- /* @__PURE__ */ a("div", { className: "flex items-center gap-2", children: [
2764
- /* @__PURE__ */ r("span", { className: "text-xs uppercase font-bold text-muted-foreground tracking-wider leading-none", children: "Status" }),
2765
- /* @__PURE__ */ a(Ke, { onValueChange: (m) => v("status", m), value: F("status"), children: [
2766
- /* @__PURE__ */ r(Je, { className: "h-8 w-[110px] text-sm", children: /* @__PURE__ */ r(Ge, { placeholder: "Status" }) }),
2767
- /* @__PURE__ */ a(He, { children: [
2768
- /* @__PURE__ */ r(re, { value: "draft", children: "Draft" }),
2769
- /* @__PURE__ */ r(re, { value: "active", children: "Active" }),
2770
- /* @__PURE__ */ r(re, { value: "archived", children: "Archived" })
2771
- ] })
2772
- ] })
2773
- ] }),
2774
- /* @__PURE__ */ r(ce, { disabled: f, type: "submit", size: "sm", className: "h-8 text-sm px-5", children: f ? "Saving..." : "Save Changes" })
2775
- ] })
2776
- ] })
2777
- ] });
2778
- }
2779
- function T(e, t, n) {
2780
- const s = e(t);
2781
- return s === t ? n : s;
2782
- }
2783
- function Gs(e) {
2784
- return {
2785
- invoice: T(e, "invoice", "Invoice"),
2786
- invoiceNumber: T(e, "invoice_number", "Invoice #"),
2787
- orderNumber: T(e, "order_number", "Order #"),
2788
- paidOn: T(e, "paid_on", "Paid on"),
2789
- status: T(e, "status", "Status"),
2790
- from: T(e, "from", "From"),
2791
- billTo: T(e, "bill_to", "Bill to"),
2792
- shipTo: T(e, "ship_to", "Ship to"),
2793
- item: T(e, "product", "Item"),
2794
- details: T(e, "details", "Details"),
2795
- quantity: T(e, "ecommerce.qty", "Qty"),
2796
- price: T(e, "price", "Price"),
2797
- amount: T(e, "amount", "Amount"),
2798
- subtotal: T(e, "ecommerce.subtotal", "Subtotal"),
2799
- discount: T(e, "ecommerce.discount", "Discount"),
2800
- shipping: T(e, "ecommerce.shipping", "Shipping"),
2801
- tax: T(e, "ecommerce.tax", "Tax"),
2802
- total: T(e, "ecommerce.total", "Total"),
2803
- taxBreakdown: T(e, "tax_breakdown", "Tax breakdown"),
2804
- taxRegistrations: T(
2805
- e,
2806
- "tax_registrations",
2807
- "Tax registrations"
2808
- )
2809
- };
2810
- }
2811
- function Hs(e) {
2812
- return e === "fr" ? "fr-CA" : "en-US";
2813
- }
2814
- function rs(e, t) {
2815
- if (!e)
2816
- return "";
2817
- switch (e.toLowerCase()) {
2818
- case "paid":
2819
- return T(t, "order_status_paid", "Paid");
2820
- case "pending":
2821
- return T(t, "order_status_pending", "Pending");
2822
- case "trial":
2823
- return T(t, "order_status_trial", "Trial");
2824
- case "shipped":
2825
- return T(t, "order_status_shipped", "Shipped");
2826
- case "cancelled":
2827
- return T(t, "order_status_cancelled", "Cancelled");
2828
- case "refunded":
2829
- return T(t, "order_status_refunded", "Refunded");
2830
- default:
2831
- return e;
2832
- }
2833
- }
2834
- function Qs(e, t) {
2835
- return e ? {
2836
- ...e,
2837
- order: {
2838
- ...e.order,
2839
- status: rs(e.order.status, t)
2840
- }
2841
- } : null;
2842
- }
2843
- export {
2844
- Us as A,
2845
- Rs as B,
2846
- Es as C,
2847
- qt as D,
2848
- Os as E,
2849
- $s as F,
2850
- Ms as G,
2851
- Bs as H,
2852
- ws as I,
2853
- Ls as J,
2854
- Xr as K,
2855
- As as L,
2856
- Fs as M,
2857
- Ks as N,
2858
- Qr as O,
2859
- Yr as P,
2860
- Fr as a,
2861
- Ts as b,
2862
- Js as c,
2863
- Rt as d,
2864
- Gs as e,
2865
- Ps as f,
2866
- Is as g,
2867
- se as h,
2868
- Tr as i,
2869
- Qe as j,
2870
- Hs as k,
2871
- Ze as l,
2872
- $e as m,
2873
- Me as n,
2874
- Qs as o,
2875
- Ss as p,
2876
- ks as q,
2877
- qr as r,
2878
- Cs as s,
2879
- T as t,
2880
- rs as u,
2881
- qs as v,
2882
- js as w,
2883
- Ds as x,
2884
- zs as y,
2885
- Vs as z
2886
- };