@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.
- package/CHANGELOG.md +4 -0
- package/README.md +53 -41
- package/dist/add-to-existing.d.ts +19 -13
- package/dist/add-to-existing.js +1 -1
- package/dist/assets/demo-data/assets/branding/logo.svg +4 -0
- package/dist/assets/demo-data/assets/images/absorbent-pad.webp +0 -0
- package/dist/assets/demo-data/assets/images/adjustable-wrench.webp +0 -0
- package/dist/assets/demo-data/assets/images/anchor-bolt.webp +0 -0
- package/dist/assets/demo-data/assets/images/angle-grinder.webp +0 -0
- package/dist/assets/demo-data/assets/images/barrier-tape.webp +0 -0
- package/dist/assets/demo-data/assets/images/bench-grinder.webp +0 -0
- package/dist/assets/demo-data/assets/images/bracket.webp +0 -0
- package/dist/assets/demo-data/assets/images/broom.webp +0 -0
- package/dist/assets/demo-data/assets/images/bucket.webp +0 -0
- package/dist/assets/demo-data/assets/images/cable-gland.webp +0 -0
- package/dist/assets/demo-data/assets/images/cable-tie.webp +0 -0
- package/dist/assets/demo-data/assets/images/cable-tray.webp +0 -0
- package/dist/assets/demo-data/assets/images/cable.webp +0 -0
- package/dist/assets/demo-data/assets/images/chimney-base-kit.webp +0 -0
- package/dist/assets/demo-data/assets/images/chimney-cowl-bird-guard.webp +0 -0
- package/dist/assets/demo-data/assets/images/chimney-cowl-open.webp +0 -0
- package/dist/assets/demo-data/assets/images/chimney-storm-collar.webp +0 -0
- package/dist/assets/demo-data/assets/images/chimney-wall-bracket.webp +0 -0
- package/dist/assets/demo-data/assets/images/circular-saw.webp +0 -0
- package/dist/assets/demo-data/assets/images/cleaning-spray.webp +0 -0
- package/dist/assets/demo-data/assets/images/conduit.webp +0 -0
- package/dist/assets/demo-data/assets/images/cordless-drill.webp +0 -0
- package/dist/assets/demo-data/assets/images/drill-bits.webp +0 -0
- package/dist/assets/demo-data/assets/images/dust-mask.webp +0 -0
- package/dist/assets/demo-data/assets/images/ear-defenders.webp +0 -0
- package/dist/assets/demo-data/assets/images/ear-plugs.webp +0 -0
- package/dist/assets/demo-data/assets/images/extension-lead.webp +0 -0
- package/dist/assets/demo-data/assets/images/eye-wash-station.webp +0 -0
- package/dist/assets/demo-data/assets/images/face-shield.webp +0 -0
- package/dist/assets/demo-data/assets/images/file-set.webp +0 -0
- package/dist/assets/demo-data/assets/images/first-aid-kit.webp +0 -0
- package/dist/assets/demo-data/assets/images/floor-sign.webp +0 -0
- package/dist/assets/demo-data/assets/images/flue-bend-45.webp +0 -0
- package/dist/assets/demo-data/assets/images/flue-bend-90.webp +0 -0
- package/dist/assets/demo-data/assets/images/flue-section-1000mm.webp +0 -0
- package/dist/assets/demo-data/assets/images/flue-section-250mm.webp +0 -0
- package/dist/assets/demo-data/assets/images/flue-section-500mm.webp +0 -0
- package/dist/assets/demo-data/assets/images/fuse.webp +0 -0
- package/dist/assets/demo-data/assets/images/glove-dispenser.webp +0 -0
- package/dist/assets/demo-data/assets/images/grinding-disc.webp +0 -0
- package/dist/assets/demo-data/assets/images/hacksaw.webp +0 -0
- package/dist/assets/demo-data/assets/images/hammer.webp +0 -0
- package/dist/assets/demo-data/assets/images/hand-sanitiser.webp +0 -0
- package/dist/assets/demo-data/assets/images/head-torch.webp +0 -0
- package/dist/assets/demo-data/assets/images/heat-gun.webp +0 -0
- package/dist/assets/demo-data/assets/images/hex-bolt.webp +0 -0
- package/dist/assets/demo-data/assets/images/hex-key-set.webp +0 -0
- package/dist/assets/demo-data/assets/images/hex-nut.webp +0 -0
- package/dist/assets/demo-data/assets/images/hi-vis-jacket.webp +0 -0
- package/dist/assets/demo-data/assets/images/hi-vis-vest.webp +0 -0
- package/dist/assets/demo-data/assets/images/hose-clamp.webp +0 -0
- package/dist/assets/demo-data/assets/images/impact-driver.webp +0 -0
- package/dist/assets/demo-data/assets/images/jigsaw.webp +0 -0
- package/dist/assets/demo-data/assets/images/junction-box.webp +0 -0
- package/dist/assets/demo-data/assets/images/knee-pads.webp +0 -0
- package/dist/assets/demo-data/assets/images/machine-screw.webp +0 -0
- package/dist/assets/demo-data/assets/images/made-to-order-configurable-chimney.webp +0 -0
- package/dist/assets/demo-data/assets/images/mallet.webp +0 -0
- package/dist/assets/demo-data/assets/images/mcb.webp +0 -0
- package/dist/assets/demo-data/assets/images/mop.webp +0 -0
- package/dist/assets/demo-data/assets/images/paper-towels.webp +0 -0
- package/dist/assets/demo-data/assets/images/pipe-wrench.webp +0 -0
- package/dist/assets/demo-data/assets/images/pliers-set.webp +0 -0
- package/dist/assets/demo-data/assets/images/pry-bar.webp +0 -0
- package/dist/assets/demo-data/assets/images/rcd.webp +0 -0
- package/dist/assets/demo-data/assets/images/reciprocating-saw.webp +0 -0
- package/dist/assets/demo-data/assets/images/rivet.webp +0 -0
- package/dist/assets/demo-data/assets/images/roof-flashing-high-pitch.webp +0 -0
- package/dist/assets/demo-data/assets/images/roof-flashing-low-pitch.webp +0 -0
- package/dist/assets/demo-data/assets/images/safety-boots.webp +0 -0
- package/dist/assets/demo-data/assets/images/safety-glasses.webp +0 -0
- package/dist/assets/demo-data/assets/images/safety-harness.webp +0 -0
- package/dist/assets/demo-data/assets/images/safety-helmet.webp +0 -0
- package/dist/assets/demo-data/assets/images/safety-sign.webp +0 -0
- package/dist/assets/demo-data/assets/images/sanding-disc.webp +0 -0
- package/dist/assets/demo-data/assets/images/saw-blade.webp +0 -0
- package/dist/assets/demo-data/assets/images/screwdriver-set.webp +0 -0
- package/dist/assets/demo-data/assets/images/screwdriver.webp +0 -0
- package/dist/assets/demo-data/assets/images/self-tapping-screw.webp +0 -0
- package/dist/assets/demo-data/assets/images/socket-set.webp +0 -0
- package/dist/assets/demo-data/assets/images/socket.webp +0 -0
- package/dist/assets/demo-data/assets/images/spanner-set.webp +0 -0
- package/dist/assets/demo-data/assets/images/spanner.webp +0 -0
- package/dist/assets/demo-data/assets/images/spill-kit.webp +0 -0
- package/dist/assets/demo-data/assets/images/spirit-level.webp +0 -0
- package/dist/assets/demo-data/assets/images/switch.webp +0 -0
- package/dist/assets/demo-data/assets/images/tape-measure.webp +0 -0
- package/dist/assets/demo-data/assets/images/terminal-block.webp +0 -0
- package/dist/assets/demo-data/assets/images/threaded-rod.webp +0 -0
- package/dist/assets/demo-data/assets/images/torque-wrench.webp +0 -0
- package/dist/assets/demo-data/assets/images/utility-knife.webp +0 -0
- package/dist/assets/demo-data/assets/images/wall-pass-sleeve.webp +0 -0
- package/dist/assets/demo-data/assets/images/wall-plug.webp +0 -0
- package/dist/assets/demo-data/assets/images/washer.webp +0 -0
- package/dist/assets/demo-data/assets/images/waste-bin.webp +0 -0
- package/dist/assets/demo-data/assets/images/wire-connector.webp +0 -0
- package/dist/assets/demo-data/assets/images/wire-cutters.webp +0 -0
- package/dist/assets/demo-data/assets/images/wood-screw.webp +0 -0
- package/dist/assets/demo-data/assets/images/work-gloves.webp +0 -0
- package/dist/assets/demo-data/assets/images/work-light.webp +0 -0
- package/dist/assets/demo-data/assets/initial-data.json +667 -0
- package/dist/assets/demo-data/assets/products.csv +779 -0
- package/dist/assets/demo-data/initial-data.json +663 -663
- package/dist/assets/storefront/components.json +20 -20
- package/dist/assets/storefront/eslint.config.mjs +10 -10
- package/dist/assets/storefront/graphql.config.yml +1 -1
- package/dist/assets/storefront/next-env.d.ts +2 -1
- package/dist/assets/storefront/next.config.ts +19 -17
- package/dist/assets/storefront/package.json +3 -2
- package/dist/assets/storefront/postcss.config.mjs +1 -1
- package/dist/assets/storefront/src/app/[locale]/(catalog)/catalog/page.tsx +17 -21
- package/dist/assets/storefront/src/app/[locale]/(catalog)/collection/[slug]/page.tsx +64 -42
- package/dist/assets/storefront/src/app/[locale]/(catalog)/layout.tsx +1 -5
- package/dist/assets/storefront/src/app/[locale]/(catalog)/product/[slug]/actions.ts +69 -65
- package/dist/assets/storefront/src/app/[locale]/(catalog)/product/[slug]/page.tsx +64 -38
- package/dist/assets/storefront/src/app/[locale]/(catalog)/search/page.tsx +24 -27
- package/dist/assets/storefront/src/app/[locale]/(catalog)/search/search-results.tsx +11 -9
- package/dist/assets/storefront/src/app/[locale]/(catalog)/search/search-term.tsx +4 -4
- package/dist/assets/storefront/src/app/[locale]/(scenario)/[...path]/page.tsx +1 -1
- package/dist/assets/storefront/src/app/[locale]/accept-invitation/[token]/accept-invitation-client.tsx +8 -13
- package/dist/assets/storefront/src/app/[locale]/accept-invitation/[token]/actions.ts +11 -14
- package/dist/assets/storefront/src/app/[locale]/accept-invitation/[token]/page.tsx +30 -33
- package/dist/assets/storefront/src/app/[locale]/accept-invitation/[token]/sign-out-and-retry.tsx +6 -6
- package/dist/assets/storefront/src/app/[locale]/account/addresses/actions.ts +30 -45
- package/dist/assets/storefront/src/app/[locale]/account/addresses/address-form.tsx +166 -159
- package/dist/assets/storefront/src/app/[locale]/account/addresses/addresses-client.tsx +35 -26
- package/dist/assets/storefront/src/app/[locale]/account/addresses/loading.tsx +1 -3
- package/dist/assets/storefront/src/app/[locale]/account/addresses/page.tsx +18 -18
- package/dist/assets/storefront/src/app/[locale]/account/approvals/actions.ts +5 -8
- package/dist/assets/storefront/src/app/[locale]/account/approvals/page.tsx +79 -69
- package/dist/assets/storefront/src/app/[locale]/account/company/actions.ts +10 -11
- package/dist/assets/storefront/src/app/[locale]/account/company/addresses/actions.ts +6 -15
- package/dist/assets/storefront/src/app/[locale]/account/company/addresses/address-form.tsx +57 -49
- package/dist/assets/storefront/src/app/[locale]/account/company/addresses/addresses-client.tsx +23 -25
- package/dist/assets/storefront/src/app/[locale]/account/company/addresses/page.tsx +30 -30
- package/dist/assets/storefront/src/app/[locale]/account/company/business-units/actions.ts +20 -29
- package/dist/assets/storefront/src/app/[locale]/account/company/business-units/business-unit-form.tsx +32 -37
- package/dist/assets/storefront/src/app/[locale]/account/company/business-units/business-units-client.tsx +32 -25
- package/dist/assets/storefront/src/app/[locale]/account/company/business-units/page.tsx +26 -24
- package/dist/assets/storefront/src/app/[locale]/account/company/business-units/types.ts +7 -4
- package/dist/assets/storefront/src/app/[locale]/account/company/edit-company-form.tsx +11 -21
- package/dist/assets/storefront/src/app/[locale]/account/company/page.tsx +25 -28
- package/dist/assets/storefront/src/app/[locale]/account/company/payment-methods/page.tsx +26 -24
- package/dist/assets/storefront/src/app/[locale]/account/company/payment-methods/payment-methods-client.tsx +5 -7
- package/dist/assets/storefront/src/app/[locale]/account/company/roles/page.tsx +24 -25
- package/dist/assets/storefront/src/app/[locale]/account/company/roles/roles-client.tsx +11 -26
- package/dist/assets/storefront/src/app/[locale]/account/company/tax-ids/actions.ts +6 -10
- package/dist/assets/storefront/src/app/[locale]/account/company/tax-ids/page.tsx +18 -16
- package/dist/assets/storefront/src/app/[locale]/account/company/tax-ids/tax-ids-client.tsx +74 -67
- package/dist/assets/storefront/src/app/[locale]/account/company/users/actions.ts +16 -25
- package/dist/assets/storefront/src/app/[locale]/account/company/users/edit-user-form.tsx +27 -25
- package/dist/assets/storefront/src/app/[locale]/account/company/users/invite-user-form.tsx +27 -19
- package/dist/assets/storefront/src/app/[locale]/account/company/users/page.tsx +34 -29
- package/dist/assets/storefront/src/app/[locale]/account/company/users/users-client.tsx +35 -38
- package/dist/assets/storefront/src/app/[locale]/account/error.tsx +1 -3
- package/dist/assets/storefront/src/app/[locale]/account/layout.tsx +16 -22
- package/dist/assets/storefront/src/app/[locale]/account/orders/[code]/page.tsx +151 -103
- package/dist/assets/storefront/src/app/[locale]/account/orders/[code]/reorder-actions.ts +6 -7
- package/dist/assets/storefront/src/app/[locale]/account/orders/[code]/reorder-dialog.tsx +22 -48
- package/dist/assets/storefront/src/app/[locale]/account/orders/loading.tsx +8 -8
- package/dist/assets/storefront/src/app/[locale]/account/orders/page.tsx +101 -61
- package/dist/assets/storefront/src/app/[locale]/account/profile/actions.ts +32 -23
- package/dist/assets/storefront/src/app/[locale]/account/profile/change-password-form.tsx +6 -16
- package/dist/assets/storefront/src/app/[locale]/account/profile/edit-email-form.tsx +7 -17
- package/dist/assets/storefront/src/app/[locale]/account/profile/edit-profile-form.tsx +6 -16
- package/dist/assets/storefront/src/app/[locale]/account/profile/loading.tsx +12 -18
- package/dist/assets/storefront/src/app/[locale]/account/profile/page.tsx +17 -15
- package/dist/assets/storefront/src/app/[locale]/account/quick-order/file-upload-tab.tsx +2 -6
- package/dist/assets/storefront/src/app/[locale]/account/quick-order/manual-entry-tab.tsx +18 -15
- package/dist/assets/storefront/src/app/[locale]/account/quick-order/page.tsx +5 -6
- package/dist/assets/storefront/src/app/[locale]/account/quick-order/preview-table.tsx +10 -2
- package/dist/assets/storefront/src/app/[locale]/account/quick-order/save-to-list-dialog.tsx +24 -26
- package/dist/assets/storefront/src/app/[locale]/account/quick-order/sku-autocomplete.tsx +19 -10
- package/dist/assets/storefront/src/app/[locale]/account/quick-order/text-input-tab.tsx +3 -8
- package/dist/assets/storefront/src/app/[locale]/account/quotes/[id]/page.tsx +93 -62
- package/dist/assets/storefront/src/app/[locale]/account/quotes/actions.ts +38 -45
- package/dist/assets/storefront/src/app/[locale]/account/quotes/new/new-quote-form.tsx +3 -5
- package/dist/assets/storefront/src/app/[locale]/account/quotes/new/page.tsx +6 -6
- package/dist/assets/storefront/src/app/[locale]/account/quotes/page.tsx +92 -59
- package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/add-item-search.tsx +11 -9
- package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/add-member-form.tsx +31 -15
- package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/members-panel.tsx +52 -33
- package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/page.tsx +22 -14
- package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/rename-dialog.tsx +34 -13
- package/dist/assets/storefront/src/app/[locale]/account/shared-carts/actions.ts +117 -72
- package/dist/assets/storefront/src/app/[locale]/account/shared-carts/new/new-shared-cart-form.tsx +21 -14
- package/dist/assets/storefront/src/app/[locale]/account/shared-carts/new/page.tsx +10 -10
- package/dist/assets/storefront/src/app/[locale]/account/shared-carts/page.tsx +54 -41
- package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/[id]/page.tsx +22 -8
- package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/[id]/shopping-list-detail-client.tsx +62 -49
- package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/actions.ts +9 -4
- package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/create-shopping-list-form.tsx +5 -11
- package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/loading.tsx +1 -1
- package/dist/assets/storefront/src/app/[locale]/account/shopping-lists/page.tsx +32 -42
- package/dist/assets/storefront/src/app/[locale]/account/store-credits/actions.ts +8 -8
- package/dist/assets/storefront/src/app/[locale]/account/store-credits/claim-form.tsx +6 -10
- package/dist/assets/storefront/src/app/[locale]/account/store-credits/page.tsx +76 -55
- package/dist/assets/storefront/src/app/[locale]/account/store-credits/reveal-code.tsx +10 -6
- package/dist/assets/storefront/src/app/[locale]/account/verify-email/page.tsx +32 -39
- package/dist/assets/storefront/src/app/[locale]/cart/actions.ts +29 -23
- package/dist/assets/storefront/src/app/[locale]/cart/cart-items.tsx +111 -40
- package/dist/assets/storefront/src/app/[locale]/cart/cart-line-actions.tsx +9 -9
- package/dist/assets/storefront/src/app/[locale]/cart/cart-quantity-control.tsx +61 -48
- package/dist/assets/storefront/src/app/[locale]/cart/cart-remove-button.tsx +15 -9
- package/dist/assets/storefront/src/app/[locale]/cart/cart.tsx +38 -41
- package/dist/assets/storefront/src/app/[locale]/cart/code-input.tsx +8 -8
- package/dist/assets/storefront/src/app/[locale]/cart/order-summary.tsx +56 -35
- package/dist/assets/storefront/src/app/[locale]/cart/page.tsx +11 -11
- package/dist/assets/storefront/src/app/[locale]/cart/promotion-code.tsx +56 -47
- package/dist/assets/storefront/src/app/[locale]/cart/reapproval-confirm.tsx +22 -20
- package/dist/assets/storefront/src/app/[locale]/cart/request-quote-button.tsx +7 -16
- package/dist/assets/storefront/src/app/[locale]/checkout/actions.ts +39 -65
- package/dist/assets/storefront/src/app/[locale]/checkout/cancel-quote-checkout-button.tsx +5 -5
- package/dist/assets/storefront/src/app/[locale]/checkout/checkout-flow.tsx +202 -202
- package/dist/assets/storefront/src/app/[locale]/checkout/checkout-provider.tsx +142 -142
- package/dist/assets/storefront/src/app/[locale]/checkout/order-summary.tsx +158 -139
- package/dist/assets/storefront/src/app/[locale]/checkout/page.tsx +58 -47
- package/dist/assets/storefront/src/app/[locale]/checkout/steps/delivery-step.tsx +86 -88
- package/dist/assets/storefront/src/app/[locale]/checkout/steps/payment-step.tsx +90 -91
- package/dist/assets/storefront/src/app/[locale]/checkout/steps/review-step.tsx +166 -161
- package/dist/assets/storefront/src/app/[locale]/checkout/steps/shipping-address-step.tsx +573 -494
- package/dist/assets/storefront/src/app/[locale]/error.tsx +3 -5
- package/dist/assets/storefront/src/app/[locale]/forgot-password/actions.ts +10 -7
- package/dist/assets/storefront/src/app/[locale]/forgot-password/forgot-password-form.tsx +10 -25
- package/dist/assets/storefront/src/app/[locale]/forgot-password/page.tsx +5 -5
- package/dist/assets/storefront/src/app/[locale]/globals.css +48 -48
- package/dist/assets/storefront/src/app/[locale]/layout.tsx +56 -50
- package/dist/assets/storefront/src/app/[locale]/not-found.tsx +3 -5
- package/dist/assets/storefront/src/app/[locale]/order-confirmation/[code]/order-confirmation.tsx +71 -102
- package/dist/assets/storefront/src/app/[locale]/order-confirmation/[code]/page.tsx +7 -5
- package/dist/assets/storefront/src/app/[locale]/page.tsx +33 -35
- package/dist/assets/storefront/src/app/[locale]/register/actions.ts +7 -7
- package/dist/assets/storefront/src/app/[locale]/register/page.tsx +22 -16
- package/dist/assets/storefront/src/app/[locale]/register/registration-form.tsx +22 -34
- package/dist/assets/storefront/src/app/[locale]/register-company/actions.ts +15 -19
- package/dist/assets/storefront/src/app/[locale]/register-company/page.tsx +17 -15
- package/dist/assets/storefront/src/app/[locale]/register-company/registration-form.tsx +9 -15
- package/dist/assets/storefront/src/app/[locale]/reset-password/actions.ts +7 -8
- package/dist/assets/storefront/src/app/[locale]/reset-password/page.tsx +18 -12
- package/dist/assets/storefront/src/app/[locale]/reset-password/reset-password-form.tsx +8 -16
- package/dist/assets/storefront/src/app/[locale]/shopping-list/[code]/add-to-cart-button.tsx +10 -4
- package/dist/assets/storefront/src/app/[locale]/shopping-list/[code]/page.tsx +62 -30
- package/dist/assets/storefront/src/app/[locale]/sign-in/actions.ts +14 -16
- package/dist/assets/storefront/src/app/[locale]/sign-in/login-form.tsx +17 -30
- package/dist/assets/storefront/src/app/[locale]/sign-in/page.tsx +35 -30
- package/dist/assets/storefront/src/app/[locale]/verify/actions.ts +8 -8
- package/dist/assets/storefront/src/app/[locale]/verify/page.tsx +18 -14
- package/dist/assets/storefront/src/app/[locale]/verify/verify-content.tsx +25 -27
- package/dist/assets/storefront/src/app/[locale]/verify-pending/page.tsx +23 -23
- package/dist/assets/storefront/src/app/api/clear-company-context/route.ts +6 -3
- package/dist/assets/storefront/src/app/api/revalidate/route.ts +19 -28
- package/dist/assets/storefront/src/app/api/search-analytics/route.ts +1 -1
- package/dist/assets/storefront/src/components/commerce/account-nav-items.ts +43 -18
- package/dist/assets/storefront/src/components/commerce/account-sidebar.tsx +30 -22
- package/dist/assets/storefront/src/components/commerce/active-filters.tsx +1 -1
- package/dist/assets/storefront/src/components/commerce/add-to-shared-cart.tsx +49 -27
- package/dist/assets/storefront/src/components/commerce/approval-decision-form.tsx +9 -13
- package/dist/assets/storefront/src/components/commerce/approval-status-badge.tsx +23 -15
- package/dist/assets/storefront/src/components/commerce/business-unit-switcher.tsx +11 -11
- package/dist/assets/storefront/src/components/commerce/catalog-search-bar.tsx +2 -2
- package/dist/assets/storefront/src/components/commerce/category-product-section.tsx +28 -16
- package/dist/assets/storefront/src/components/commerce/category-sidebar.tsx +31 -18
- package/dist/assets/storefront/src/components/commerce/collection-hero-banner.tsx +2 -4
- package/dist/assets/storefront/src/components/commerce/company-state-badge.tsx +10 -16
- package/dist/assets/storefront/src/components/commerce/company-switcher.tsx +12 -12
- package/dist/assets/storefront/src/components/commerce/configurator-form.tsx +188 -79
- package/dist/assets/storefront/src/components/commerce/facet-filters.tsx +29 -49
- package/dist/assets/storefront/src/components/commerce/gift-card-pdp.tsx +4 -4
- package/dist/assets/storefront/src/components/commerce/gift-card-product-info.tsx +20 -30
- package/dist/assets/storefront/src/components/commerce/instant-search-dropdown.tsx +258 -227
- package/dist/assets/storefront/src/components/commerce/order-status-badge.tsx +27 -19
- package/dist/assets/storefront/src/components/commerce/packaging-unit-selector.tsx +27 -26
- package/dist/assets/storefront/src/components/commerce/permission-gate.tsx +4 -4
- package/dist/assets/storefront/src/components/commerce/price-range-filter.tsx +5 -5
- package/dist/assets/storefront/src/components/commerce/price-tiers.tsx +38 -21
- package/dist/assets/storefront/src/components/commerce/price.tsx +3 -3
- package/dist/assets/storefront/src/components/commerce/product-card-list.tsx +39 -16
- package/dist/assets/storefront/src/components/commerce/product-card.tsx +35 -18
- package/dist/assets/storefront/src/components/commerce/product-carousel.tsx +20 -12
- package/dist/assets/storefront/src/components/commerce/product-grid.tsx +14 -13
- package/dist/assets/storefront/src/components/commerce/product-image-carousel.tsx +10 -8
- package/dist/assets/storefront/src/components/commerce/product-info.tsx +118 -74
- package/dist/assets/storefront/src/components/commerce/product-list-expansion.tsx +102 -74
- package/dist/assets/storefront/src/components/commerce/product-list-view.tsx +1 -1
- package/dist/assets/storefront/src/components/commerce/product-sidebar.tsx +36 -11
- package/dist/assets/storefront/src/components/commerce/product-view-switcher.tsx +33 -21
- package/dist/assets/storefront/src/components/commerce/quote-action-buttons.tsx +80 -45
- package/dist/assets/storefront/src/components/commerce/quote-activity-timeline.tsx +126 -50
- package/dist/assets/storefront/src/components/commerce/quote-comment-form.tsx +9 -13
- package/dist/assets/storefront/src/components/commerce/quote-csv-export-button.tsx +6 -6
- package/dist/assets/storefront/src/components/commerce/quote-product-search.tsx +22 -18
- package/dist/assets/storefront/src/components/commerce/quote-request-form.tsx +28 -27
- package/dist/assets/storefront/src/components/commerce/quote-status-badge.tsx +26 -18
- package/dist/assets/storefront/src/components/commerce/quote-validity-indicator.tsx +7 -7
- package/dist/assets/storefront/src/components/commerce/quote-version-comparison.tsx +50 -30
- package/dist/assets/storefront/src/components/commerce/related-products.tsx +37 -28
- package/dist/assets/storefront/src/components/commerce/shared-cart-status-badge.tsx +12 -8
- package/dist/assets/storefront/src/components/commerce/shop-by-category.tsx +8 -7
- package/dist/assets/storefront/src/components/commerce/shopping-list-toggle.tsx +14 -20
- package/dist/assets/storefront/src/components/commerce/sort-dropdown.tsx +9 -16
- package/dist/assets/storefront/src/components/commerce/store-credit-summary.tsx +30 -32
- package/dist/assets/storefront/src/components/commerce/subcollection-tiles.tsx +11 -13
- package/dist/assets/storefront/src/components/layout/auth-page-shell.tsx +2 -2
- package/dist/assets/storefront/src/components/layout/draft-mode-indicator.tsx +2 -7
- package/dist/assets/storefront/src/components/layout/draft-mode-link.tsx +4 -2
- package/dist/assets/storefront/src/components/layout/footer.tsx +70 -28
- package/dist/assets/storefront/src/components/layout/navbar/actions.ts +9 -12
- package/dist/assets/storefront/src/components/layout/navbar/cart-icon.tsx +9 -9
- package/dist/assets/storefront/src/components/layout/navbar/channel-picker-wrapper.tsx +4 -9
- package/dist/assets/storefront/src/components/layout/navbar/channel-picker.tsx +13 -8
- package/dist/assets/storefront/src/components/layout/navbar/currency-picker-wrapper.tsx +4 -4
- package/dist/assets/storefront/src/components/layout/navbar/currency-picker.tsx +11 -6
- package/dist/assets/storefront/src/components/layout/navbar/language-picker.tsx +7 -7
- package/dist/assets/storefront/src/components/layout/navbar/login-button.tsx +24 -21
- package/dist/assets/storefront/src/components/layout/navbar/mobile-nav.tsx +8 -8
- package/dist/assets/storefront/src/components/layout/navbar/nav-menu-items.tsx +4 -6
- package/dist/assets/storefront/src/components/layout/navbar/navbar-cart.tsx +1 -1
- package/dist/assets/storefront/src/components/layout/navbar/navbar-collections.tsx +41 -42
- package/dist/assets/storefront/src/components/layout/navbar/navbar-link.tsx +7 -10
- package/dist/assets/storefront/src/components/layout/navbar/navbar-user.tsx +18 -23
- package/dist/assets/storefront/src/components/layout/navbar/theme-switcher.tsx +9 -9
- package/dist/assets/storefront/src/components/layout/navbar.tsx +36 -31
- package/dist/assets/storefront/src/components/layout/search-input.tsx +35 -32
- package/dist/assets/storefront/src/components/providers/awaiting-approval-banner.tsx +12 -10
- package/dist/assets/storefront/src/components/providers/cart-count-server.tsx +14 -12
- package/dist/assets/storefront/src/components/providers/company-context-guard.tsx +4 -4
- package/dist/assets/storefront/src/components/providers/company-permissions-server.tsx +2 -6
- package/dist/assets/storefront/src/components/providers/theme-provider.tsx +3 -3
- package/dist/assets/storefront/src/components/shared/breadcrumbs.tsx +4 -1
- package/dist/assets/storefront/src/components/shared/country-select.tsx +63 -67
- package/dist/assets/storefront/src/components/shared/pagination.tsx +15 -28
- package/dist/assets/storefront/src/components/shared/prefetch-link.tsx +1 -1
- package/dist/assets/storefront/src/components/shared/skeletons/search-input-skeleton.tsx +1 -3
- package/dist/assets/storefront/src/components/ui/accordion.tsx +46 -51
- package/dist/assets/storefront/src/components/ui/alert-dialog.tsx +94 -121
- package/dist/assets/storefront/src/components/ui/alert.tsx +48 -54
- package/dist/assets/storefront/src/components/ui/aspect-ratio.tsx +5 -7
- package/dist/assets/storefront/src/components/ui/avatar.tsx +29 -44
- package/dist/assets/storefront/src/components/ui/badge.tsx +28 -37
- package/dist/assets/storefront/src/components/ui/breadcrumb.tsx +82 -89
- package/dist/assets/storefront/src/components/ui/button.tsx +43 -49
- package/dist/assets/storefront/src/components/ui/calendar.tsx +157 -198
- package/dist/assets/storefront/src/components/ui/card.tsx +53 -76
- package/dist/assets/storefront/src/components/ui/carousel.tsx +194 -212
- package/dist/assets/storefront/src/components/ui/chart.tsx +274 -317
- package/dist/assets/storefront/src/components/ui/checkbox.tsx +24 -27
- package/dist/assets/storefront/src/components/ui/collapsible.tsx +9 -21
- package/dist/assets/storefront/src/components/ui/command.tsx +114 -159
- package/dist/assets/storefront/src/components/ui/context-menu.tsx +167 -199
- package/dist/assets/storefront/src/components/ui/dialog.tsx +97 -114
- package/dist/assets/storefront/src/components/ui/drawer.tsx +93 -107
- package/dist/assets/storefront/src/components/ui/dropdown-menu.tsx +171 -206
- package/dist/assets/storefront/src/components/ui/empty-state.tsx +5 -5
- package/dist/assets/storefront/src/components/ui/field.tsx +196 -208
- package/dist/assets/storefront/src/components/ui/form.tsx +115 -139
- package/dist/assets/storefront/src/components/ui/hover-card.tsx +27 -33
- package/dist/assets/storefront/src/components/ui/input-otp.tsx +50 -59
- package/dist/assets/storefront/src/components/ui/input.tsx +17 -17
- package/dist/assets/storefront/src/components/ui/kbd-shortcut.tsx +3 -1
- package/dist/assets/storefront/src/components/ui/label.tsx +16 -19
- package/dist/assets/storefront/src/components/ui/menubar.tsx +193 -223
- package/dist/assets/storefront/src/components/ui/navigation-menu.tsx +123 -130
- package/dist/assets/storefront/src/components/ui/pagination.tsx +87 -108
- package/dist/assets/storefront/src/components/ui/popover.tsx +29 -35
- package/dist/assets/storefront/src/components/ui/progress.tsx +19 -26
- package/dist/assets/storefront/src/components/ui/radio-group.tsx +32 -38
- package/dist/assets/storefront/src/components/ui/resizable.tsx +37 -42
- package/dist/assets/storefront/src/components/ui/scroll-area.tsx +41 -47
- package/dist/assets/storefront/src/components/ui/select.tsx +130 -152
- package/dist/assets/storefront/src/components/ui/separator.tsx +21 -21
- package/dist/assets/storefront/src/components/ui/sheet.tsx +90 -111
- package/dist/assets/storefront/src/components/ui/sidebar.tsx +611 -649
- package/dist/assets/storefront/src/components/ui/skeleton.tsx +10 -10
- package/dist/assets/storefront/src/components/ui/slider.tsx +50 -55
- package/dist/assets/storefront/src/components/ui/sonner.tsx +20 -20
- package/dist/assets/storefront/src/components/ui/switch.tsx +23 -26
- package/dist/assets/storefront/src/components/ui/table.tsx +65 -97
- package/dist/assets/storefront/src/components/ui/tabs.tsx +39 -55
- package/dist/assets/storefront/src/components/ui/textarea.tsx +14 -14
- package/dist/assets/storefront/src/components/ui/toggle-group.tsx +56 -62
- package/dist/assets/storefront/src/components/ui/toggle.tsx +37 -38
- package/dist/assets/storefront/src/components/ui/tooltip.tsx +38 -46
- package/dist/assets/storefront/src/config/capabilities.ts +41 -0
- package/dist/assets/storefront/src/config/scenario-meta.ts +2 -2
- package/dist/assets/storefront/src/config/scenario.ts +24 -16
- package/dist/assets/storefront/src/contexts/auth-context.tsx +5 -6
- package/dist/assets/storefront/src/graphql-env.d.ts +47 -41
- package/dist/assets/storefront/src/graphql.ts +5 -5
- package/dist/assets/storefront/src/hooks/use-mobile.ts +13 -13
- package/dist/assets/storefront/src/i18n/locale-utils.ts +3 -3
- package/dist/assets/storefront/src/i18n/navigation.ts +4 -4
- package/dist/assets/storefront/src/i18n/request.ts +4 -4
- package/dist/assets/storefront/src/i18n/routing.ts +5 -5
- package/dist/assets/storefront/src/i18n/server.ts +35 -7
- package/dist/assets/storefront/src/lib/actions/switch-channel.ts +9 -9
- package/dist/assets/storefront/src/lib/actions/switch-currency.ts +7 -7
- package/dist/assets/storefront/src/lib/auth.ts +1 -1
- package/dist/assets/storefront/src/lib/backend-health.ts +14 -6
- package/dist/assets/storefront/src/lib/cart-count-context.tsx +10 -4
- package/dist/assets/storefront/src/lib/cart-guard-utils.ts +2 -1
- package/dist/assets/storefront/src/lib/cart-guard.ts +7 -6
- package/dist/assets/storefront/src/lib/channel-server.ts +4 -4
- package/dist/assets/storefront/src/lib/company-context.ts +1 -1
- package/dist/assets/storefront/src/lib/company-permissions-context.tsx +1 -5
- package/dist/assets/storefront/src/lib/currency-server.ts +4 -4
- package/dist/assets/storefront/src/lib/format.ts +16 -7
- package/dist/assets/storefront/src/lib/metadata.ts +39 -44
- package/dist/assets/storefront/src/lib/quantity.ts +2 -4
- package/dist/assets/storefront/src/lib/search-bar-context.tsx +7 -4
- package/dist/assets/storefront/src/lib/use-recent-searches.ts +8 -6
- package/dist/assets/storefront/src/lib/utils.ts +3 -3
- package/dist/assets/storefront/src/lib/vendure/actions.ts +18 -16
- package/dist/assets/storefront/src/lib/vendure/api.ts +36 -23
- package/dist/assets/storefront/src/lib/vendure/approval-utils.ts +9 -8
- package/dist/assets/storefront/src/lib/vendure/cached.ts +20 -15
- package/dist/assets/storefront/src/lib/vendure/capability-documents.ts +246 -0
- package/dist/assets/storefront/src/lib/vendure/capability-schema.ts +358 -0
- package/dist/assets/storefront/src/lib/vendure/capability-ui.ts +15 -0
- package/dist/assets/storefront/src/lib/vendure/mutations.ts +835 -532
- package/dist/assets/storefront/src/lib/vendure/queries.ts +877 -524
- package/dist/assets/storefront/src/proxy.ts +11 -0
- package/dist/assets/storefront/src/scenarios/customer/hero.tsx +2 -2
- package/dist/assets/storefront/src/scenarios/customer/meta.ts +1 -1
- package/dist/assets/storefront/src/schema.graphql +337 -243
- package/dist/assets/templates/README.md.hbs +25 -1
- package/dist/assets/templates/docker-compose.yml.hbs +4 -0
- package/dist/assets/templates/env.hbs +34 -9
- package/dist/assets/templates/environment.d.ts.hbs +1 -0
- package/dist/assets/templates/gitignore.hbs +7 -4
- package/dist/assets/templates/migrate.ts.hbs +55 -0
- package/dist/assets/templates/npmrc.hbs +7 -2
- package/dist/assets/templates/platform-edition.ts.hbs +21 -0
- package/dist/assets/templates/server-package.json.hbs +15 -8
- package/dist/assets/templates/vendure-config.ts.hbs +18 -0
- package/dist/bin/run.js +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +1 -1
- package/dist/console-onboarding.d.ts +44 -0
- package/dist/console-onboarding.js +1 -0
- package/dist/hub-projects.d.ts +48 -0
- package/dist/hub-projects.js +1 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.js +1 -1
- package/dist/plugin-registry.d.ts +61 -2
- package/dist/plugin-registry.js +1 -1
- package/dist/registry.d.ts +16 -13
- package/dist/registry.js +1 -1
- package/dist/scaffold-shared.js +1 -1
- package/dist/scaffold-storefront-only.js +1 -1
- package/dist/scaffolder.d.ts +11 -0
- package/dist/scaffolder.js +1 -1
- package/dist/storefront-copier.d.ts +7 -2
- package/dist/storefront-copier.js +1 -1
- package/dist/template-renderer.d.ts +26 -5
- package/dist/template-renderer.js +1 -1
- package/dist/types.d.ts +54 -23
- package/package.json +14 -2
- package/dist/assets/storefront/src/middleware.ts +0 -11
|
@@ -4,11 +4,11 @@ import type { introspection } from './graphql-env.d.ts';
|
|
|
4
4
|
export const graphql = initGraphQLTada<{
|
|
5
5
|
introspection: introspection;
|
|
6
6
|
scalars: {
|
|
7
|
-
DateTime: string
|
|
8
|
-
JSON: Record<string, unknown
|
|
9
|
-
Money: number
|
|
10
|
-
}
|
|
7
|
+
DateTime: string;
|
|
8
|
+
JSON: Record<string, unknown>;
|
|
9
|
+
Money: number;
|
|
10
|
+
};
|
|
11
11
|
}>();
|
|
12
12
|
|
|
13
|
+
export { readFragment } from 'gql.tada';
|
|
13
14
|
export type { FragmentOf, ResultOf, VariablesOf } from 'gql.tada';
|
|
14
|
-
export { readFragment } from 'gql.tada';
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import * as React from
|
|
1
|
+
import * as React from 'react';
|
|
2
2
|
|
|
3
|
-
const MOBILE_BREAKPOINT = 768
|
|
3
|
+
const MOBILE_BREAKPOINT = 768;
|
|
4
4
|
|
|
5
5
|
export function useIsMobile() {
|
|
6
|
-
|
|
6
|
+
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined);
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
React.useEffect(() => {
|
|
9
|
+
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
|
10
|
+
const onChange = () => {
|
|
11
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
12
|
+
};
|
|
13
|
+
mql.addEventListener('change', onChange);
|
|
14
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
15
|
+
return () => mql.removeEventListener('change', onChange);
|
|
16
|
+
}, []);
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
return !!isMobile;
|
|
19
19
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {routing, type Locale} from './routing';
|
|
1
|
+
import { routing, type Locale } from './routing';
|
|
2
2
|
|
|
3
|
-
const INTL_LOCALE_MAP: Record<Locale, string> = {en: 'en-US', de: 'de-DE'};
|
|
4
|
-
const OG_LOCALE_MAP: Record<Locale, string> = {en: 'en_US', de: 'de_DE'};
|
|
3
|
+
const INTL_LOCALE_MAP: Record<Locale, string> = { en: 'en-US', de: 'de-DE' };
|
|
4
|
+
const OG_LOCALE_MAP: Record<Locale, string> = { en: 'en_US', de: 'de_DE' };
|
|
5
5
|
|
|
6
6
|
/** Map a routing locale to a full BCP-47 tag for Intl APIs. Falls back to the raw locale. */
|
|
7
7
|
export function toIntlLocale(locale: string): string {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {createNavigation} from 'next-intl/navigation';
|
|
2
|
-
import {routing} from './routing';
|
|
1
|
+
import { createNavigation } from 'next-intl/navigation';
|
|
2
|
+
import { routing } from './routing';
|
|
3
3
|
|
|
4
4
|
const nav = createNavigation(routing);
|
|
5
5
|
|
|
@@ -29,7 +29,7 @@ export const getPathname = nav.getPathname;
|
|
|
29
29
|
* bundling since this module also exports Link).
|
|
30
30
|
*/
|
|
31
31
|
export async function redirect(pathname: string, type?: 'push' | 'replace'): Promise<never> {
|
|
32
|
-
const {getLocale} = await import('next-intl/server');
|
|
32
|
+
const { getLocale } = await import('next-intl/server');
|
|
33
33
|
const locale = await getLocale();
|
|
34
|
-
return nav.redirect({href: pathname, locale}, type);
|
|
34
|
+
return nav.redirect({ href: pathname, locale }, type);
|
|
35
35
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {hasLocale} from 'next-intl';
|
|
2
|
-
import {getRequestConfig} from 'next-intl/server';
|
|
3
|
-
import {routing} from './routing';
|
|
1
|
+
import { hasLocale } from 'next-intl';
|
|
2
|
+
import { getRequestConfig } from 'next-intl/server';
|
|
3
|
+
import { routing } from './routing';
|
|
4
4
|
|
|
5
5
|
// Static per-locale imports. When adding a new locale to routing.locales,
|
|
6
6
|
// add a corresponding entry here.
|
|
@@ -9,7 +9,7 @@ const messageImports = {
|
|
|
9
9
|
de: () => import('../../messages/de.json'),
|
|
10
10
|
} as const;
|
|
11
11
|
|
|
12
|
-
export default getRequestConfig(async ({requestLocale}) => {
|
|
12
|
+
export default getRequestConfig(async ({ requestLocale }) => {
|
|
13
13
|
const requested = await requestLocale;
|
|
14
14
|
const locale = hasLocale(routing.locales, requested) ? requested : routing.defaultLocale;
|
|
15
15
|
return {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {LOCALES, type Locale, localeNames} from './locales';
|
|
1
|
+
import { getScenarioMeta } from '@/config/scenario-meta';
|
|
2
|
+
import { defineRouting } from 'next-intl/routing';
|
|
3
|
+
import { LOCALES, type Locale, localeNames } from './locales';
|
|
4
4
|
|
|
5
5
|
// Scenarios declare their preferred default locale in their own
|
|
6
6
|
// `meta.ts` (a client-safe projection that never imports React or
|
|
@@ -15,5 +15,5 @@ export const routing = defineRouting({
|
|
|
15
15
|
defaultLocale: scenarioDefaultLocale,
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
-
export
|
|
19
|
-
export {
|
|
18
|
+
export { localeNames };
|
|
19
|
+
export type { Locale };
|
|
@@ -1,16 +1,44 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { hasLocale } from 'next-intl';
|
|
2
|
+
import { getLocale, setRequestLocale } from 'next-intl/server';
|
|
3
|
+
import { locale as rootLocale } from 'next/root-params';
|
|
4
|
+
import { routing, type Locale } from './routing';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
* Resolve the current locale from
|
|
7
|
+
* Resolve the current locale from the `[locale]` root param, with validation.
|
|
8
|
+
* Falls back to defaultLocale if the segment isn't in routing config.
|
|
9
|
+
*
|
|
10
|
+
* This is the default on the server, including 'use cache' scopes. Root params
|
|
11
|
+
* carry no request state, so a component that resolves the locale this way
|
|
12
|
+
* still prerenders.
|
|
13
|
+
*/
|
|
14
|
+
export async function getRootLocale(): Promise<Locale> {
|
|
15
|
+
const loc = await rootLocale();
|
|
16
|
+
return hasLocale(routing.locales, loc) ? (loc as Locale) : routing.defaultLocale;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Resolve the current locale from request context, with validation.
|
|
7
21
|
* Falls back to defaultLocale if the resolved locale isn't in routing config.
|
|
8
22
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
23
|
+
* Only for scopes root params cannot reach: Client Components, Server Actions
|
|
24
|
+
* and Route Handlers, plus server code that already renders dynamically.
|
|
25
|
+
* Reading request state blocks prerendering, so a Server Component that calls
|
|
26
|
+
* this serves no static shell — call `getRootLocale()` there instead.
|
|
12
27
|
*/
|
|
13
28
|
export async function getRouteLocale(): Promise<Locale> {
|
|
14
29
|
const loc = await getLocale();
|
|
15
30
|
return hasLocale(routing.locales, loc) ? (loc as Locale) : routing.defaultLocale;
|
|
16
31
|
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Pin the `[locale]` root param as next-intl's request locale.
|
|
35
|
+
*
|
|
36
|
+
* Call this before the first next-intl call in a Server Component that does not
|
|
37
|
+
* already pin the locale from `params`. Without it, `getTranslations()` resolves
|
|
38
|
+
* the locale through next-intl's request scope, which under `cacheComponents` is
|
|
39
|
+
* uncached request state: the route then fails `next build --debug-prerender`
|
|
40
|
+
* and serves no static shell.
|
|
41
|
+
*/
|
|
42
|
+
export async function pinRootLocale(): Promise<void> {
|
|
43
|
+
setRequestLocale(await getRootLocale());
|
|
44
|
+
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
3
|
+
import { getChannelsConfig } from '@/config/scenario';
|
|
4
|
+
import { CHANNEL_COOKIE } from '@/lib/channel';
|
|
5
|
+
import { CURRENCY_COOKIE } from '@/lib/currency';
|
|
6
|
+
import { revalidatePath } from 'next/cache';
|
|
7
|
+
import { cookies } from 'next/headers';
|
|
8
8
|
|
|
9
9
|
export async function switchChannel(token: string) {
|
|
10
10
|
const channelsConfig = getChannelsConfig();
|
|
11
11
|
if (!channelsConfig) {
|
|
12
|
-
return {success: false, message: 'Channel switching not configured'};
|
|
12
|
+
return { success: false, message: 'Channel switching not configured' };
|
|
13
13
|
}
|
|
14
|
-
if (!channelsConfig.available.some(c => c.token === token)) {
|
|
15
|
-
return {success: false, message: 'Invalid channel token'};
|
|
14
|
+
if (!channelsConfig.available.some((c) => c.token === token)) {
|
|
15
|
+
return { success: false, message: 'Invalid channel token' };
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
const jar = await cookies();
|
|
@@ -28,5 +28,5 @@ export async function switchChannel(token: string) {
|
|
|
28
28
|
jar.delete(CURRENCY_COOKIE);
|
|
29
29
|
|
|
30
30
|
revalidatePath('/', 'layout');
|
|
31
|
-
return {success: true};
|
|
31
|
+
return { success: true };
|
|
32
32
|
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
3
|
+
import { CURRENCY_COOKIE } from '@/lib/currency';
|
|
4
|
+
import { getActiveChannelCached } from '@/lib/vendure/cached';
|
|
5
|
+
import { revalidatePath } from 'next/cache';
|
|
6
|
+
import { cookies } from 'next/headers';
|
|
7
7
|
|
|
8
8
|
export async function switchCurrency(currencyCode: string) {
|
|
9
|
-
const {getActiveChannelToken} = await import('@/lib/channel-server');
|
|
9
|
+
const { getActiveChannelToken } = await import('@/lib/channel-server');
|
|
10
10
|
const channelToken = await getActiveChannelToken();
|
|
11
11
|
const channel = await getActiveChannelCached(channelToken);
|
|
12
12
|
if (!channel.availableCurrencyCodes.includes(currencyCode as never)) {
|
|
13
|
-
return {success: false, message: 'Invalid currency code'};
|
|
13
|
+
return { success: false, message: 'Invalid currency code' };
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
const jar = await cookies();
|
|
@@ -21,5 +21,5 @@ export async function switchCurrency(currencyCode: string) {
|
|
|
21
21
|
});
|
|
22
22
|
|
|
23
23
|
revalidatePath('/', 'layout');
|
|
24
|
-
return {success: true};
|
|
24
|
+
return { success: true };
|
|
25
25
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {cacheLife} from 'next/cache';
|
|
1
|
+
import { cacheLife } from 'next/cache';
|
|
2
2
|
|
|
3
3
|
const HEALTH_CHECK_TIMEOUT_MS = 3000;
|
|
4
4
|
|
|
@@ -10,12 +10,20 @@ const HEALTH_CHECK_TIMEOUT_MS = 3000;
|
|
|
10
10
|
* on Vercel) but every API call fails, leaving the user with a branded but
|
|
11
11
|
* empty shell. When this returns false we render a "Demo Paused" page instead.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
13
|
+
* This is cacheLife('seconds') with one field changed: `expire` goes from 60 to
|
|
14
|
+
* 300. The preset's 60s expire is too short for Next 16.3's build-time cache,
|
|
15
|
+
* which drops the entry between the cache-warming phase and the final prerender
|
|
16
|
+
* phase, and every prerendered page that mounts this gate then logs an
|
|
17
|
+
* "Unexpected cache miss" during `next build`. Measured on 16.3: expire 300 is
|
|
18
|
+
* retained, 120 is not.
|
|
19
|
+
*
|
|
20
|
+
* `stale` and `revalidate` keep the preset's values, so how fast a stop/start of
|
|
21
|
+
* the backend is picked up is unchanged. `expire` only bounds how long a stale
|
|
22
|
+
* value may be served when revalidation never runs.
|
|
15
23
|
*/
|
|
16
24
|
export async function isBackendReachable(): Promise<boolean> {
|
|
17
25
|
'use cache';
|
|
18
|
-
cacheLife(
|
|
26
|
+
cacheLife({ stale: 30, revalidate: 1, expire: 300 });
|
|
19
27
|
|
|
20
28
|
const apiUrl = process.env.VENDURE_SHOP_API_URL || process.env.NEXT_PUBLIC_VENDURE_SHOP_API_URL;
|
|
21
29
|
if (!apiUrl) return true;
|
|
@@ -25,8 +33,8 @@ export async function isBackendReachable(): Promise<boolean> {
|
|
|
25
33
|
try {
|
|
26
34
|
const res = await fetch(apiUrl, {
|
|
27
35
|
method: 'POST',
|
|
28
|
-
headers: {'Content-Type': 'application/json'},
|
|
29
|
-
body: JSON.stringify({query: '{ __typename }'}),
|
|
36
|
+
headers: { 'Content-Type': 'application/json' },
|
|
37
|
+
body: JSON.stringify({ query: '{ __typename }' }),
|
|
30
38
|
signal: controller.signal,
|
|
31
39
|
});
|
|
32
40
|
return res.ok;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { createContext,
|
|
3
|
+
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
|
|
4
4
|
|
|
5
5
|
interface CartCountContextType {
|
|
6
6
|
count: number;
|
|
@@ -13,11 +13,17 @@ interface CartCountContextType {
|
|
|
13
13
|
|
|
14
14
|
const CartCountContext = createContext<CartCountContextType | null>(null);
|
|
15
15
|
|
|
16
|
-
export function CartCountProvider({
|
|
16
|
+
export function CartCountProvider({
|
|
17
|
+
initialCount,
|
|
18
|
+
children,
|
|
19
|
+
}: {
|
|
20
|
+
initialCount: number;
|
|
21
|
+
children: React.ReactNode;
|
|
22
|
+
}) {
|
|
17
23
|
const [count, setCount] = useState(initialCount);
|
|
18
24
|
const [awaitingApprovalOrderCode, setAwaitingApprovalOrderCode] = useState<string | null>(null);
|
|
19
|
-
const increment = useCallback(() => setCount(c => c + 1), []);
|
|
20
|
-
const decrement = useCallback(() => setCount(c => Math.max(0, c - 1)), []);
|
|
25
|
+
const increment = useCallback(() => setCount((c) => c + 1), []);
|
|
26
|
+
const decrement = useCallback(() => setCount((c) => Math.max(0, c - 1)), []);
|
|
21
27
|
|
|
22
28
|
return (
|
|
23
29
|
<CartCountContext.Provider
|
|
@@ -6,5 +6,6 @@ import type { CartGuardResult } from './cart-guard';
|
|
|
6
6
|
*/
|
|
7
7
|
export function getGuardError(guard: CartGuardResult): string | undefined {
|
|
8
8
|
if (guard.blocked) return 'Order is awaiting approval and cannot be modified';
|
|
9
|
-
if (guard.quoteLocked)
|
|
9
|
+
if (guard.quoteLocked)
|
|
10
|
+
return 'You have a quote checkout in progress. Complete checkout or cancel the quote checkout to modify your cart.';
|
|
10
11
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
3
|
import { client } from '@/lib/vendure/api';
|
|
4
|
-
import { GetActiveOrderQuery, GetApprovalHistoryForEntityQuery } from '@/lib/vendure/queries';
|
|
5
4
|
import { TransitionOrderToStateMutation } from '@/lib/vendure/mutations';
|
|
5
|
+
import { GetActiveOrderQuery, GetApprovalHistoryForEntityQuery } from '@/lib/vendure/queries';
|
|
6
6
|
|
|
7
7
|
export interface CartGuardResult {
|
|
8
8
|
/** Whether the order was in a non-AddingItems state and had to be transitioned */
|
|
@@ -23,12 +23,13 @@ export interface CartGuardResult {
|
|
|
23
23
|
* and the full cart guard.
|
|
24
24
|
*/
|
|
25
25
|
async function checkOrderApprovalStatus(orderId: string): Promise<boolean> {
|
|
26
|
-
const [approvalResult] = await client.query(
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
const [approvalResult] = await client.query(GetApprovalHistoryForEntityQuery, {
|
|
27
|
+
entityType: 'Order',
|
|
28
|
+
entityId: orderId,
|
|
29
|
+
});
|
|
30
|
+
const history = [...(approvalResult?.data?.approvalHistoryForEntity ?? [])].sort(
|
|
31
|
+
(a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),
|
|
29
32
|
);
|
|
30
|
-
const history = [...(approvalResult?.data?.approvalHistoryForEntity ?? [])]
|
|
31
|
-
.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
|
|
32
33
|
const latestApproval = history[0] ?? null;
|
|
33
34
|
return latestApproval?.status === 'APPROVED';
|
|
34
35
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { getChannelsConfig } from '@/config/scenario';
|
|
2
|
+
import { cookies } from 'next/headers';
|
|
3
|
+
import { CHANNEL_COOKIE } from './channel';
|
|
4
4
|
|
|
5
5
|
const FALLBACK_TOKEN = process.env.VENDURE_CHANNEL_TOKEN || process.env.NEXT_PUBLIC_VENDURE_CHANNEL_TOKEN;
|
|
6
6
|
|
|
@@ -20,7 +20,7 @@ export async function getActiveChannelToken(): Promise<string | undefined> {
|
|
|
20
20
|
const cookie = jar.get(CHANNEL_COOKIE)?.value;
|
|
21
21
|
|
|
22
22
|
// Validate: cookie token must be one of the declared available tokens
|
|
23
|
-
if (cookie && channelsConfig.available.some(c => c.token === cookie)) {
|
|
23
|
+
if (cookie && channelsConfig.available.some((c) => c.token === cookie)) {
|
|
24
24
|
return cookie;
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -28,11 +28,7 @@ export function CompanyPermissionsProvider({
|
|
|
28
28
|
},
|
|
29
29
|
};
|
|
30
30
|
|
|
31
|
-
return
|
|
32
|
-
<CompanyPermissionsContext.Provider value={value}>
|
|
33
|
-
{children}
|
|
34
|
-
</CompanyPermissionsContext.Provider>
|
|
35
|
-
);
|
|
31
|
+
return <CompanyPermissionsContext.Provider value={value}>{children}</CompanyPermissionsContext.Provider>;
|
|
36
32
|
}
|
|
37
33
|
|
|
38
34
|
export function useCompanyPermissions() {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {cookies} from 'next/headers';
|
|
2
|
-
import {CURRENCY_COOKIE} from './currency';
|
|
3
|
-
import {getActiveChannelCached} from './vendure/cached';
|
|
1
|
+
import { cookies } from 'next/headers';
|
|
2
|
+
import { CURRENCY_COOKIE } from './currency';
|
|
3
|
+
import { getActiveChannelCached } from './vendure/cached';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Resolve the active currency code from the cookie, falling back to the
|
|
@@ -13,7 +13,7 @@ export async function getActiveCurrencyCode(): Promise<string> {
|
|
|
13
13
|
// Dynamic import to avoid circular dependency: currencyMiddleware (api.ts)
|
|
14
14
|
// → getActiveCurrencyCode → channel-server → scenario.ts. Do NOT import
|
|
15
15
|
// anything from api.ts in channel-server.ts or this chain becomes circular.
|
|
16
|
-
const {getActiveChannelToken} = await import('./channel-server');
|
|
16
|
+
const { getActiveChannelToken } = await import('./channel-server');
|
|
17
17
|
const channelToken = await getActiveChannelToken();
|
|
18
18
|
const channel = await getActiveChannelCached(channelToken);
|
|
19
19
|
return channel.defaultCurrencyCode;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {toIntlLocale} from '@/i18n/locale-utils';
|
|
1
|
+
import { toIntlLocale } from '@/i18n/locale-utils';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Format a price value
|
|
@@ -6,7 +6,12 @@ import {toIntlLocale} from '@/i18n/locale-utils';
|
|
|
6
6
|
* @param locale Routing locale (e.g. 'en', 'de')
|
|
7
7
|
* @param currencyCode ISO 4217 currency code (e.g. 'EUR', 'USD')
|
|
8
8
|
*/
|
|
9
|
-
export function formatPrice(
|
|
9
|
+
export function formatPrice(
|
|
10
|
+
price: number,
|
|
11
|
+
locale: string,
|
|
12
|
+
currencyCode = 'EUR',
|
|
13
|
+
options?: Intl.NumberFormatOptions,
|
|
14
|
+
): string {
|
|
10
15
|
return new Intl.NumberFormat(toIntlLocale(locale), {
|
|
11
16
|
style: 'currency',
|
|
12
17
|
currency: currencyCode,
|
|
@@ -23,9 +28,10 @@ type DateFormat = 'short' | 'long';
|
|
|
23
28
|
* @param format 'short' (Jan 15, 2024) or 'long' (January 15, 2024)
|
|
24
29
|
*/
|
|
25
30
|
export function formatDate(dateString: string, locale: string, format: DateFormat = 'short'): string {
|
|
26
|
-
const options: Intl.DateTimeFormatOptions =
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
const options: Intl.DateTimeFormatOptions =
|
|
32
|
+
format === 'long'
|
|
33
|
+
? { year: 'numeric', month: 'long', day: 'numeric' }
|
|
34
|
+
: { year: 'numeric', month: 'short', day: 'numeric' };
|
|
29
35
|
|
|
30
36
|
return new Date(dateString).toLocaleDateString(toIntlLocale(locale), options);
|
|
31
37
|
}
|
|
@@ -37,8 +43,11 @@ export function formatDate(dateString: string, locale: string, format: DateForma
|
|
|
37
43
|
*/
|
|
38
44
|
export function formatDateTime(dateString: string, locale: string): string {
|
|
39
45
|
return new Date(dateString).toLocaleString(toIntlLocale(locale), {
|
|
40
|
-
month: 'short',
|
|
41
|
-
|
|
46
|
+
month: 'short',
|
|
47
|
+
day: 'numeric',
|
|
48
|
+
year: 'numeric',
|
|
49
|
+
hour: 'numeric',
|
|
50
|
+
minute: '2-digit',
|
|
42
51
|
});
|
|
43
52
|
}
|
|
44
53
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Metadata } from 'next';
|
|
2
1
|
import { getBranding } from '@/config/branding';
|
|
3
2
|
import { routing } from '@/i18n/routing';
|
|
3
|
+
import type { Metadata } from 'next';
|
|
4
4
|
|
|
5
5
|
export const SITE_NAME = process.env.NEXT_PUBLIC_SITE_NAME || getBranding().siteName;
|
|
6
6
|
export const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL || 'https://example.com';
|
|
@@ -9,77 +9,72 @@ export const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL || 'https://example.com
|
|
|
9
9
|
* Truncate text to a maximum length, preserving word boundaries.
|
|
10
10
|
* Strips HTML tags and is ideal for meta descriptions (recommended 150-160 chars).
|
|
11
11
|
*/
|
|
12
|
-
export function truncateDescription(
|
|
13
|
-
|
|
14
|
-
maxLength = 155
|
|
15
|
-
): string {
|
|
16
|
-
if (!text) return '';
|
|
12
|
+
export function truncateDescription(text: string | null | undefined, maxLength = 155): string {
|
|
13
|
+
if (!text) return '';
|
|
17
14
|
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
// Strip HTML tags if present
|
|
16
|
+
const cleanText = text.replace(/<[^>]*>/g, '').trim();
|
|
20
17
|
|
|
21
|
-
|
|
18
|
+
if (cleanText.length <= maxLength) return cleanText;
|
|
22
19
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
// Find the last space before maxLength to avoid cutting words
|
|
21
|
+
const truncated = cleanText.substring(0, maxLength);
|
|
22
|
+
const lastSpaceIndex = truncated.lastIndexOf(' ');
|
|
26
23
|
|
|
27
|
-
|
|
28
|
-
? truncated.substring(0, lastSpaceIndex) + '...'
|
|
29
|
-
: truncated + '...';
|
|
24
|
+
return lastSpaceIndex > 0 ? truncated.substring(0, lastSpaceIndex) + '...' : truncated + '...';
|
|
30
25
|
}
|
|
31
26
|
|
|
32
27
|
/**
|
|
33
28
|
* Build a canonical URL for a given path, optionally prefixed with locale.
|
|
34
29
|
*/
|
|
35
30
|
export function buildCanonicalUrl(path: string, locale?: string): string {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
31
|
+
const baseUrl = SITE_URL.replace(/\/$/, '');
|
|
32
|
+
const cleanPath = path.startsWith('/') ? path : `/${path}`;
|
|
33
|
+
const prefix = locale ? `/${locale}` : '';
|
|
34
|
+
return `${baseUrl}${prefix}${cleanPath}`;
|
|
40
35
|
}
|
|
41
36
|
|
|
42
37
|
/**
|
|
43
38
|
* Build hreflang alternates for all configured locales.
|
|
44
39
|
*/
|
|
45
40
|
export function buildAlternates(path: string, currentLocale?: string): Metadata['alternates'] {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
41
|
+
const languages: Record<string, string> = {};
|
|
42
|
+
for (const loc of routing.locales) {
|
|
43
|
+
languages[loc] = buildCanonicalUrl(path, loc);
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
canonical: buildCanonicalUrl(path, currentLocale),
|
|
47
|
+
languages,
|
|
48
|
+
};
|
|
54
49
|
}
|
|
55
50
|
|
|
56
51
|
/**
|
|
57
52
|
* Build Open Graph image array from an image URL.
|
|
58
53
|
*/
|
|
59
54
|
export function buildOgImages(
|
|
60
|
-
|
|
61
|
-
|
|
55
|
+
imageUrl: string | null | undefined,
|
|
56
|
+
alt?: string,
|
|
62
57
|
): NonNullable<Metadata['openGraph']>['images'] {
|
|
63
|
-
|
|
58
|
+
if (!imageUrl) return undefined;
|
|
64
59
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
60
|
+
return [
|
|
61
|
+
{
|
|
62
|
+
url: imageUrl,
|
|
63
|
+
alt: alt || 'Product image',
|
|
64
|
+
},
|
|
65
|
+
];
|
|
71
66
|
}
|
|
72
67
|
|
|
73
68
|
/**
|
|
74
69
|
* Create noindex/nofollow robots config for protected pages.
|
|
75
70
|
*/
|
|
76
71
|
export function noIndexRobots(): Metadata['robots'] {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
72
|
+
return {
|
|
73
|
+
index: false,
|
|
74
|
+
follow: false,
|
|
75
|
+
googleBot: {
|
|
76
|
+
index: false,
|
|
77
|
+
follow: false,
|
|
78
|
+
},
|
|
79
|
+
};
|
|
85
80
|
}
|
|
@@ -8,13 +8,11 @@ export function normalizeQuantity(
|
|
|
8
8
|
value: number | string | null | undefined,
|
|
9
9
|
minimum: number = MIN_ORDER_QUANTITY,
|
|
10
10
|
) {
|
|
11
|
-
const parsed = typeof value === 'number'
|
|
12
|
-
? value
|
|
13
|
-
: Number.parseInt(value ?? '', 10);
|
|
11
|
+
const parsed = typeof value === 'number' ? value : Number.parseInt(value ?? '', 10);
|
|
14
12
|
|
|
15
13
|
if (!Number.isFinite(parsed)) {
|
|
16
14
|
return minimum;
|
|
17
15
|
}
|
|
18
16
|
|
|
19
17
|
return Math.max(minimum, Math.floor(parsed));
|
|
20
|
-
}
|
|
18
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import { createContext,
|
|
3
|
+
import { createContext, useCallback, useContext, useEffect, useRef, useState } from 'react';
|
|
4
4
|
|
|
5
5
|
interface SearchBarContextType {
|
|
6
6
|
hasInlineSearch: boolean;
|
|
@@ -22,8 +22,9 @@ export function SearchBarProvider({ children }: { children: React.ReactNode }) {
|
|
|
22
22
|
function handleKeyDown(e: KeyboardEvent) {
|
|
23
23
|
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
|
|
24
24
|
e.preventDefault();
|
|
25
|
-
const input =
|
|
26
|
-
??
|
|
25
|
+
const input =
|
|
26
|
+
searchInputRef.current ??
|
|
27
|
+
document.querySelector<HTMLInputElement>('input[type="search"]');
|
|
27
28
|
input?.focus();
|
|
28
29
|
}
|
|
29
30
|
}
|
|
@@ -32,7 +33,9 @@ export function SearchBarProvider({ children }: { children: React.ReactNode }) {
|
|
|
32
33
|
}, []);
|
|
33
34
|
|
|
34
35
|
return (
|
|
35
|
-
<SearchBarContext.Provider
|
|
36
|
+
<SearchBarContext.Provider
|
|
37
|
+
value={{ hasInlineSearch, registerInlineSearch, unregisterInlineSearch, searchInputRef }}
|
|
38
|
+
>
|
|
36
39
|
{children}
|
|
37
40
|
</SearchBarContext.Provider>
|
|
38
41
|
);
|