@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,32 +1,34 @@
1
- import type {Metadata} from 'next';
2
- import {Suspense} from 'react';
3
- import {ChevronLeft, AlertTriangle, Info} from 'lucide-react';
4
- import {client} from '@/lib/vendure/api';
5
- import {GetMyQuoteDetailQuery} from '@/lib/vendure/queries';
6
- import {Button} from '@/components/ui/button';
7
- import {Card, CardContent, CardHeader, CardTitle} from '@/components/ui/card';
8
- import {Separator} from '@/components/ui/separator';
9
- import {Price} from '@/components/commerce/price';
10
- import {QuoteStatusBadge} from '@/components/commerce/quote-status-badge';
11
- import {QuoteActionButtons} from '@/components/commerce/quote-action-buttons';
12
- import {QuoteVersionComparison} from '@/components/commerce/quote-version-comparison';
13
- import {QuoteActivityTimeline} from '@/components/commerce/quote-activity-timeline';
14
- import {QuoteValidityIndicator} from '@/components/commerce/quote-validity-indicator';
15
- import {QuoteCsvExportButton} from '@/components/commerce/quote-csv-export-button';
16
- import {formatDate} from '@/lib/format';
17
- import {getActiveChannelCached} from '@/lib/vendure/cached';
18
- import {getActiveChannelToken} from '@/lib/channel-server';
19
- import {setRequestLocale, getTranslations} from 'next-intl/server';
20
- import {Link, redirect} from '@/i18n/navigation';
1
+ import { Price } from '@/components/commerce/price';
2
+ import { QuoteActionButtons } from '@/components/commerce/quote-action-buttons';
3
+ import { QuoteActivityTimeline } from '@/components/commerce/quote-activity-timeline';
4
+ import { QuoteCsvExportButton } from '@/components/commerce/quote-csv-export-button';
5
+ import { QuoteStatusBadge } from '@/components/commerce/quote-status-badge';
6
+ import { QuoteValidityIndicator } from '@/components/commerce/quote-validity-indicator';
7
+ import { QuoteVersionComparison } from '@/components/commerce/quote-version-comparison';
8
+ import { Button } from '@/components/ui/button';
9
+ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
10
+ import { Separator } from '@/components/ui/separator';
11
+ import { hasCapability } from '@/config/capabilities';
12
+ import { Link, redirect } from '@/i18n/navigation';
13
+ import { getActiveChannelToken } from '@/lib/channel-server';
14
+ import { formatDate } from '@/lib/format';
15
+ import { client } from '@/lib/vendure/api';
16
+ import { getActiveChannelCached } from '@/lib/vendure/cached';
17
+ import { getQuoteNegotiationData } from '@/lib/vendure/capability-ui';
18
+ import { GetMyQuoteDetailQuery, type QuoteComment, type QuoteVersion } from '@/lib/vendure/queries';
19
+ import { AlertTriangle, ChevronLeft, Info } from 'lucide-react';
20
+ import type { Metadata } from 'next';
21
+ import { getTranslations, setRequestLocale } from 'next-intl/server';
22
+ import { Suspense } from 'react';
21
23
 
22
24
  const TERMINAL_STATUSES = new Set(['ACCEPTED', 'REJECTED', 'CANCELLED', 'EXPIRED']);
23
25
 
24
26
  interface QuoteDetailPageProps {
25
- params: Promise<{locale: string; id: string}>;
27
+ params: Promise<{ locale: string; id: string }>;
26
28
  }
27
29
 
