@vendure-platform/create 0.4.0 → 0.5.1
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 +8 -0
- package/README.md +39 -39
- package/dist/add-to-existing.js +1 -1
- 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/messages/de.json +2 -0
- package/dist/assets/storefront/messages/en.json +2 -0
- package/dist/assets/storefront/next.config.ts +5 -4
- package/dist/assets/storefront/package.json +1 -1
- 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 +68 -37
- 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 +16 -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 +77 -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 +24 -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 +23 -28
- package/dist/assets/storefront/src/app/[locale]/account/company/payment-methods/page.tsx +24 -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 +22 -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 +32 -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 +15 -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 +3 -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 +86 -59
- 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]/activity-feed.tsx +152 -0
- package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/add-item-search.tsx +132 -0
- package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/add-member-form.tsx +140 -0
- package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/members-panel.tsx +259 -0
- package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/page.tsx +55 -0
- package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/rename-dialog.tsx +117 -0
- package/dist/assets/storefront/src/app/[locale]/account/shared-carts/[id]/shared-cart-detail-client.tsx +555 -0
- package/dist/assets/storefront/src/app/[locale]/account/shared-carts/actions.ts +305 -0
- package/dist/assets/storefront/src/app/[locale]/account/shared-carts/new/new-shared-cart-form.tsx +84 -0
- package/dist/assets/storefront/src/app/[locale]/account/shared-carts/new/page.tsx +47 -0
- package/dist/assets/storefront/src/app/[locale]/account/shared-carts/page.tsx +276 -0
- 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 +70 -29
- package/dist/assets/storefront/src/app/[locale]/cart/page.tsx +11 -11
- package/dist/assets/storefront/src/app/[locale]/cart/promotion-code.tsx +48 -42
- 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 +56 -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 +53 -47
- 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 -44
- 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 +44 -17
- 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 +247 -0
- 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 +35 -14
- package/dist/assets/storefront/src/components/commerce/product-card.tsx +31 -16
- 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 +129 -72
- 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 +54 -36
- 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-role.ts +39 -0
- package/dist/assets/storefront/src/components/commerce/shared-cart-status-badge.tsx +28 -0
- 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/scenario-meta.ts +2 -2
- package/dist/assets/storefront/src/config/scenario.ts +14 -16
- package/dist/assets/storefront/src/contexts/auth-context.tsx +5 -6
- package/dist/assets/storefront/src/graphql-env.d.ts +18 -5
- 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 +3 -3
- 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 +3 -3
- 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 +44 -27
- 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/mutations.ts +96 -0
- package/dist/assets/storefront/src/lib/vendure/queries.ts +157 -5
- package/dist/assets/storefront/src/middleware.ts +1 -1
- 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 +134 -0
- package/dist/bin/run.js +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +1 -1
- package/dist/plugin-registry.js +1 -1
- package/dist/scaffold-storefront-only.js +1 -1
- package/dist/scaffolder.js +1 -1
- package/dist/template-renderer.js +1 -1
- package/package.json +2 -2
|
@@ -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
|
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { useCallback, useState } from 'react';
|
|
4
4
|
|
|
5
5
|
const STORAGE_KEY = 'vendure-recent-searches';
|
|
6
6
|
const MAX_RECENT = 5;
|
|
@@ -11,7 +11,9 @@ function readFromStorage(): string[] {
|
|
|
11
11
|
const raw = localStorage.getItem(STORAGE_KEY);
|
|
12
12
|
if (!raw) return [];
|
|
13
13
|
const parsed = JSON.parse(raw);
|
|
14
|
-
return Array.isArray(parsed)
|
|
14
|
+
return Array.isArray(parsed)
|
|
15
|
+
? parsed.filter((s): s is string => typeof s === 'string').slice(0, MAX_RECENT)
|
|
16
|
+
: [];
|
|
15
17
|
} catch {
|
|
16
18
|
return [];
|
|
17
19
|
}
|
|
@@ -31,16 +33,16 @@ export function useRecentSearches() {
|
|
|
31
33
|
const addSearch = useCallback((term: string) => {
|
|
32
34
|
const trimmed = term.trim();
|
|
33
35
|
if (!trimmed) return;
|
|
34
|
-
setSearches(prev => {
|
|
35
|
-
const next = [trimmed, ...prev.filter(s => s !== trimmed)].slice(0, MAX_RECENT);
|
|
36
|
+
setSearches((prev) => {
|
|
37
|
+
const next = [trimmed, ...prev.filter((s) => s !== trimmed)].slice(0, MAX_RECENT);
|
|
36
38
|
writeToStorage(next);
|
|
37
39
|
return next;
|
|
38
40
|
});
|
|
39
41
|
}, []);
|
|
40
42
|
|
|
41
43
|
const removeSearch = useCallback((term: string) => {
|
|
42
|
-
setSearches(prev => {
|
|
43
|
-
const next = prev.filter(s => s !== term);
|
|
44
|
+
setSearches((prev) => {
|
|
45
|
+
const next = prev.filter((s) => s !== term);
|
|
44
46
|
writeToStorage(next);
|
|
45
47
|
return next;
|
|
46
48
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { clsx, type ClassValue } from
|
|
2
|
-
import { twMerge } from
|
|
1
|
+
import { clsx, type ClassValue } from 'clsx';
|
|
2
|
+
import { twMerge } from 'tailwind-merge';
|
|
3
3
|
|
|
4
4
|
export function cn(...inputs: ClassValue[]) {
|
|
5
|
-
|
|
5
|
+
return twMerge(clsx(inputs));
|
|
6
6
|
}
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {GetActiveCustomerQuery, GetCompanyAccountQuery, GetMyCompaniesQuery, type CompanyUserCompany} from './queries';
|
|
3
|
-
import {getActiveChannelCached} from './cached';
|
|
4
|
-
import {cache} from "react";
|
|
5
|
-
import {readFragment, ResultOf} from "@/graphql";
|
|
1
|
+
import { readFragment, ResultOf } from '@/graphql';
|
|
6
2
|
import {
|
|
7
3
|
ActiveCustomerFragment,
|
|
8
4
|
CompanyBusinessUnitFragment,
|
|
@@ -10,7 +6,16 @@ import {
|
|
|
10
6
|
CompanyPermissionFragment,
|
|
11
7
|
CompanyRoleFragment,
|
|
12
8
|
CompanyUserFragment,
|
|
13
|
-
} from
|
|
9
|
+
} from '@/lib/vendure/fragments';
|
|
10
|
+
import { cache } from 'react';
|
|
11
|
+
import { client } from './api';
|
|
12
|
+
import { getActiveChannelCached } from './cached';
|
|
13
|
+
import {
|
|
14
|
+
GetActiveCustomerQuery,
|
|
15
|
+
GetCompanyAccountQuery,
|
|
16
|
+
GetMyCompaniesQuery,
|
|
17
|
+
type CompanyUserCompany,
|
|
18
|
+
} from './queries';
|
|
14
19
|
|
|
15
20
|
type CompanyRoleData = Omit<ResultOf<typeof CompanyRoleFragment>, 'permissions'> & {
|
|
16
21
|
permissions: ResultOf<typeof CompanyPermissionFragment>[];
|
|
@@ -34,7 +39,7 @@ export const getActiveCustomer = cache(async () => {
|
|
|
34
39
|
return null;
|
|
35
40
|
}
|
|
36
41
|
return readFragment(ActiveCustomerFragment, result.data.activeCustomer);
|
|
37
|
-
})
|
|
42
|
+
});
|
|
38
43
|
|
|
39
44
|
export const getCompanyAccount = cache(async (): Promise<CompanyAccount | null> => {
|
|
40
45
|
const [result, error] = await client.query(GetCompanyAccountQuery);
|
|
@@ -52,14 +57,14 @@ export const getCompanyAccount = cache(async (): Promise<CompanyAccount | null>
|
|
|
52
57
|
|
|
53
58
|
const companyUser: CompanyUserData = {
|
|
54
59
|
...rawUser,
|
|
55
|
-
companyRoles: rawUser.companyRoles.map(r => {
|
|
60
|
+
companyRoles: rawUser.companyRoles.map((r) => {
|
|
56
61
|
const role = readFragment(CompanyRoleFragment, r);
|
|
57
62
|
return {
|
|
58
63
|
...role,
|
|
59
|
-
permissions: role.permissions.map(p => readFragment(CompanyPermissionFragment, p)),
|
|
64
|
+
permissions: role.permissions.map((p) => readFragment(CompanyPermissionFragment, p)),
|
|
60
65
|
};
|
|
61
66
|
}),
|
|
62
|
-
businessUnits: rawUser.businessUnits.map(bu => readFragment(CompanyBusinessUnitFragment, bu)),
|
|
67
|
+
businessUnits: rawUser.businessUnits.map((bu) => readFragment(CompanyBusinessUnitFragment, bu)),
|
|
63
68
|
};
|
|
64
69
|
|
|
65
70
|
return {
|
|
@@ -76,8 +81,8 @@ export const getMyCompanies = cache(async (): Promise<CompanyUserCompany[]> => {
|
|
|
76
81
|
const customer = result.data.activeCustomer;
|
|
77
82
|
if (!customer) return [];
|
|
78
83
|
return customer.companyUsers
|
|
79
|
-
.filter(cu => cu.state === 'Active')
|
|
80
|
-
.map(cu => ({ id: cu.company.id, name: cu.company.name, state: cu.company.state }));
|
|
84
|
+
.filter((cu) => cu.state === 'Active')
|
|
85
|
+
.map((cu) => ({ id: cu.company.id, name: cu.company.name, state: cu.company.state }));
|
|
81
86
|
});
|
|
82
87
|
|
|
83
88
|
/**
|
|
@@ -86,10 +91,7 @@ export const getMyCompanies = cache(async (): Promise<CompanyUserCompany[]> => {
|
|
|
86
91
|
* to getMyCompanies (which includes pending companies via CompanyUser state).
|
|
87
92
|
*/
|
|
88
93
|
export const getHasCompany = cache(async (): Promise<boolean> => {
|
|
89
|
-
const [companyAccount, companies] = await Promise.all([
|
|
90
|
-
getCompanyAccount(),
|
|
91
|
-
getMyCompanies(),
|
|
92
|
-
]);
|
|
94
|
+
const [companyAccount, companies] = await Promise.all([getCompanyAccount(), getMyCompanies()]);
|
|
93
95
|
return !!companyAccount || companies.length > 0;
|
|
94
96
|
});
|
|
95
97
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import type { RequestMiddleware } from '@vendure-platform/storefront-client';
|
|
2
|
+
import { createClient } from '@vendure-platform/storefront-client';
|
|
3
3
|
|
|
4
4
|
const DRAFT_MODE_SECRET = process.env.DRAFT_MODE_SECRET;
|
|
5
5
|
|
|
@@ -11,7 +11,7 @@ const DRAFT_MODE_SECRET = process.env.DRAFT_MODE_SECRET;
|
|
|
11
11
|
const draftModeMiddleware: RequestMiddleware = async (req, next) => {
|
|
12
12
|
if (DRAFT_MODE_SECRET) {
|
|
13
13
|
try {
|
|
14
|
-
const {draftMode} = await import('next/headers');
|
|
14
|
+
const { draftMode } = await import('next/headers');
|
|
15
15
|
const draft = await draftMode();
|
|
16
16
|
if (draft.isEnabled) {
|
|
17
17
|
const url = new URL(req.url);
|
|
@@ -26,35 +26,44 @@ const draftModeMiddleware: RequestMiddleware = async (req, next) => {
|
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
const VENDURE_API_URL = process.env.VENDURE_SHOP_API_URL || process.env.NEXT_PUBLIC_VENDURE_SHOP_API_URL;
|
|
29
|
-
const VENDURE_CHANNEL_TOKEN =
|
|
29
|
+
const VENDURE_CHANNEL_TOKEN =
|
|
30
|
+
process.env.VENDURE_CHANNEL_TOKEN || process.env.NEXT_PUBLIC_VENDURE_CHANNEL_TOKEN;
|
|
30
31
|
const VENDURE_AUTH_TOKEN_HEADER = process.env.VENDURE_AUTH_TOKEN_HEADER || 'vendure-auth-token';
|
|
31
32
|
const VENDURE_CHANNEL_TOKEN_HEADER = process.env.VENDURE_CHANNEL_TOKEN_HEADER || 'vendure-token';
|
|
32
33
|
|
|
33
34
|
if (!VENDURE_API_URL) {
|
|
34
|
-
throw new Error(
|
|
35
|
+
throw new Error(
|
|
36
|
+
'VENDURE_SHOP_API_URL or NEXT_PUBLIC_VENDURE_SHOP_API_URL environment variable is not set',
|
|
37
|
+
);
|
|
35
38
|
}
|
|
36
39
|
|
|
37
40
|
// Dynamic imports to avoid Next.js static analysis marking this module as dynamic.
|
|
38
41
|
// cookies() is only available in request context — providers gracefully return undefined otherwise.
|
|
39
42
|
async function safeGetAuthToken(): Promise<string | undefined> {
|
|
40
43
|
try {
|
|
41
|
-
const {getAuthToken} = await import('@/lib/auth');
|
|
44
|
+
const { getAuthToken } = await import('@/lib/auth');
|
|
42
45
|
return await getAuthToken();
|
|
43
|
-
} catch {
|
|
46
|
+
} catch {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
44
49
|
}
|
|
45
50
|
|
|
46
51
|
async function safeGetCompanyId(): Promise<string | undefined> {
|
|
47
52
|
try {
|
|
48
|
-
const {getCompanyId} = await import('@/lib/company-context');
|
|
53
|
+
const { getCompanyId } = await import('@/lib/company-context');
|
|
49
54
|
return await getCompanyId();
|
|
50
|
-
} catch {
|
|
55
|
+
} catch {
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
51
58
|
}
|
|
52
59
|
|
|
53
60
|
async function safeGetBusinessUnitId(): Promise<string | undefined> {
|
|
54
61
|
try {
|
|
55
|
-
const {getBusinessUnitId} = await import('@/lib/company-context');
|
|
62
|
+
const { getBusinessUnitId } = await import('@/lib/company-context');
|
|
56
63
|
return await getBusinessUnitId();
|
|
57
|
-
} catch {
|
|
64
|
+
} catch {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
58
67
|
}
|
|
59
68
|
|
|
60
69
|
/**
|
|
@@ -65,16 +74,20 @@ async function safeGetBusinessUnitId(): Promise<string | undefined> {
|
|
|
65
74
|
*/
|
|
66
75
|
async function safeGetChannelToken(): Promise<string | undefined> {
|
|
67
76
|
try {
|
|
68
|
-
const {getActiveChannelToken} = await import('@/lib/channel-server');
|
|
77
|
+
const { getActiveChannelToken } = await import('@/lib/channel-server');
|
|
69
78
|
return await getActiveChannelToken();
|
|
70
|
-
} catch {
|
|
79
|
+
} catch {
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
71
82
|
}
|
|
72
83
|
|
|
73
84
|
async function safeGetLanguageCode(): Promise<string | undefined> {
|
|
74
85
|
try {
|
|
75
|
-
const {getLocale} = await import('next-intl/server');
|
|
86
|
+
const { getLocale } = await import('next-intl/server');
|
|
76
87
|
return await getLocale();
|
|
77
|
-
} catch {
|
|
88
|
+
} catch {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
78
91
|
}
|
|
79
92
|
|
|
80
93
|
const sharedConfig = {
|
|
@@ -84,6 +97,9 @@ const sharedConfig = {
|
|
|
84
97
|
authToken: VENDURE_AUTH_TOKEN_HEADER,
|
|
85
98
|
channelToken: VENDURE_CHANNEL_TOKEN_HEADER,
|
|
86
99
|
},
|
|
100
|
+
// Dev-only guard: these operations return wrong-language results when no
|
|
101
|
+
// languageCode reaches the request (silent fallback to channel default).
|
|
102
|
+
warnOnMissingLanguageCode: ['search', 'searchCollections', 'quickOrderSearch'],
|
|
87
103
|
} as const;
|
|
88
104
|
|
|
89
105
|
/**
|
|
@@ -92,7 +108,7 @@ const sharedConfig = {
|
|
|
92
108
|
*/
|
|
93
109
|
const currencyMiddleware: RequestMiddleware = async (req, next) => {
|
|
94
110
|
try {
|
|
95
|
-
const {getActiveCurrencyCode} = await import('@/lib/currency-server');
|
|
111
|
+
const { getActiveCurrencyCode } = await import('@/lib/currency-server');
|
|
96
112
|
const currency = await getActiveCurrencyCode();
|
|
97
113
|
const url = new URL(req.url);
|
|
98
114
|
url.searchParams.set('currencyCode', currency);
|
|
@@ -113,10 +129,11 @@ export const client = createClient({
|
|
|
113
129
|
channelToken: safeGetChannelToken,
|
|
114
130
|
companyId: safeGetCompanyId,
|
|
115
131
|
businessUnitId: safeGetBusinessUnitId,
|
|
116
|
-
//
|
|
117
|
-
//
|
|
118
|
-
//
|
|
119
|
-
//
|
|
132
|
+
// Resolves the route locale via next-intl's getLocale(); fails soft
|
|
133
|
+
// (undefined) outside request scope. Not available on publicClient —
|
|
134
|
+
// 'use cache' scopes must receive languageCode as an explicit argument
|
|
135
|
+
// since it is part of the cache key.
|
|
136
|
+
languageCode: safeGetLanguageCode,
|
|
120
137
|
},
|
|
121
138
|
});
|
|
122
139
|
|
|
@@ -126,7 +143,7 @@ export const client = createClient({
|
|
|
126
143
|
* access cookies, headers, or draftMode. Pass languageCode and currencyCode explicitly
|
|
127
144
|
* as query options from the calling function.
|
|
128
145
|
*/
|
|
129
|
-
export const publicClient = createClient({...sharedConfig});
|
|
146
|
+
export const publicClient = createClient({ ...sharedConfig });
|
|
130
147
|
|
|
131
148
|
/**
|
|
132
149
|
* Pre-resolved context for use at cache boundaries where cookies() is not available.
|
|
@@ -145,20 +162,20 @@ export interface VendureContext {
|
|
|
145
162
|
* Use this at cache boundaries ('use cache') where providers can't access cookies().
|
|
146
163
|
*/
|
|
147
164
|
export async function getVendureContext(): Promise<VendureContext> {
|
|
148
|
-
const {getAuthToken} = await import('@/lib/auth');
|
|
165
|
+
const { getAuthToken } = await import('@/lib/auth');
|
|
149
166
|
const authToken = await getAuthToken();
|
|
150
167
|
let companyId: string | undefined;
|
|
151
168
|
let businessUnitId: string | undefined;
|
|
152
169
|
try {
|
|
153
|
-
const {getCompanyId, getBusinessUnitId} = await import('@/lib/company-context');
|
|
170
|
+
const { getCompanyId, getBusinessUnitId } = await import('@/lib/company-context');
|
|
154
171
|
companyId = await getCompanyId();
|
|
155
172
|
businessUnitId = await getBusinessUnitId();
|
|
156
173
|
} catch {}
|
|
157
|
-
const {getActiveChannelToken} = await import('@/lib/channel-server');
|
|
174
|
+
const { getActiveChannelToken } = await import('@/lib/channel-server');
|
|
158
175
|
const channelToken = await getActiveChannelToken();
|
|
159
|
-
const {getRouteLocale} = await import('@/i18n/server');
|
|
176
|
+
const { getRouteLocale } = await import('@/i18n/server');
|
|
160
177
|
const locale = await getRouteLocale();
|
|
161
|
-
const {getActiveCurrencyCode} = await import('@/lib/currency-server');
|
|
178
|
+
const { getActiveCurrencyCode } = await import('@/lib/currency-server');
|
|
162
179
|
const currencyCode = await getActiveCurrencyCode();
|
|
163
|
-
return {authToken, channelToken, companyId, businessUnitId, locale, currencyCode};
|
|
180
|
+
return { authToken, channelToken, companyId, businessUnitId, locale, currencyCode };
|
|
164
181
|
}
|
|
@@ -1,21 +1,22 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import {GetApprovalHistoryForEntityQuery} from '@/lib/vendure/queries';
|
|
1
|
+
import type { VendureContext } from '@/lib/vendure/api';
|
|
2
|
+
import { client } from '@/lib/vendure/api';
|
|
3
|
+
import { GetApprovalHistoryForEntityQuery } from '@/lib/vendure/queries';
|
|
4
4
|
|
|
5
5
|
export async function getLatestApprovalForOrder(orderId: string, ctx?: VendureContext) {
|
|
6
6
|
const queryArgs = { entityType: 'Order', entityId: orderId } as const;
|
|
7
7
|
const [result] = ctx
|
|
8
8
|
? await client.query(GetApprovalHistoryForEntityQuery, queryArgs, ctx)
|
|
9
9
|
: await client.query(GetApprovalHistoryForEntityQuery, queryArgs);
|
|
10
|
-
const history = [...(result?.data?.approvalHistoryForEntity ?? [])]
|
|
11
|
-
|
|
10
|
+
const history = [...(result?.data?.approvalHistoryForEntity ?? [])].sort(
|
|
11
|
+
(a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),
|
|
12
|
+
);
|
|
12
13
|
const latestApproval = history[0] ?? null;
|
|
13
14
|
const changesRequested = latestApproval?.status === 'CHANGES_REQUESTED';
|
|
14
15
|
const changesComment = changesRequested
|
|
15
16
|
? latestApproval.decisions
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
?.filter((d: any) => d.decision === 'CHANGES_REQUESTED' && d.comment)
|
|
18
|
+
.map((d: any) => d.comment)
|
|
19
|
+
.at(-1) ?? null
|
|
19
20
|
: null;
|
|
20
21
|
return { latestApproval, changesRequested, changesComment };
|
|
21
22
|
}
|