@nextblock-cms/ecom 0.8.1 → 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 (241) hide show
  1. package/index.cjs.js +1 -1
  2. package/index.es.js +136 -3224
  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/lib/cart-store.es.js +116 -0
  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/lib/components/AddToCartButton.es.js +60 -0
  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/lib/components/CartDrawer.es.js +119 -0
  15. package/lib/components/CartIcon.cjs.js +1 -0
  16. package/lib/components/CartIcon.es.js +34 -0
  17. package/lib/components/Checkout.cjs.js +1 -0
  18. package/lib/components/Checkout.es.js +987 -0
  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/lib/components/CurrencySwitcher.es.js +18 -0
  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/lib/components/FeaturedProduct.es.js +72 -0
  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/SimpleTiptapRenderer.cjs.js +1 -0
  42. package/lib/components/SimpleTiptapRenderer.es.js +187 -0
  43. package/lib/components/SubscriptionSelector.cjs.js +1 -0
  44. package/lib/components/SubscriptionSelector.es.js +140 -0
  45. package/lib/countries.cjs.js +1 -0
  46. package/lib/countries.es.js +77 -0
  47. package/lib/coupon-server.cjs.js +1 -0
  48. package/lib/coupon-server.es.js +234 -0
  49. package/lib/coupons.cjs.js +1 -0
  50. package/lib/coupons.es.js +17 -0
  51. package/lib/currency-constants.cjs.js +1 -0
  52. package/lib/currency-constants.es.js +4 -0
  53. package/lib/currency-store.cjs.js +1 -0
  54. package/lib/currency-store.es.js +27 -0
  55. package/lib/currency-sync.cjs.js +1 -0
  56. package/lib/currency-sync.es.js +180 -0
  57. package/lib/currency.cjs.js +1 -0
  58. package/lib/currency.es.js +312 -0
  59. package/lib/customer-addresses.cjs.js +1 -0
  60. package/lib/customer-addresses.es.js +116 -0
  61. package/lib/customer-orders.cjs.js +1 -0
  62. package/lib/customer-orders.es.js +45 -0
  63. package/lib/customer.cjs.js +1 -0
  64. package/lib/customer.es.js +58 -0
  65. package/lib/export-helpers.cjs.js +1 -0
  66. package/lib/export-helpers.es.js +56 -0
  67. package/lib/factory.cjs.js +1 -0
  68. package/lib/factory.es.js +8 -0
  69. package/lib/freemius-coupons.cjs.js +1 -0
  70. package/lib/freemius-coupons.es.js +272 -0
  71. package/lib/freemius-order-sync.cjs.js +1 -0
  72. package/lib/freemius-order-sync.es.js +284 -0
  73. package/lib/inventory-settings.cjs.js +1 -0
  74. package/lib/inventory-settings.es.js +86 -0
  75. package/lib/invoice-server.cjs.js +33 -0
  76. package/lib/invoice-server.es.js +141 -0
  77. package/lib/invoice-ui.cjs.js +1 -0
  78. package/lib/invoice-ui.es.js +71 -0
  79. package/lib/invoice.cjs.js +1 -0
  80. package/lib/invoice.es.js +102 -0
  81. package/lib/order-inventory.cjs.js +61 -0
  82. package/lib/order-inventory.es.js +128 -0
  83. package/lib/order-tax-details.cjs.js +1 -0
  84. package/lib/order-tax-details.es.js +164 -0
  85. package/lib/pages/cms/coupons/CouponEditorForm.cjs.js +1 -0
  86. package/lib/pages/cms/coupons/CouponEditorForm.es.js +189 -0
  87. package/lib/pages/cms/coupons/CouponsPage.cjs.js +5 -0
  88. package/lib/pages/cms/coupons/CouponsPage.es.js +171 -0
  89. package/lib/pages/cms/coupons/CreateCouponDialog.cjs.js +1 -0
  90. package/lib/pages/cms/coupons/CreateCouponDialog.es.js +35 -0
  91. package/lib/pages/cms/coupons/EditCouponPage.cjs.js +1 -0
  92. package/lib/pages/cms/coupons/EditCouponPage.es.js +48 -0
  93. package/lib/pages/cms/coupons/ProductScopePicker.cjs.js +1 -0
  94. package/lib/pages/cms/coupons/ProductScopePicker.es.js +120 -0
  95. package/lib/pages/cms/coupons/actions.cjs.js +1 -0
  96. package/lib/pages/cms/coupons/actions.es.js +128 -0
  97. package/lib/pages/cms/coupons/product-options.cjs.js +1 -0
  98. package/lib/pages/cms/coupons/product-options.es.js +27 -0
  99. package/lib/pages/cms/orders/ExportReportsDialog.cjs.js +1 -0
  100. package/lib/pages/cms/orders/ExportReportsDialog.es.js +130 -0
  101. package/lib/pages/cms/orders/OrderDetailPage.cjs.js +1 -0
  102. package/lib/pages/cms/orders/OrderDetailPage.es.js +137 -0
  103. package/lib/pages/cms/orders/OrderPrintButton.cjs.js +1 -0
  104. package/lib/pages/cms/orders/OrderPrintButton.es.js +22 -0
  105. package/lib/pages/cms/orders/OrderStatusForm.cjs.js +1 -0
  106. package/lib/pages/cms/orders/OrderStatusForm.es.js +71 -0
  107. package/lib/pages/cms/orders/OrdersPage.cjs.js +1 -0
  108. package/lib/pages/cms/orders/OrdersPage.es.js +104 -0
  109. package/lib/pages/cms/orders/actions.cjs.js +7 -0
  110. package/lib/pages/cms/orders/actions.es.js +71 -0
  111. package/lib/pages/cms/orders/export-actions.cjs.js +1 -0
  112. package/lib/pages/cms/orders/export-actions.es.js +27 -0
  113. package/lib/pages/cms/orders/server-actions.cjs.js +1 -0
  114. package/lib/pages/cms/orders/server-actions.es.js +55 -0
  115. package/lib/pages/cms/payments/PaymentsClient.cjs.js +1 -0
  116. package/lib/pages/cms/payments/PaymentsClient.es.js +188 -0
  117. package/lib/pages/cms/payments/PaymentsPage.cjs.js +1 -0
  118. package/lib/pages/cms/payments/PaymentsPage.es.js +29 -0
  119. package/lib/pages/cms/payments/actions.cjs.js +1 -0
  120. package/lib/pages/cms/payments/actions.es.js +23 -0
  121. package/lib/pages/cms/payments/queries.cjs.js +1 -0
  122. package/lib/pages/cms/payments/queries.es.js +30 -0
  123. package/lib/pages/cms/products/ProductsPage.cjs.js +1 -0
  124. package/lib/pages/cms/products/ProductsPage.es.js +46 -0
  125. package/lib/pages/cms/products/_id_/edit/EditProductPage.cjs.js +1 -0
  126. package/lib/pages/cms/products/_id_/edit/EditProductPage.es.js +156 -0
  127. package/lib/pages/cms/products/actions.cjs.js +44 -0
  128. package/lib/pages/cms/products/actions.es.js +175 -0
  129. package/lib/pages/cms/products/attributes/AttributeManagementPage.cjs.js +1 -0
  130. package/lib/pages/cms/products/attributes/AttributeManagementPage.es.js +48 -0
  131. package/lib/pages/cms/products/attributes/components/AttributeManager.cjs.js +1 -0
  132. package/lib/pages/cms/products/attributes/components/AttributeManager.es.js +291 -0
  133. package/lib/pages/cms/products/categories/CategoryManagementPage.cjs.js +1 -0
  134. package/lib/pages/cms/products/categories/CategoryManagementPage.es.js +36 -0
  135. package/lib/pages/cms/products/categories/components/CategoryManager.cjs.js +1 -0
  136. package/lib/pages/cms/products/categories/components/CategoryManager.es.js +263 -0
  137. package/lib/pages/cms/products/components/CopyProductFromLanguage.cjs.js +1 -0
  138. package/lib/pages/cms/products/components/CopyProductFromLanguage.es.js +114 -0
  139. package/lib/pages/cms/products/components/CurrencyPriceFields.cjs.js +1 -0
  140. package/lib/pages/cms/products/components/CurrencyPriceFields.es.js +107 -0
  141. package/lib/pages/cms/products/components/DeleteProductButton.cjs.js +1 -0
  142. package/lib/pages/cms/products/components/DeleteProductButton.es.js +48 -0
  143. package/lib/pages/cms/products/components/FreemiusPricingDashboard.cjs.js +1 -0
  144. package/lib/pages/cms/products/components/FreemiusPricingDashboard.es.js +86 -0
  145. package/lib/pages/cms/products/components/ProductCategorySelector.cjs.js +1 -0
  146. package/lib/pages/cms/products/components/ProductCategorySelector.es.js +160 -0
  147. package/lib/pages/cms/products/components/ProductForm.cjs.js +1 -0
  148. package/lib/pages/cms/products/components/ProductForm.es.js +702 -0
  149. package/lib/pages/cms/products/components/ProductMediaManager.cjs.js +1 -0
  150. package/lib/pages/cms/products/components/ProductMediaManager.es.js +104 -0
  151. package/lib/pages/cms/products/components/ProductsBulkTable.cjs.js +1 -0
  152. package/lib/pages/cms/products/components/ProductsBulkTable.es.js +228 -0
  153. package/lib/pages/cms/products/components/SaleScheduleFields.cjs.js +1 -0
  154. package/lib/pages/cms/products/components/SaleScheduleFields.es.js +137 -0
  155. package/lib/pages/cms/products/components/SyncFreemiusButton.cjs.js +1 -0
  156. package/lib/pages/cms/products/components/SyncFreemiusButton.es.js +36 -0
  157. package/lib/pages/cms/products/components/SyncFreemiusPricingButton.cjs.js +1 -0
  158. package/lib/pages/cms/products/components/SyncFreemiusPricingButton.es.js +40 -0
  159. package/lib/pages/cms/products/components/VariationsEditor.cjs.js +1 -0
  160. package/lib/pages/cms/products/components/VariationsEditor.es.js +408 -0
  161. package/lib/pages/cms/products/inventory/InventoryPage.cjs.js +1 -0
  162. package/lib/pages/cms/products/inventory/InventoryPage.es.js +16 -0
  163. package/lib/pages/cms/products/inventory/InventoryTableClient.cjs.js +2 -0
  164. package/lib/pages/cms/products/inventory/InventoryTableClient.es.js +214 -0
  165. package/lib/pages/cms/products/inventory/actions.cjs.js +3 -0
  166. package/lib/pages/cms/products/inventory/actions.es.js +95 -0
  167. package/lib/pages/cms/products/new/NewProductPage.cjs.js +1 -0
  168. package/lib/pages/cms/products/new/NewProductPage.es.js +76 -0
  169. package/lib/pages/cms/products/product-price-sync.cjs.js +1 -0
  170. package/lib/pages/cms/products/product-price-sync.es.js +98 -0
  171. package/lib/pages/cms/products/server-actions.cjs.js +1 -0
  172. package/lib/pages/cms/products/server-actions.es.js +193 -0
  173. package/lib/pages/cms/shipping/ShippingPage.cjs.js +5 -0
  174. package/lib/pages/cms/shipping/ShippingPage.es.js +211 -0
  175. package/lib/pages/cms/shipping/components/RateForm.cjs.js +1 -0
  176. package/lib/pages/cms/shipping/components/RateForm.es.js +441 -0
  177. package/lib/pages/cms/shipping/components/ZoneForm.cjs.js +1 -0
  178. package/lib/pages/cms/shipping/components/ZoneForm.es.js +228 -0
  179. package/lib/pages/cms/shipping/server-actions.cjs.js +1 -0
  180. package/lib/pages/cms/shipping/server-actions.es.js +159 -0
  181. package/lib/pages/cms/taxes/TaxesPage.cjs.js +1 -0
  182. package/lib/pages/cms/taxes/TaxesPage.es.js +172 -0
  183. package/lib/pages/cms/taxes/actions.cjs.js +1 -0
  184. package/lib/pages/cms/taxes/actions.es.js +57 -0
  185. package/lib/pages/cms/taxes/components/TaxRateForm.cjs.js +1 -0
  186. package/lib/pages/cms/taxes/components/TaxRateForm.es.js +100 -0
  187. package/lib/product-actions.cjs.js +237 -0
  188. package/lib/product-actions.es.js +524 -0
  189. package/lib/product-context.cjs.js +1 -0
  190. package/lib/product-context.es.js +16 -0
  191. package/lib/product-schema.cjs.js +1 -0
  192. package/lib/product-schema.es.js +134 -0
  193. package/lib/providers/freemius.cjs.js +5 -0
  194. package/lib/providers/freemius.es.js +538 -0
  195. package/lib/providers/stripe.cjs.js +1 -0
  196. package/lib/providers/stripe.es.js +473 -0
  197. package/lib/server-actions/coupon-actions.cjs.js +1 -0
  198. package/lib/server-actions/coupon-actions.es.js +23 -0
  199. package/lib/server-actions/customer-actions.cjs.js +1 -0
  200. package/lib/server-actions/customer-actions.es.js +30 -0
  201. package/lib/server-actions/product-actions.cjs.js +1 -0
  202. package/lib/server-actions/product-actions.es.js +16 -0
  203. package/lib/server-actions/shipping-actions.cjs.js +1 -0
  204. package/lib/server-actions/shipping-actions.es.js +27 -0
  205. package/lib/server-actions/tax-actions.cjs.js +1 -0
  206. package/lib/server-actions/tax-actions.es.js +40 -0
  207. package/lib/shared-inventory.cjs.js +15 -0
  208. package/lib/shared-inventory.es.js +171 -0
  209. package/lib/shipping/resolver.cjs.js +7 -0
  210. package/lib/shipping/resolver.es.js +62 -0
  211. package/lib/shipping-rate-currency.cjs.js +1 -0
  212. package/lib/shipping-rate-currency.es.js +72 -0
  213. package/lib/states.cjs.js +1 -0
  214. package/lib/states.es.js +127 -0
  215. package/lib/stripe/checkout.cjs.js +1 -0
  216. package/lib/stripe/checkout.es.js +182 -0
  217. package/lib/stripe/client.cjs.js +1 -0
  218. package/lib/stripe/client.es.js +7 -0
  219. package/lib/stripe/order-sync.cjs.js +1 -0
  220. package/lib/stripe/order-sync.es.js +130 -0
  221. package/lib/stripe/webhooks.cjs.js +1 -0
  222. package/lib/stripe/webhooks.es.js +30 -0
  223. package/lib/tax-calculation.cjs.js +1 -0
  224. package/lib/tax-calculation.es.js +101 -0
  225. package/lib/trials.cjs.js +1 -0
  226. package/lib/trials.es.js +29 -0
  227. package/lib/types.cjs.js +1 -0
  228. package/lib/types.es.js +33 -0
  229. package/lib/use-cart.cjs.js +1 -0
  230. package/lib/use-cart.es.js +44 -0
  231. package/lib/variation-utils.cjs.js +1 -0
  232. package/lib/variation-utils.es.js +246 -0
  233. package/lib/zod-config.cjs.js +1 -0
  234. package/lib/zod-config.es.js +6 -0
  235. package/package.json +10 -5
  236. package/server.cjs.js +1 -110
  237. package/server.es.js +178 -6037
  238. package/invoice-ui-BJZfedDd.cjs +0 -332
  239. package/invoice-ui-GJ1ADAjn.js +0 -5759
  240. /package/{currency-rest-client-uolJxUkL.cjs → lib/currency-rest-client.cjs.js} +0 -0
  241. /package/{currency-rest-client-CwoqdgAP.js → lib/currency-rest-client.es.js} +0 -0
