@vendure-platform/create 0.5.0 → 1.0.0-major.202609091053.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +53 -41
  3. package/dist/add-to-existing.d.ts +19 -13
  4. package/dist/add-to-existing.js +1 -1
  5. package/dist/assets/demo-data/assets/branding/logo.svg +4 -0
  6. package/dist/assets/demo-data/assets/images/absorbent-pad.webp +0 -0
  7. package/dist/assets/demo-data/assets/images/adjustable-wrench.webp +0 -0
  8. package/dist/assets/demo-data/assets/images/anchor-bolt.webp +0 -0
  9. package/dist/assets/demo-data/assets/images/angle-grinder.webp +0 -0
  10. package/dist/assets/demo-data/assets/images/barrier-tape.webp +0 -0
  11. package/dist/assets/demo-data/assets/images/bench-grinder.webp +0 -0
  12. package/dist/assets/demo-data/assets/images/bracket.webp +0 -0
  13. package/dist/assets/demo-data/assets/images/broom.webp +0 -0
  14. package/dist/assets/demo-data/assets/images/bucket.webp +0 -0
  15. package/dist/assets/demo-data/assets/images/cable-gland.webp +0 -0
  16. package/dist/assets/demo-data/assets/images/cable-tie.webp +0 -0
  17. package/dist/assets/demo-data/assets/images/cable-tray.webp +0 -0
  18. package/dist/assets/demo-data/assets/images/cable.webp +0 -0
  19. package/dist/assets/demo-data/assets/images/chimney-base-kit.webp +0 -0
  20. package/dist/assets/demo-data/assets/images/chimney-cowl-bird-guard.webp +0 -0
  21. package/dist/assets/demo-data/assets/images/chimney-cowl-open.webp +0 -0
  22. package/dist/assets/demo-data/assets/images/chimney-storm-collar.webp +0 -0
  23. package/dist/assets/demo-data/assets/images/chimney-wall-bracket.webp +0 -0
  24. package/dist/assets/demo-data/assets/images/circular-saw.webp +0 -0
  25. package/dist/assets/demo-data/assets/images/cleaning-spray.webp +0 -0
  26. package/dist/assets/demo-data/assets/images/conduit.webp +0 -0
  27. package/dist/assets/demo-data/assets/images/cordless-drill.webp +0 -0
  28. package/dist/assets/demo-data/assets/images/drill-bits.webp +0 -0
  29. package/dist/assets/demo-data/assets/images/dust-mask.webp +0 -0
  30. package/dist/assets/demo-data/assets/images/ear-defenders.webp +0 -0
  31. package/dist/assets/demo-data/assets/images/ear-plugs.webp +0 -0
  32. package/dist/assets/demo-data/assets/images/extension-lead.webp +0 -0
  33. package/dist/assets/demo-data/assets/images/eye-wash-station.webp +0 -0
  34. package/dist/assets/demo-data/assets/images/face-shield.webp +0 -0
  35. package/dist/assets/demo-data/assets/images/file-set.webp +0 -0
  36. package/dist/assets/demo-data/assets/images/first-aid-kit.webp +0 -0
  37. package/dist/assets/demo-data/assets/images/floor-sign.webp +0 -0
  38. package/dist/assets/demo-data/assets/images/flue-bend-45.webp +0 -0
  39. package/dist/assets/demo-data/assets/images/flue-bend-90.webp +0 -0
  40. package/dist/assets/demo-data/assets/images/flue-section-1000mm.webp +0 -0
  41. package/dist/assets/demo-data/assets/images/flue-section-250mm.webp +0 -0
  42. package/dist/assets/demo-data/assets/images/flue-section-500mm.webp +0 -0
  43. package/dist/assets/demo-data/assets/images/fuse.webp +0 -0
  44. package/dist/assets/demo-data/assets/images/glove-dispenser.webp +0 -0
  45. package/dist/assets/demo-data/assets/images/grinding-disc.webp +0 -0
  46. package/dist/assets/demo-data/assets/images/hacksaw.webp +0 -0
  47. package/dist/assets/demo-data/assets/images/hammer.webp +0 -0
  48. package/dist/assets/demo-data/assets/images/hand-sanitiser.webp +0 -0
  49. package/dist/assets/demo-data/assets/images/head-torch.webp +0 -0
  50. package/dist/assets/demo-data/assets/images/heat-gun.webp +0 -0
  51. package/dist/assets/demo-data/assets/images/hex-bolt.webp +0 -0
  52. package/dist/assets/demo-data/assets/images/hex-key-set.webp +0 -0
  53. package/dist/assets/demo-data/assets/images/hex-nut.webp +0 -0
  54. package/dist/assets/demo-data/assets/images/hi-vis-jacket.webp +0 -0
  55. package/dist/assets/demo-data/assets/images/hi-vis-vest.webp +0 -0
  56. package/dist/assets/demo-data/assets/images/hose-clamp.webp +0 -0
  57. package/dist/assets/demo-data/assets/images/impact-driver.webp +0 -0
  58. package/dist/assets/demo-data/assets/images/jigsaw.webp +0 -0
  59. package/dist/assets/demo-data/assets/images/junction-box.webp +0 -0
  60. package/dist/assets/demo-data/assets/images/knee-pads.webp +0 -0
  61. package/dist/assets/demo-data/assets/images/machine-screw.webp +0 -0
  62. package/dist/assets/demo-data/assets/images/made-to-order-configurable-chimney.webp +0 -0
  63. package/dist/assets/demo-data/assets/images/mallet.webp +0 -0
  64. package/dist/assets/demo-data/assets/images/mcb.webp +0 -0
  65. package/dist/assets/demo-data/assets/images/mop.webp +0 -0
  66. package/dist/assets/demo-data/assets/images/paper-towels.webp +0 -0
  67. package/dist/assets/demo-data/assets/images/pipe-wrench.webp +0 -0
  68. package/dist/assets/demo-data/assets/images/pliers-set.webp +0 -0
  69. package/dist/assets/demo-data/assets/images/pry-bar.webp +0 -0
  70. package/dist/assets/demo-data/assets/images/rcd.webp +0 -0
  71. package/dist/assets/demo-data/assets/images/reciprocating-saw.webp +0 -0
  72. package/dist/assets/demo-data/assets/images/rivet.webp +0 -0
  73. package/dist/assets/demo-data/assets/images/roof-flashing-high-pitch.webp +0 -0
  74. package/dist/assets/demo-data/assets/images/roof-flashing-low-pitch.webp +0 -0
  75. package/dist/assets/demo-data/assets/images/safety-boots.webp +0 -0
  76. package/dist/assets/demo-data/assets/images/safety-glasses.webp +0 -0
  77. package/dist/assets/demo-data/assets/images/safety-harness.webp +0 -0
  78. package/dist/assets/demo-data/assets/images/safety-helmet.webp +0 -0
  79. package/dist/assets/demo-data/assets/images/safety-sign.webp +0 -0
  80. package/dist/assets/demo-data/assets/images/sanding-disc.webp +0 -0
  81. package/dist/assets/demo-data/assets/images/saw-blade.webp +0 -0
  82. package/dist/assets/demo-data/assets/images/screwdriver-set.webp +0 -0
  83. package/dist/assets/demo-data/assets/images/screwdriver.webp +0 -0
  84. package/dist/assets/demo-data/assets/images/self-tapping-screw.webp +0 -0
  85. package/dist/assets/demo-data/assets/images/socket-set.webp +0 -0
  86. package/dist/assets/demo-data/assets/images/socket.webp +0 -0
  87. package/dist/assets/demo-data/assets/images/spanner-set.webp +0 -0
  88. package/dist/assets/demo-data/assets/images/spanner.webp +0 -0
  89. package/dist/assets/demo-data/assets/images/spill-kit.webp +0 -0
  90. package/dist/assets/demo-data/assets/images/spirit-level.webp +0 -0
  91. package/dist/assets/demo-data/assets/images/switch.webp +0 -0
  92. package/dist/assets/demo-data/assets/images/tape-measure.webp +0 -0
  93. package/dist/assets/demo-data/assets/images/terminal-block.webp +0 -0
  94. package/dist/assets/demo-data/assets/images/threaded-rod.webp +0 -0
  95. package/dist/assets/demo-data/assets/images/torque-wrench.webp +0 -0
  96. package/dist/assets/demo-data/assets/images/utility-knife.webp +0 -0
  97. package/dist/assets/demo-data/assets/images/wall-pass-sleeve.webp +0 -0
  98. package/dist/assets/demo-data/assets/images/wall-plug.webp +0 -0
  99. package/dist/assets/demo-data/assets/images/washer.webp +0 -0
  100. package/dist/assets/demo-data/assets/images/waste-bin.webp +0 -0
  101. package/dist/assets/demo-data/assets/images/wire-connector.webp +0 -0
  102. package/dist/assets/demo-data/assets/images/wire-cutters.webp +0 -0
  103. package/dist/assets/demo-data/assets/images/wood-screw.webp +0 -0
  104. package/dist/assets/demo-data/assets/images/work-gloves.webp +0 -0
  105. package/dist/assets/demo-data/assets/images/work-light.webp +0 -0
  106. package/dist/assets/demo-data/assets/initial-data.json +667 -0
  107. package/dist/assets/demo-data/assets/products.csv +779 -0
  108. package/dist/assets/demo-data/initial-data.json +663 -663
  109. package/dist/assets/storefront/components.json +20 -20
  110. package/dist/assets/storefront/eslint.config.mjs +10 -10
  111. package/dist/assets/storefront/graphql.config.yml +1 -1
  112. package/dist/assets/storefront/next-env.d.ts +2 -1
  113. package/dist/assets/storefront/next.config.ts +19 -17
  114. package/dist/assets/storefront/package.json +3 -2
  115. package/dist/assets/storefront/postcss.config.mjs +1 -1
  116. package/dist/assets/storefront/src/app/[locale]/(catalog)/catalog/page.tsx +17 -21
  117. package/dist/assets/storefront/src/app/[locale]/(catalog)/collection/[slug]/page.tsx +64 -42
  118. package/dist/assets/storefront/src/app/[locale]/(catalog)/layout.tsx +1 -5
  119. package/dist/assets/storefront/src/app/[locale]/(catalog)/product/[slug]/actions.ts +69 -65
  120. package/dist/assets/storefront/src/app/[locale]/(catalog)/product/[slug]/page.tsx +64 -38
  121. package/dist/assets/storefront/src/app/[locale]/(catalog)/search/page.tsx +24 -27
  122. package/dist/assets/storefront/src/app/[locale]/(catalog)/search/search-results.tsx +11 -9
  123. package/dist/assets/storefront/src/app/[locale]/(catalog)/search/search-term.tsx +4 -4
  124. package/dist/assets/storefront/src/app/[locale]/(scenario)/[...path]/page.tsx +1 -1
  125. package/dist/assets/storefront/src/app/[locale]/accept-invitation/[token]/accept-invitation-client.tsx +8 -13
  126. package/dist/assets/storefront/src/app/[locale]/accept-invitation/[token]/actions.ts +11 -14
  127. package/dist/assets/storefront/src/app/[locale]/accept-invitation/[token]/page.tsx +30 -33
  128. package/dist/assets/storefront/src/app/[locale]/accept-invitation/[token]/sign-out-and-retry.tsx +6 -6
  129. package/dist/assets/storefront/src/app/[locale]/account/addresses/actions.ts +30 -45
  130. package/dist/assets/storefront/src/app/[locale]/account/addresses/address-form.tsx +166 -159
  131. package/dist/assets/storefront/src/app/[locale]/account/addresses/addresses-client.tsx +35 -26
  132. package/dist/assets/storefront/src/app/[locale]/account/addresses/loading.tsx +1 -3
  133. package/dist/assets/storefront/src/app/[locale]/account/addresses/page.tsx +18 -18
  134. package/dist/assets/storefront/src/app/[locale]/account/approvals/actions.ts +5 -8
  135. package/dist/assets/storefront/src/app/[locale]/account/approvals/page.tsx +79 -69
  136. package/dist/assets/storefront/src/app/[locale]/account/company/actions.ts +10 -11
  137. package/dist/assets/storefront/src/app/[locale]/account/company/addresses/actions.ts +6 -15
  138. package/dist/assets/storefront/src/app/[locale]/account/company/addresses/address-form.tsx +57 -49
  139. package/dist/assets/storefront/src/app/[locale]/account/company/addresses/addresses-client.tsx +23 -25
  140. package/dist/assets/storefront/src/app/[locale]/account/company/addresses/page.tsx +30 -30
  141. package/dist/assets/storefront/src/app/[locale]/account/company/business-units/actions.ts +20 -29
  142. package/dist/assets/storefront/src/app/[locale]/account/company/business-units/business-unit-form.tsx +32 -37
  143. package/dist/assets/storefront/src/app/[locale]/account/company/business-units/business-units-client.tsx +32 -25
  144. package/dist/assets/storefront/src/app/[locale]/account/company/business-units/page.tsx +26 -24
  145. package/dist/assets/storefront/src/app/[locale]/account/company/business-units/types.ts +7 -4
  146. package/dist/assets/storefront/src/app/[locale]/account/company/edit-company-form.tsx +11 -21
  147. package/dist/assets/storefront/src/app/[locale]/account/company/page.tsx +25 -28
  148. package/dist/assets/storefront/src/app/[locale]/account/company/payment-methods/page.tsx +26 -24
  149. package/dist/assets/storefront/src/app/[locale]/account/company/payment-methods/payment-methods-client.tsx +5 -7
  150. package/dist/assets/storefront/src/app/[locale]/account/company/roles/page.tsx +24 -25
  151. package/dist/assets/storefront/src/app/[locale]/account/company/roles/roles-client.tsx +11 -26
  152. package/dist/assets/storefront/src/app/[locale]/account/company/tax-ids/actions.ts +6 -10
  153. package/dist/assets/storefront/src/app/[locale]/account/company/tax-ids/page.tsx +18 -16
  154. package/dist/assets/storefront/src/app/[locale]/account/company/tax-ids/tax-ids-client.tsx +74 -67
  155. package/dist/assets/storefront/src/app/[locale]/account/company/users/actions.ts +16 -25
  156. package/dist/assets/storefront/src/app/[locale]/account/company/users/edit-user-form.tsx +27 -25
  157. package/dist/assets/storefront/src/app/[locale]/account/company/users/invite-user-form.tsx +27 -19
  158. package/dist/assets/storefront/src/app/[locale]/account/company/users/page.tsx +34 -29
  159. package/dist/assets/storefront/src/app/[locale]/account/company/users/users-client.tsx +35 -38
  160. package/dist/assets/storefront/src/app/[locale]/account/error.tsx +1 -3
  161. package/dist/assets/storefront/src/app/[locale]/account/layout.tsx +16 -22
  162. package/dist/assets/storefront/src/app/[locale]/account/orders/[code]/page.tsx +151 -103
  163. package/dist/assets/storefront/src/app/[locale]/account/orders/[code]/reorder-actions.ts +6 -7
  164. package/dist/assets/storefront/src/app/[locale]/account/orders/[code]/reorder-dialog.tsx +22 -48
  165. package/dist/assets/storefront/src/app/[locale]/account/orders/loading.tsx +8 -8
  166. package/dist/assets/storefront/src/app/[locale]/account/orders/page.tsx +101 -61
  167. package/dist/assets/storefront/src/app/[locale]/account/profile/actions.ts +32 -23
  168. package/dist/assets/storefront/src/app/[locale]/account/profile/change-password-form.tsx +6 -16
  169. package/dist/assets/storefront/src/app/[locale]/account/profile/edit-email-form.tsx +7 -17
  170. package/dist/assets/storefront/src/app/[locale]/account/profile/edit-profile-form.tsx +6 -16
  171. package/dist/assets/storefront/src/app/[locale]/account/profile/loading.tsx +12 -18
  172. package/dist/assets/storefront/src/app/[locale]/account/profile/page.tsx +17 -15
  173. package/dist/assets/storefront/src/app/[locale]/account/quick-order/file-upload-tab.tsx +2 -6
  174. package/dist/assets/storefront/src/app/[locale]/account/quick-order/manual-entry-tab.tsx +18 -15
  175. package/dist/assets/storefront/src/app/[locale]/account/quick-order/page.tsx +5 -6
  176. package/dist/assets/storefront/src/app/[locale]/account/quick-order/preview-table.tsx +10 -2
  177. package/dist/assets/storefront/src/app/[locale]/account/quick-order/save-to-list-dialog.tsx +24 -26
  178. package/dist/assets/storefront/src/app/[locale]/account/quick-order/sku-autocomplete.tsx +19 -10
  179. package/dist/assets/storefront/src/app/[locale]/account/quick-order/text-input-tab.tsx +3 -8
  180. package/dist/assets/storefront/src/app/[locale]/account/quotes/[id]/page.tsx +93 -62
  181. package/dist/assets/storefront/src/app/[locale]/account/quotes/actions.ts +38 -45
  182. package/dist/assets/storefront/src/app/[locale]/account/quotes/new/new-quote-form.tsx +3 -5
  183. package/dist/assets/storefront/src/app/[locale]/account/quotes/new/page.tsx +6 -6
  184. package/dist/assets/storefront/src/app/[locale]/account/quotes/page.tsx +92 -59
  185. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/add-item-search.tsx +11 -9
  186. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/add-member-form.tsx +31 -15
  187. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/members-panel.tsx +52 -33
  188. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/page.tsx +22 -14
  189. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/rename-dialog.tsx +34 -13
  190. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/actions.ts +117 -72
  191. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/new/new-shared-cart-form.tsx +21 -14
  192. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/new/page.tsx +10 -10
  193. package/dist/assets/storefront/src/app/[locale]/account/shared-carts/page.tsx +54 -41
  194. package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/[id]/page.tsx +22 -8
  195. package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/[id]/shopping-list-detail-client.tsx +62 -49
  196. package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/actions.ts +9 -4
  197. package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/create-shopping-list-form.tsx +5 -11
  198. package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/loading.tsx +1 -1
  199. package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/page.tsx +32 -42
  200. package/dist/assets/storefront/src/app/[locale]/account/store-credits/actions.ts +8 -8
  201. package/dist/assets/storefront/src/app/[locale]/account/store-credits/claim-form.tsx +6 -10
  202. package/dist/assets/storefront/src/app/[locale]/account/store-credits/page.tsx +76 -55
  203. package/dist/assets/storefront/src/app/[locale]/account/store-credits/reveal-code.tsx +10 -6
  204. package/dist/assets/storefront/src/app/[locale]/account/verify-email/page.tsx +32 -39
  205. package/dist/assets/storefront/src/app/[locale]/cart/actions.ts +29 -23
  206. package/dist/assets/storefront/src/app/[locale]/cart/cart-items.tsx +111 -40
  207. package/dist/assets/storefront/src/app/[locale]/cart/cart-line-actions.tsx +9 -9
  208. package/dist/assets/storefront/src/app/[locale]/cart/cart-quantity-control.tsx +61 -48
  209. package/dist/assets/storefront/src/app/[locale]/cart/cart-remove-button.tsx +15 -9
  210. package/dist/assets/storefront/src/app/[locale]/cart/cart.tsx +38 -41
  211. package/dist/assets/storefront/src/app/[locale]/cart/code-input.tsx +8 -8
  212. package/dist/assets/storefront/src/app/[locale]/cart/order-summary.tsx +56 -35
  213. package/dist/assets/storefront/src/app/[locale]/cart/page.tsx +11 -11
  214. package/dist/assets/storefront/src/app/[locale]/cart/promotion-code.tsx +56 -47
  215. package/dist/assets/storefront/src/app/[locale]/cart/reapproval-confirm.tsx +22 -20
  216. package/dist/assets/storefront/src/app/[locale]/cart/request-quote-button.tsx +7 -16
  217. package/dist/assets/storefront/src/app/[locale]/checkout/actions.ts +39 -65
  218. package/dist/assets/storefront/src/app/[locale]/checkout/cancel-quote-checkout-button.tsx +5 -5
  219. package/dist/assets/storefront/src/app/[locale]/checkout/checkout-flow.tsx +202 -202
  220. package/dist/assets/storefront/src/app/[locale]/checkout/checkout-provider.tsx +142 -142
  221. package/dist/assets/storefront/src/app/[locale]/checkout/order-summary.tsx +158 -139
  222. package/dist/assets/storefront/src/app/[locale]/checkout/page.tsx +58 -47
  223. package/dist/assets/storefront/src/app/[locale]/checkout/steps/delivery-step.tsx +86 -88
  224. package/dist/assets/storefront/src/app/[locale]/checkout/steps/payment-step.tsx +90 -91
  225. package/dist/assets/storefront/src/app/[locale]/checkout/steps/review-step.tsx +166 -161
  226. package/dist/assets/storefront/src/app/[locale]/checkout/steps/shipping-address-step.tsx +573 -494
  227. package/dist/assets/storefront/src/app/[locale]/error.tsx +3 -5
  228. package/dist/assets/storefront/src/app/[locale]/forgot-password/actions.ts +10 -7
  229. package/dist/assets/storefront/src/app/[locale]/forgot-password/forgot-password-form.tsx +10 -25
  230. package/dist/assets/storefront/src/app/[locale]/forgot-password/page.tsx +5 -5
  231. package/dist/assets/storefront/src/app/[locale]/globals.css +48 -48
  232. package/dist/assets/storefront/src/app/[locale]/layout.tsx +56 -50
  233. package/dist/assets/storefront/src/app/[locale]/not-found.tsx +3 -5
  234. package/dist/assets/storefront/src/app/[locale]/order-confirmation/[code]/order-confirmation.tsx +71 -102
  235. package/dist/assets/storefront/src/app/[locale]/order-confirmation/[code]/page.tsx +7 -5
  236. package/dist/assets/storefront/src/app/[locale]/page.tsx +33 -35
  237. package/dist/assets/storefront/src/app/[locale]/register/actions.ts +7 -7
  238. package/dist/assets/storefront/src/app/[locale]/register/page.tsx +22 -16
  239. package/dist/assets/storefront/src/app/[locale]/register/registration-form.tsx +22 -34
  240. package/dist/assets/storefront/src/app/[locale]/register-company/actions.ts +15 -19
  241. package/dist/assets/storefront/src/app/[locale]/register-company/page.tsx +17 -15
  242. package/dist/assets/storefront/src/app/[locale]/register-company/registration-form.tsx +9 -15
  243. package/dist/assets/storefront/src/app/[locale]/reset-password/actions.ts +7 -8
  244. package/dist/assets/storefront/src/app/[locale]/reset-password/page.tsx +18 -12
  245. package/dist/assets/storefront/src/app/[locale]/reset-password/reset-password-form.tsx +8 -16
  246. package/dist/assets/storefront/src/app/[locale]/shopping-list/[code]/add-to-cart-button.tsx +10 -4
  247. package/dist/assets/storefront/src/app/[locale]/shopping-list/[code]/page.tsx +62 -30
  248. package/dist/assets/storefront/src/app/[locale]/sign-in/actions.ts +14 -16
  249. package/dist/assets/storefront/src/app/[locale]/sign-in/login-form.tsx +17 -30
  250. package/dist/assets/storefront/src/app/[locale]/sign-in/page.tsx +35 -30
  251. package/dist/assets/storefront/src/app/[locale]/verify/actions.ts +8 -8
  252. package/dist/assets/storefront/src/app/[locale]/verify/page.tsx +18 -14
  253. package/dist/assets/storefront/src/app/[locale]/verify/verify-content.tsx +25 -27
  254. package/dist/assets/storefront/src/app/[locale]/verify-pending/page.tsx +23 -23
  255. package/dist/assets/storefront/src/app/api/clear-company-context/route.ts +6 -3
  256. package/dist/assets/storefront/src/app/api/revalidate/route.ts +19 -28
  257. package/dist/assets/storefront/src/app/api/search-analytics/route.ts +1 -1
  258. package/dist/assets/storefront/src/components/commerce/account-nav-items.ts +43 -18
  259. package/dist/assets/storefront/src/components/commerce/account-sidebar.tsx +30 -22
  260. package/dist/assets/storefront/src/components/commerce/active-filters.tsx +1 -1
  261. package/dist/assets/storefront/src/components/commerce/add-to-shared-cart.tsx +49 -27
  262. package/dist/assets/storefront/src/components/commerce/approval-decision-form.tsx +9 -13
  263. package/dist/assets/storefront/src/components/commerce/approval-status-badge.tsx +23 -15
  264. package/dist/assets/storefront/src/components/commerce/business-unit-switcher.tsx +11 -11
  265. package/dist/assets/storefront/src/components/commerce/catalog-search-bar.tsx +2 -2
  266. package/dist/assets/storefront/src/components/commerce/category-product-section.tsx +28 -16
  267. package/dist/assets/storefront/src/components/commerce/category-sidebar.tsx +31 -18
  268. package/dist/assets/storefront/src/components/commerce/collection-hero-banner.tsx +2 -4
  269. package/dist/assets/storefront/src/components/commerce/company-state-badge.tsx +10 -16
  270. package/dist/assets/storefront/src/components/commerce/company-switcher.tsx +12 -12
  271. package/dist/assets/storefront/src/components/commerce/configurator-form.tsx +188 -79
  272. package/dist/assets/storefront/src/components/commerce/facet-filters.tsx +29 -49
  273. package/dist/assets/storefront/src/components/commerce/gift-card-pdp.tsx +4 -4
  274. package/dist/assets/storefront/src/components/commerce/gift-card-product-info.tsx +20 -30
  275. package/dist/assets/storefront/src/components/commerce/instant-search-dropdown.tsx +258 -227
  276. package/dist/assets/storefront/src/components/commerce/order-status-badge.tsx +27 -19
  277. package/dist/assets/storefront/src/components/commerce/packaging-unit-selector.tsx +27 -26
  278. package/dist/assets/storefront/src/components/commerce/permission-gate.tsx +4 -4
  279. package/dist/assets/storefront/src/components/commerce/price-range-filter.tsx +5 -5
  280. package/dist/assets/storefront/src/components/commerce/price-tiers.tsx +38 -21
  281. package/dist/assets/storefront/src/components/commerce/price.tsx +3 -3
  282. package/dist/assets/storefront/src/components/commerce/product-card-list.tsx +39 -16
  283. package/dist/assets/storefront/src/components/commerce/product-card.tsx +35 -18
  284. package/dist/assets/storefront/src/components/commerce/product-carousel.tsx +20 -12
  285. package/dist/assets/storefront/src/components/commerce/product-grid.tsx +14 -13
  286. package/dist/assets/storefront/src/components/commerce/product-image-carousel.tsx +10 -8
  287. package/dist/assets/storefront/src/components/commerce/product-info.tsx +118 -74
  288. package/dist/assets/storefront/src/components/commerce/product-list-expansion.tsx +102 -74
  289. package/dist/assets/storefront/src/components/commerce/product-list-view.tsx +1 -1
  290. package/dist/assets/storefront/src/components/commerce/product-sidebar.tsx +36 -11
  291. package/dist/assets/storefront/src/components/commerce/product-view-switcher.tsx +33 -21
  292. package/dist/assets/storefront/src/components/commerce/quote-action-buttons.tsx +80 -45
  293. package/dist/assets/storefront/src/components/commerce/quote-activity-timeline.tsx +126 -50
  294. package/dist/assets/storefront/src/components/commerce/quote-comment-form.tsx +9 -13
  295. package/dist/assets/storefront/src/components/commerce/quote-csv-export-button.tsx +6 -6
  296. package/dist/assets/storefront/src/components/commerce/quote-product-search.tsx +22 -18
  297. package/dist/assets/storefront/src/components/commerce/quote-request-form.tsx +28 -27
  298. package/dist/assets/storefront/src/components/commerce/quote-status-badge.tsx +26 -18
  299. package/dist/assets/storefront/src/components/commerce/quote-validity-indicator.tsx +7 -7
  300. package/dist/assets/storefront/src/components/commerce/quote-version-comparison.tsx +50 -30
  301. package/dist/assets/storefront/src/components/commerce/related-products.tsx +37 -28
  302. package/dist/assets/storefront/src/components/commerce/shared-cart-status-badge.tsx +12 -8
  303. package/dist/assets/storefront/src/components/commerce/shop-by-category.tsx +8 -7
  304. package/dist/assets/storefront/src/components/commerce/shopping-list-toggle.tsx +14 -20
  305. package/dist/assets/storefront/src/components/commerce/sort-dropdown.tsx +9 -16
  306. package/dist/assets/storefront/src/components/commerce/store-credit-summary.tsx +30 -32
  307. package/dist/assets/storefront/src/components/commerce/subcollection-tiles.tsx +11 -13
  308. package/dist/assets/storefront/src/components/layout/auth-page-shell.tsx +2 -2
  309. package/dist/assets/storefront/src/components/layout/draft-mode-indicator.tsx +2 -7
  310. package/dist/assets/storefront/src/components/layout/draft-mode-link.tsx +4 -2
  311. package/dist/assets/storefront/src/components/layout/footer.tsx +70 -28
  312. package/dist/assets/storefront/src/components/layout/navbar/actions.ts +9 -12
  313. package/dist/assets/storefront/src/components/layout/navbar/cart-icon.tsx +9 -9
  314. package/dist/assets/storefront/src/components/layout/navbar/channel-picker-wrapper.tsx +4 -9
  315. package/dist/assets/storefront/src/components/layout/navbar/channel-picker.tsx +13 -8
  316. package/dist/assets/storefront/src/components/layout/navbar/currency-picker-wrapper.tsx +4 -4
  317. package/dist/assets/storefront/src/components/layout/navbar/currency-picker.tsx +11 -6
  318. package/dist/assets/storefront/src/components/layout/navbar/language-picker.tsx +7 -7
  319. package/dist/assets/storefront/src/components/layout/navbar/login-button.tsx +24 -21
  320. package/dist/assets/storefront/src/components/layout/navbar/mobile-nav.tsx +8 -8
  321. package/dist/assets/storefront/src/components/layout/navbar/nav-menu-items.tsx +4 -6
  322. package/dist/assets/storefront/src/components/layout/navbar/navbar-cart.tsx +1 -1
  323. package/dist/assets/storefront/src/components/layout/navbar/navbar-collections.tsx +41 -42
  324. package/dist/assets/storefront/src/components/layout/navbar/navbar-link.tsx +7 -10
  325. package/dist/assets/storefront/src/components/layout/navbar/navbar-user.tsx +18 -23
  326. package/dist/assets/storefront/src/components/layout/navbar/theme-switcher.tsx +9 -9
  327. package/dist/assets/storefront/src/components/layout/navbar.tsx +36 -31
  328. package/dist/assets/storefront/src/components/layout/search-input.tsx +35 -32
  329. package/dist/assets/storefront/src/components/providers/awaiting-approval-banner.tsx +12 -10
  330. package/dist/assets/storefront/src/components/providers/cart-count-server.tsx +14 -12
  331. package/dist/assets/storefront/src/components/providers/company-context-guard.tsx +4 -4
  332. package/dist/assets/storefront/src/components/providers/company-permissions-server.tsx +2 -6
  333. package/dist/assets/storefront/src/components/providers/theme-provider.tsx +3 -3
  334. package/dist/assets/storefront/src/components/shared/breadcrumbs.tsx +4 -1
  335. package/dist/assets/storefront/src/components/shared/country-select.tsx +63 -67
  336. package/dist/assets/storefront/src/components/shared/pagination.tsx +15 -28
  337. package/dist/assets/storefront/src/components/shared/prefetch-link.tsx +1 -1
  338. package/dist/assets/storefront/src/components/shared/skeletons/search-input-skeleton.tsx +1 -3
  339. package/dist/assets/storefront/src/components/ui/accordion.tsx +46 -51
  340. package/dist/assets/storefront/src/components/ui/alert-dialog.tsx +94 -121
  341. package/dist/assets/storefront/src/components/ui/alert.tsx +48 -54
  342. package/dist/assets/storefront/src/components/ui/aspect-ratio.tsx +5 -7
  343. package/dist/assets/storefront/src/components/ui/avatar.tsx +29 -44
  344. package/dist/assets/storefront/src/components/ui/badge.tsx +28 -37
  345. package/dist/assets/storefront/src/components/ui/breadcrumb.tsx +82 -89
  346. package/dist/assets/storefront/src/components/ui/button.tsx +43 -49
  347. package/dist/assets/storefront/src/components/ui/calendar.tsx +157 -198
  348. package/dist/assets/storefront/src/components/ui/card.tsx +53 -76
  349. package/dist/assets/storefront/src/components/ui/carousel.tsx +194 -212
  350. package/dist/assets/storefront/src/components/ui/chart.tsx +274 -317
  351. package/dist/assets/storefront/src/components/ui/checkbox.tsx +24 -27
  352. package/dist/assets/storefront/src/components/ui/collapsible.tsx +9 -21
  353. package/dist/assets/storefront/src/components/ui/command.tsx +114 -159
  354. package/dist/assets/storefront/src/components/ui/context-menu.tsx +167 -199
  355. package/dist/assets/storefront/src/components/ui/dialog.tsx +97 -114
  356. package/dist/assets/storefront/src/components/ui/drawer.tsx +93 -107
  357. package/dist/assets/storefront/src/components/ui/dropdown-menu.tsx +171 -206
  358. package/dist/assets/storefront/src/components/ui/empty-state.tsx +5 -5
  359. package/dist/assets/storefront/src/components/ui/field.tsx +196 -208
  360. package/dist/assets/storefront/src/components/ui/form.tsx +115 -139
  361. package/dist/assets/storefront/src/components/ui/hover-card.tsx +27 -33
  362. package/dist/assets/storefront/src/components/ui/input-otp.tsx +50 -59
  363. package/dist/assets/storefront/src/components/ui/input.tsx +17 -17
  364. package/dist/assets/storefront/src/components/ui/kbd-shortcut.tsx +3 -1
  365. package/dist/assets/storefront/src/components/ui/label.tsx +16 -19
  366. package/dist/assets/storefront/src/components/ui/menubar.tsx +193 -223
  367. package/dist/assets/storefront/src/components/ui/navigation-menu.tsx +123 -130
  368. package/dist/assets/storefront/src/components/ui/pagination.tsx +87 -108
  369. package/dist/assets/storefront/src/components/ui/popover.tsx +29 -35
  370. package/dist/assets/storefront/src/components/ui/progress.tsx +19 -26
  371. package/dist/assets/storefront/src/components/ui/radio-group.tsx +32 -38
  372. package/dist/assets/storefront/src/components/ui/resizable.tsx +37 -42
  373. package/dist/assets/storefront/src/components/ui/scroll-area.tsx +41 -47
  374. package/dist/assets/storefront/src/components/ui/select.tsx +130 -152
  375. package/dist/assets/storefront/src/components/ui/separator.tsx +21 -21
  376. package/dist/assets/storefront/src/components/ui/sheet.tsx +90 -111
  377. package/dist/assets/storefront/src/components/ui/sidebar.tsx +611 -649
  378. package/dist/assets/storefront/src/components/ui/skeleton.tsx +10 -10
  379. package/dist/assets/storefront/src/components/ui/slider.tsx +50 -55
  380. package/dist/assets/storefront/src/components/ui/sonner.tsx +20 -20
  381. package/dist/assets/storefront/src/components/ui/switch.tsx +23 -26
  382. package/dist/assets/storefront/src/components/ui/table.tsx +65 -97
  383. package/dist/assets/storefront/src/components/ui/tabs.tsx +39 -55
  384. package/dist/assets/storefront/src/components/ui/textarea.tsx +14 -14
  385. package/dist/assets/storefront/src/components/ui/toggle-group.tsx +56 -62
  386. package/dist/assets/storefront/src/components/ui/toggle.tsx +37 -38
  387. package/dist/assets/storefront/src/components/ui/tooltip.tsx +38 -46
  388. package/dist/assets/storefront/src/config/capabilities.ts +41 -0
  389. package/dist/assets/storefront/src/config/scenario-meta.ts +2 -2
  390. package/dist/assets/storefront/src/config/scenario.ts +24 -16
  391. package/dist/assets/storefront/src/contexts/auth-context.tsx +5 -6
  392. package/dist/assets/storefront/src/graphql-env.d.ts +47 -41
  393. package/dist/assets/storefront/src/graphql.ts +5 -5
  394. package/dist/assets/storefront/src/hooks/use-mobile.ts +13 -13
  395. package/dist/assets/storefront/src/i18n/locale-utils.ts +3 -3
  396. package/dist/assets/storefront/src/i18n/navigation.ts +4 -4
  397. package/dist/assets/storefront/src/i18n/request.ts +4 -4
  398. package/dist/assets/storefront/src/i18n/routing.ts +5 -5
  399. package/dist/assets/storefront/src/i18n/server.ts +35 -7
  400. package/dist/assets/storefront/src/lib/actions/switch-channel.ts +9 -9
  401. package/dist/assets/storefront/src/lib/actions/switch-currency.ts +7 -7
  402. package/dist/assets/storefront/src/lib/auth.ts +1 -1
  403. package/dist/assets/storefront/src/lib/backend-health.ts +14 -6
  404. package/dist/assets/storefront/src/lib/cart-count-context.tsx +10 -4
  405. package/dist/assets/storefront/src/lib/cart-guard-utils.ts +2 -1
  406. package/dist/assets/storefront/src/lib/cart-guard.ts +7 -6
  407. package/dist/assets/storefront/src/lib/channel-server.ts +4 -4
  408. package/dist/assets/storefront/src/lib/company-context.ts +1 -1
  409. package/dist/assets/storefront/src/lib/company-permissions-context.tsx +1 -5
  410. package/dist/assets/storefront/src/lib/currency-server.ts +4 -4
  411. package/dist/assets/storefront/src/lib/format.ts +16 -7
  412. package/dist/assets/storefront/src/lib/metadata.ts +39 -44
  413. package/dist/assets/storefront/src/lib/quantity.ts +2 -4
  414. package/dist/assets/storefront/src/lib/search-bar-context.tsx +7 -4
  415. package/dist/assets/storefront/src/lib/use-recent-searches.ts +8 -6
  416. package/dist/assets/storefront/src/lib/utils.ts +3 -3
  417. package/dist/assets/storefront/src/lib/vendure/actions.ts +18 -16
  418. package/dist/assets/storefront/src/lib/vendure/api.ts +36 -23
  419. package/dist/assets/storefront/src/lib/vendure/approval-utils.ts +9 -8
  420. package/dist/assets/storefront/src/lib/vendure/cached.ts +20 -15
  421. package/dist/assets/storefront/src/lib/vendure/capability-documents.ts +246 -0
  422. package/dist/assets/storefront/src/lib/vendure/capability-schema.ts +358 -0
  423. package/dist/assets/storefront/src/lib/vendure/capability-ui.ts +15 -0
  424. package/dist/assets/storefront/src/lib/vendure/mutations.ts +835 -532
  425. package/dist/assets/storefront/src/lib/vendure/queries.ts +877 -524
  426. package/dist/assets/storefront/src/proxy.ts +11 -0
  427. package/dist/assets/storefront/src/scenarios/customer/hero.tsx +2 -2
  428. package/dist/assets/storefront/src/scenarios/customer/meta.ts +1 -1
  429. package/dist/assets/storefront/src/schema.graphql +337 -243
  430. package/dist/assets/templates/README.md.hbs +25 -1
  431. package/dist/assets/templates/docker-compose.yml.hbs +4 -0
  432. package/dist/assets/templates/env.hbs +34 -9
  433. package/dist/assets/templates/environment.d.ts.hbs +1 -0
  434. package/dist/assets/templates/gitignore.hbs +7 -4
  435. package/dist/assets/templates/migrate.ts.hbs +55 -0
  436. package/dist/assets/templates/npmrc.hbs +7 -2
  437. package/dist/assets/templates/platform-edition.ts.hbs +21 -0
  438. package/dist/assets/templates/server-package.json.hbs +15 -8
  439. package/dist/assets/templates/vendure-config.ts.hbs +18 -0
  440. package/dist/bin/run.js +1 -1
  441. package/dist/cli.d.ts +1 -1
  442. package/dist/cli.js +1 -1
  443. package/dist/console-onboarding.d.ts +44 -0
  444. package/dist/console-onboarding.js +1 -0
  445. package/dist/hub-projects.d.ts +48 -0
  446. package/dist/hub-projects.js +1 -0
  447. package/dist/index.d.ts +5 -5
  448. package/dist/index.js +1 -1
  449. package/dist/plugin-registry.d.ts +61 -2
  450. package/dist/plugin-registry.js +1 -1
  451. package/dist/registry.d.ts +16 -13
  452. package/dist/registry.js +1 -1
  453. package/dist/scaffold-shared.js +1 -1
  454. package/dist/scaffold-storefront-only.js +1 -1
  455. package/dist/scaffolder.d.ts +11 -0
  456. package/dist/scaffolder.js +1 -1
  457. package/dist/storefront-copier.d.ts +7 -2
  458. package/dist/storefront-copier.js +1 -1
  459. package/dist/template-renderer.d.ts +26 -5
  460. package/dist/template-renderer.js +1 -1
  461. package/dist/types.d.ts +54 -23
  462. package/package.json +14 -2
  463. package/dist/assets/storefront/src/middleware.ts +0 -11
