@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,19 +1,19 @@
1
1
  'use client';
2
2
 
3
- import {useState, useTransition, useCallback, useEffect, useRef} from 'react';
4
- import {useRouter} from '@/i18n/navigation';
5
- import {Button} from '@/components/ui/button';
6
- import {Textarea} from '@/components/ui/textarea';
7
- import {XCircle, MessageSquare, ShoppingCart, Send, Loader2, AlertTriangle} from 'lucide-react';
8
- import {useTranslations} from 'next-intl';
9
3
  import {
10
- submitQuote,
4
+ acceptAndConvertQuote,
11
5
  acceptQuote,
6
+ checkQuoteStock,
12
7
  rejectQuote,
13
8
  requestQuoteChanges,
14
- acceptAndConvertQuote,
15
- checkQuoteStock,
9
+ submitQuote,
16
10
  } from '@/app/[locale]/account/quotes/actions';
11
+ import { Button } from '@/components/ui/button';
12
+ import { Textarea } from '@/components/ui/textarea';
13
+ import { useRouter } from '@/i18n/navigation';
14
+ import { AlertTriangle, Loader2, MessageSquare, Send, ShoppingCart, XCircle } from 'lucide-react';
15
+ import { useTranslations } from 'next-intl';
16
+ import { useCallback, useEffect, useRef, useState, useTransition } from 'react';
17
17
 
18
18
  const TERMINAL_STATUSES = new Set(['ACCEPTED', 'REJECTED', 'CANCELLED', 'EXPIRED']);
19
19
  const POLL_INTERVAL_MS = 1000;
@@ -23,14 +23,29 @@ interface QuoteActionButtonsProps {
23
23
  quoteId: string;
24
24
  status: string;
25
25
  convertedOrderId?: string | null;
26
+ /**
27
+ * Whether the deployment is granted `quote.negotiation`.
28
+ *
29
+ * Resolved by the server component that renders this one. Reading the
30
+ * capability hint here instead would inline the deployment's entire granted
31
+ * capability list into this client chunk, because Next.js replaces
32
+ * `process.env.NEXT_PUBLIC_*` with its literal value wherever the module
33
+ * graph reaches the browser.
34
+ */
35
+ hasQuoteNegotiation: boolean;
26
36
  }
27
37
 
