@vendure-platform/create 0.5.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 +4 -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/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 +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 +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]/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 +50 -32
- 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 +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 +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 +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 +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-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/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.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 +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/queries.ts +15 -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/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/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,31 +1,47 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { useTranslations } from 'next-intl';
|
|
5
|
-
import { Input } from '@/components/ui/input';
|
|
3
|
+
import { Price } from '@/components/commerce/price';
|
|
6
4
|
import { Button } from '@/components/ui/button';
|
|
5
|
+
import { Drawer, DrawerContent, DrawerHeader, DrawerTitle } from '@/components/ui/drawer';
|
|
6
|
+
import { Input } from '@/components/ui/input';
|
|
7
7
|
import { Label } from '@/components/ui/label';
|
|
8
|
-
import { Switch } from '@/components/ui/switch';
|
|
9
8
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
|
10
|
-
import {
|
|
11
|
-
import { Price } from '@/components/commerce/price';
|
|
12
|
-
import { ShoppingCart, CheckCircle2, ChevronDown, Info, AlertCircle, Loader2, Minus, Plus } from 'lucide-react';
|
|
13
|
-
import { toast } from 'sonner';
|
|
9
|
+
import { Switch } from '@/components/ui/switch';
|
|
14
10
|
import type {
|
|
15
|
-
ConfiguratorSystem,
|
|
16
|
-
ConfiguratorModule,
|
|
17
|
-
ConfiguratorField,
|
|
18
11
|
ConfigurationEvaluation,
|
|
12
|
+
ConfiguratorField,
|
|
13
|
+
ConfiguratorModule,
|
|
14
|
+
ConfiguratorSystem,
|
|
19
15
|
EvaluatedField,
|
|
20
16
|
EvaluatedLine,
|
|
21
17
|
} from '@/lib/vendure/queries';
|
|
18
|
+
import {
|
|
19
|
+
AlertCircle,
|
|
20
|
+
CheckCircle2,
|
|
21
|
+
ChevronDown,
|
|
22
|
+
Info,
|
|
23
|
+
Loader2,
|
|
24
|
+
Minus,
|
|
25
|
+
Plus,
|
|
26
|
+
ShoppingCart,
|
|
27
|
+
} from 'lucide-react';
|
|
28
|
+
import { useTranslations } from 'next-intl';
|
|
29
|
+
import { useCallback, useEffect, useRef, useState, useTransition, type ReactNode } from 'react';
|
|
30
|
+
import { toast } from 'sonner';
|
|
22
31
|
|
|
23
32
|
interface ConfiguratorFormProps {
|
|
24
33
|
system: ConfiguratorSystem;
|
|
25
34
|
productName: string;
|
|
26
35
|
currencyCode?: string;
|
|
27
|
-
evaluateAction: (
|
|
28
|
-
|
|
36
|
+
evaluateAction: (
|
|
37
|
+
systemId: string,
|
|
38
|
+
values: { fieldRef: string; value: string }[],
|
|
39
|
+
) => Promise<{ data?: ConfigurationEvaluation; error?: string }>;
|
|
40
|
+
addToOrderAction: (
|
|
41
|
+
systemId: string,
|
|
42
|
+
values: { fieldRef: string; value: string }[],
|
|
43
|
+
name?: string,
|
|
44
|
+
) => Promise<{ success: boolean; error?: string }>;
|
|
29
45
|
children?: ReactNode;
|
|
30
46
|
}
|
|
31
47
|
|
|
@@ -33,7 +49,14 @@ function buildFieldRef(moduleCode: string, fieldCode: string) {
|
|
|
33
49
|
return `${moduleCode}.${fieldCode}`;
|
|
34
50
|
}
|
|
35
51
|
|
|
36
|
-
export function ConfiguratorForm({
|
|
52
|
+
export function ConfiguratorForm({
|
|
53
|
+
system,
|
|
54
|
+
productName,
|
|
55
|
+
currencyCode,
|
|
56
|
+
evaluateAction,
|
|
57
|
+
addToOrderAction,
|
|
58
|
+
children,
|
|
59
|
+
}: ConfiguratorFormProps) {
|
|
37
60
|
const t = useTranslations('Configurator');
|
|
38
61
|
const [values, setValues] = useState<Record<string, string>>(() => {
|
|
39
62
|
const initial: Record<string, string> = {};
|
|
@@ -52,7 +75,7 @@ export function ConfiguratorForm({ system, productName, currencyCode, evaluateAc
|
|
|
52
75
|
const [isAdding, startAddTransition] = useTransition();
|
|
53
76
|
const [isAdded, setIsAdded] = useState(false);
|
|
54
77
|
const [expandedModules, setExpandedModules] = useState<Set<string>>(() => {
|
|
55
|
-
return new Set(system.modules.map(m => m.code));
|
|
78
|
+
return new Set(system.modules.map((m) => m.code));
|
|
56
79
|
});
|
|
57
80
|
const [bomDrawerOpen, setBomDrawerOpen] = useState(false);
|
|
58
81
|
const evalTimeoutRef = useRef<ReturnType<typeof setTimeout>>(undefined);
|
|
@@ -79,7 +102,7 @@ export function ConfiguratorForm({ system, productName, currencyCode, evaluateAc
|
|
|
79
102
|
}, [values, system.id, evaluateAction, fieldValueEntries]);
|
|
80
103
|
|
|
81
104
|
const handleFieldChange = (moduleCode: string, fieldCode: string, value: string) => {
|
|
82
|
-
setValues(prev => ({ ...prev, [buildFieldRef(moduleCode, fieldCode)]: value }));
|
|
105
|
+
setValues((prev) => ({ ...prev, [buildFieldRef(moduleCode, fieldCode)]: value }));
|
|
83
106
|
};
|
|
84
107
|
|
|
85
108
|
const handleAddToOrder = () => {
|
|
@@ -97,7 +120,7 @@ export function ConfiguratorForm({ system, productName, currencyCode, evaluateAc
|
|
|
97
120
|
};
|
|
98
121
|
|
|
99
122
|
const toggleModule = (code: string) => {
|
|
100
|
-
setExpandedModules(prev => {
|
|
123
|
+
setExpandedModules((prev) => {
|
|
101
124
|
const next = new Set(prev);
|
|
102
125
|
if (next.has(code)) next.delete(code);
|
|
103
126
|
else next.add(code);
|
|
@@ -131,8 +154,8 @@ export function ConfiguratorForm({ system, productName, currencyCode, evaluateAc
|
|
|
131
154
|
}
|
|
132
155
|
}
|
|
133
156
|
const allErrors = [
|
|
134
|
-
...systemErrors.map(e => e.message),
|
|
135
|
-
...fieldIssues.map(e => `${e.fieldName}: ${e.message}`),
|
|
157
|
+
...systemErrors.map((e) => e.message),
|
|
158
|
+
...fieldIssues.map((e) => `${e.fieldName}: ${e.message}`),
|
|
136
159
|
];
|
|
137
160
|
const hasErrors = allErrors.length > 0;
|
|
138
161
|
|
|
@@ -159,9 +182,7 @@ export function ConfiguratorForm({ system, productName, currencyCode, evaluateAc
|
|
|
159
182
|
<div className="lg:col-span-3">
|
|
160
183
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
|
161
184
|
{/* Image + description — sticky */}
|
|
162
|
-
<div className="md:sticky md:top-20 md:self-start space-y-5">
|
|
163
|
-
{children}
|
|
164
|
-
</div>
|
|
185
|
+
<div className="md:sticky md:top-20 md:self-start space-y-5">{children}</div>
|
|
165
186
|
|
|
166
187
|
{/* Configurator form */}
|
|
167
188
|
<div>
|
|
@@ -170,7 +191,11 @@ export function ConfiguratorForm({ system, productName, currencyCode, evaluateAc
|
|
|
170
191
|
{lines.length > 0 && (
|
|
171
192
|
<div className="flex items-center gap-2">
|
|
172
193
|
<span className="text-3xl font-bold text-primary">
|
|
173
|
-
<Price
|
|
194
|
+
<Price
|
|
195
|
+
value={totalPrice}
|
|
196
|
+
currencyCode={currencyCode}
|
|
197
|
+
taxLabel="excl"
|
|
198
|
+
/>
|
|
174
199
|
</span>
|
|
175
200
|
</div>
|
|
176
201
|
)}
|
|
@@ -179,7 +204,10 @@ export function ConfiguratorForm({ system, productName, currencyCode, evaluateAc
|
|
|
179
204
|
{allErrors.length > 0 && (
|
|
180
205
|
<div className="mt-4 space-y-2">
|
|
181
206
|
{allErrors.map((msg, i) => (
|
|
182
|
-
<div
|
|
207
|
+
<div
|
|
208
|
+
key={i}
|
|
209
|
+
className="rounded-lg border border-red-200 bg-red-50 px-3 py-2.5 flex items-start gap-2"
|
|
210
|
+
>
|
|
183
211
|
<AlertCircle className="w-4 h-4 mt-0.5 shrink-0 text-red-500" />
|
|
184
212
|
<p className="text-sm text-red-800">{msg}</p>
|
|
185
213
|
</div>
|
|
@@ -201,7 +229,6 @@ export function ConfiguratorForm({ system, productName, currencyCode, evaluateAc
|
|
|
201
229
|
/>
|
|
202
230
|
))}
|
|
203
231
|
</div>
|
|
204
|
-
|
|
205
232
|
</div>
|
|
206
233
|
</div>
|
|
207
234
|
</div>
|
|
@@ -211,9 +238,7 @@ export function ConfiguratorForm({ system, productName, currencyCode, evaluateAc
|
|
|
211
238
|
<div className="lg:hidden fixed bottom-0 inset-x-0 z-40 border-t border-border bg-background shadow-[0_-4px_12px_rgba(0,0,0,0.05)]">
|
|
212
239
|
<div className="flex items-center justify-between px-4 py-3">
|
|
213
240
|
<div>
|
|
214
|
-
<p className="text-xs text-muted-foreground">
|
|
215
|
-
{t('items', { count: lines.length })}
|
|
216
|
-
</p>
|
|
241
|
+
<p className="text-xs text-muted-foreground">{t('items', { count: lines.length })}</p>
|
|
217
242
|
<p className="text-lg font-bold">
|
|
218
243
|
<Price value={totalPrice} currencyCode={currencyCode} />
|
|
219
244
|
</p>
|
|
@@ -230,11 +255,20 @@ export function ConfiguratorForm({ system, productName, currencyCode, evaluateAc
|
|
|
230
255
|
onClick={handleAddToOrder}
|
|
231
256
|
>
|
|
232
257
|
{isAdded ? (
|
|
233
|
-
|
|
258
|
+
<>
|
|
259
|
+
<CheckCircle2 className="mr-1.5 h-4 w-4" />
|
|
260
|
+
{t('addedToCart')}
|
|
261
|
+
</>
|
|
234
262
|
) : isAdding ? (
|
|
235
|
-
|
|
263
|
+
<>
|
|
264
|
+
<Loader2 className="mr-1.5 h-4 w-4 animate-spin" />
|
|
265
|
+
{t('adding')}
|
|
266
|
+
</>
|
|
236
267
|
) : (
|
|
237
|
-
|
|
268
|
+
<>
|
|
269
|
+
<ShoppingCart className="mr-1.5 h-4 w-4" />
|
|
270
|
+
{t('addToCart')}
|
|
271
|
+
</>
|
|
238
272
|
)}
|
|
239
273
|
</Button>
|
|
240
274
|
</div>
|
|
@@ -249,15 +283,25 @@ export function ConfiguratorForm({ system, productName, currencyCode, evaluateAc
|
|
|
249
283
|
</DrawerHeader>
|
|
250
284
|
<div className="px-4 pb-6 overflow-y-auto max-h-[60vh]">
|
|
251
285
|
{lines.map((line, i) => (
|
|
252
|
-
<div
|
|
286
|
+
<div
|
|
287
|
+
key={line.sourceKey ?? i}
|
|
288
|
+
className="flex items-center justify-between py-2.5 border-b border-border last:border-0"
|
|
289
|
+
>
|
|
253
290
|
<div className="min-w-0 flex-1">
|
|
254
291
|
<p className="text-sm font-medium">{line.productVariant.name}</p>
|
|
255
|
-
<p className="text-[11px] text-muted-foreground font-mono">
|
|
292
|
+
<p className="text-[11px] text-muted-foreground font-mono">
|
|
293
|
+
{line.productVariant.sku}
|
|
294
|
+
</p>
|
|
256
295
|
</div>
|
|
257
296
|
<div className="flex items-center gap-3 shrink-0 ml-3">
|
|
258
|
-
<span className="text-xs text-muted-foreground font-mono"
|
|
297
|
+
<span className="text-xs text-muted-foreground font-mono">
|
|
298
|
+
×{line.quantity}
|
|
299
|
+
</span>
|
|
259
300
|
<span className="text-sm font-mono tabular-nums">
|
|
260
|
-
<Price
|
|
301
|
+
<Price
|
|
302
|
+
value={line.productVariant.priceWithTax * line.quantity}
|
|
303
|
+
currencyCode={currencyCode}
|
|
304
|
+
/>
|
|
261
305
|
</span>
|
|
262
306
|
</div>
|
|
263
307
|
</div>
|
|
@@ -308,7 +352,9 @@ function BomSidebar({
|
|
|
308
352
|
{lines.length}
|
|
309
353
|
</span>
|
|
310
354
|
)}
|
|
311
|
-
{isEvaluating &&
|
|
355
|
+
{isEvaluating && (
|
|
356
|
+
<Loader2 className="w-3.5 h-3.5 animate-spin text-muted-foreground ml-auto" />
|
|
357
|
+
)}
|
|
312
358
|
</div>
|
|
313
359
|
|
|
314
360
|
{lines.length > 0 ? (
|
|
@@ -317,21 +363,28 @@ function BomSidebar({
|
|
|
317
363
|
<div key={line.sourceKey ?? i} className="py-2">
|
|
318
364
|
<div className="flex items-start justify-between gap-2">
|
|
319
365
|
<div className="min-w-0 flex-1">
|
|
320
|
-
<p className="text-sm font-medium leading-tight">
|
|
321
|
-
|
|
366
|
+
<p className="text-sm font-medium leading-tight">
|
|
367
|
+
{line.productVariant.name}
|
|
368
|
+
</p>
|
|
369
|
+
<p className="text-[11px] text-muted-foreground font-mono mt-0.5">
|
|
370
|
+
{line.productVariant.sku}
|
|
371
|
+
</p>
|
|
322
372
|
</div>
|
|
323
|
-
<span className="text-xs text-muted-foreground font-mono tabular-nums shrink-0"
|
|
373
|
+
<span className="text-xs text-muted-foreground font-mono tabular-nums shrink-0">
|
|
374
|
+
×{line.quantity}
|
|
375
|
+
</span>
|
|
324
376
|
</div>
|
|
325
377
|
<p className="text-sm font-mono tabular-nums text-right mt-0.5">
|
|
326
|
-
<Price
|
|
378
|
+
<Price
|
|
379
|
+
value={line.productVariant.priceWithTax * line.quantity}
|
|
380
|
+
currencyCode={currencyCode}
|
|
381
|
+
/>
|
|
327
382
|
</p>
|
|
328
383
|
</div>
|
|
329
384
|
))}
|
|
330
385
|
</div>
|
|
331
386
|
) : (
|
|
332
|
-
<p className="text-sm text-muted-foreground py-4">
|
|
333
|
-
{t('emptyBom')}
|
|
334
|
-
</p>
|
|
387
|
+
<p className="text-sm text-muted-foreground py-4">{t('emptyBom')}</p>
|
|
335
388
|
)}
|
|
336
389
|
</div>
|
|
337
390
|
|
|
@@ -350,11 +403,20 @@ function BomSidebar({
|
|
|
350
403
|
onClick={onAddToOrder}
|
|
351
404
|
>
|
|
352
405
|
{isAdded ? (
|
|
353
|
-
|
|
406
|
+
<>
|
|
407
|
+
<CheckCircle2 className="mr-2 h-5 w-5" />
|
|
408
|
+
{t('addedToCart')}
|
|
409
|
+
</>
|
|
354
410
|
) : isAdding ? (
|
|
355
|
-
|
|
411
|
+
<>
|
|
412
|
+
<Loader2 className="mr-2 h-5 w-5 animate-spin" />
|
|
413
|
+
{t('adding')}
|
|
414
|
+
</>
|
|
356
415
|
) : (
|
|
357
|
-
|
|
416
|
+
<>
|
|
417
|
+
<ShoppingCart className="mr-2 h-5 w-5" />
|
|
418
|
+
{t('addToCart')}
|
|
419
|
+
</>
|
|
358
420
|
)}
|
|
359
421
|
</Button>
|
|
360
422
|
</div>
|
|
@@ -384,21 +446,21 @@ function ModuleSection({
|
|
|
384
446
|
}) {
|
|
385
447
|
const t = useTranslations('Configurator');
|
|
386
448
|
const visibleFields = mod.fields
|
|
387
|
-
.filter(f => {
|
|
449
|
+
.filter((f) => {
|
|
388
450
|
const ef = evalFieldMap.get(buildFieldRef(mod.code, f.code));
|
|
389
451
|
return !ef?.hidden;
|
|
390
452
|
})
|
|
391
453
|
.sort((a, b) => a.sortOrder - b.sortOrder);
|
|
392
454
|
|
|
393
455
|
const allFilled = visibleFields
|
|
394
|
-
.filter(f => f.required)
|
|
395
|
-
.every(f => {
|
|
456
|
+
.filter((f) => f.required)
|
|
457
|
+
.every((f) => {
|
|
396
458
|
const val = values[buildFieldRef(mod.code, f.code)];
|
|
397
459
|
return val != null && val !== '';
|
|
398
460
|
});
|
|
399
461
|
|
|
400
462
|
const summaryParts = visibleFields
|
|
401
|
-
.map(f => {
|
|
463
|
+
.map((f) => {
|
|
402
464
|
const val = values[buildFieldRef(mod.code, f.code)];
|
|
403
465
|
if (!val) return null;
|
|
404
466
|
if (f.fieldType === 'BOOL') return val === 'true' ? f.name : null;
|
|
@@ -409,17 +471,23 @@ function ModuleSection({
|
|
|
409
471
|
const summary = summaryParts.slice(0, 3).join(', ');
|
|
410
472
|
|
|
411
473
|
return (
|
|
412
|
-
<section
|
|
474
|
+
<section
|
|
475
|
+
className={`border border-border rounded-lg overflow-hidden transition-shadow ${
|
|
476
|
+
expanded ? 'ring-1 ring-primary/20' : ''
|
|
477
|
+
}`}
|
|
478
|
+
>
|
|
413
479
|
<button
|
|
414
480
|
type="button"
|
|
415
481
|
onClick={onToggle}
|
|
416
482
|
className="w-full flex items-center gap-2.5 px-4 py-3 text-left hover:bg-muted/30 transition-colors"
|
|
417
483
|
>
|
|
418
|
-
<div
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
484
|
+
<div
|
|
485
|
+
className={`w-5 h-5 rounded-full flex items-center justify-center text-[10px] font-semibold shrink-0 ${
|
|
486
|
+
allFilled && summaryParts.length > 0
|
|
487
|
+
? 'bg-primary text-white'
|
|
488
|
+
: 'border-2 border-muted-foreground/30 text-muted-foreground'
|
|
489
|
+
}`}
|
|
490
|
+
>
|
|
423
491
|
{allFilled && summaryParts.length > 0 ? (
|
|
424
492
|
<CheckCircle2 className="w-3 h-3" />
|
|
425
493
|
) : (
|
|
@@ -427,26 +495,44 @@ function ModuleSection({
|
|
|
427
495
|
)}
|
|
428
496
|
</div>
|
|
429
497
|
<div className="flex-1 min-w-0">
|
|
430
|
-
<h2
|
|
498
|
+
<h2
|
|
499
|
+
className={`text-sm font-semibold ${
|
|
500
|
+
allFilled && summaryParts.length > 0
|
|
501
|
+
? 'text-foreground'
|
|
502
|
+
: expanded
|
|
503
|
+
? 'text-foreground'
|
|
504
|
+
: 'text-muted-foreground'
|
|
505
|
+
}`}
|
|
506
|
+
>
|
|
431
507
|
{mod.name}
|
|
432
|
-
{mod.optional &&
|
|
508
|
+
{mod.optional && (
|
|
509
|
+
<span className="ml-1.5 text-xs font-normal text-muted-foreground">
|
|
510
|
+
{t('optional')}
|
|
511
|
+
</span>
|
|
512
|
+
)}
|
|
433
513
|
</h2>
|
|
434
514
|
</div>
|
|
435
515
|
{!expanded && summary && (
|
|
436
|
-
<span className="text-xs text-muted-foreground hidden sm:inline truncate max-w-32">
|
|
516
|
+
<span className="text-xs text-muted-foreground hidden sm:inline truncate max-w-32">
|
|
517
|
+
{summary}
|
|
518
|
+
</span>
|
|
437
519
|
)}
|
|
438
|
-
<ChevronDown
|
|
520
|
+
<ChevronDown
|
|
521
|
+
className={`w-4 h-4 text-muted-foreground transition-transform ${
|
|
522
|
+
expanded ? 'rotate-180' : ''
|
|
523
|
+
}`}
|
|
524
|
+
/>
|
|
439
525
|
</button>
|
|
440
526
|
{expanded && (
|
|
441
527
|
<div className="px-4 pb-4 pt-2 space-y-3.5 border-t border-border">
|
|
442
|
-
{visibleFields.map(field => (
|
|
528
|
+
{visibleFields.map((field) => (
|
|
443
529
|
<FieldInput
|
|
444
530
|
key={field.id}
|
|
445
531
|
field={field}
|
|
446
532
|
moduleCode={mod.code}
|
|
447
533
|
value={values[buildFieldRef(mod.code, field.code)] ?? ''}
|
|
448
534
|
evalField={evalFieldMap.get(buildFieldRef(mod.code, field.code))}
|
|
449
|
-
onChange={val => onFieldChange(mod.code, field.code, val)}
|
|
535
|
+
onChange={(val) => onFieldChange(mod.code, field.code, val)}
|
|
450
536
|
/>
|
|
451
537
|
))}
|
|
452
538
|
</div>
|
|
@@ -480,7 +566,7 @@ function FieldInput({
|
|
|
480
566
|
<Label className="text-sm font-medium">{field.name}</Label>
|
|
481
567
|
<Switch
|
|
482
568
|
checked={value === 'true'}
|
|
483
|
-
onCheckedChange={checked => onChange(checked ? 'true' : 'false')}
|
|
569
|
+
onCheckedChange={(checked) => onChange(checked ? 'true' : 'false')}
|
|
484
570
|
/>
|
|
485
571
|
</div>
|
|
486
572
|
) : (
|
|
@@ -494,15 +580,22 @@ function FieldInput({
|
|
|
494
580
|
) : field.fieldType === 'SELECT' || field.fieldType === 'DYNAMIC_SELECT' ? (
|
|
495
581
|
<SelectInput field={field} value={value} evalField={evalField} onChange={onChange} />
|
|
496
582
|
) : (
|
|
497
|
-
<Input value={value} onChange={e => onChange(e.target.value)} />
|
|
583
|
+
<Input value={value} onChange={(e) => onChange(e.target.value)} />
|
|
498
584
|
)}
|
|
499
585
|
</>
|
|
500
586
|
)}
|
|
501
587
|
|
|
502
588
|
{messages.map((msg, i) => (
|
|
503
|
-
<p
|
|
504
|
-
|
|
505
|
-
|
|
589
|
+
<p
|
|
590
|
+
key={i}
|
|
591
|
+
className={`text-xs flex items-center gap-1 ${
|
|
592
|
+
msg.type === 'error'
|
|
593
|
+
? 'text-red-600'
|
|
594
|
+
: msg.type === 'warning'
|
|
595
|
+
? 'text-amber-600'
|
|
596
|
+
: 'text-muted-foreground'
|
|
597
|
+
}`}
|
|
598
|
+
>
|
|
506
599
|
<Info className="w-3 h-3 shrink-0" />
|
|
507
600
|
{msg.message}
|
|
508
601
|
</p>
|
|
@@ -512,20 +605,37 @@ function FieldInput({
|
|
|
512
605
|
<p className="text-xs text-muted-foreground font-mono tabular-nums">
|
|
513
606
|
{field.min && field.max
|
|
514
607
|
? t('range', {
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
608
|
+
min: `${Number(field.min).toLocaleString()}`,
|
|
609
|
+
max: `${Number(field.max).toLocaleString()}${
|
|
610
|
+
field.unit ? ` ${field.unit}` : ''
|
|
611
|
+
}`,
|
|
612
|
+
})
|
|
518
613
|
: field.min
|
|
519
|
-
? t('min', {
|
|
520
|
-
|
|
521
|
-
|
|
614
|
+
? t('min', {
|
|
615
|
+
value: `${Number(field.min).toLocaleString()}${
|
|
616
|
+
field.unit ? ` ${field.unit}` : ''
|
|
617
|
+
}`,
|
|
618
|
+
})
|
|
619
|
+
: t('max', {
|
|
620
|
+
value: `${Number(field.max).toLocaleString()}${
|
|
621
|
+
field.unit ? ` ${field.unit}` : ''
|
|
622
|
+
}`,
|
|
623
|
+
})}
|
|
522
624
|
</p>
|
|
523
625
|
)}
|
|
524
626
|
</div>
|
|
525
627
|
);
|
|
526
628
|
}
|
|
527
629
|
|
|
528
|
-
function NumberInput({
|
|
630
|
+
function NumberInput({
|
|
631
|
+
field,
|
|
632
|
+
value,
|
|
633
|
+
onChange,
|
|
634
|
+
}: {
|
|
635
|
+
field: ConfiguratorField;
|
|
636
|
+
value: string;
|
|
637
|
+
onChange: (v: string) => void;
|
|
638
|
+
}) {
|
|
529
639
|
const step = field.unit === 'mm' ? 100 : 1;
|
|
530
640
|
const min = field.min ? Number(field.min) : undefined;
|
|
531
641
|
const max = field.max ? Number(field.max) : undefined;
|
|
@@ -553,7 +663,7 @@ function NumberInput({ field, value, onChange }: { field: ConfiguratorField; val
|
|
|
553
663
|
min={min}
|
|
554
664
|
max={max}
|
|
555
665
|
step={step}
|
|
556
|
-
onChange={e => onChange(e.target.value)}
|
|
666
|
+
onChange={(e) => onChange(e.target.value)}
|
|
557
667
|
className="flex-1 h-9 px-3 text-sm focus:outline-none bg-transparent font-mono tabular-nums text-center [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
|
|
558
668
|
/>
|
|
559
669
|
<button
|
|
@@ -585,8 +695,8 @@ function SelectInput({
|
|
|
585
695
|
}) {
|
|
586
696
|
const t = useTranslations('Configurator');
|
|
587
697
|
const options = evalField?.availableOptions?.length
|
|
588
|
-
? evalField.availableOptions.map(o => ({ value: o.value, label: o.label ?? o.value }))
|
|
589
|
-
: (field.options ?? []).map(o => ({ value: o.code, label: o.label }));
|
|
698
|
+
? evalField.availableOptions.map((o) => ({ value: o.value, label: o.label ?? o.value }))
|
|
699
|
+
: (field.options ?? []).map((o) => ({ value: o.code, label: o.label }));
|
|
590
700
|
|
|
591
701
|
return (
|
|
592
702
|
<Select value={value || undefined} onValueChange={onChange}>
|
|
@@ -594,7 +704,7 @@ function SelectInput({
|
|
|
594
704
|
<SelectValue placeholder={t('selectPlaceholder', { field: field.name.toLowerCase() })} />
|
|
595
705
|
</SelectTrigger>
|
|
596
706
|
<SelectContent>
|
|
597
|
-
{options.map(opt => (
|
|
707
|
+
{options.map((opt) => (
|
|
598
708
|
<SelectItem key={opt.value} value={opt.value}>
|
|
599
709
|
{opt.label}
|
|
600
710
|
</SelectItem>
|
|
@@ -603,4 +713,3 @@ function SelectInput({
|
|
|
603
713
|
</Select>
|
|
604
714
|
);
|
|
605
715
|
}
|
|
606
|
-
|
|
@@ -1,32 +1,21 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { usePathname, useRouter } from '@/i18n/navigation';
|
|
3
|
+
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion';
|
|
4
|
+
import { Badge } from '@/components/ui/badge';
|
|
5
|
+
import { Button } from '@/components/ui/button';
|
|
7
6
|
import { Checkbox } from '@/components/ui/checkbox';
|
|
8
7
|
import { Label } from '@/components/ui/label';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
Accordion,
|
|
13
|
-
AccordionContent,
|
|
14
|
-
AccordionItem,
|
|
15
|
-
AccordionTrigger,
|
|
16
|
-
} from '@/components/ui/accordion';
|
|
17
|
-
import {
|
|
18
|
-
Sheet,
|
|
19
|
-
SheetContent,
|
|
20
|
-
SheetHeader,
|
|
21
|
-
SheetTitle,
|
|
22
|
-
SheetTrigger,
|
|
23
|
-
} from '@/components/ui/sheet';
|
|
24
|
-
import { SlidersHorizontal, Layers, ListTree, Tag } from 'lucide-react';
|
|
25
|
-
import { type SearchProductsResult } from '@/lib/vendure/queries';
|
|
8
|
+
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from '@/components/ui/sheet';
|
|
9
|
+
import { Switch } from '@/components/ui/switch';
|
|
10
|
+
import { usePathname, useRouter } from '@/i18n/navigation';
|
|
26
11
|
import { RESERVED_PARAMS, STRUCTURAL_PARAMS } from '@/lib/search-helpers';
|
|
12
|
+
import { type SearchProductsResult } from '@/lib/vendure/queries';
|
|
13
|
+
import { Layers, ListTree, SlidersHorizontal, Tag } from 'lucide-react';
|
|
14
|
+
import { useTranslations } from 'next-intl';
|
|
15
|
+
import { useSearchParams } from 'next/navigation';
|
|
16
|
+
import { use, useState } from 'react';
|
|
27
17
|
import { ActiveFilters } from './active-filters';
|
|
28
18
|
import { PriceRangeFilter } from './price-range-filter';
|
|
29
|
-
import { Switch } from '@/components/ui/switch';
|
|
30
19
|
|
|
31
20
|
const VISIBLE_COUNT = 6;
|
|
32
21
|
|
|
@@ -79,9 +68,9 @@ export function FacetFilters({ productDataPromise }: FacetFiltersProps) {
|
|
|
79
68
|
const activeFilterCount =
|
|
80
69
|
[...searchParams.entries()]
|
|
81
70
|
.filter(([key]) => !RESERVED_PARAMS.has(key))
|
|
82
|
-
.reduce((n, [, v]) => n + v.split(',').length, 0)
|
|
83
|
-
|
|
84
|
-
|
|
71
|
+
.reduce((n, [, v]) => n + v.split(',').length, 0) +
|
|
72
|
+
(searchParams.has('priceMin') || searchParams.has('priceMax') ? 1 : 0) +
|
|
73
|
+
(searchParams.get('inStock') === 'true' ? 1 : 0);
|
|
85
74
|
|
|
86
75
|
const toggleFacet = (facetCode: string, valueCode: string) => {
|
|
87
76
|
const params = new URLSearchParams(searchParams);
|
|
@@ -143,7 +132,9 @@ export function FacetFilters({ productDataPromise }: FacetFiltersProps) {
|
|
|
143
132
|
variant="ghost"
|
|
144
133
|
size="sm"
|
|
145
134
|
onClick={clearFilters}
|
|
146
|
-
className={`h-7 text-xs text-muted-foreground hover:text-foreground ${
|
|
135
|
+
className={`h-7 text-xs text-muted-foreground hover:text-foreground ${
|
|
136
|
+
!hasActiveFilters ? 'invisible' : ''
|
|
137
|
+
}`}
|
|
147
138
|
>
|
|
148
139
|
{t('clearAll')}
|
|
149
140
|
</Button>
|
|
@@ -155,11 +146,7 @@ export function FacetFilters({ productDataPromise }: FacetFiltersProps) {
|
|
|
155
146
|
<Label htmlFor="in-stock-toggle" className="text-sm font-normal cursor-pointer">
|
|
156
147
|
{t('inStockOnly')}
|
|
157
148
|
</Label>
|
|
158
|
-
<Switch
|
|
159
|
-
id="in-stock-toggle"
|
|
160
|
-
checked={isInStock}
|
|
161
|
-
onCheckedChange={toggleInStock}
|
|
162
|
-
/>
|
|
149
|
+
<Switch id="in-stock-toggle" checked={isInStock} onCheckedChange={toggleInStock} />
|
|
163
150
|
</div>
|
|
164
151
|
|
|
165
152
|
<PriceRangeFilter min={prices.range.min} max={prices.range.max} />
|
|
@@ -167,9 +154,12 @@ export function FacetFilters({ productDataPromise }: FacetFiltersProps) {
|
|
|
167
154
|
<Accordion type="multiple" defaultValue={defaultOpen}>
|
|
168
155
|
{facetGroups.map((facet) => {
|
|
169
156
|
const facetNameLower = facet.name.toLowerCase();
|
|
170
|
-
const FacetIcon = facetNameLower.includes('subcategory')
|
|
171
|
-
|
|
172
|
-
: facetNameLower.includes('
|
|
157
|
+
const FacetIcon = facetNameLower.includes('subcategory')
|
|
158
|
+
? ListTree
|
|
159
|
+
: facetNameLower.includes('category')
|
|
160
|
+
? Layers
|
|
161
|
+
: facetNameLower.includes('brand')
|
|
162
|
+
? Tag
|
|
173
163
|
: SlidersHorizontal;
|
|
174
164
|
|
|
175
165
|
const selectedValues = searchParams.get(facet.code)?.split(',') ?? [];
|
|
@@ -200,9 +190,7 @@ export function FacetFilters({ productDataPromise }: FacetFiltersProps) {
|
|
|
200
190
|
return (
|
|
201
191
|
<>
|
|
202
192
|
{/* Desktop: sticky sidebar */}
|
|
203
|
-
<div className="hidden lg:block sticky top-20">
|
|
204
|
-
{filterContent}
|
|
205
|
-
</div>
|
|
193
|
+
<div className="hidden lg:block sticky top-20">{filterContent}</div>
|
|
206
194
|
|
|
207
195
|
{/* Mobile: sheet trigger */}
|
|
208
196
|
<div className="lg:hidden">
|
|
@@ -212,9 +200,7 @@ export function FacetFilters({ productDataPromise }: FacetFiltersProps) {
|
|
|
212
200
|
<SlidersHorizontal className="h-4 w-4" />
|
|
213
201
|
{t('filtersButton')}
|
|
214
202
|
{hasActiveFilters && (
|
|
215
|
-
<Badge className="h-5 min-w-5 px-1.5 text-[10px]">
|
|
216
|
-
{activeFilterCount}
|
|
217
|
-
</Badge>
|
|
203
|
+
<Badge className="h-5 min-w-5 px-1.5 text-[10px]">{activeFilterCount}</Badge>
|
|
218
204
|
)}
|
|
219
205
|
</Button>
|
|
220
206
|
</SheetTrigger>
|
|
@@ -261,12 +247,8 @@ function FacetValueList({
|
|
|
261
247
|
htmlFor={`facet-${facetCode}-${value.code}`}
|
|
262
248
|
className="text-sm font-normal cursor-pointer flex-1 flex items-center justify-between"
|
|
263
249
|
>
|
|
264
|
-
<span className={isChecked ? 'text-foreground' : ''}>
|
|
265
|
-
|
|
266
|
-
</span>
|
|
267
|
-
<span className="text-xs text-muted-foreground tabular-nums">
|
|
268
|
-
{value.count}
|
|
269
|
-
</span>
|
|
250
|
+
<span className={isChecked ? 'text-foreground' : ''}>{value.name}</span>
|
|
251
|
+
<span className="text-xs text-muted-foreground tabular-nums">{value.count}</span>
|
|
270
252
|
</Label>
|
|
271
253
|
</div>
|
|
272
254
|
);
|
|
@@ -276,9 +258,7 @@ function FacetValueList({
|
|
|
276
258
|
onClick={() => setExpanded(!expanded)}
|
|
277
259
|
className="text-xs text-primary hover:text-primary/80 pt-1"
|
|
278
260
|
>
|
|
279
|
-
{expanded
|
|
280
|
-
? t('showLess')
|
|
281
|
-
: t('moreCount', { count: values.length - VISIBLE_COUNT })}
|
|
261
|
+
{expanded ? t('showLess') : t('moreCount', { count: values.length - VISIBLE_COUNT })}
|
|
282
262
|
</button>
|
|
283
263
|
)}
|
|
284
264
|
</div>
|