@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
@@ -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;