28
- export async function generateMetadata({params}: QuoteDetailPageProps): Promise<Metadata> {
29
- const {id} = await params;
30
+ export async function generateMetadata({ params }: QuoteDetailPageProps): Promise<Metadata> {
31
+ const { id } = await params;
30
32
  return {
31
33
  title: `Quote ${id}`,
32
34
  };
@@ -36,19 +38,15 @@ type QuoteDetailTranslations = Awaited<ReturnType<typeof getTranslations<'Quotes
36
38
 
37
39
  function getValidityBanner(validUntil: string | null | undefined, t: QuoteDetailTranslations) {
38
40
  if (!validUntil) return null;
39
- const daysRemaining = Math.ceil(
40
- (new Date(validUntil).getTime() - Date.now()) / (1000 * 60 * 60 * 24),
41
- );
41
+ const daysRemaining = Math.ceil((new Date(validUntil).getTime() - Date.now()) / (1000 * 60 * 60 * 24));
42
42
  if (daysRemaining < 0) {
43
43
  return (
44
44
  <div className="rounded-lg border border-red-200 bg-red-50 p-4 mb-6">
45
45
  <div className="flex gap-3">
46
- <AlertTriangle className="h-5 w-5 text-red-600 flex-shrink-0 mt-0.5"/>
46
+ <AlertTriangle className="h-5 w-5 text-red-600 flex-shrink-0 mt-0.5" />
47
47
  <div>
48
48
  <h3 className="font-medium text-red-900">{t('quoteExpiredTitle')}</h3>
49
- <p className="text-sm text-red-800 mt-1">
50
- {t('quoteExpiredMessage')}
51
- </p>
49
+ <p className="text-sm text-red-800 mt-1">{t('quoteExpiredMessage')}</p>
52
50
  </div>
53
51
  </div>
54
52
  </div>
@@ -58,11 +56,11 @@ function getValidityBanner(validUntil: string | null | undefined, t: QuoteDetail
58
56
  return (
59
57
  <div className="rounded-lg border border-amber-200 bg-amber-50 p-4 mb-6">
60
58
  <div className="flex gap-3">
61
- <AlertTriangle className="h-5 w-5 text-amber-600 flex-shrink-0 mt-0.5"/>
59
+ <AlertTriangle className="h-5 w-5 text-amber-600 flex-shrink-0 mt-0.5" />
62
60
  <div>
63
61
  <h3 className="font-medium text-amber-900">{t('quoteExpiringSoonTitle')}</h3>
64
62
  <p className="text-sm text-amber-800 mt-1">
65
- {t('quoteExpiresIn', {days: daysRemaining})}
63
+ {t('quoteExpiresIn', { days: daysRemaining })}
66
64
  </p>
67
65
  </div>
68
66
  </div>
@@ -74,19 +72,29 @@ function getValidityBanner(validUntil: string | null | undefined, t: QuoteDetail
74
72
 
75
73
  export default async function QuoteDetailPage(props: QuoteDetailPageProps) {
76
74
  return (
77
- <Suspense fallback={<div><p className="text-sm text-muted-foreground">Loading quote...</p></div>}>
75
+ <Suspense
76
+ fallback={
77
+ <div>
78
+ <p className="text-sm text-muted-foreground">Loading quote...</p>
79
+ </div>
80
+ }
81
+ >
78
82
  <QuoteDetailContent paramsPromise={props.params} />
79
83
  </Suspense>
80
84
  );
81
85
  }
82
86
 
83
- async function QuoteDetailContent({paramsPromise}: {paramsPromise: Promise<{locale: string; id: string}>}) {
84
- const {locale, id} = await paramsPromise;
87
+ async function QuoteDetailContent({
88
+ paramsPromise,
89
+ }: {
90
+ paramsPromise: Promise<{ locale: string; id: string }>;
91
+ }) {
92
+ const { locale, id } = await paramsPromise;
85
93
  setRequestLocale(locale);
86
94
  const channelToken = await getActiveChannelToken();
87
95
  const [t, [result, error], channel] = await Promise.all([
88
96
  getTranslations('Quotes'),
89
- client.query(GetMyQuoteDetailQuery, {id}),
97
+ client.query(GetMyQuoteDetailQuery, { id }),
90
98
  getActiveChannelCached(channelToken),
91
99
  ]);
92
100
  const currencyCode = channel.defaultCurrencyCode;
@@ -99,18 +107,20 @@ async function QuoteDetailContent({paramsPromise}: {paramsPromise: Promise<{loca
99
107
  return await redirect('/account/quotes');
100
108
  }
101
109
  const version = quote.currentVersion;
110
+ const negotiation = getQuoteNegotiationData<QuoteComment, QuoteVersion>(quote);
102
111
  const isTerminal = TERMINAL_STATUSES.has(quote.status);
103
- const v1 = quote.versions.find(v => v.versionNumber === 1);
104
- const v1LineItems = v1 && quote.versions.length > 1
105
- ? v1.lineItems.map(item => ({sku: item.sku, unitPrice: item.unitPrice}))
106
- : undefined;
112
+ const v1 = negotiation.versions.find((item) => item.versionNumber === 1);
113
+ const v1LineItems =
114
+ v1 && negotiation.versions.length > 1
115
+ ? v1.lineItems.map((item) => ({ sku: item.sku, unitPrice: item.unitPrice }))
116
+ : undefined;
107
117
 
108
118
  return (
109
119
  <div>
110
120
  <div className="mb-6">
111
121
  <Button variant="ghost" size="sm" asChild className="mb-4">
112
122
  <Link href="/account/quotes">
113
- <ChevronLeft className="h-4 w-4 mr-2"/>
123
+ <ChevronLeft className="h-4 w-4 mr-2" />
114
124
  {t('backToQuotes')}
115
125
  </Link>
116
126
  </Button>
@@ -119,7 +129,7 @@ async function QuoteDetailContent({paramsPromise}: {paramsPromise: Promise<{loca
119
129
  <div>
120
130
  <h1 className="text-3xl font-bold">Quote {quote.quoteNumber}</h1>
121
131
  <p className="text-muted-foreground mt-1">
122
- {t('createdOn', {date: formatDate(quote.createdAt, locale, 'long')})}
132
+ {t('createdOn', { date: formatDate(quote.createdAt, locale, 'long') })}
123
133
  </p>
124
134
  </div>
125
135
  </div>
@@ -134,7 +144,7 @@ async function QuoteDetailContent({paramsPromise}: {paramsPromise: Promise<{loca
134
144
  v1LineItems={v1LineItems}
135
145
  />
136
146
  )}
137
- <QuoteStatusBadge status={quote.status}/>
147
+ <QuoteStatusBadge status={quote.status} />
138
148
  </div>
139
149
  </div>
140
150
  </div>
@@ -142,12 +152,10 @@ async function QuoteDetailContent({paramsPromise}: {paramsPromise: Promise<{loca
142
152
  {quote.status === 'IN_REVIEW' && (
143
153
  <div className="rounded-lg border border-blue-200 bg-blue-50 p-4 mb-6">
144
154
  <div className="flex gap-3">
145
- <Info className="h-5 w-5 text-blue-600 flex-shrink-0 mt-0.5"/>
155
+ <Info className="h-5 w-5 text-blue-600 flex-shrink-0 mt-0.5" />
146
156
  <div>
147
157
  <h3 className="font-medium text-blue-900">{t('inReviewBannerTitle')}</h3>
148
- <p className="text-sm text-blue-800 mt-1">
149
- {t('inReviewBannerMessage')}
150
- </p>
158
+ <p className="text-sm text-blue-800 mt-1">{t('inReviewBannerMessage')}</p>
151
159
  </div>
152
160
  </div>
153
161
  </div>
@@ -162,7 +170,7 @@ async function QuoteDetailContent({paramsPromise}: {paramsPromise: Promise<{loca
162
170
  {version && (
163
171
  <QuoteVersionComparison
164
172
  currentVersion={version}
165
- versions={quote.versions}
173
+ versions={negotiation.versions}
166
174
  currencyCode={currencyCode}
167
175
  />
168
176
  )}
@@ -176,23 +184,41 @@ async function QuoteDetailContent({paramsPromise}: {paramsPromise: Promise<{loca
176
184
  <CardContent>
177
185
  <div className="space-y-2">
178
186
  <div className="flex justify-between text-sm">
179
- <span className="text-muted-foreground">{t('subtotal')} <span className="text-[10px]">({t('subtotalExclTax')})</span></span>
180
- <span><Price value={version.subtotal} currencyCode={currencyCode}/></span>
187
+ <span className="text-muted-foreground">
188
+ {t('subtotal')}{' '}
189
+ <span className="text-[10px]">({t('subtotalExclTax')})</span>
190
+ </span>
191
+ <span>
192
+ <Price value={version.subtotal} currencyCode={currencyCode} />
193
+ </span>
181
194
  </div>
182
195
  <div className="flex justify-between text-sm">
183
196
  <span className="text-muted-foreground">{t('shipping')}</span>
184
197
  <span>
185
- {version.shippingCost > 0
186
- ? <Price value={version.shippingCost} currencyCode={currencyCode}/>
187
- : t('shippingIncluded')}
198
+ {version.shippingCost > 0 ? (
199
+ <Price
200
+ value={version.shippingCost}
201
+ currencyCode={currencyCode}
202
+ />
203
+ ) : (
204
+ t('shippingIncluded')
205
+ )}
188
206
  </span>
189
207
  </div>
190
- <Separator className="my-2"/>
208
+ <Separator className="my-2" />
191
209
  <div className="flex justify-between font-bold text-lg">
192
210
  <span>{t('total')}</span>
193
- <span><Price value={version.total} currencyCode={currencyCode} taxLabel="excl" /></span>
211
+ <span>
212
+ <Price
213
+ value={version.total}
214
+ currencyCode={currencyCode}
215
+ taxLabel="excl"
216
+ />
217
+ </span>
194
218
  </div>
195
- <p className="text-xs text-muted-foreground mt-2 italic">{t('taxCalculatedAtCheckout')}</p>
219
+ <p className="text-xs text-muted-foreground mt-2 italic">
220
+ {t('taxCalculatedAtCheckout')}
221
+ </p>
196
222
  </div>
197
223
  </CardContent>
198
224
  </Card>
@@ -200,8 +226,8 @@ async function QuoteDetailContent({paramsPromise}: {paramsPromise: Promise<{loca
200
226
 
201
227
  {/* Activity Timeline */}
202
228
  <QuoteActivityTimeline
203
- versions={quote.versions}
204
- comments={quote.comments}
229
+ versions={negotiation.versions}
230
+ comments={negotiation.comments}
205
231
  currentVersionNumber={version?.versionNumber}
206
232
  currencyCode={currencyCode}
207
233
  />
@@ -217,7 +243,7 @@ async function QuoteDetailContent({paramsPromise}: {paramsPromise: Promise<{loca
217
243
  <CardContent className="space-y-3 text-sm">
218
244
  <div className="flex items-center justify-between">
219
245
  <span className="text-muted-foreground">{t('infoStatus')}</span>
220
- <QuoteStatusBadge status={quote.status}/>
246
+ <QuoteStatusBadge status={quote.status} />
221
247
  </div>
222
248
  <div className="flex justify-between">
223
249
  <span className="text-muted-foreground">{t('infoQuoteNumber')}</span>
@@ -226,20 +252,24 @@ async function QuoteDetailContent({paramsPromise}: {paramsPromise: Promise<{loca
226
252
  {quote.validUntil && (
227
253
  <div className="flex justify-between">
228
254
  <span className="text-muted-foreground">{t('infoValidUntil')}</span>
229
- <QuoteValidityIndicator validUntil={quote.validUntil}/>
255
+ <QuoteValidityIndicator validUntil={quote.validUntil} />
230
256
  </div>
231
257
  )}
232
258
  {quote.convertedOrderId && (
233
259
  <div className="flex justify-between">
234
260
  <span className="text-muted-foreground">{t('infoConvertedOrder')}</span>
235
- <span className="font-medium text-green-700">{t('infoConvertedOrderYes')}</span>
261
+ <span className="font-medium text-green-700">
262
+ {t('infoConvertedOrderYes')}
263
+ </span>
236
264
  </div>
237
265
  )}
238
266
  </CardContent>
239
267
  </Card>
240
268
 
241
269
  {/* Actions */}
242
- {(quote.status === 'DRAFT' || quote.status === 'QUOTED' || (quote.status === 'ACCEPTED' && !quote.convertedOrderId)) && (
270
+ {(quote.status === 'DRAFT' ||
271
+ quote.status === 'QUOTED' ||
272
+ (quote.status === 'ACCEPTED' && !quote.convertedOrderId)) && (
243
273
  <Card>
244
274
  <CardHeader>
245
275
  <CardTitle>{t('actionsCardTitle')}</CardTitle>
@@ -249,6 +279,7 @@ async function QuoteDetailContent({paramsPromise}: {paramsPromise: Promise<{loca
249
279
  quoteId={quote.id}
250
280
  status={quote.status}
251
281
  convertedOrderId={quote.convertedOrderId}
282
+ hasQuoteNegotiation={hasCapability('quote.negotiation')}
252
283
  />
253
284
  </CardContent>
254
285
  </Card>
@@ -1,21 +1,21 @@
1
1
  'use server';
2
2
 
3
- import {client} from '@/lib/vendure/api';
3
+ import { redirect } from '@/i18n/navigation';
4
+ import { client } from '@/lib/vendure/api';
4
5
  import {
5
- RequestQuoteFromCartMutation,
6
- SubmitQuoteMutation,
6
+ AcceptAndConvertQuoteMutation,
7
7
  AcceptQuoteMutation,
8
+ AddQuoteCommentMutation,
9
+ CancelQuoteCheckoutMutation,
8
10
  RejectQuoteMutation,
11
+ RemoveAllOrderLinesMutation,
9
12
  RequestQuoteChangesMutation,
10
- AcceptAndConvertQuoteMutation,
11
- AddQuoteCommentMutation,
13
+ RequestQuoteFromCartMutation,
12
14
  RequestQuoteMutation,
13
- RemoveAllOrderLinesMutation,
14
- CancelQuoteCheckoutMutation,
15
+ SubmitQuoteMutation,
15
16
  } from '@/lib/vendure/mutations';
16
- import {QuoteStockCheckQuery, SearchVariantsQuery} from '@/lib/vendure/queries';
17
- import {revalidatePath, updateTag} from 'next/cache';
18
- import {redirect} from '@/i18n/navigation';
17
+ import { QuoteStockCheckQuery, SearchVariantsQuery } from '@/lib/vendure/queries';
18
+ import { revalidatePath, updateTag } from 'next/cache';
19
19
 
20
20
  function invalidateCart() {
21
21
  updateTag('cart');
@@ -29,17 +29,16 @@ type QuoteLineItemInput = { productVariantId: string; quantity: number; note?: s
29
29
  * Returns the quote ID on success, or throws on failure.
30
30
  */
31
31
  async function createAndSubmitQuote(lineItems: QuoteLineItemInput[], note?: string) {
32
- const [result, error] = await client.mutate(
33
- RequestQuoteMutation,
34
- {input: {lineItems, note: note || undefined}},
35
- );
32
+ const [result, error] = await client.mutate(RequestQuoteMutation, {
33
+ input: { lineItems, note: note || undefined },
34
+ });
36
35
  if (error) {
37
36
  throw new Error(error.message || 'Failed to create quote');
38
37
  }
39
38
  const quoteId = result.data.requestQuote.id;
40
39
  // Auto-submit — if this fails, user lands on the quote detail page
41
40
  // where they can see the DRAFT and manually submit
42
- const [, submitError] = await client.mutate(SubmitQuoteMutation, {quoteId});
41
+ const [, submitError] = await client.mutate(SubmitQuoteMutation, { quoteId });
43
42
  if (submitError) {
44
43
  console.error('[createAndSubmitQuote] Submit failed:', submitError);
45
44
  }
@@ -57,8 +56,8 @@ export async function searchVariantsForQuote(term: string) {
57
56
  }
58
57
 
59
58
  return result.data.search.items
60
- .filter(item => item.price.__typename === 'SinglePrice')
61
- .map(item => ({
59
+ .filter((item) => item.price.__typename === 'SinglePrice')
60
+ .map((item) => ({
62
61
  productVariantId: item.productVariantId,
63
62
  productName: item.productName,
64
63
  variantName: item.productVariantName,
@@ -75,13 +74,13 @@ export async function requestQuoteFromCart() {
75
74
  if (error) {
76
75
  const message = error.message || 'Failed to request quote';
77
76
  console.error('[requestQuoteFromCart] FAILED:', message);
78
- return {success: false, message};
77
+ return { success: false, message };
79
78
  }
80
79
  const quoteId = result.data.requestQuoteFromCart.id;
81
80
 
82
81
  // Auto-submit — if this fails, user still lands on the quote detail page
83
82
  // where they can see the DRAFT and manually submit
84
- const [, submitError] = await client.mutate(SubmitQuoteMutation, {quoteId});
83
+ const [, submitError] = await client.mutate(SubmitQuoteMutation, { quoteId });
85
84
  if (submitError) {
86
85
  console.error('[requestQuoteFromCart] Submit failed, redirecting to draft:', submitError);
87
86
  }
@@ -91,20 +90,20 @@ export async function requestQuoteFromCart() {
91
90
  }
92
91
 
93
92
  export async function submitQuote(quoteId: string) {
94
- const [, error] = await client.mutate(SubmitQuoteMutation, {quoteId});
93
+ const [, error] = await client.mutate(SubmitQuoteMutation, { quoteId });
95
94
 
96
95
  if (error) {
97
96
  const message = error.message || 'Failed to submit quote';
98
97
  console.error('[submitQuote] FAILED:', message);
99
- return {success: false, message};
98
+ return { success: false, message };
100
99
  }
101
100
 
102
101
  revalidatePath('/account/quotes', 'layout');
103
- return {success: true};
102
+ return { success: true };
104
103
  }
105
104
 
106
105
  export async function acceptQuote(quoteId: string) {
107
- const [, error] = await client.mutate(AcceptQuoteMutation, {quoteId});
106
+ const [, error] = await client.mutate(AcceptQuoteMutation, { quoteId });
108
107
 
109
108
  if (error) {
110
109
  return {
@@ -114,11 +113,11 @@ export async function acceptQuote(quoteId: string) {
114
113
  }
115
114
 
116
115
  revalidatePath('/account/quotes', 'layout');
117
- return {success: true};
116
+ return { success: true };
118
117
  }
119
118
 
120
119
  export async function rejectQuote(quoteId: string, reason?: string) {
121
- const [, error] = await client.mutate(RejectQuoteMutation, {quoteId, reason: reason ?? null});
120
+ const [, error] = await client.mutate(RejectQuoteMutation, { quoteId, reason: reason ?? null });
122
121
 
123
122
  if (error) {
124
123
  return {
@@ -128,11 +127,11 @@ export async function rejectQuote(quoteId: string, reason?: string) {
128
127
  }
129
128
 
130
129
  revalidatePath('/account/quotes', 'layout');
131
- return {success: true};
130
+ return { success: true };
132
131
  }
133
132
 
134
133
  export async function requestQuoteChanges(quoteId: string, reason?: string) {
135
- const [, error] = await client.mutate(RequestQuoteChangesMutation, {quoteId, reason: reason ?? null});
134
+ const [, error] = await client.mutate(RequestQuoteChangesMutation, { quoteId, reason: reason ?? null });
136
135
 
137
136
  if (error) {
138
137
  return {
@@ -142,11 +141,11 @@ export async function requestQuoteChanges(quoteId: string, reason?: string) {
142
141
  }
143
142
 
144
143
  revalidatePath('/account/quotes', 'layout');
145
- return {success: true};
144
+ return { success: true };
146
145
  }
147
146
 
148
147
  export async function acceptAndConvertQuote(quoteId: string) {
149
- const [result, error] = await client.mutate(AcceptAndConvertQuoteMutation, {quoteId});
148
+ const [result, error] = await client.mutate(AcceptAndConvertQuoteMutation, { quoteId });
150
149
 
151
150
  if (error) {
152
151
  return {
@@ -167,15 +166,15 @@ export async function acceptAndConvertQuote(quoteId: string) {
167
166
  export async function cancelQuoteCheckout() {
168
167
  const [, error] = await client.mutate(CancelQuoteCheckoutMutation, {});
169
168
  if (error) {
170
- return {success: false, message: error.message || 'Failed to cancel'};
169
+ return { success: false, message: error.message || 'Failed to cancel' };
171
170
  }
172
171
  invalidateCart();
173
172
  revalidatePath('/checkout', 'layout');
174
- return {success: true};
173
+ return { success: true };
175
174
  }
176
175
 
177
176
  export async function addQuoteComment(quoteId: string, text: string) {
178
- const [, error] = await client.mutate(AddQuoteCommentMutation, {quoteId, text});
177
+ const [, error] = await client.mutate(AddQuoteCommentMutation, { quoteId, text });
179
178
 
180
179
  if (error) {
181
180
  return {
@@ -185,23 +184,20 @@ export async function addQuoteComment(quoteId: string, text: string) {
185
184
  }
186
185
 
187
186
  revalidatePath('/account/quotes', 'layout');
188
- return {success: true};
187
+ return { success: true };
189
188
  }
190
189
 
191
190
  /**
192
191
  * Standalone flow: create quote from line items, submit, redirect to detail.
193
192
  * On success, redirects (throws NEXT_REDIRECT) — only failure returns a result.
194
193
  */
195
- export async function requestQuoteWithItems(
196
- lineItems: QuoteLineItemInput[],
197
- note?: string,
198
- ) {
194
+ export async function requestQuoteWithItems(lineItems: QuoteLineItemInput[], note?: string) {
199
195
  let quoteId: string;
200
196
  try {
201
197
  quoteId = await createAndSubmitQuote(lineItems, note);
202
198
  } catch (err) {
203
199
  const message = err instanceof Error ? err.message : 'Failed to create quote';
204
- return {success: false as const, message};
200
+ return { success: false as const, message };
205
201
  }
206
202
  revalidatePath('/account/quotes', 'layout');
207
203
  await redirect(`/account/quotes/${quoteId}`);
@@ -211,16 +207,13 @@ export async function requestQuoteWithItems(
211
207
  * Cart flow: create quote from line items, submit, clear cart, redirect.
212
208
  * On success, redirects (throws NEXT_REDIRECT) — only failure returns a result.
213
209
  */
214
- export async function requestQuoteFromCartWithReview(
215
- lineItems: QuoteLineItemInput[],
216
- note?: string,
217
- ) {
210
+ export async function requestQuoteFromCartWithReview(lineItems: QuoteLineItemInput[], note?: string) {
218
211
  let quoteId: string;
219
212
  try {
220
213
  quoteId = await createAndSubmitQuote(lineItems, note);
221
214
  } catch (err) {
222
215
  const message = err instanceof Error ? err.message : 'Failed to create quote';
223
- return {success: false as const, message};
216
+ return { success: false as const, message };
224
217
  }
225
218
  const [, clearError] = await client.mutate(RemoveAllOrderLinesMutation, {});
226
219
  if (clearError) {
@@ -242,12 +235,12 @@ type StockCheckResult = {
242
235
  };
243
236
 
244
237
  export async function checkQuoteStock(quoteId: string): Promise<StockCheckResult> {
245
- const [result, error] = await client.query(QuoteStockCheckQuery, {quoteId});
238
+ const [result, error] = await client.query(QuoteStockCheckQuery, { quoteId });
246
239
  if (error) {
247
240
  // Fail open — if the stock check itself fails, let the conversion
248
241
  // service catch real stock issues. Better than showing an empty warning.
249
242
  console.error('[checkQuoteStock] Failed:', error);
250
- return {allInStock: true, outOfStockItems: []};
243
+ return { allInStock: true, outOfStockItems: [] };
251
244
  }
252
245
  return result.data.quoteStockCheck as StockCheckResult;
253
246
  }
@@ -1,8 +1,8 @@
1
1
  'use client';
2
2
 
3
- import { QuoteRequestForm } from '@/components/commerce/quote-request-form';
4
- import { QuoteProductSearch } from '@/components/commerce/quote-product-search';
5
3
  import { requestQuoteWithItems } from '@/app/[locale]/account/quotes/actions';
4
+ import { QuoteProductSearch } from '@/components/commerce/quote-product-search';
5
+ import { QuoteRequestForm } from '@/components/commerce/quote-request-form';
6
6
  import { useRouter } from '@/i18n/navigation';
7
7
 
8
8
  interface NewQuoteFormProps {
@@ -20,9 +20,7 @@ export function NewQuoteForm({ sender, currencyCode }: NewQuoteFormProps) {
20
20
  mode="standalone"
21
21
  onSubmit={requestQuoteWithItems}
22
22
  onCancel={() => router.push('/account/quotes')}
23
- renderSearch={(addItem) => (
24
- <QuoteProductSearch onAddItem={addItem} currencyCode={currencyCode} />
25
- )}
23
+ renderSearch={(addItem) => <QuoteProductSearch onAddItem={addItem} currencyCode={currencyCode} />}
26
24
  />
27
25
  );
28
26
  }
@@ -1,13 +1,13 @@
1
- import type { Metadata } from 'next';
2
- import { client } from '@/lib/vendure/api';
3
1
  import { readFragment } from '@/graphql';
4
- import { GetActiveCustomerQuery, GetActiveChannelQuery, GetCompanyAccountQuery } from '@/lib/vendure/queries';
5
- import { ActiveCustomerFragment, CompanyFragment } from '@/lib/vendure/fragments';
6
2
  import { redirect } from '@/i18n/navigation';
7
- import { NewQuoteForm } from './new-quote-form';
8
- import { locale as rootLocale } from 'next/root-params';
9
3
  import type { Locale } from '@/i18n/routing';
4
+ import { client } from '@/lib/vendure/api';
5
+ import { ActiveCustomerFragment, CompanyFragment } from '@/lib/vendure/fragments';
6
+ import { GetActiveChannelQuery, GetActiveCustomerQuery, GetCompanyAccountQuery } from '@/lib/vendure/queries';
7
+ import type { Metadata } from 'next';
10
8
  import { getTranslations } from 'next-intl/server';
9
+ import { locale as rootLocale } from 'next/root-params';
10
+ import { NewQuoteForm } from './new-quote-form';
11
11
 
12
12
  export async function generateMetadata(): Promise<Metadata> {
13
13
  const locale = (await rootLocale()) as Locale;