@@ -1,31 +1,25 @@
1
- import {Badge} from '@/components/ui/badge';
2
- import {
3
- Clock,
4
- CheckCircle,
5
- XCircle,
6
- Ban,
7
- type LucideIcon,
8
- } from 'lucide-react';
1
+ import { Badge } from '@/components/ui/badge';
2
+ import { Ban, CheckCircle, Clock, XCircle, type LucideIcon } from 'lucide-react';
9
3
 
10
4
  const STATE_CONFIG: Record<string, { color: string; label: string; icon: LucideIcon }> = {
11
- Pending: {color: 'bg-amber-100 text-amber-800', label: 'Pending', icon: Clock},
12
- Active: {color: 'bg-green-100 text-green-800', label: 'Active', icon: CheckCircle},
13
- Suspended: {color: 'bg-red-100 text-red-800', label: 'Suspended', icon: XCircle},
14
- Denied: {color: 'bg-red-100 text-red-800', label: 'Denied', icon: Ban},
15
- Closed: {color: 'bg-gray-100 text-gray-500', label: 'Closed', icon: Ban},
5
+ Pending: { color: 'bg-amber-100 text-amber-800', label: 'Pending', icon: Clock },
6
+ Active: { color: 'bg-green-100 text-green-800', label: 'Active', icon: CheckCircle },
7
+ Suspended: { color: 'bg-red-100 text-red-800', label: 'Suspended', icon: XCircle },
8
+ Denied: { color: 'bg-red-100 text-red-800', label: 'Denied', icon: Ban },
9
+ Closed: { color: 'bg-gray-100 text-gray-500', label: 'Closed', icon: Ban },
16
10
  };