@@ -0,0 +1,408 @@
1
+ 'use client';
2
+ import { jsxs as i, jsx as o } from "react/jsx-runtime";
3
+ import F from "next/link";
4
+ import { useState as R, useMemo as E, useEffect as v } from "react";
5
+ import { Badge as D, Button as z, Label as P, Input as U } from "@nextblock-cms/ui";
6
+ import { extractSelectedTermsByAttribute as re, resolveTermValue as L, resolveAttributeName as q, generateVariantDrafts as ne } from "../../../../variation-utils.es.js";
7
+ import { CurrencyPriceFields as oe } from "./CurrencyPriceFields.es.js";
8
+ import { SaleScheduleFields as se } from "./SaleScheduleFields.es.js";
9
+ import { normalizeSalePriceMap as ie, normalizePriceMap as de, convertMinorUnitAmount as I } from "../../../../currency.es.js";
10
+ import { sanitizeVariantDraftsForStoreManagedCurrencies as K, getStoreManagedPriceCurrencyCodes as ce, resolveEditorCurrencyPriceMaps as le } from "../product-price-sync.es.js";
11
+ import { majorUnitAmountToMinor as X, minorUnitAmountToMajor as G } from "@nextblock-cms/utils";
12
+ const O = process.env.NEXT_PUBLIC_R2_BASE_URL || "", Q = process.env.NEXT_PUBLIC_SUPABASE_URL || "", ae = (c) => c.startsWith("http") ? c : O ? `${O.replace(/\/+$/, "")}/${c.replace(/^\/+/, "")}` : Q ? `${Q.replace(/\/+$/, "")}/storage/v1/object/public/media/${c.replace(/^\/+/, "")}` : c;
13
+ function W(c, m = "USD") {
14
+ return new Intl.NumberFormat("en-US", {
15
+ style: "currency",
16
+ currency: m
17
+ }).format(c);
18
+ }
19
+ function me(c) {
20
+ return Object.entries(c).filter(([, m]) => m.length > 0).map(([m, _]) => ({ attribute_id: m, term_ids: _ }));
21
+ }
22
+ function Ne({
23
+ globalAttributes: c,
24
+ currentLanguageCode: m,
25
+ baseSku: _,
26
+ basePrice: $,
27
+ basePrices: M,
28
+ baseSalePrice: w,
29
+ baseSalePrices: A,
30
+ currencies: d,
31
+ availableVariantImages: x = [],
32
+ initialVariationAttributes: b,
33
+ initialVariants: T,
34
+ onChange: B
35
+ }) {
36
+ const [g, H] = R(() => b && b.length > 0 ? b.reduce((e, r) => (e[r.attribute_id] = r.term_ids, e), {}) : re(T || [])), [h, f] = R(
37
+ K(
38
+ T || [],
39
+ d
40
+ )
41
+ ), y = E(
42
+ () => c.map((e) => ({
43
+ attribute_id: e.id,
44
+ attribute_name: q(e, m),
45
+ terms: e.terms.filter((r) => (g[e.id] || []).includes(r.id)).map((r) => ({
46
+ ...r,
47
+ value: L(r, m)
48
+ }))
49
+ })).filter((e) => e.terms.length > 0),
50
+ [m, c, g]
51
+ );
52
+ v(() => {
53
+ if (y.length === 0) {
54
+ f([]);
55
+ return;
56
+ }
57
+ f(
58
+ (e) => K(
59
+ ne({
60
+ baseSku: _,
61
+ basePrice: $,
62
+ basePrices: de(M),
63
+ baseSalePrice: w,
64
+ baseSalePrices: ie(A),
65
+ selectedAttributes: y,
66
+ previousVariants: e
67
+ }),
68
+ d
69
+ )
70
+ );
71
+ }, [$, M, w, A, _, d, y]), v(() => {
72
+ B({
73
+ variationAttributes: me(g),
74
+ variants: h
75
+ });
76
+ }, [B, g, h]);
77
+ const J = h.reduce(
78
+ (e, r) => e + (r.stock_quantity || 0),
79
+ 0
80
+ ), k = d.find((e) => e.is_default) ?? d[0], N = E(
81
+ () => ce(d),
82
+ [d]
83
+ ), Y = (e, r) => {
84
+ H((t) => {
85
+ const n = new Set(t[e] || []);
86
+ return n.has(r) ? n.delete(r) : n.add(r), {
87
+ ...t,
88
+ [e]: [...n]
89
+ };
90
+ });
91
+ }, C = (e, r, t) => {
92
+ f(
93
+ (n) => n.map((s) => {
94
+ if (s.combination_key !== e)
95
+ return s;
96
+ if (r === "sku")
97
+ return {
98
+ ...s,
99
+ sku: t
100
+ };
101
+ if (r === "upc")
102
+ return {
103
+ ...s,
104
+ upc: t
105
+ };
106
+ if (r === "sale_price" && t === "")
107
+ return {
108
+ ...s,
109
+ sale_price: null
110
+ };
111
+ if (r === "prices" || r === "sale_prices")
112
+ return s;
113
+ const l = t === "" ? 0 : Number(t);
114
+ return {
115
+ ...s,
116
+ [r]: Number.isFinite(l) ? l : 0
117
+ };
118
+ })
119
+ );
120
+ }, Z = (e, r, t) => {
121
+ f(
122
+ (n) => n.map(
123
+ (s) => s.combination_key === e ? { ...s, [r]: t } : s
124
+ )
125
+ );
126
+ }, V = (e, r, t, n) => {
127
+ const s = d.find((l) => l.is_default) ?? d[0];
128
+ f(
129
+ (l) => l.map((p) => {
130
+ if (p.combination_key !== e)
131
+ return p;
132
+ const u = {
133
+ ...t === "prices" ? p.prices : p.sale_prices,
134
+ [r]: n
135
+ };
136
+ return {
137
+ ...p,
138
+ [t]: u,
139
+ ...r === s?.code ? t === "prices" ? { price: n ?? 0 } : { sale_price: n } : {}
140
+ };
141
+ })
142
+ );
143
+ }, ee = (e) => {
144
+ const r = d.find((n) => n.is_default) ?? d[0], t = new Set(N);
145
+ r && f(
146
+ (n) => n.map((s) => {
147
+ if (s.combination_key !== e)
148
+ return s;
149
+ const l = d.reduce((u, a) => {
150
+ if (a.code !== r.code && t.has(a.code))
151
+ return u;
152
+ const S = I({
153
+ amount: X(s.price, r.code),
154
+ fromCurrencyCode: r.code,
155
+ toCurrencyCode: a.code,
156
+ currencies: d,
157
+ applyRounding: !0
158
+ });
159
+ return u[a.code] = G(S, a.code), u;
160
+ }, {}), p = d.reduce(
161
+ (u, a) => {
162
+ if (a.code !== r.code && t.has(a.code))
163
+ return u;
164
+ if (typeof s.sale_price != "number")
165
+ return u[a.code] = null, u;
166
+ const S = I({
167
+ amount: X(s.sale_price, r.code),
168
+ fromCurrencyCode: r.code,
169
+ toCurrencyCode: a.code,
170
+ currencies: d,
171
+ applyRounding: !0
172
+ });
173
+ return u[a.code] = G(S, a.code), u;
174
+ },
175
+ {}
176
+ );
177
+ return {
178
+ ...s,
179
+ prices: l,
180
+ sale_prices: p
181
+ };
182
+ })
183
+ );
184
+ }, te = (e, r) => {
185
+ const t = x.find((l) => l.media_id === r);
186
+ if (!t)
187
+ return;
188
+ const n = t.file_path, s = ae(n);
189
+ f(
190
+ (l) => l.map(
191
+ (p) => p.combination_key === e ? {
192
+ ...p,
193
+ main_media_id: t.media_id,
194
+ main_image_url: s
195
+ } : p
196
+ )
197
+ );
198
+ }, j = (e) => {
199
+ f(
200
+ (r) => r.map(
201
+ (t) => t.combination_key === e ? {
202
+ ...t,
203
+ main_media_id: null,
204
+ main_image_url: null
205
+ } : t
206
+ )
207
+ );
208
+ };
209
+ return c.length === 0 ? /* @__PURE__ */ i("div", { className: "rounded-lg border border-dashed p-6 text-sm text-muted-foreground", children: [
210
+ "No global attributes have been created yet. Create them first in",
211
+ " ",
212
+ /* @__PURE__ */ o(F, { href: "/cms/products/attributes", className: "font-medium text-primary underline-offset-4 hover:underline", children: "Attribute Management" }),
213
+ "."
214
+ ] }) : /* @__PURE__ */ i("div", { className: "space-y-3", children: [
215
+ /* @__PURE__ */ i("div", { className: "space-y-2", children: [
216
+ /* @__PURE__ */ i("div", { className: "flex items-center justify-between gap-3", children: [
217
+ /* @__PURE__ */ i("div", { className: "flex items-center gap-3", children: [
218
+ /* @__PURE__ */ o("span", { className: "text-xs uppercase font-bold text-muted-foreground tracking-wider leading-none", children: "Attributes" }),
219
+ /* @__PURE__ */ i(D, { variant: "outline", className: "text-[10px] px-1.5 h-4", children: [
220
+ h.length,
221
+ " variants"
222
+ ] }),
223
+ /* @__PURE__ */ i(D, { variant: "secondary", className: "text-[10px] px-1.5 h-4", children: [
224
+ "Stock: ",
225
+ J
226
+ ] })
227
+ ] }),
228
+ /* @__PURE__ */ o(z, { asChild: !0, variant: "outline", size: "sm", className: "h-7 text-xs px-3", children: /* @__PURE__ */ o(F, { href: "/cms/products/attributes", children: "Manage" }) })
229
+ ] }),
230
+ /* @__PURE__ */ o("div", { className: "grid gap-2 lg:grid-cols-2", children: c.map((e) => {
231
+ const r = g[e.id] || [];
232
+ return /* @__PURE__ */ i("div", { className: "flex items-center gap-3 rounded border p-2.5", children: [
233
+ /* @__PURE__ */ i("div", { className: "shrink-0 w-[100px]", children: [
234
+ /* @__PURE__ */ o("span", { className: "text-sm font-bold block leading-tight", children: q(e, m) }),
235
+ /* @__PURE__ */ i("span", { className: "text-[10px] text-muted-foreground leading-none", children: [
236
+ r.length,
237
+ " selected"
238
+ ] })
239
+ ] }),
240
+ /* @__PURE__ */ o("div", { className: "flex flex-wrap gap-1.5 flex-1", children: e.terms.map((t) => {
241
+ const n = r.includes(t.id);
242
+ return /* @__PURE__ */ o(
243
+ "button",
244
+ {
245
+ type: "button",
246
+ onClick: () => Y(e.id, t.id),
247
+ className: `rounded-full border px-2.5 py-0.5 text-[11px] font-medium transition-colors ${n ? "border-primary bg-primary/10 text-primary" : "border-border bg-background text-foreground hover:border-primary/40"}`,
248
+ children: L(t, m)
249
+ },
250
+ t.id
251
+ );
252
+ }) })
253
+ ] }, e.id);
254
+ }) })
255
+ ] }),
256
+ h.length === 0 ? /* @__PURE__ */ o("div", { className: "rounded border border-dashed p-3 text-xs text-muted-foreground text-center", children: "Select terms above to generate variations." }) : /* @__PURE__ */ o("div", { className: "space-y-2", children: h.map((e) => {
257
+ const r = le({
258
+ currencies: d,
259
+ prices: e.prices || {},
260
+ salePrices: e.sale_prices || {},
261
+ fallbackPrice: e.price,
262
+ fallbackSalePrice: e.sale_price
263
+ });
264
+ return /* @__PURE__ */ i("div", { className: "rounded border p-3 space-y-2", children: [
265
+ /* @__PURE__ */ i("div", { className: "flex items-center justify-between gap-3", children: [
266
+ /* @__PURE__ */ i("div", { className: "flex items-center gap-2", children: [
267
+ /* @__PURE__ */ o("span", { className: "text-sm font-bold", children: e.label }),
268
+ /* @__PURE__ */ o("span", { className: "text-xs text-muted-foreground", children: e.selected_options.map((t) => `${t.attribute_name}: ${t.term_value}`).join(" · ") })
269
+ ] }),
270
+ /* @__PURE__ */ i("div", { className: "flex items-center gap-3 text-xs text-muted-foreground", children: [
271
+ /* @__PURE__ */ i("span", { children: [
272
+ "Reg: ",
273
+ W(e.price, k?.code || "USD")
274
+ ] }),
275
+ /* @__PURE__ */ i("span", { children: [
276
+ "Sale:",
277
+ " ",
278
+ e.sale_price !== null && e.sale_price !== void 0 ? W(e.sale_price, k?.code || "USD") : "—"
279
+ ] })
280
+ ] })
281
+ ] }),
282
+ /* @__PURE__ */ i("div", { className: "grid grid-cols-3 gap-2.5", children: [
283
+ /* @__PURE__ */ i("div", { className: "flex items-center gap-2", children: [
284
+ /* @__PURE__ */ o(P, { htmlFor: `variant-sku-${e.combination_key}`, className: "text-xs uppercase font-bold text-muted-foreground tracking-wider shrink-0", children: "SKU" }),
285
+ /* @__PURE__ */ o(
286
+ U,
287
+ {
288
+ id: `variant-sku-${e.combination_key}`,
289
+ value: e.sku,
290
+ onChange: (t) => C(e.combination_key, "sku", t.target.value),
291
+ placeholder: "SKU",
292
+ className: "h-8 text-sm font-mono"
293
+ }
294
+ )
295
+ ] }),
296
+ /* @__PURE__ */ i("div", { className: "flex items-center gap-2", children: [
297
+ /* @__PURE__ */ o(P, { htmlFor: `variant-upc-${e.combination_key}`, className: "text-xs uppercase font-bold text-muted-foreground tracking-wider shrink-0", children: "UPC" }),
298
+ /* @__PURE__ */ o(
299
+ U,
300
+ {
301
+ id: `variant-upc-${e.combination_key}`,
302
+ value: e.upc ?? "",
303
+ onChange: (t) => C(e.combination_key, "upc", t.target.value),
304
+ placeholder: "—",
305
+ className: "h-8 text-sm font-mono"
306
+ }
307
+ )
308
+ ] }),
309
+ /* @__PURE__ */ i("div", { className: "flex items-center gap-2", children: [
310
+ /* @__PURE__ */ o(P, { htmlFor: `variant-stock-${e.combination_key}`, className: "text-xs uppercase font-bold text-muted-foreground tracking-wider shrink-0", children: "Qty" }),
311
+ /* @__PURE__ */ o(
312
+ U,
313
+ {
314
+ id: `variant-stock-${e.combination_key}`,
315
+ type: "number",
316
+ min: "0",
317
+ value: e.stock_quantity,
318
+ onChange: (t) => C(
319
+ e.combination_key,
320
+ "stock_quantity",
321
+ t.target.value
322
+ ),
323
+ className: "h-8 text-sm font-mono w-20"
324
+ }
325
+ )
326
+ ] })
327
+ ] }),
328
+ /* @__PURE__ */ o(
329
+ oe,
330
+ {
331
+ idPrefix: `variant-${e.combination_key}`,
332
+ currencies: d,
333
+ prices: r.prices,
334
+ salePrices: r.salePrices,
335
+ managedCurrencyCodes: N,
336
+ onPriceChange: (t, n) => V(
337
+ e.combination_key,
338
+ t,
339
+ "prices",
340
+ n
341
+ ),
342
+ onSalePriceChange: (t, n) => V(
343
+ e.combination_key,
344
+ t,
345
+ "sale_prices",
346
+ n
347
+ ),
348
+ onAutoFill: () => ee(e.combination_key),
349
+ helperText: N.length > 0 ? `Store-managed currencies derive from ${k?.code || "the base currency"}.` : void 0,
350
+ trailing: /* @__PURE__ */ o(
351
+ se,
352
+ {
353
+ idPrefix: `variant-${e.combination_key}`,
354
+ startAt: e.sale_start_at,
355
+ endAt: e.sale_end_at,
356
+ onChange: (t, n) => Z(e.combination_key, t, n),
357
+ bare: !0
358
+ }
359
+ )
360
+ }
361
+ ),
362
+ /* @__PURE__ */ i("div", { className: "flex items-center gap-3 pt-1.5 border-t border-muted/30", children: [
363
+ e.main_image_url && /* @__PURE__ */ o("div", { className: "h-9 w-9 overflow-hidden rounded border bg-background shrink-0", children: /* @__PURE__ */ o(
364
+ "img",
365
+ {
366
+ src: e.main_image_url,
367
+ alt: `${e.label} image`,
368
+ className: "h-full w-full object-cover"
369
+ }
370
+ ) }),
371
+ /* @__PURE__ */ o("span", { className: "text-xs uppercase font-bold text-muted-foreground tracking-wider shrink-0", children: "Image" }),
372
+ x.length > 0 ? /* @__PURE__ */ i(
373
+ "select",
374
+ {
375
+ className: "flex h-8 rounded-md border border-input bg-background px-2 py-1 text-sm min-w-[180px]",
376
+ value: e.main_media_id ?? "",
377
+ onChange: (t) => {
378
+ if (!t.target.value) {
379
+ j(e.combination_key);
380
+ return;
381
+ }
382
+ te(e.combination_key, t.target.value);
383
+ },
384
+ children: [
385
+ /* @__PURE__ */ o("option", { value: "", children: "Use parent image" }),
386
+ x.map((t, n) => /* @__PURE__ */ o("option", { value: t.media_id, children: t.alt?.trim() || `Gallery image ${n + 1}` }, t.media_id))
387
+ ]
388
+ }
389
+ ) : /* @__PURE__ */ o("span", { className: "text-xs text-muted-foreground", children: "Add gallery images first." }),
390
+ e.main_media_id && /* @__PURE__ */ o(
391
+ z,
392
+ {
393
+ type: "button",
394
+ variant: "ghost",
395
+ size: "sm",
396
+ className: "h-7 text-xs px-2 text-muted-foreground hover:text-destructive",
397
+ onClick: () => j(e.combination_key),
398
+ children: "Remove"
399
+ }
400
+ )
401
+ ] })
402
+ ] }, e.combination_key);
403
+ }) })
404
+ ] });
405
+ }
406
+ export {
407
+ Ne as VariationsEditor
408
+ };
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),n=require("../../../../shared-inventory.cjs.js"),s=require("./InventoryTableClient.cjs.js");async function a(){const t=await n.getInventoryItems();return e.jsxs("div",{className:"p-8 space-y-6",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx("h1",{className:"text-3xl font-bold",children:"Inventory"}),e.jsx("p",{className:"max-w-3xl text-sm text-muted-foreground",children:"Manage source-of-truth stock for every sellable SKU in one place. Matching SKUs share the same quantity across products, translations, and variants, and you can update those shared quantities inline or in bulk through CSV import and export."})]}),e.jsx(s.InventoryTableClient,{initialItems:t})]})}exports.InventoryPage=a;
@@ -0,0 +1,16 @@
1
+ import { jsxs as t, jsx as e } from "react/jsx-runtime";
2
+ import { getInventoryItems as a } from "../../../../shared-inventory.es.js";
3
+ import { InventoryTableClient as r } from "./InventoryTableClient.es.js";
4
+ async function l() {
5
+ const n = await a();
6
+ return /* @__PURE__ */ t("div", { className: "p-8 space-y-6", children: [
7
+ /* @__PURE__ */ t("div", { className: "space-y-2", children: [
8
+ /* @__PURE__ */ e("h1", { className: "text-3xl font-bold", children: "Inventory" }),
9
+ /* @__PURE__ */ e("p", { className: "max-w-3xl text-sm text-muted-foreground", children: "Manage source-of-truth stock for every sellable SKU in one place. Matching SKUs share the same quantity across products, translations, and variants, and you can update those shared quantities inline or in bulk through CSV import and export." })
10
+ ] }),
11
+ /* @__PURE__ */ e(r, { initialItems: n })
12
+ ] });
13
+ }
14
+ export {
15
+ l as InventoryPage
16
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),d=require("react"),t=require("@nextblock-cms/ui"),y=require("lucide-react"),j=require("sonner"),S=require("./actions.cjs.js");function R(o){const i=String(o??"");return/[",\n]/.test(i)?`"${i.replace(/"/g,'""')}"`:i}function K(o){const i=["sku","stock","usage_type","product_titles","languages","statuses","parent_product_skus"],b=o.map(c=>[c.sku,c.stock,c.usageType,c.productTitles.join("|"),c.languages.join("|"),c.statuses.join("|"),c.parentProductSkus.join("|")]);return[i,...b].map(c=>c.map(p=>R(p)).join(",")).join(`
2
+ `)}function B(o){return o.usageType==="mixed"?"Shared SKU":o.usageType==="variant"?`Variant SKU ${o.sku}`:"Simple Product"}function L(o){return o.usageType==="variant"?"secondary":"outline"}function P({initialItems:o}){const[i,b]=d.useState(o),[c,p]=d.useState(()=>o.reduce((s,n)=>(s[n.key]=String(n.stock),s),{})),[k,T]=d.useState(""),[h,f]=d.useTransition(),[w,x]=d.useState(null),v=d.useRef(null),m=d.useMemo(()=>{const s=k.trim().toLowerCase();return s?i.filter(n=>n.sku.toLowerCase().includes(s)||n.productTitles.join(" ").toLowerCase().includes(s)||n.parentProductSkus.join(" ").toLowerCase().includes(s)||n.languages.join(" ").toLowerCase().includes(s)):i},[i,k]),C=()=>{const s=K(i),n=new Blob([s],{type:"text/csv;charset=utf-8;"}),r=URL.createObjectURL(n),l=document.createElement("a");l.href=r,l.download="inventory-export.csv",l.click(),URL.revokeObjectURL(r)},N=s=>{const n=c[s.key]??String(s.stock),r=Number.parseInt(n,10);if(!Number.isFinite(r)||r<0){j.toast.error("Stock must be a non-negative whole number.");return}x(s.key),f(async()=>{const l=await S.updateInventoryQuantityAction({sku:s.sku,stock:r});if(!l.success){j.toast.error(l.error||"Failed to update inventory."),x(null);return}const u=typeof l.stock=="number"?l.stock:r;b(a=>a.map(g=>g.key===s.key?{...g,stock:u}:g)),p(a=>({...a,[s.key]:String(u)})),x(null),j.toast.success(`Inventory updated for ${s.sku}.`)})},I=()=>{v.current?.click()},U=async s=>{const n=await s.text();x("import"),f(async()=>{const r=await S.importInventoryCsvAction(n);if(!r.success){j.toast.error(r.error||"Failed to import inventory CSV."),x(null);return}const l=r.items||[];b(l),p(l.reduce((u,a)=>(u[a.key]=String(a.stock),u),{})),x(null),j.toast.success(`Imported ${r.updatedCount||0} inventory updates.`)})};return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex flex-col gap-3 rounded-xl border bg-card p-4",children:[e.jsxs("div",{className:"flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between",children:[e.jsxs("div",{className:"relative w-full lg:max-w-md",children:[e.jsx(y.Search,{className:"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground"}),e.jsx(t.Input,{value:k,onChange:s=>T(s.target.value),placeholder:"Search by SKU, product title, parent SKU, or language...",className:"pl-9"})]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx("input",{ref:v,type:"file",accept:".csv,text/csv",className:"hidden",onChange:s=>{const n=s.target.files?.[0];n&&U(n),s.currentTarget.value=""}}),e.jsxs(t.Button,{type:"button",variant:"outline",onClick:I,disabled:h,children:[e.jsx(y.Upload,{className:"mr-2 h-4 w-4"}),"Import CSV"]}),e.jsxs(t.Button,{type:"button",variant:"outline",onClick:C,disabled:h,children:[e.jsx(y.Download,{className:"mr-2 h-4 w-4"}),"Export CSV"]})]})]}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Inventory is keyed by sellable SKU. Any product or variant using the same SKU shares the same quantity, and CSV imports can update those shared SKU quantities in bulk."})]}),e.jsx("div",{className:"rounded-xl border bg-card",children:e.jsxs(t.Table,{children:[e.jsx(t.TableHeader,{children:e.jsxs(t.TableRow,{children:[e.jsx(t.TableHead,{children:"SKU"}),e.jsx(t.TableHead,{children:"Usage"}),e.jsx(t.TableHead,{children:"Linked Products"}),e.jsx(t.TableHead,{children:"Languages"}),e.jsx(t.TableHead,{children:"Status"}),e.jsx(t.TableHead,{className:"w-[160px]",children:"Quantity"}),e.jsx(t.TableHead,{className:"text-right",children:"Actions"})]})}),e.jsx(t.TableBody,{children:m.length>0?m.map(s=>{const n=c[s.key]??String(s.stock),r=Number.parseInt(n,10),l=Number.isFinite(r)&&r!==s.stock,u=w===s.key;return e.jsxs(t.TableRow,{children:[e.jsx(t.TableCell,{className:"font-mono text-sm",children:s.sku}),e.jsx(t.TableCell,{children:e.jsx(t.Badge,{variant:L(s),children:B(s)})}),e.jsx(t.TableCell,{children:e.jsxs("div",{className:"space-y-1",children:[e.jsx("p",{className:"font-medium",children:s.productTitles.join(", ")}),s.usageType!=="product"?e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Parent SKU",s.parentProductSkus.length>1?"s":"",":"," ",e.jsx("span",{className:"font-mono",children:s.parentProductSkus.join(", ")})]}):null]})}),e.jsx(t.TableCell,{children:e.jsx("div",{className:"flex flex-wrap gap-1",children:s.languages.map(a=>e.jsx(t.Badge,{variant:"outline",children:a},`${s.key}:${a}`))})}),e.jsx(t.TableCell,{children:e.jsx("div",{className:"flex flex-wrap gap-1",children:s.statuses.map(a=>e.jsx(t.Badge,{variant:"outline",children:a},`${s.key}:${a}`))})}),e.jsx(t.TableCell,{children:e.jsx(t.Input,{type:"number",min:0,step:1,value:n,disabled:h,onChange:a=>p(g=>({...g,[s.key]:a.target.value})),className:"w-28"})}),e.jsx(t.TableCell,{className:"text-right",children:e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsxs(t.Button,{type:"button",size:"sm",variant:"ghost",disabled:!l||h,onClick:()=>p(a=>({...a,[s.key]:String(s.stock)})),children:[e.jsx(y.RotateCcw,{className:"mr-2 h-4 w-4"}),"Reset"]}),e.jsxs(t.Button,{type:"button",size:"sm",disabled:!l||h,onClick:()=>N(s),children:[e.jsx(y.Save,{className:"mr-2 h-4 w-4"}),u?"Saving...":"Save"]})]})})]},s.key)}):e.jsx(t.TableRow,{children:e.jsx(t.TableCell,{colSpan:7,className:"py-10 text-center text-muted-foreground",children:"No inventory rows matched your search."})})})]})})]})}exports.InventoryTableClient=P;
@@ -0,0 +1,214 @@
1
+ 'use client';
2
+ import { jsxs as a, jsx as t } from "react/jsx-runtime";
3
+ import { useState as v, useTransition as V, useRef as $, useMemo as B } from "react";
4
+ import { Input as j, Button as b, Table as D, TableHeader as F, TableRow as x, TableHead as p, TableBody as z, TableCell as u, Badge as w } from "@nextblock-cms/ui";
5
+ import { Search as A, Upload as _, Download as q, RotateCcw as E, Save as H } from "lucide-react";
6
+ import { toast as m } from "sonner";
7
+ import { importInventoryCsvAction as O, updateInventoryQuantityAction as Q } from "./actions.es.js";
8
+ function M(c) {
9
+ const i = String(c ?? "");
10
+ return /[",\n]/.test(i) ? `"${i.replace(/"/g, '""')}"` : i;
11
+ }
12
+ function G(c) {
13
+ const i = [
14
+ "sku",
15
+ "stock",
16
+ "usage_type",
17
+ "product_titles",
18
+ "languages",
19
+ "statuses",
20
+ "parent_product_skus"
21
+ ], k = c.map((l) => [
22
+ l.sku,
23
+ l.stock,
24
+ l.usageType,
25
+ l.productTitles.join("|"),
26
+ l.languages.join("|"),
27
+ l.statuses.join("|"),
28
+ l.parentProductSkus.join("|")
29
+ ]);
30
+ return [i, ...k].map((l) => l.map((h) => M(h)).join(",")).join(`
31
+ `);
32
+ }
33
+ function J(c) {
34
+ return c.usageType === "mixed" ? "Shared SKU" : c.usageType === "variant" ? `Variant SKU ${c.sku}` : "Simple Product";
35
+ }
36
+ function W(c) {
37
+ return c.usageType === "variant" ? "secondary" : "outline";
38
+ }
39
+ function re({ initialItems: c }) {
40
+ const [i, k] = v(c), [l, h] = v(
41
+ () => c.reduce((e, n) => (e[n.key] = String(n.stock), e), {})
42
+ ), [S, I] = v(""), [y, N] = V(), [U, g] = v(null), C = $(null), T = B(() => {
43
+ const e = S.trim().toLowerCase();
44
+ return e ? i.filter((n) => n.sku.toLowerCase().includes(e) || n.productTitles.join(" ").toLowerCase().includes(e) || n.parentProductSkus.join(" ").toLowerCase().includes(e) || n.languages.join(" ").toLowerCase().includes(e)) : i;
45
+ }, [i, S]), K = () => {
46
+ const e = G(i), n = new Blob([e], { type: "text/csv;charset=utf-8;" }), s = URL.createObjectURL(n), o = document.createElement("a");
47
+ o.href = s, o.download = "inventory-export.csv", o.click(), URL.revokeObjectURL(s);
48
+ }, L = (e) => {
49
+ const n = l[e.key] ?? String(e.stock), s = Number.parseInt(n, 10);
50
+ if (!Number.isFinite(s) || s < 0) {
51
+ m.error("Stock must be a non-negative whole number.");
52
+ return;
53
+ }
54
+ g(e.key), N(async () => {
55
+ const o = await Q({
56
+ sku: e.sku,
57
+ stock: s
58
+ });
59
+ if (!o.success) {
60
+ m.error(o.error || "Failed to update inventory."), g(null);
61
+ return;
62
+ }
63
+ const d = typeof o.stock == "number" ? o.stock : s;
64
+ k(
65
+ (r) => r.map(
66
+ (f) => f.key === e.key ? {
67
+ ...f,
68
+ stock: d
69
+ } : f
70
+ )
71
+ ), h((r) => ({
72
+ ...r,
73
+ [e.key]: String(d)
74
+ })), g(null), m.success(`Inventory updated for ${e.sku}.`);
75
+ });
76
+ }, P = () => {
77
+ C.current?.click();
78
+ }, R = async (e) => {
79
+ const n = await e.text();
80
+ g("import"), N(async () => {
81
+ const s = await O(n);
82
+ if (!s.success) {
83
+ m.error(s.error || "Failed to import inventory CSV."), g(null);
84
+ return;
85
+ }
86
+ const o = s.items || [];
87
+ k(o), h(
88
+ o.reduce((d, r) => (d[r.key] = String(r.stock), d), {})
89
+ ), g(null), m.success(`Imported ${s.updatedCount || 0} inventory updates.`);
90
+ });
91
+ };
92
+ return /* @__PURE__ */ a("div", { className: "space-y-4", children: [
93
+ /* @__PURE__ */ a("div", { className: "flex flex-col gap-3 rounded-xl border bg-card p-4", children: [
94
+ /* @__PURE__ */ a("div", { className: "flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between", children: [
95
+ /* @__PURE__ */ a("div", { className: "relative w-full lg:max-w-md", children: [
96
+ /* @__PURE__ */ t(A, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
97
+ /* @__PURE__ */ t(
98
+ j,
99
+ {
100
+ value: S,
101
+ onChange: (e) => I(e.target.value),
102
+ placeholder: "Search by SKU, product title, parent SKU, or language...",
103
+ className: "pl-9"
104
+ }
105
+ )
106
+ ] }),
107
+ /* @__PURE__ */ a("div", { className: "flex flex-wrap gap-2", children: [
108
+ /* @__PURE__ */ t(
109
+ "input",
110
+ {
111
+ ref: C,
112
+ type: "file",
113
+ accept: ".csv,text/csv",
114
+ className: "hidden",
115
+ onChange: (e) => {
116
+ const n = e.target.files?.[0];
117
+ n && R(n), e.currentTarget.value = "";
118
+ }
119
+ }
120
+ ),
121
+ /* @__PURE__ */ a(b, { type: "button", variant: "outline", onClick: P, disabled: y, children: [
122
+ /* @__PURE__ */ t(_, { className: "mr-2 h-4 w-4" }),
123
+ "Import CSV"
124
+ ] }),
125
+ /* @__PURE__ */ a(b, { type: "button", variant: "outline", onClick: K, disabled: y, children: [
126
+ /* @__PURE__ */ t(q, { className: "mr-2 h-4 w-4" }),
127
+ "Export CSV"
128
+ ] })
129
+ ] })
130
+ ] }),
131
+ /* @__PURE__ */ t("p", { className: "text-sm text-muted-foreground", children: "Inventory is keyed by sellable SKU. Any product or variant using the same SKU shares the same quantity, and CSV imports can update those shared SKU quantities in bulk." })
132
+ ] }),
133
+ /* @__PURE__ */ t("div", { className: "rounded-xl border bg-card", children: /* @__PURE__ */ a(D, { children: [
134
+ /* @__PURE__ */ t(F, { children: /* @__PURE__ */ a(x, { children: [
135
+ /* @__PURE__ */ t(p, { children: "SKU" }),
136
+ /* @__PURE__ */ t(p, { children: "Usage" }),
137
+ /* @__PURE__ */ t(p, { children: "Linked Products" }),
138
+ /* @__PURE__ */ t(p, { children: "Languages" }),
139
+ /* @__PURE__ */ t(p, { children: "Status" }),
140
+ /* @__PURE__ */ t(p, { className: "w-[160px]", children: "Quantity" }),
141
+ /* @__PURE__ */ t(p, { className: "text-right", children: "Actions" })
142
+ ] }) }),
143
+ /* @__PURE__ */ t(z, { children: T.length > 0 ? T.map((e) => {
144
+ const n = l[e.key] ?? String(e.stock), s = Number.parseInt(n, 10), o = Number.isFinite(s) && s !== e.stock, d = U === e.key;
145
+ return /* @__PURE__ */ a(x, { children: [
146
+ /* @__PURE__ */ t(u, { className: "font-mono text-sm", children: e.sku }),
147
+ /* @__PURE__ */ t(u, { children: /* @__PURE__ */ t(w, { variant: W(e), children: J(e) }) }),
148
+ /* @__PURE__ */ t(u, { children: /* @__PURE__ */ a("div", { className: "space-y-1", children: [
149
+ /* @__PURE__ */ t("p", { className: "font-medium", children: e.productTitles.join(", ") }),
150
+ e.usageType !== "product" ? /* @__PURE__ */ a("p", { className: "text-xs text-muted-foreground", children: [
151
+ "Parent SKU",
152
+ e.parentProductSkus.length > 1 ? "s" : "",
153
+ ":",
154
+ " ",
155
+ /* @__PURE__ */ t("span", { className: "font-mono", children: e.parentProductSkus.join(", ") })
156
+ ] }) : null
157
+ ] }) }),
158
+ /* @__PURE__ */ t(u, { children: /* @__PURE__ */ t("div", { className: "flex flex-wrap gap-1", children: e.languages.map((r) => /* @__PURE__ */ t(w, { variant: "outline", children: r }, `${e.key}:${r}`)) }) }),
159
+ /* @__PURE__ */ t(u, { children: /* @__PURE__ */ t("div", { className: "flex flex-wrap gap-1", children: e.statuses.map((r) => /* @__PURE__ */ t(w, { variant: "outline", children: r }, `${e.key}:${r}`)) }) }),
160
+ /* @__PURE__ */ t(u, { children: /* @__PURE__ */ t(
161
+ j,
162
+ {
163
+ type: "number",
164
+ min: 0,
165
+ step: 1,
166
+ value: n,
167
+ disabled: y,
168
+ onChange: (r) => h((f) => ({
169
+ ...f,
170
+ [e.key]: r.target.value
171
+ })),
172
+ className: "w-28"
173
+ }
174
+ ) }),
175
+ /* @__PURE__ */ t(u, { className: "text-right", children: /* @__PURE__ */ a("div", { className: "flex justify-end gap-2", children: [
176
+ /* @__PURE__ */ a(
177
+ b,
178
+ {
179
+ type: "button",
180
+ size: "sm",
181
+ variant: "ghost",
182
+ disabled: !o || y,
183
+ onClick: () => h((r) => ({
184
+ ...r,
185
+ [e.key]: String(e.stock)
186
+ })),
187
+ children: [
188
+ /* @__PURE__ */ t(E, { className: "mr-2 h-4 w-4" }),
189
+ "Reset"
190
+ ]
191
+ }
192
+ ),
193
+ /* @__PURE__ */ a(
194
+ b,
195
+ {
196
+ type: "button",
197
+ size: "sm",
198
+ disabled: !o || y,
199
+ onClick: () => L(e),
200
+ children: [
201
+ /* @__PURE__ */ t(H, { className: "mr-2 h-4 w-4" }),
202
+ d ? "Saving..." : "Save"
203
+ ]
204
+ }
205
+ )
206
+ ] }) })
207
+ ] }, e.key);
208
+ }) : /* @__PURE__ */ t(x, { children: /* @__PURE__ */ t(u, { colSpan: 7, className: "py-10 text-center text-muted-foreground", children: "No inventory rows matched your search." }) }) })
209
+ ] }) })
210
+ ] });
211
+ }
212
+ export {
213
+ re as InventoryTableClient
214
+ };
@@ -0,0 +1,3 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("next/cache"),m=require("@nextblock-cms/db/server"),d=require("../../../../shared-inventory.cjs.js");function p(t){const e=[];let o=[],r="",a=!1;for(let n=0;n<t.length;n+=1){const s=t[n],c=t[n+1];if(s==='"'){a&&c==='"'?(r+='"',n+=1):a=!a;continue}if(s===","&&!a){o.push(r),r="";continue}if((s===`
2
+ `||s==="\r")&&!a){s==="\r"&&c===`
3
+ `&&(n+=1),(r.length>0||o.length>0)&&(o.push(r),e.push(o)),o=[],r="";continue}r+=s}return(r.length>0||o.length>0)&&(o.push(r),e.push(o)),e.filter(n=>n.some(s=>s.trim().length>0))}function v(t){return t.sku}async function I(t){try{const e=Math.max(0,Math.trunc(t.stock));return await d.setSharedInventoryQuantity({sku:t.sku,stock:e}),u.revalidatePath("/cms/products"),u.revalidatePath("/cms/products/inventory"),{success:!0,itemKey:v(t),stock:e}}catch(e){return{success:!1,error:e instanceof Error?e.message:"Failed to update inventory."}}}async function g(t){try{const e=p(t);if(e.length<2)return{success:!1,error:"The CSV file is empty."};const[o,...r]=e,a=o.map(i=>i.trim().toLowerCase()),n=a.indexOf("sku"),s=a.indexOf("stock");if(n===-1||s===-1)return{success:!1,error:"The CSV format is invalid. Please import a file exported from the Inventory page."};const c=m.getServiceRoleSupabaseClient();let h=0;for(const i of r){const l=(i[n]||"").trim(),f=Number.parseInt((i[s]||"").trim(),10);if(l){if(!Number.isFinite(f)||f<0)return{success:!1,error:`Invalid stock value for SKU "${l}".`};await d.setSharedInventoryQuantity({sku:l,stock:f},c),h+=1}}const y=await d.getInventoryItems(c);return u.revalidatePath("/cms/products"),u.revalidatePath("/cms/products/inventory"),{success:!0,updatedCount:h,items:y}}catch(e){return{success:!1,error:e instanceof Error?e.message:"Failed to import inventory CSV."}}}exports.importInventoryCsvAction=g;exports.updateInventoryQuantityAction=I;