28
- export function QuoteActionButtons({quoteId, status, convertedOrderId}: QuoteActionButtonsProps) {
38
+ export function QuoteActionButtons({
39
+ quoteId,
40
+ status,
41
+ convertedOrderId,
42
+ hasQuoteNegotiation,
43
+ }: QuoteActionButtonsProps) {
29
44
  const router = useRouter();
30
45
  const t = useTranslations('Quotes');
31
46
  const [reason, setReason] = useState('');
32
47
  const [isPending, startTransition] = useTransition();
33
- const [result, setResult] = useState<{success: boolean; message?: string} | null>(null);
48
+ const [result, setResult] = useState<{ success: boolean; message?: string } | null>(null);
34
49
  const [polling, setPolling] = useState(false);
35
50
  const pollCount = useRef(0);
36
51
  const initialStatus = useRef(status);
@@ -66,19 +81,22 @@ export function QuoteActionButtons({quoteId, status, convertedOrderId}: QuoteAct
66
81
  return () => clearInterval(timer);
67
82
  }, [polling, router]);
68
83
 
69
- const handleAction = useCallback((action: () => Promise<{success: boolean; message?: string; redirectTo?: string}>) => {
70
- startTransition(async () => {
71
- const res = await action();
72
- setResult(res);
73
- if (res.success && 'redirectTo' in res && res.redirectTo) {
74
- router.push(res.redirectTo);
75
- } else if (res.success) {
76
- pollCount.current = 0;
77
- setPolling(true);
78
- router.refresh();
79
- }
80
- });
81
- }, [router]);
84
+ const handleAction = useCallback(
85
+ (action: () => Promise<{ success: boolean; message?: string; redirectTo?: string }>) => {
86
+ startTransition(async () => {
87
+ const res = await action();
88
+ setResult(res);
89
+ if (res.success && 'redirectTo' in res && res.redirectTo) {
90
+ router.push(res.redirectTo);
91
+ } else if (res.success) {
92
+ pollCount.current = 0;
93
+ setPolling(true);
94
+ router.refresh();
95
+ }
96
+ });
97
+ },
98
+ [router],
99
+ );
82
100
 
83
101
  if (TERMINAL_STATUSES.has(status) && status !== 'ACCEPTED') {
84
102
  return null;
@@ -91,7 +109,7 @@ export function QuoteActionButtons({quoteId, status, convertedOrderId}: QuoteAct
91
109
  if (polling) {
92
110
  return (
93
111
  <div className="flex items-center gap-2 rounded-md border border-blue-200 bg-blue-50 p-3 text-sm text-blue-800">
94
- <Loader2 className="h-4 w-4 animate-spin"/>
112
+ <Loader2 className="h-4 w-4 animate-spin" />
95
113
  {t('actionProcessing')}
96
114
  </div>
97
115
  );
@@ -106,7 +124,7 @@ export function QuoteActionButtons({quoteId, status, convertedOrderId}: QuoteAct
106
124
  disabled={isPending}
107
125
  className="w-full"
108
126
  >
109
- <Send className="h-4 w-4 mr-1"/>
127
+ <Send className="h-4 w-4 mr-1" />
110
128
  {t('actionSubmitQuoteRequest')}
111
129
  </Button>
112
130
  )}
@@ -116,14 +134,23 @@ export function QuoteActionButtons({quoteId, status, convertedOrderId}: QuoteAct
116
134
  {stockWarning && (
117
135
  <div className="rounded-md border border-amber-200 bg-amber-50 p-4 space-y-3">
118
136
  <div className="flex items-start gap-2">
119
- <AlertTriangle className="h-4 w-4 text-amber-600 mt-0.5 shrink-0"/>
137
+ <AlertTriangle className="h-4 w-4 text-amber-600 mt-0.5 shrink-0" />
120
138
  <div>
121
- <p className="text-sm font-medium text-amber-900">{t('stockWarningTitle')}</p>
139
+ <p className="text-sm font-medium text-amber-900">
140
+ {t('stockWarningTitle')}
141
+ </p>
122
142
  <ul className="text-xs text-amber-800 mt-1.5 space-y-1">
123
- {stockWarning.map(item => (
143
+ {stockWarning.map((item) => (
124
144
  <li key={item.sku}>
125
145
  <span className="font-medium">{item.productName}</span>
126
- <span className="text-amber-700"> — {t('stockWarningNeedAvailable', {needed: item.requestedQuantity, available: item.availableStock})}</span>
146
+ <span className="text-amber-700">
147
+ {' '}
148
+ —{' '}
149
+ {t('stockWarningNeedAvailable', {
150
+ needed: item.requestedQuantity,
151
+ available: item.availableStock,
152
+ })}
153
+ </span>
127
154
  </li>
128
155
  ))}
129
156
  </ul>
@@ -162,7 +189,7 @@ export function QuoteActionButtons({quoteId, status, convertedOrderId}: QuoteAct
162
189
  )}
163
190
  {!stockWarning && (
164
191
  <>
165
- {status === 'QUOTED' && (
192
+ {status === 'QUOTED' && hasQuoteNegotiation && (
166
193
  <Textarea
167
194
  placeholder={t('changeRequestPlaceholder')}
168
195
  value={reason}
@@ -194,29 +221,37 @@ export function QuoteActionButtons({quoteId, status, convertedOrderId}: QuoteAct
194
221
  disabled={isPending}
195
222
  className="w-full"
196
223
  >
197
- <ShoppingCart className="h-4 w-4 mr-2"/>
198
- {status === 'ACCEPTED' ? t('actionProceedToCheckout') : t('actionAcceptAndCheckout')}
224
+ <ShoppingCart className="h-4 w-4 mr-2" />
225
+ {status === 'ACCEPTED'
226
+ ? t('actionProceedToCheckout')
227
+ : t('actionAcceptAndCheckout')}
199
228
  </Button>
200
229
  {status === 'QUOTED' && (
201
230
  <>
202
- <Button
203
- variant="outline"
204
- size="sm"
205
- onClick={() => handleAction(() => requestQuoteChanges(quoteId, reason))}
206
- disabled={isPending || !reason.trim()}
207
- className="w-full"
208
- >
209
- <MessageSquare className="h-4 w-4 mr-1"/>
210
- {t('actionRequestChanges')}
211
- </Button>
231
+ {hasQuoteNegotiation && (
232
+ <Button
233
+ variant="outline"
234
+ size="sm"
235
+ onClick={() =>
236
+ handleAction(() => requestQuoteChanges(quoteId, reason))
237
+ }
238
+ disabled={isPending || !reason.trim()}
239
+ className="w-full"
240
+ >
241
+ <MessageSquare className="h-4 w-4 mr-1" />
242
+ {t('actionRequestChanges')}
243
+ </Button>
244
+ )}
212
245
  <Button
213
246
  variant="destructive"
214
247
  size="sm"
215
- onClick={() => handleAction(() => rejectQuote(quoteId, reason || undefined))}
248
+ onClick={() =>
249
+ handleAction(() => rejectQuote(quoteId, reason || undefined))
250
+ }
216
251
  disabled={isPending}
217
252
  className="w-full"
218
253
  >
219
- <XCircle className="h-4 w-4 mr-1"/>
254
+ <XCircle className="h-4 w-4 mr-1" />
220
255
  {t('actionRejectQuote')}
221
256
  </Button>
222
257
  </>
@@ -1,12 +1,21 @@
1
1
  'use client';
2
2
 
3
- import {useState} from 'react';
4
- import {useLocale} from 'next-intl';
5
- import {Card, CardContent, CardHeader, CardTitle} from '@/components/ui/card';
6
- import {Price} from '@/components/commerce/price';
7
- import {formatDateTime} from '@/lib/format';
8
- import {FileText, MessageSquare, Send, ArrowRight, Plus, Minus, ChevronDown, ChevronRight} from 'lucide-react';
9
- import type {QuoteVersion, QuoteComment} from '@/lib/vendure/queries';
3
+ import { Price } from '@/components/commerce/price';
4
+ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
5
+ import { formatDateTime } from '@/lib/format';
6
+ import type { QuoteComment, QuoteVersion } from '@/lib/vendure/queries';
7
+ import {
8
+ ArrowRight,
9
+ ChevronDown,
10
+ ChevronRight,
11
+ FileText,
12
+ MessageSquare,
13
+ Minus,
14
+ Plus,
15
+ Send,
16
+ } from 'lucide-react';
17
+ import { useLocale } from 'next-intl';
18
+ import { useState } from 'react';
10
19
 
11
20
  type TimelineItem =
12
21
  | { type: 'version'; version: QuoteVersion; timestamp: number }
@@ -24,17 +33,27 @@ interface QuoteActivityTimelineProps {
24
33
  currencyCode: string;
25
34
  }
26
35
 
27
- export function QuoteActivityTimeline({versions, comments, currentVersionNumber, currencyCode}: QuoteActivityTimelineProps) {
36
+ export function QuoteActivityTimeline({
37
+ versions,
38
+ comments,
39
+ currentVersionNumber,
40
+ currencyCode,
41
+ }: QuoteActivityTimelineProps) {
28
42
  const locale = useLocale();
29
43
  const sorted = [...versions].sort((a, b) => a.versionNumber - b.versionNumber);
30
44
 
31
45
  // Build timeline items
32
46
  const items: TimelineItem[] = [];
33
47
  for (const version of sorted) {
34
- items.push({type: 'version', version, timestamp: new Date(version.createdAt).getTime()});
48
+ items.push({ type: 'version', version, timestamp: new Date(version.createdAt).getTime() });
35
49
  }
36
50
  for (const comment of comments) {
37
- items.push({type: 'comment', comment, timestamp: new Date(comment.createdAt).getTime(), grouped: false});
51
+ items.push({
52
+ type: 'comment',
53
+ comment,
54
+ timestamp: new Date(comment.createdAt).getTime(),
55
+ grouped: false,
56
+ });
38
57
  }
39
58
  items.sort((a, b) => a.timestamp - b.timestamp);
40
59
 
@@ -44,12 +63,18 @@ export function QuoteActivityTimeline({versions, comments, currentVersionNumber,
44
63
  if (item.type === 'comment') {
45
64
  for (let j = i - 1; j >= 0; j--) {
46
65
  if (Math.abs(item.timestamp - items[j].timestamp) > GROUP_THRESHOLD_MS) break;
47
- if (items[j].type === 'version') {item.grouped = true; break;}
66
+ if (items[j].type === 'version') {
67
+ item.grouped = true;
68
+ break;
69
+ }
48
70
  }
49
71
  if (!item.grouped) {
50
72
  for (let j = i + 1; j < items.length; j++) {
51
73
  if (Math.abs(items[j].timestamp - item.timestamp) > GROUP_THRESHOLD_MS) break;
52
- if (items[j].type === 'version') {item.grouped = true; break;}
74
+ if (items[j].type === 'version') {
75
+ item.grouped = true;
76
+ break;
77
+ }
53
78
  }
54
79
  }
55
80
  }
@@ -103,8 +128,8 @@ export function QuoteActivityTimeline({versions, comments, currentVersionNumber,
103
128
  // ── Version diff logic ──
104
129
 
105
130
  interface VersionDiff {
106
- addedItems: Array<{productName: string; sku: string; quantity: number; unitPrice: number}>;
107
- removedItems: Array<{productName: string; sku: string}>;
131
+ addedItems: Array<{ productName: string; sku: string; quantity: number; unitPrice: number }>;
132
+ removedItems: Array<{ productName: string; sku: string }>;
108
133
  changedItems: Array<{
109
134
  productName: string;
110
135
  sku: string;
@@ -119,8 +144,8 @@ interface VersionDiff {
119
144
  }
120
145
 
121
146
  function computeDiff(prev: QuoteVersion, curr: QuoteVersion): VersionDiff {
122
- const prevBySku = new Map(prev.lineItems.map(li => [li.sku, li]));
123
- const currBySku = new Map(curr.lineItems.map(li => [li.sku, li]));
147
+ const prevBySku = new Map(prev.lineItems.map((li) => [li.sku, li]));
148
+ const currBySku = new Map(curr.lineItems.map((li) => [li.sku, li]));
124
149
 
125
150
  const addedItems: VersionDiff['addedItems'] = [];
126
151
  const removedItems: VersionDiff['removedItems'] = [];
@@ -129,7 +154,12 @@ function computeDiff(prev: QuoteVersion, curr: QuoteVersion): VersionDiff {
129
154
  for (const [sku, item] of currBySku) {
130
155
  const prevItem = prevBySku.get(sku);
131
156
  if (!prevItem) {
132
- addedItems.push({productName: item.productName, sku, quantity: item.quantity, unitPrice: item.unitPrice});
157
+ addedItems.push({
158
+ productName: item.productName,
159
+ sku,
160
+ quantity: item.quantity,
161
+ unitPrice: item.unitPrice,
162
+ });
133
163
  } else {
134
164
  const priceChanged = item.unitPrice !== prevItem.unitPrice;
135
165
  const qtyChanged = item.quantity !== prevItem.quantity;
@@ -149,19 +179,21 @@ function computeDiff(prev: QuoteVersion, curr: QuoteVersion): VersionDiff {
149
179
  }
150
180
  for (const [sku, item] of prevBySku) {
151
181
  if (!currBySku.has(sku)) {
152
- removedItems.push({productName: item.productName, sku});
182
+ removedItems.push({ productName: item.productName, sku });
153
183
  }
154
184
  }
155
185
 
156
- return {addedItems, removedItems, changedItems, totalDelta: curr.total - prev.total};
186
+ return { addedItems, removedItems, changedItems, totalDelta: curr.total - prev.total };
157
187
  }
158
188
 
159
189
  function buildSummary(diff: VersionDiff): string {
160
190
  const parts: string[] = [];
161
- if (diff.addedItems.length > 0) parts.push(`+${diff.addedItems.length} item${diff.addedItems.length > 1 ? 's' : ''}`);
162
- if (diff.removedItems.length > 0) parts.push(`-${diff.removedItems.length} item${diff.removedItems.length > 1 ? 's' : ''}`);
163
- const priceChanges = diff.changedItems.filter(c => c.priceChanged).length;
164
- const qtyChanges = diff.changedItems.filter(c => c.qtyChanged).length;
191
+ if (diff.addedItems.length > 0)
192
+ parts.push(`+${diff.addedItems.length} item${diff.addedItems.length > 1 ? 's' : ''}`);
193
+ if (diff.removedItems.length > 0)
194
+ parts.push(`-${diff.removedItems.length} item${diff.removedItems.length > 1 ? 's' : ''}`);
195
+ const priceChanges = diff.changedItems.filter((c) => c.priceChanged).length;
196
+ const qtyChanges = diff.changedItems.filter((c) => c.qtyChanged).length;
165
197
  if (priceChanges > 0) parts.push(`${priceChanges} price change${priceChanges > 1 ? 's' : ''}`);
166
198
  if (qtyChanges > 0) parts.push(`${qtyChanges} qty change${qtyChanges > 1 ? 's' : ''}`);
167
199
  return parts.join(', ');
@@ -169,7 +201,19 @@ function buildSummary(diff: VersionDiff): string {
169
201
 
170
202
  // ── Timeline entries ──
171
203
 
172
- function VersionEntry({version, isCurrent, diff, locale, currencyCode}: {version: QuoteVersion; isCurrent: boolean; diff?: VersionDiff; locale: string; currencyCode: string}) {
204
+ function VersionEntry({
205
+ version,
206
+ isCurrent,
207
+ diff,
208
+ locale,
209
+ currencyCode,
210
+ }: {
211
+ version: QuoteVersion;
212
+ isCurrent: boolean;
213
+ diff?: VersionDiff;
214
+ locale: string;
215
+ currencyCode: string;
216
+ }) {
173
217
  const isFirst = version.versionNumber === 1;
174
218
  const summary = diff ? buildSummary(diff) : null;
175
219
  const totalChanges = diff
@@ -178,18 +222,22 @@ function VersionEntry({version, isCurrent, diff, locale, currencyCode}: {version
178
222
  const hasChanges = totalChanges > 0;
179
223
  const [expanded, setExpanded] = useState(totalChanges <= COLLAPSE_THRESHOLD);
180
224
 
181
- const allDiffRows = diff ? [
182
- ...diff.addedItems.map(item => ({type: 'added' as const, ...item})),
183
- ...diff.removedItems.map(item => ({type: 'removed' as const, ...item})),
184
- ...diff.changedItems.map(item => ({type: 'changed' as const, ...item})),
185
- ] : [];
225
+ const allDiffRows = diff
226
+ ? [
227
+ ...diff.addedItems.map((item) => ({ type: 'added' as const, ...item })),
228
+ ...diff.removedItems.map((item) => ({ type: 'removed' as const, ...item })),
229
+ ...diff.changedItems.map((item) => ({ type: 'changed' as const, ...item })),
230
+ ]
231
+ : [];
186
232
 
187
233
  return (
188
234
  <div className="relative flex gap-3 py-3 group">
189
235
  <div className="relative z-10 flex-shrink-0">
190
- <div className={`h-6 w-6 rounded-full flex items-center justify-center shadow-sm ${
191
- isFirst ? 'bg-muted text-muted-foreground' : 'bg-primary text-primary-foreground'
192
- }`}>
236
+ <div
237
+ className={`h-6 w-6 rounded-full flex items-center justify-center shadow-sm ${
238
+ isFirst ? 'bg-muted text-muted-foreground' : 'bg-primary text-primary-foreground'
239
+ }`}
240
+ >
193
241
  {isFirst ? <FileText className="h-3 w-3" /> : <Send className="h-3 w-3" />}
194
242
  </div>
195
243
  </div>
@@ -206,12 +254,12 @@ function VersionEntry({version, isCurrent, diff, locale, currencyCode}: {version
206
254
  </span>
207
255
  )}
208
256
  </div>
209
- {summary && (
210
- <p className="text-xs text-muted-foreground mt-0.5">{summary}</p>
211
- )}
257
+ {summary && <p className="text-xs text-muted-foreground mt-0.5">{summary}</p>}
212
258
  </div>
213
259
  <div className="text-right flex-shrink-0 ml-4">
214
- <p className="text-xs text-muted-foreground">{formatDateTime(version.createdAt, locale)}</p>
260
+ <p className="text-xs text-muted-foreground">
261
+ {formatDateTime(version.createdAt, locale)}
262
+ </p>
215
263
  <p className="text-sm font-medium">
216
264
  <Price value={version.total} currencyCode={currencyCode} taxLabel="excl" />
217
265
  </p>
@@ -225,28 +273,37 @@ function VersionEntry({version, isCurrent, diff, locale, currencyCode}: {version
225
273
  onClick={() => setExpanded(!expanded)}
226
274
  className="flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors mb-1"
227
275
  >
228
- {expanded
229
- ? <ChevronDown className="h-3 w-3" />
230
- : <ChevronRight className="h-3 w-3" />
231
- }
276
+ {expanded ? (
277
+ <ChevronDown className="h-3 w-3" />
278
+ ) : (
279
+ <ChevronRight className="h-3 w-3" />
280
+ )}
232
281
  {expanded ? 'Hide' : 'Show'} {totalChanges} changes
233
282
  </button>
234
283
  )}
235
284
  {expanded && (
236
285
  <div className="text-xs space-y-1 border-l-2 border-muted pl-3">
237
- {allDiffRows.map(row => {
286
+ {allDiffRows.map((row) => {
238
287
  if (row.type === 'added') {
239
288
  return (
240
- <div key={row.sku} className="flex items-center gap-1.5 text-green-600 dark:text-green-400">
289
+ <div
290
+ key={row.sku}
291
+ className="flex items-center gap-1.5 text-green-600 dark:text-green-400"
292
+ >
241
293
  <Plus className="h-3 w-3" />
242
294
  <span>{row.productName}</span>
243
- <span className="text-muted-foreground">× {row.quantity}</span>
295
+ <span className="text-muted-foreground">
296
+ × {row.quantity}
297
+ </span>
244
298
  </div>
245
299
  );
246
300
  }
247
301
  if (row.type === 'removed') {
248
302
  return (
249
- <div key={row.sku} className="flex items-center gap-1.5 text-red-600 dark:text-red-400 line-through">
303
+ <div
304
+ key={row.sku}
305
+ className="flex items-center gap-1.5 text-red-600 dark:text-red-400 line-through"
306
+ >
250
307
  <Minus className="h-3 w-3" />
251
308
  <span>{row.productName}</span>
252
309
  </div>
@@ -259,11 +316,22 @@ function VersionEntry({version, isCurrent, diff, locale, currencyCode}: {version
259
316
  {row.priceChanged && (
260
317
  <span>
261
318
  <span className="text-muted-foreground line-through">
262
- <Price value={row.prevPrice} currencyCode={currencyCode} />
263
- </span>
264
- {' '}
265
- <span className={row.newPrice < row.prevPrice ? 'text-green-600' : 'text-red-600'}>
266
- <Price value={row.newPrice} currencyCode={currencyCode} />
319
+ <Price
320
+ value={row.prevPrice}
321
+ currencyCode={currencyCode}
322
+ />
323
+ </span>{' '}
324
+ <span
325
+ className={
326
+ row.newPrice < row.prevPrice
327
+ ? 'text-green-600'
328
+ : 'text-red-600'
329
+ }
330
+ >
331
+ <Price
332
+ value={row.newPrice}
333
+ currencyCode={currencyCode}
334
+ />
267
335
  </span>
268
336
  </span>
269
337
  )}
@@ -284,7 +352,15 @@ function VersionEntry({version, isCurrent, diff, locale, currencyCode}: {version
284
352
  );
285
353
  }
286
354
 
287
- function CommentEntry({comment, grouped, locale}: {comment: QuoteComment; grouped: boolean; locale: string}) {
355
+ function CommentEntry({
356
+ comment,
357
+ grouped,
358
+ locale,
359
+ }: {
360
+ comment: QuoteComment;
361
+ grouped: boolean;
362
+ locale: string;
363
+ }) {
288
364
  const authorName = comment.authorCustomer
289
365
  ? `${comment.authorCustomer.firstName} ${comment.authorCustomer.lastName}`
290
366
  : 'Seller';
@@ -1,19 +1,19 @@
1
1
  'use client';
2
2
 
3
- import {useState, useTransition} from 'react';
4
- import {Button} from '@/components/ui/button';
5
- import {Textarea} from '@/components/ui/textarea';
6
- import {Send} from 'lucide-react';
7
- import {addQuoteComment} from '@/app/[locale]/account/quotes/actions';
3
+ import { addQuoteComment } from '@/app/[locale]/account/quotes/actions';
4
+ import { Button } from '@/components/ui/button';
5
+ import { Textarea } from '@/components/ui/textarea';
6
+ import { Send } from 'lucide-react';
7
+ import { useState, useTransition } from 'react';
8
8
 
9
9
  interface QuoteCommentFormProps {
10
10
  quoteId: string;
11
11
  }
12
12
 
13
- export function QuoteCommentForm({quoteId}: QuoteCommentFormProps) {
13
+ export function QuoteCommentForm({ quoteId }: QuoteCommentFormProps) {
14
14
  const [text, setText] = useState('');
15
15
  const [isPending, startTransition] = useTransition();
16
- const [result, setResult] = useState<{success: boolean; message?: string} | null>(null);
16
+ const [result, setResult] = useState<{ success: boolean; message?: string } | null>(null);
17
17
 
18
18
  function handleSubmit() {
19
19
  if (!text.trim()) return;
@@ -39,12 +39,8 @@ export function QuoteCommentForm({quoteId}: QuoteCommentFormProps) {
39
39
  {result && !result.success && (
40
40
  <p className="text-sm text-red-600">{result.message || 'Failed to add comment'}</p>
41
41
  )}
42
- <Button
43
- size="sm"
44
- onClick={handleSubmit}
45
- disabled={isPending || !text.trim()}
46
- >
47
- <Send className="h-4 w-4 mr-1"/>
42
+ <Button size="sm" onClick={handleSubmit} disabled={isPending || !text.trim()}>
43
+ <Send className="h-4 w-4 mr-1" />
48
44
  Send
49
45
  </Button>
50
46
  </div>
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
- import {Download} from 'lucide-react';
4
- import {Button} from '@/components/ui/button';
3
+ import { Button } from '@/components/ui/button';
4
+ import { Download } from 'lucide-react';
5
5
 
6
6
  interface QuoteCsvExportButtonProps {
7
7
  quoteNumber: string;
@@ -37,7 +37,7 @@ export function QuoteCsvExportButton({
37
37
  v1LineItems,
38
38
  }: QuoteCsvExportButtonProps) {
39
39
  const hasComparison = v1LineItems && v1LineItems.length > 0;
40
- const v1BySku = new Map(v1LineItems?.map(item => [item.sku, item]) ?? []);
40
+ const v1BySku = new Map(v1LineItems?.map((item) => [item.sku, item]) ?? []);
41
41
 
42
42
  function handleExport() {
43
43
  const headers = ['SKU', 'Product Name', 'Quantity', 'Unit Price', 'Line Total'];
@@ -78,8 +78,8 @@ export function QuoteCsvExportButton({
78
78
  rows.push(['', '', '', 'Shipping', (shippingCost / 100).toFixed(2)]);
79
79
  rows.push(['', '', '', 'Total', (total / 100).toFixed(2)]);
80
80
 
81
- const csv = rows.map(row => row.join(',')).join('\n');
82
- const blob = new Blob([csv], {type: 'text/csv;charset=utf-8;'});
81
+ const csv = rows.map((row) => row.join(',')).join('\n');
82
+ const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
83
83
  const url = URL.createObjectURL(blob);
84
84
  const link = document.createElement('a');
85
85
  link.href = url;
@@ -90,7 +90,7 @@ export function QuoteCsvExportButton({
90
90
 
91
91
  return (
92
92
  <Button variant="outline" size="sm" onClick={handleExport}>
93
- <Download className="h-4 w-4 mr-2"/>
93
+ <Download className="h-4 w-4 mr-2" />
94
94
  Export CSV
95
95
  </Button>
96
96
  );