17
11
 
18
12
  interface CompanyStateBadgeProps {
19
13
  state: string;
20
14
  }
21
15
 
22
- export function CompanyStateBadge({state}: CompanyStateBadgeProps) {
23
- const config = STATE_CONFIG[state] || {color: 'bg-gray-100 text-gray-800', label: state, icon: Clock};
16
+ export function CompanyStateBadge({ state }: CompanyStateBadgeProps) {
17
+ const config = STATE_CONFIG[state] || { color: 'bg-gray-100 text-gray-800', label: state, icon: Clock };
24
18
  const Icon = config.icon;
25
19
 
26
20
  return (
27
21
  <Badge className={config.color} variant="secondary">
28
- <Icon className="h-3 w-3 mr-1"/>
22
+ <Icon className="h-3 w-3 mr-1" />
29
23
  {config.label}
30
24
  </Badge>
31
25
  );
@@ -1,25 +1,25 @@
1
1
  'use client';
2
2
 
3
- import {useTransition} from 'react';
3
+ import { switchCompanyAction } from '@/components/layout/navbar/actions';
4
+ import { Button } from '@/components/ui/button';
4
5
  import {
5
6
  DropdownMenu,
6
7
  DropdownMenuContent,
7
8
  DropdownMenuItem,
8
9
  DropdownMenuTrigger,
9
10
  } from '@/components/ui/dropdown-menu';
10
- import {Button} from '@/components/ui/button';
11
- import {Building, Check, ChevronDown} from 'lucide-react';
12
- import {switchCompanyAction} from '@/components/layout/navbar/actions';
13
- import type {CompanyUserCompany} from '@/lib/vendure/queries';
11
+ import type { CompanyUserCompany } from '@/lib/vendure/queries';
12
+ import { Building, Check, ChevronDown } from 'lucide-react';
13
+ import { useTransition } from 'react';
14
14
 
15
15
  interface CompanySwitcherProps {
16
16
  companies: CompanyUserCompany[];
17
17
  activeCompanyId: string;
18
18
  }
19
19
 
20
- export function CompanySwitcher({companies, activeCompanyId}: CompanySwitcherProps) {
20
+ export function CompanySwitcher({ companies, activeCompanyId }: CompanySwitcherProps) {
21
21
  const [isPending, startTransition] = useTransition();
22
- const activeCompany = companies.find(c => c.id === activeCompanyId);
22
+ const activeCompany = companies.find((c) => c.id === activeCompanyId);
23
23
 
24
24
  if (companies.length <= 1) {
25
25
  return null;
@@ -30,14 +30,14 @@ export function CompanySwitcher({companies, activeCompanyId}: CompanySwitcherPro
30
30
  <DropdownMenuTrigger asChild>
31
31
  <Button variant="ghost" size="sm" className="w-full justify-between" disabled={isPending}>
32
32
  <span className="flex items-center gap-2">
33
- <Building className="h-4 w-4"/>
34
- {isPending ? 'Switching...' : (activeCompany?.name ?? 'Select Company')}
33
+ <Building className="h-4 w-4" />
34
+ {isPending ? 'Switching...' : activeCompany?.name ?? 'Select Company'}
35
35
  </span>
36
- <ChevronDown className="h-3 w-3"/>
36
+ <ChevronDown className="h-3 w-3" />
37
37
  </Button>
38
38
  </DropdownMenuTrigger>
39
39
  <DropdownMenuContent align="start">
40
- {companies.map(company => (
40
+ {companies.map((company) => (
41
41
  <DropdownMenuItem
42
42
  key={company.id}
43
43
  onClick={() => {
@@ -47,7 +47,7 @@ export function CompanySwitcher({companies, activeCompanyId}: CompanySwitcherPro
47
47
  }}
48
48
  >
49
49
  <span className="flex items-center gap-2">
50
- {company.id === activeCompanyId && <Check className="h-3 w-3"/>}
50
+ {company.id === activeCompanyId && <Check className="h-3 w-3" />}
51
51
  {company.name}
52
52
  </span>
53
53
  </DropdownMenuItem>
@@ -1,31 +1,47 @@
1
1
  'use client';
2
2
 
3
- import { useState, useEffect, useRef, useCallback, useTransition, type ReactNode } from 'react';
4
- import { useTranslations } from 'next-intl';
5
- import { Input } from '@/components/ui/input';
3
+ import { Price } from '@/components/commerce/price';
6
4
  import { Button } from '@/components/ui/button';
5
+ import { Drawer, DrawerContent, DrawerHeader, DrawerTitle } from '@/components/ui/drawer';
6
+ import { Input } from '@/components/ui/input';
7
7
  import { Label } from '@/components/ui/label';
8
- import { Switch } from '@/components/ui/switch';
9
8
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
10
- import { Drawer, DrawerContent, DrawerHeader, DrawerTitle } from '@/components/ui/drawer';
11
- import { Price } from '@/components/commerce/price';
12
- import { ShoppingCart, CheckCircle2, ChevronDown, Info, AlertCircle, Loader2, Minus, Plus } from 'lucide-react';
13
- import { toast } from 'sonner';
9
+ import { Switch } from '@/components/ui/switch';
14
10
  import type {
15
- ConfiguratorSystem,
16
- ConfiguratorModule,
17
- ConfiguratorField,
18
11
  ConfigurationEvaluation,
12
+ ConfiguratorField,
13
+ ConfiguratorModule,
14
+ ConfiguratorSystem,
19
15
  EvaluatedField,
20
16
  EvaluatedLine,
21
17
  } from '@/lib/vendure/queries';
18
+ import {
19
+ AlertCircle,
20
+ CheckCircle2,
21
+ ChevronDown,
22
+ Info,
23
+ Loader2,
24
+ Minus,
25
+ Plus,
26
+ ShoppingCart,
27
+ } from 'lucide-react';
28
+ import { useTranslations } from 'next-intl';
29
+ import { useCallback, useEffect, useRef, useState, useTransition, type ReactNode } from 'react';
30
+ import { toast } from 'sonner';
22
31
 
23
32
  interface ConfiguratorFormProps {
24
33
  system: ConfiguratorSystem;
25
34
  productName: string;
26
35
  currencyCode?: string;
27
- evaluateAction: (systemId: string, values: { fieldRef: string; value: string }[]) => Promise<{ data?: ConfigurationEvaluation; error?: string }>;
28
- addToOrderAction: (systemId: string, values: { fieldRef: string; value: string }[], name?: string) => Promise<{ success: boolean; error?: string }>;
36
+ evaluateAction: (
37
+ systemId: string,
38
+ values: { fieldRef: string; value: string }[],
39
+ ) => Promise<{ data?: ConfigurationEvaluation; error?: string }>;
40
+ addToOrderAction: (
41
+ systemId: string,
42
+ values: { fieldRef: string; value: string }[],
43
+ name?: string,
44
+ ) => Promise<{ success: boolean; error?: string }>;
29
45
  children?: ReactNode;
30
46
  }
31
47
 
@@ -33,7 +49,14 @@ function buildFieldRef(moduleCode: string, fieldCode: string) {
33
49
  return `${moduleCode}.${fieldCode}`;
34
50
  }
35
51
 
36
- export function ConfiguratorForm({ system, productName, currencyCode, evaluateAction, addToOrderAction, children }: ConfiguratorFormProps) {
52
+ export function ConfiguratorForm({
53
+ system,
54
+ productName,
55
+ currencyCode,
56
+ evaluateAction,
57
+ addToOrderAction,
58
+ children,
59
+ }: ConfiguratorFormProps) {
37
60
  const t = useTranslations('Configurator');
38
61
  const [values, setValues] = useState<Record<string, string>>(() => {
39
62
  const initial: Record<string, string> = {};
@@ -52,7 +75,7 @@ export function ConfiguratorForm({ system, productName, currencyCode, evaluateAc
52
75
  const [isAdding, startAddTransition] = useTransition();
53
76
  const [isAdded, setIsAdded] = useState(false);
54
77
  const [expandedModules, setExpandedModules] = useState<Set<string>>(() => {
55
- return new Set(system.modules.map(m => m.code));
78
+ return new Set(system.modules.map((m) => m.code));
56
79
  });
57
80
  const [bomDrawerOpen, setBomDrawerOpen] = useState(false);
58
81
  const evalTimeoutRef = useRef<ReturnType<typeof setTimeout>>(undefined);
@@ -79,7 +102,7 @@ export function ConfiguratorForm({ system, productName, currencyCode, evaluateAc
79
102
  }, [values, system.id, evaluateAction, fieldValueEntries]);
80
103
 
81
104
  const handleFieldChange = (moduleCode: string, fieldCode: string, value: string) => {
82
- setValues(prev => ({ ...prev, [buildFieldRef(moduleCode, fieldCode)]: value }));
105
+ setValues((prev) => ({ ...prev, [buildFieldRef(moduleCode, fieldCode)]: value }));
83
106
  };
84
107
 
85
108
  const handleAddToOrder = () => {
@@ -97,7 +120,7 @@ export function ConfiguratorForm({ system, productName, currencyCode, evaluateAc
97
120
  };
98
121
 
99
122
  const toggleModule = (code: string) => {
100
- setExpandedModules(prev => {
123
+ setExpandedModules((prev) => {
101
124
  const next = new Set(prev);
102
125
  if (next.has(code)) next.delete(code);
103
126
  else next.add(code);
@@ -131,8 +154,8 @@ export function ConfiguratorForm({ system, productName, currencyCode, evaluateAc
131
154
  }
132
155
  }
133
156
  const allErrors = [
134
- ...systemErrors.map(e => e.message),
135
- ...fieldIssues.map(e => `${e.fieldName}: ${e.message}`),
157
+ ...systemErrors.map((e) => e.message),
158
+ ...fieldIssues.map((e) => `${e.fieldName}: ${e.message}`),
136
159
  ];
137
160
  const hasErrors = allErrors.length > 0;
138
161
 
@@ -159,9 +182,7 @@ export function ConfiguratorForm({ system, productName, currencyCode, evaluateAc
159
182
  <div className="lg:col-span-3">
160
183
  <div className="grid grid-cols-1 md:grid-cols-2 gap-8">
161
184
  {/* Image + description — sticky */}
162
- <div className="md:sticky md:top-20 md:self-start space-y-5">
163
- {children}
164
- </div>
185
+ <div className="md:sticky md:top-20 md:self-start space-y-5">{children}</div>
165
186
 
166
187
  {/* Configurator form */}
167
188
  <div>
@@ -170,7 +191,11 @@ export function ConfiguratorForm({ system, productName, currencyCode, evaluateAc
170
191
  {lines.length > 0 && (
171
192
  <div className="flex items-center gap-2">
172
193
  <span className="text-3xl font-bold text-primary">
173
- <Price value={totalPrice} currencyCode={currencyCode} taxLabel="excl" />
194
+ <Price
195
+ value={totalPrice}
196
+ currencyCode={currencyCode}
197
+ taxLabel="excl"
198
+ />
174
199
  </span>
175
200
  </div>
176
201
  )}
@@ -179,7 +204,10 @@ export function ConfiguratorForm({ system, productName, currencyCode, evaluateAc
179
204
  {allErrors.length > 0 && (
180
205
  <div className="mt-4 space-y-2">
181
206
  {allErrors.map((msg, i) => (
182
- <div key={i} className="rounded-lg border border-red-200 bg-red-50 px-3 py-2.5 flex items-start gap-2">
207
+ <div
208
+ key={i}
209
+ className="rounded-lg border border-red-200 bg-red-50 px-3 py-2.5 flex items-start gap-2"
210
+ >
183
211
  <AlertCircle className="w-4 h-4 mt-0.5 shrink-0 text-red-500" />
184
212
  <p className="text-sm text-red-800">{msg}</p>
185
213
  </div>
@@ -201,7 +229,6 @@ export function ConfiguratorForm({ system, productName, currencyCode, evaluateAc
201
229
  />
202
230
  ))}
203
231
  </div>
204
-
205
232
  </div>
206
233
  </div>
207
234
  </div>
@@ -211,9 +238,7 @@ export function ConfiguratorForm({ system, productName, currencyCode, evaluateAc
211
238
  <div className="lg:hidden fixed bottom-0 inset-x-0 z-40 border-t border-border bg-background shadow-[0_-4px_12px_rgba(0,0,0,0.05)]">
212
239
  <div className="flex items-center justify-between px-4 py-3">
213
240
  <div>
214
- <p className="text-xs text-muted-foreground">
215
- {t('items', { count: lines.length })}
216
- </p>
241
+ <p className="text-xs text-muted-foreground">{t('items', { count: lines.length })}</p>
217
242
  <p className="text-lg font-bold">
218
243
  <Price value={totalPrice} currencyCode={currencyCode} />
219
244
  </p>
@@ -230,11 +255,20 @@ export function ConfiguratorForm({ system, productName, currencyCode, evaluateAc
230
255
  onClick={handleAddToOrder}
231
256
  >
232
257
  {isAdded ? (
233
- <><CheckCircle2 className="mr-1.5 h-4 w-4" />{t('addedToCart')}</>
258
+ <>
259
+ <CheckCircle2 className="mr-1.5 h-4 w-4" />
260
+ {t('addedToCart')}
261
+ </>
234
262
  ) : isAdding ? (
235
- <><Loader2 className="mr-1.5 h-4 w-4 animate-spin" />{t('adding')}</>
263
+ <>
264
+ <Loader2 className="mr-1.5 h-4 w-4 animate-spin" />
265
+ {t('adding')}
266
+ </>
236
267
  ) : (
237
- <><ShoppingCart className="mr-1.5 h-4 w-4" />{t('addToCart')}</>
268
+ <>
269
+ <ShoppingCart className="mr-1.5 h-4 w-4" />
270
+ {t('addToCart')}
271
+ </>
238
272
  )}
239
273
  </Button>
240
274
  </div>
@@ -249,15 +283,25 @@ export function ConfiguratorForm({ system, productName, currencyCode, evaluateAc
249
283
  </DrawerHeader>
250
284
  <div className="px-4 pb-6 overflow-y-auto max-h-[60vh]">
251
285
  {lines.map((line, i) => (
252
- <div key={line.sourceKey ?? i} className="flex items-center justify-between py-2.5 border-b border-border last:border-0">
286
+ <div
287
+ key={line.sourceKey ?? i}
288
+ className="flex items-center justify-between py-2.5 border-b border-border last:border-0"
289
+ >
253
290
  <div className="min-w-0 flex-1">
254
291
  <p className="text-sm font-medium">{line.productVariant.name}</p>
255
- <p className="text-[11px] text-muted-foreground font-mono">{line.productVariant.sku}</p>
292
+ <p className="text-[11px] text-muted-foreground font-mono">
293
+ {line.productVariant.sku}
294
+ </p>
256
295
  </div>
257
296
  <div className="flex items-center gap-3 shrink-0 ml-3">
258
- <span className="text-xs text-muted-foreground font-mono">×{line.quantity}</span>
297
+ <span className="text-xs text-muted-foreground font-mono">
298
+ ×{line.quantity}
299
+ </span>
259
300
  <span className="text-sm font-mono tabular-nums">
260
- <Price value={line.productVariant.priceWithTax * line.quantity} currencyCode={currencyCode} />
301
+ <Price
302
+ value={line.productVariant.priceWithTax * line.quantity}
303
+ currencyCode={currencyCode}
304
+ />
261
305
  </span>
262
306
  </div>
263
307
  </div>
@@ -308,7 +352,9 @@ function BomSidebar({
308
352
  {lines.length}
309
353
  </span>
310
354
  )}
311
- {isEvaluating && <Loader2 className="w-3.5 h-3.5 animate-spin text-muted-foreground ml-auto" />}
355
+ {isEvaluating && (
356
+ <Loader2 className="w-3.5 h-3.5 animate-spin text-muted-foreground ml-auto" />
357
+ )}
312
358
  </div>
313
359
 
314
360
  {lines.length > 0 ? (
@@ -317,21 +363,28 @@ function BomSidebar({
317
363
  <div key={line.sourceKey ?? i} className="py-2">
318
364
  <div className="flex items-start justify-between gap-2">
319
365
  <div className="min-w-0 flex-1">
320
- <p className="text-sm font-medium leading-tight">{line.productVariant.name}</p>
321
- <p className="text-[11px] text-muted-foreground font-mono mt-0.5">{line.productVariant.sku}</p>
366
+ <p className="text-sm font-medium leading-tight">
367
+ {line.productVariant.name}
368
+ </p>
369
+ <p className="text-[11px] text-muted-foreground font-mono mt-0.5">
370
+ {line.productVariant.sku}
371
+ </p>
322
372
  </div>
323
- <span className="text-xs text-muted-foreground font-mono tabular-nums shrink-0">×{line.quantity}</span>
373
+ <span className="text-xs text-muted-foreground font-mono tabular-nums shrink-0">
374
+ ×{line.quantity}
375
+ </span>
324
376
  </div>
325
377
  <p className="text-sm font-mono tabular-nums text-right mt-0.5">
326
- <Price value={line.productVariant.priceWithTax * line.quantity} currencyCode={currencyCode} />
378
+ <Price
379
+ value={line.productVariant.priceWithTax * line.quantity}
380
+ currencyCode={currencyCode}
381
+ />
327
382
  </p>
328
383
  </div>
329
384
  ))}
330
385
  </div>
331
386
  ) : (
332
- <p className="text-sm text-muted-foreground py-4">
333
- {t('emptyBom')}
334
- </p>
387
+ <p className="text-sm text-muted-foreground py-4">{t('emptyBom')}</p>
335
388
  )}
336
389
  </div>
337
390
 
@@ -350,11 +403,20 @@ function BomSidebar({
350
403
  onClick={onAddToOrder}
351
404
  >
352
405
  {isAdded ? (
353
- <><CheckCircle2 className="mr-2 h-5 w-5" />{t('addedToCart')}</>
406
+ <>
407
+ <CheckCircle2 className="mr-2 h-5 w-5" />
408
+ {t('addedToCart')}
409
+ </>
354
410
  ) : isAdding ? (
355
- <><Loader2 className="mr-2 h-5 w-5 animate-spin" />{t('adding')}</>
411
+ <>
412
+ <Loader2 className="mr-2 h-5 w-5 animate-spin" />
413
+ {t('adding')}
414
+ </>
356
415
  ) : (
357
- <><ShoppingCart className="mr-2 h-5 w-5" />{t('addToCart')}</>
416
+ <>
417
+ <ShoppingCart className="mr-2 h-5 w-5" />
418
+ {t('addToCart')}
419
+ </>
358
420
  )}
359
421
  </Button>
360
422
  </div>
@@ -384,21 +446,21 @@ function ModuleSection({
384
446
  }) {
385
447
  const t = useTranslations('Configurator');
386
448
  const visibleFields = mod.fields
387
- .filter(f => {
449
+ .filter((f) => {
388
450
  const ef = evalFieldMap.get(buildFieldRef(mod.code, f.code));
389
451
  return !ef?.hidden;
390
452
  })
391
453
  .sort((a, b) => a.sortOrder - b.sortOrder);
392
454
 
393
455
  const allFilled = visibleFields
394
- .filter(f => f.required)
395
- .every(f => {
456
+ .filter((f) => f.required)
457
+ .every((f) => {
396
458
  const val = values[buildFieldRef(mod.code, f.code)];
397
459
  return val != null && val !== '';
398
460
  });
399
461
 
400
462
  const summaryParts = visibleFields
401
- .map(f => {
463
+ .map((f) => {
402
464
  const val = values[buildFieldRef(mod.code, f.code)];
403
465
  if (!val) return null;
404
466
  if (f.fieldType === 'BOOL') return val === 'true' ? f.name : null;
@@ -409,17 +471,23 @@ function ModuleSection({
409
471
  const summary = summaryParts.slice(0, 3).join(', ');
410
472
 
411
473
  return (
412
- <section className={`border border-border rounded-lg overflow-hidden transition-shadow ${expanded ? 'ring-1 ring-primary/20' : ''}`}>
474
+ <section
475
+ className={`border border-border rounded-lg overflow-hidden transition-shadow ${
476
+ expanded ? 'ring-1 ring-primary/20' : ''
477
+ }`}
478
+ >
413
479
  <button
414
480
  type="button"
415
481
  onClick={onToggle}
416
482
  className="w-full flex items-center gap-2.5 px-4 py-3 text-left hover:bg-muted/30 transition-colors"
417
483
  >
418
- <div className={`w-5 h-5 rounded-full flex items-center justify-center text-[10px] font-semibold shrink-0 ${
419
- allFilled && summaryParts.length > 0
420
- ? 'bg-primary text-white'
421
- : 'border-2 border-muted-foreground/30 text-muted-foreground'
422
- }`}>
484
+ <div
485
+ className={`w-5 h-5 rounded-full flex items-center justify-center text-[10px] font-semibold shrink-0 ${
486
+ allFilled && summaryParts.length > 0
487
+ ? 'bg-primary text-white'
488
+ : 'border-2 border-muted-foreground/30 text-muted-foreground'
489
+ }`}
490
+ >
423
491
  {allFilled && summaryParts.length > 0 ? (
424
492
  <CheckCircle2 className="w-3 h-3" />
425
493
  ) : (
@@ -427,26 +495,44 @@ function ModuleSection({
427
495
  )}
428
496
  </div>
429
497
  <div className="flex-1 min-w-0">
430
- <h2 className={`text-sm font-semibold ${allFilled && summaryParts.length > 0 ? 'text-foreground' : expanded ? 'text-foreground' : 'text-muted-foreground'}`}>
498
+ <h2
499
+ className={`text-sm font-semibold ${
500
+ allFilled && summaryParts.length > 0
501
+ ? 'text-foreground'
502
+ : expanded
503
+ ? 'text-foreground'
504
+ : 'text-muted-foreground'
505
+ }`}
506
+ >
431
507
  {mod.name}
432
- {mod.optional && <span className="ml-1.5 text-xs font-normal text-muted-foreground">{t('optional')}</span>}
508
+ {mod.optional && (
509
+ <span className="ml-1.5 text-xs font-normal text-muted-foreground">
510
+ {t('optional')}
511
+ </span>
512
+ )}
433
513
  </h2>
434
514
  </div>
435
515
  {!expanded && summary && (
436
- <span className="text-xs text-muted-foreground hidden sm:inline truncate max-w-32">{summary}</span>
516
+ <span className="text-xs text-muted-foreground hidden sm:inline truncate max-w-32">
517
+ {summary}
518
+ </span>
437
519
  )}
438
- <ChevronDown className={`w-4 h-4 text-muted-foreground transition-transform ${expanded ? 'rotate-180' : ''}`} />
520
+ <ChevronDown
521
+ className={`w-4 h-4 text-muted-foreground transition-transform ${
522
+ expanded ? 'rotate-180' : ''
523
+ }`}
524
+ />
439
525
  </button>
440
526
  {expanded && (
441
527
  <div className="px-4 pb-4 pt-2 space-y-3.5 border-t border-border">
442
- {visibleFields.map(field => (
528
+ {visibleFields.map((field) => (
443
529
  <FieldInput
444
530
  key={field.id}
445
531
  field={field}
446
532
  moduleCode={mod.code}
447
533
  value={values[buildFieldRef(mod.code, field.code)] ?? ''}
448
534
  evalField={evalFieldMap.get(buildFieldRef(mod.code, field.code))}
449
- onChange={val => onFieldChange(mod.code, field.code, val)}
535
+ onChange={(val) => onFieldChange(mod.code, field.code, val)}
450
536
  />
451
537
  ))}
452
538
  </div>
@@ -480,7 +566,7 @@ function FieldInput({
480
566
  <Label className="text-sm font-medium">{field.name}</Label>
481
567
  <Switch
482
568
  checked={value === 'true'}
483
- onCheckedChange={checked => onChange(checked ? 'true' : 'false')}
569
+ onCheckedChange={(checked) => onChange(checked ? 'true' : 'false')}
484
570
  />
485
571
  </div>
486
572
  ) : (
@@ -494,15 +580,22 @@ function FieldInput({
494
580
  ) : field.fieldType === 'SELECT' || field.fieldType === 'DYNAMIC_SELECT' ? (
495
581
  <SelectInput field={field} value={value} evalField={evalField} onChange={onChange} />
496
582
  ) : (
497
- <Input value={value} onChange={e => onChange(e.target.value)} />
583
+ <Input value={value} onChange={(e) => onChange(e.target.value)} />
498
584
  )}
499
585
  </>
500
586
  )}
501
587
 
502
588
  {messages.map((msg, i) => (
503
- <p key={i} className={`text-xs flex items-center gap-1 ${
504
- msg.type === 'error' ? 'text-red-600' : msg.type === 'warning' ? 'text-amber-600' : 'text-muted-foreground'
505
- }`}>
589
+ <p
590
+ key={i}
591
+ className={`text-xs flex items-center gap-1 ${
592
+ msg.type === 'error'
593
+ ? 'text-red-600'
594
+ : msg.type === 'warning'
595
+ ? 'text-amber-600'
596
+ : 'text-muted-foreground'
597
+ }`}
598
+ >
506
599
  <Info className="w-3 h-3 shrink-0" />
507
600
  {msg.message}
508
601
  </p>
@@ -512,20 +605,37 @@ function FieldInput({
512
605
  <p className="text-xs text-muted-foreground font-mono tabular-nums">
513
606
  {field.min && field.max
514
607
  ? t('range', {
515
- min: `${Number(field.min).toLocaleString()}`,
516
- max: `${Number(field.max).toLocaleString()}${field.unit ? ` ${field.unit}` : ''}`,
517
- })
608
+ min: `${Number(field.min).toLocaleString()}`,
609
+ max: `${Number(field.max).toLocaleString()}${
610
+ field.unit ? ` ${field.unit}` : ''
611
+ }`,
612
+ })
518
613
  : field.min
519
- ? t('min', { value: `${Number(field.min).toLocaleString()}${field.unit ? ` ${field.unit}` : ''}` })
520
- : t('max', { value: `${Number(field.max).toLocaleString()}${field.unit ? ` ${field.unit}` : ''}` })
521
- }
614
+ ? t('min', {
615
+ value: `${Number(field.min).toLocaleString()}${
616
+ field.unit ? ` ${field.unit}` : ''
617
+ }`,
618
+ })
619
+ : t('max', {
620
+ value: `${Number(field.max).toLocaleString()}${
621
+ field.unit ? ` ${field.unit}` : ''
622
+ }`,
623
+ })}
522
624
  </p>
523
625
  )}
524
626
  </div>
525
627
  );
526
628
  }
527
629
 
528
- function NumberInput({ field, value, onChange }: { field: ConfiguratorField; value: string; onChange: (v: string) => void }) {
630
+ function NumberInput({
631
+ field,
632
+ value,
633
+ onChange,
634
+ }: {
635
+ field: ConfiguratorField;
636
+ value: string;
637
+ onChange: (v: string) => void;
638
+ }) {
529
639
  const step = field.unit === 'mm' ? 100 : 1;
530
640
  const min = field.min ? Number(field.min) : undefined;
531
641
  const max = field.max ? Number(field.max) : undefined;
@@ -553,7 +663,7 @@ function NumberInput({ field, value, onChange }: { field: ConfiguratorField; val
553
663
  min={min}
554
664
  max={max}
555
665
  step={step}
556
- onChange={e => onChange(e.target.value)}
666
+ onChange={(e) => onChange(e.target.value)}
557
667
  className="flex-1 h-9 px-3 text-sm focus:outline-none bg-transparent font-mono tabular-nums text-center [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
558
668
  />
559
669
  <button
@@ -585,8 +695,8 @@ function SelectInput({
585
695
  }) {
586
696
  const t = useTranslations('Configurator');
587
697
  const options = evalField?.availableOptions?.length
588
- ? evalField.availableOptions.map(o => ({ value: o.value, label: o.label ?? o.value }))
589
- : (field.options ?? []).map(o => ({ value: o.code, label: o.label }));
698
+ ? evalField.availableOptions.map((o) => ({ value: o.value, label: o.label ?? o.value }))
699
+ : (field.options ?? []).map((o) => ({ value: o.code, label: o.label }));
590
700
 
591
701
  return (
592
702
  <Select value={value || undefined} onValueChange={onChange}>
@@ -594,7 +704,7 @@ function SelectInput({
594
704
  <SelectValue placeholder={t('selectPlaceholder', { field: field.name.toLowerCase() })} />
595
705
  </SelectTrigger>
596
706
  <SelectContent>
597
- {options.map(opt => (
707
+ {options.map((opt) => (
598
708
  <SelectItem key={opt.value} value={opt.value}>
599
709
  {opt.label}
600
710
  </SelectItem>
@@ -603,4 +713,3 @@ function SelectInput({
603
713
  </Select>
604
714
  );
605
715
  }
606
-