@vendure/dashboard 3.4.3-master-202509260228 → 3.5.0-minor-202510012036
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/README.md +4 -0
- package/dist/plugin/api/api-extensions.js +11 -14
- package/dist/plugin/api/metrics.resolver.d.ts +2 -2
- package/dist/plugin/api/metrics.resolver.js +2 -2
- package/dist/plugin/config/metrics-strategies.d.ts +9 -9
- package/dist/plugin/config/metrics-strategies.js +6 -6
- package/dist/plugin/constants.d.ts +2 -0
- package/dist/plugin/constants.js +3 -1
- package/dist/plugin/dashboard.plugin.js +13 -0
- package/dist/plugin/service/metrics.service.d.ts +3 -3
- package/dist/plugin/service/metrics.service.js +37 -53
- package/dist/plugin/types.d.ts +9 -12
- package/dist/plugin/types.js +7 -11
- package/dist/vite/vite-plugin-config.js +13 -9
- package/dist/vite/vite-plugin-translations.d.ts +22 -0
- package/dist/vite/vite-plugin-translations.js +66 -0
- package/dist/vite/vite-plugin-vendure-dashboard.js +10 -8
- package/lingui.config.js +25 -2
- package/package.json +159 -156
- package/src/app/app-providers.tsx +0 -4
- package/src/app/common/delete-bulk-action.tsx +6 -5
- package/src/app/common/duplicate-bulk-action.tsx +4 -5
- package/src/app/common/duplicate-entity-dialog.tsx +1 -1
- package/src/app/common/set-document-direction.ts +7 -0
- package/src/app/main.tsx +50 -17
- package/src/app/routes/_authenticated/_administrators/administrators.tsx +8 -6
- package/src/app/routes/_authenticated/_administrators/administrators_.$id.tsx +17 -6
- package/src/app/routes/_authenticated/_administrators/components/role-permissions-display.tsx +2 -2
- package/src/app/routes/_authenticated/_assets/assets.tsx +1 -1
- package/src/app/routes/_authenticated/_assets/assets_.$id.tsx +4 -4
- package/src/app/routes/_authenticated/_assets/components/asset-bulk-actions.tsx +8 -6
- package/src/app/routes/_authenticated/_assets/components/asset-tag-filter.tsx +1 -1
- package/src/app/routes/_authenticated/_assets/components/asset-tags-editor.tsx +1 -1
- package/src/app/routes/_authenticated/_assets/components/manage-tags-dialog.tsx +3 -8
- package/src/app/routes/_authenticated/_channels/channels.tsx +3 -6
- package/src/app/routes/_authenticated/_channels/channels_.$id.tsx +5 -5
- package/src/app/routes/_authenticated/_collections/collections.tsx +10 -6
- package/src/app/routes/_authenticated/_collections/collections_.$id.tsx +16 -5
- package/src/app/routes/_authenticated/_collections/components/collection-bulk-actions.tsx +1 -1
- package/src/app/routes/_authenticated/_collections/components/collection-contents-sheet.tsx +1 -1
- package/src/app/routes/_authenticated/_collections/components/move-collections-dialog.tsx +6 -6
- package/src/app/routes/_authenticated/_countries/countries.graphql.ts +2 -0
- package/src/app/routes/_authenticated/_countries/countries.tsx +2 -3
- package/src/app/routes/_authenticated/_countries/countries_.$id.tsx +4 -4
- package/src/app/routes/_authenticated/_customer-groups/components/customer-group-members-sheet.tsx +1 -1
- package/src/app/routes/_authenticated/_customer-groups/components/customer-group-members-table.tsx +4 -4
- package/src/app/routes/_authenticated/_customer-groups/customer-groups.tsx +2 -4
- package/src/app/routes/_authenticated/_customer-groups/customer-groups_.$id.tsx +13 -6
- package/src/app/routes/_authenticated/_customers/components/customer-address-card.tsx +8 -8
- package/src/app/routes/_authenticated/_customers/components/customer-address-form.tsx +3 -3
- package/src/app/routes/_authenticated/_customers/components/customer-history/customer-history-container.tsx +1 -1
- package/src/app/routes/_authenticated/_customers/components/customer-history/customer-history-utils.tsx +1 -1
- package/src/app/routes/_authenticated/_customers/components/customer-history/default-customer-history-components.tsx +1 -1
- package/src/app/routes/_authenticated/_customers/components/customer-history/use-customer-history.ts +1 -1
- package/src/app/routes/_authenticated/_customers/components/customer-status-badge.tsx +1 -1
- package/src/app/routes/_authenticated/_customers/customers.graphql.ts +4 -0
- package/src/app/routes/_authenticated/_customers/customers.tsx +23 -11
- package/src/app/routes/_authenticated/_customers/customers_.$id.tsx +10 -8
- package/src/app/routes/_authenticated/_facets/components/edit-facet-value.tsx +1 -1
- package/src/app/routes/_authenticated/_facets/components/facet-bulk-actions.tsx +6 -5
- package/src/app/routes/_authenticated/_facets/components/facet-values-sheet.tsx +1 -1
- package/src/app/routes/_authenticated/_facets/components/facet-values-table.tsx +1 -1
- package/src/app/routes/_authenticated/_facets/facets.tsx +5 -5
- package/src/app/routes/_authenticated/_facets/facets_.$facetId.values_.$id.tsx +7 -5
- package/src/app/routes/_authenticated/_facets/facets_.$id.tsx +18 -6
- package/src/app/routes/_authenticated/_global-settings/global-settings.tsx +5 -5
- package/src/app/routes/_authenticated/_orders/components/add-manual-payment-dialog.tsx +19 -21
- package/src/app/routes/_authenticated/_orders/components/customer-address-selector.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/components/edit-order-table.tsx +22 -22
- package/src/app/routes/_authenticated/_orders/components/fulfill-order-dialog.tsx +6 -6
- package/src/app/routes/_authenticated/_orders/components/fulfillment-details.tsx +15 -9
- package/src/app/routes/_authenticated/_orders/components/order-address.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/components/order-detail-shared.tsx +11 -9
- package/src/app/routes/_authenticated/_orders/components/order-history/default-order-history-components.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/components/order-history/order-history-container.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/components/order-history/order-history-utils.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/components/order-history/use-order-history.ts +1 -1
- package/src/app/routes/_authenticated/_orders/components/order-line-custom-fields-form.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/components/order-modification-preview-dialog.tsx +4 -4
- package/src/app/routes/_authenticated/_orders/components/order-modification-summary.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/components/order-table-totals.tsx +27 -27
- package/src/app/routes/_authenticated/_orders/components/order-table.tsx +2 -2
- package/src/app/routes/_authenticated/_orders/components/order-tax-summary.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/components/payment-details.tsx +26 -20
- package/src/app/routes/_authenticated/_orders/components/seller-orders-card.tsx +3 -1
- package/src/app/routes/_authenticated/_orders/components/settle-refund-dialog.tsx +6 -6
- package/src/app/routes/_authenticated/_orders/components/shipping-method-selector.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/components/state-transition-control.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/components/use-transition-order-to-state.tsx +3 -2
- package/src/app/routes/_authenticated/_orders/orders.tsx +5 -9
- package/src/app/routes/_authenticated/_orders/orders_.$aggregateOrderId_.seller-orders.$sellerOrderId.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/orders_.$id.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/orders_.$id_.modify.tsx +4 -4
- package/src/app/routes/_authenticated/_orders/orders_.draft.$id.tsx +17 -17
- package/src/app/routes/_authenticated/_orders/utils/order-detail-loaders.tsx +1 -1
- package/src/app/routes/_authenticated/_payment-methods/payment-methods.tsx +5 -6
- package/src/app/routes/_authenticated/_payment-methods/payment-methods_.$id.tsx +13 -6
- package/src/app/routes/_authenticated/_product-variants/components/product-variant-bulk-actions.tsx +1 -1
- package/src/app/routes/_authenticated/_product-variants/components/variant-price-detail.tsx +1 -1
- package/src/app/routes/_authenticated/_product-variants/product-variants.graphql.ts +10 -0
- package/src/app/routes/_authenticated/_product-variants/product-variants.tsx +9 -2
- package/src/app/routes/_authenticated/_product-variants/product-variants_.$id.tsx +13 -6
- package/src/app/routes/_authenticated/_products/components/add-option-group-dialog.tsx +5 -5
- package/src/app/routes/_authenticated/_products/components/add-product-variant-dialog.tsx +5 -5
- package/src/app/routes/_authenticated/_products/components/assign-facet-values-dialog.tsx +5 -4
- package/src/app/routes/_authenticated/_products/components/create-product-options-dialog.tsx +9 -12
- package/src/app/routes/_authenticated/_products/components/create-product-variants-dialog.tsx +1 -1
- package/src/app/routes/_authenticated/_products/components/create-product-variants.tsx +4 -4
- package/src/app/routes/_authenticated/_products/components/option-groups-editor.tsx +1 -1
- package/src/app/routes/_authenticated/_products/components/product-bulk-actions.tsx +1 -1
- package/src/app/routes/_authenticated/_products/components/product-option-group-badge.tsx +19 -0
- package/src/app/routes/_authenticated/_products/components/product-option-select.tsx +3 -3
- package/src/app/routes/_authenticated/_products/components/product-options-table.tsx +114 -0
- package/src/app/routes/_authenticated/_products/product-option-groups.graphql.ts +103 -0
- package/src/app/routes/_authenticated/_products/products.graphql.ts +44 -32
- package/src/app/routes/_authenticated/_products/products.tsx +34 -5
- package/src/app/routes/_authenticated/_products/products_.$id.tsx +29 -12
- package/src/app/routes/_authenticated/_products/products_.$id_.variants.tsx +11 -11
- package/src/app/routes/_authenticated/_products/products_.$productId.option-groups.$id.tsx +177 -0
- package/src/app/routes/_authenticated/_products/products_.$productId.option-groups.$productOptionGroupId.options_.$id.tsx +208 -0
- package/src/app/routes/_authenticated/_profile/profile.tsx +4 -4
- package/src/app/routes/_authenticated/_promotions/promotions.tsx +2 -4
- package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +16 -9
- package/src/app/routes/_authenticated/_roles/components/permissions-table-grid.tsx +1 -1
- package/src/app/routes/_authenticated/_roles/roles.tsx +3 -6
- package/src/app/routes/_authenticated/_roles/roles_.$id.tsx +4 -6
- package/src/app/routes/_authenticated/_sellers/sellers.tsx +3 -4
- package/src/app/routes/_authenticated/_sellers/sellers_.$id.tsx +4 -4
- package/src/app/routes/_authenticated/_shipping-methods/components/price-display.tsx +5 -5
- package/src/app/routes/_authenticated/_shipping-methods/components/shipping-method-test-result-wrapper.tsx +1 -1
- package/src/app/routes/_authenticated/_shipping-methods/components/test-address-form.tsx +11 -11
- package/src/app/routes/_authenticated/_shipping-methods/components/test-order-builder.tsx +1 -1
- package/src/app/routes/_authenticated/_shipping-methods/components/test-shipping-methods-result.tsx +8 -8
- package/src/app/routes/_authenticated/_shipping-methods/components/test-shipping-methods-sheet.tsx +1 -1
- package/src/app/routes/_authenticated/_shipping-methods/components/test-single-method-result.tsx +8 -8
- package/src/app/routes/_authenticated/_shipping-methods/components/test-single-shipping-method-sheet.tsx +4 -4
- package/src/app/routes/_authenticated/_shipping-methods/shipping-methods.tsx +2 -3
- package/src/app/routes/_authenticated/_shipping-methods/shipping-methods_.$id.tsx +2 -2
- package/src/app/routes/_authenticated/_stock-locations/stock-locations.tsx +3 -4
- package/src/app/routes/_authenticated/_stock-locations/stock-locations_.$id.tsx +13 -6
- package/src/app/routes/_authenticated/_system/healthchecks.tsx +10 -4
- package/src/app/routes/_authenticated/_system/job-queue.tsx +10 -13
- package/src/app/routes/_authenticated/_system/scheduled-tasks.tsx +18 -16
- package/src/app/routes/_authenticated/_tax-categories/tax-categories.tsx +2 -4
- package/src/app/routes/_authenticated/_tax-categories/tax-categories_.$id.tsx +13 -6
- package/src/app/routes/_authenticated/_tax-rates/tax-rates.tsx +8 -12
- package/src/app/routes/_authenticated/_tax-rates/tax-rates_.$id.tsx +6 -4
- package/src/app/routes/_authenticated/_zones/components/zone-countries-sheet.tsx +4 -1
- package/src/app/routes/_authenticated/_zones/zones.tsx +4 -4
- package/src/app/routes/_authenticated/_zones/zones_.$id.tsx +8 -5
- package/src/app/routes/_authenticated/index.tsx +46 -25
- package/src/app/styles.css +4 -0
- package/src/i18n/common-strings.ts +111 -0
- package/src/i18n/locales/ar.po +4777 -0
- package/src/i18n/locales/cs.po +4777 -0
- package/src/i18n/locales/de.po +4299 -1101
- package/src/i18n/locales/en.po +3857 -659
- package/src/i18n/locales/es.po +4777 -0
- package/src/i18n/locales/fa.po +4777 -0
- package/src/i18n/locales/fr.po +4777 -0
- package/src/i18n/locales/he.po +4777 -0
- package/src/i18n/locales/hr.po +4777 -0
- package/src/i18n/locales/it.po +4777 -0
- package/src/i18n/locales/ja.po +4777 -0
- package/src/i18n/locales/ko.po +4628 -0
- package/src/i18n/locales/nb.po +4777 -0
- package/src/i18n/locales/ne.po +4777 -0
- package/src/i18n/locales/nl.po +4628 -0
- package/src/i18n/locales/pl.po +4777 -0
- package/src/i18n/locales/pt_BR.po +4777 -0
- package/src/i18n/locales/pt_PT.po +4777 -0
- package/src/i18n/locales/ru.po +4777 -0
- package/src/i18n/locales/sv.po +4777 -0
- package/src/i18n/locales/tr.po +4777 -0
- package/src/i18n/locales/uk.po +4777 -0
- package/src/i18n/locales/zh_Hans.po +4777 -0
- package/src/i18n/locales/zh_Hant.po +4777 -0
- package/src/lib/components/data-display/json.tsx +16 -1
- package/src/lib/components/data-input/combination-mode-input.tsx +1 -1
- package/src/lib/components/data-input/custom-field-list-input.tsx +11 -7
- package/src/lib/components/data-input/customer-group-input.tsx +27 -33
- package/src/lib/components/data-input/datetime-input.tsx +40 -1
- package/src/lib/components/data-input/default-relation-input.tsx +5 -4
- package/src/lib/components/data-input/index.ts +3 -0
- package/src/lib/components/data-input/product-multi-selector-input.tsx +14 -14
- package/src/lib/components/data-input/relation-selector.tsx +1 -1
- package/src/lib/components/data-input/select-with-options.tsx +1 -1
- package/src/lib/components/data-input/slug-input.tsx +290 -0
- package/src/lib/components/data-table/add-filter-menu.tsx +17 -10
- package/src/lib/components/data-table/data-table-bulk-action-item.tsx +45 -8
- package/src/lib/components/data-table/data-table-bulk-actions.tsx +4 -4
- package/src/lib/components/data-table/data-table-column-header.tsx +13 -8
- package/src/lib/components/data-table/data-table-context.tsx +91 -0
- package/src/lib/components/data-table/data-table-faceted-filter.tsx +2 -1
- package/src/lib/components/data-table/data-table-filter-badge.tsx +9 -5
- package/src/lib/components/data-table/data-table-filter-dialog.tsx +1 -1
- package/src/lib/components/data-table/data-table-utils.ts +21 -4
- package/src/lib/components/data-table/data-table-view-options.tsx +21 -10
- package/src/lib/components/data-table/data-table.tsx +146 -94
- package/src/lib/components/data-table/filters/data-table-boolean-filter.tsx +4 -4
- package/src/lib/components/data-table/global-views-bar.tsx +97 -0
- package/src/lib/components/data-table/global-views-sheet.tsx +11 -0
- package/src/lib/components/data-table/human-readable-operator.tsx +1 -1
- package/src/lib/components/data-table/manage-global-views-button.tsx +26 -0
- package/src/lib/components/data-table/my-views-button.tsx +47 -0
- package/src/lib/components/data-table/refresh-button.tsx +12 -3
- package/src/lib/components/data-table/save-view-button.tsx +41 -0
- package/src/lib/components/data-table/save-view-dialog.tsx +113 -0
- package/src/lib/components/data-table/use-generated-columns.tsx +13 -8
- package/src/lib/components/data-table/user-views-sheet.tsx +11 -0
- package/src/lib/components/data-table/views-sheet.tsx +305 -0
- package/src/lib/components/date-range-picker.tsx +186 -0
- package/src/lib/components/layout/app-sidebar.tsx +3 -1
- package/src/lib/components/layout/channel-switcher.tsx +8 -10
- package/src/lib/components/layout/dev-mode-indicator.tsx +1 -1
- package/src/lib/components/layout/generated-breadcrumbs.tsx +10 -8
- package/src/lib/components/layout/language-dialog.tsx +34 -13
- package/src/lib/components/layout/manage-languages-dialog.tsx +1 -1
- package/src/lib/components/layout/nav-main.tsx +23 -13
- package/src/lib/components/layout/nav-user.tsx +19 -23
- package/src/lib/components/login/login-form.tsx +1 -1
- package/src/lib/components/shared/asset/asset-bulk-actions.tsx +4 -4
- package/src/lib/components/shared/asset/asset-focal-point-editor.tsx +1 -1
- package/src/lib/components/shared/asset/asset-gallery.tsx +15 -14
- package/src/lib/components/shared/assign-to-channel-bulk-action.tsx +11 -11
- package/src/lib/components/shared/assign-to-channel-dialog.tsx +6 -5
- package/src/lib/components/shared/channel-code-label.tsx +1 -1
- package/src/lib/components/shared/channel-selector.tsx +4 -4
- package/src/lib/components/shared/configurable-operation-multi-selector.tsx +16 -14
- package/src/lib/components/shared/configurable-operation-selector.tsx +1 -1
- package/src/lib/components/shared/confirmation-dialog.tsx +8 -8
- package/src/lib/components/shared/country-selector.tsx +1 -1
- package/src/lib/components/shared/currency-selector.tsx +4 -4
- package/src/lib/components/shared/custom-fields-form.tsx +8 -24
- package/src/lib/components/shared/customer-address-form.tsx +3 -3
- package/src/lib/components/shared/customer-group-selector.tsx +1 -1
- package/src/lib/components/shared/customer-selector.tsx +1 -1
- package/src/lib/components/shared/error-page.tsx +1 -1
- package/src/lib/components/shared/facet-value-selector.tsx +10 -10
- package/src/lib/components/shared/history-timeline/history-note-checkbox.tsx +1 -1
- package/src/lib/components/shared/history-timeline/history-note-editor.tsx +1 -1
- package/src/lib/components/shared/history-timeline/history-note-entry.tsx +1 -1
- package/src/lib/components/shared/language-selector.tsx +4 -4
- package/src/lib/components/shared/navigation-confirmation.tsx +1 -1
- package/src/lib/components/shared/paginated-list-data-table.tsx +64 -34
- package/src/lib/components/shared/remove-from-channel-bulk-action.tsx +6 -5
- package/src/lib/components/shared/rich-text-editor/image-dialog.tsx +1 -1
- package/src/lib/components/shared/rich-text-editor/link-dialog.tsx +1 -1
- package/src/lib/components/shared/rich-text-editor/responsive-toolbar.tsx +1 -1
- package/src/lib/components/shared/rich-text-editor/table-edit-icons.tsx +1 -1
- package/src/lib/components/shared/role-code-label.tsx +1 -1
- package/src/lib/components/shared/role-selector.tsx +4 -4
- package/src/lib/components/shared/seller-selector.tsx +1 -1
- package/src/lib/components/shared/stock-level-label.tsx +3 -5
- package/src/lib/components/shared/table-cell/order-table-cell-components.tsx +3 -1
- package/src/lib/components/shared/tax-category-selector.tsx +1 -1
- package/src/lib/components/shared/translatable-form-field.tsx +15 -15
- package/src/lib/components/shared/zone-selector.tsx +1 -1
- package/src/lib/components/ui/button.tsx +1 -1
- package/src/lib/framework/dashboard-widget/base-widget.tsx +11 -9
- package/src/lib/framework/dashboard-widget/latest-orders-widget/index.tsx +35 -6
- package/src/lib/framework/dashboard-widget/metrics-widget/index.tsx +18 -12
- package/src/lib/framework/dashboard-widget/metrics-widget/metrics-widget.graphql.ts +9 -3
- package/src/lib/framework/dashboard-widget/orders-summary/index.tsx +26 -79
- package/src/lib/framework/dashboard-widget/widget-filters-context.tsx +35 -0
- package/src/lib/framework/defaults.ts +34 -63
- package/src/lib/framework/document-introspection/add-custom-fields.spec.ts +319 -9
- package/src/lib/framework/document-introspection/add-custom-fields.ts +60 -31
- package/src/lib/framework/document-introspection/get-document-structure.spec.ts +1 -159
- package/src/lib/framework/document-introspection/include-only-selected-list-fields.spec.ts +1840 -0
- package/src/lib/framework/document-introspection/include-only-selected-list-fields.ts +940 -0
- package/src/lib/framework/document-introspection/testing-utils.ts +161 -0
- package/src/lib/framework/extension-api/display-component-extensions.tsx +2 -0
- package/src/lib/framework/extension-api/types/data-table.ts +62 -4
- package/src/lib/framework/extension-api/types/navigation.ts +16 -0
- package/src/lib/framework/form-engine/utils.ts +34 -0
- package/src/lib/framework/layout-engine/page-layout.tsx +36 -36
- package/src/lib/framework/page/detail-page.tsx +10 -10
- package/src/lib/framework/page/list-page.tsx +289 -4
- package/src/lib/framework/page/use-extended-router.tsx +101 -34
- package/src/lib/graphql/api.ts +6 -2
- package/src/lib/graphql/graphql-env.d.ts +38 -26
- package/src/lib/hooks/use-display-locale.ts +40 -0
- package/src/lib/hooks/use-dynamic-translations.ts +46 -0
- package/src/lib/hooks/use-extended-detail-query.ts +1 -1
- package/src/lib/hooks/use-extended-list-query.ts +6 -1
- package/src/lib/hooks/use-local-format.ts +15 -1
- package/src/lib/hooks/use-saved-views.ts +230 -0
- package/src/lib/hooks/use-ui-language-loader.ts +30 -0
- package/src/lib/index.ts +15 -0
- package/src/lib/lib/load-i18n-messages.ts +17 -0
- package/src/lib/lib/trans.tsx +15 -11
- package/src/lib/providers/i18n-provider.tsx +7 -14
- package/src/lib/types/saved-views.ts +39 -0
- package/src/lib/utils/saved-views-utils.ts +40 -0
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useDayPickerLocale } from '@/vdb/components/data-input/index.js';
|
|
4
|
+
import { Button } from '@/vdb/components/ui/button.js';
|
|
5
|
+
import { Calendar } from '@/vdb/components/ui/calendar.js';
|
|
6
|
+
import { Popover, PopoverContent, PopoverTrigger } from '@/vdb/components/ui/popover.js';
|
|
7
|
+
import { DefinedDateRange } from '@/vdb/framework/dashboard-widget/widget-filters-context.js';
|
|
8
|
+
import { useLocalFormat } from '@/vdb/hooks/use-local-format.js';
|
|
9
|
+
import { cn } from '@/vdb/lib/utils.js';
|
|
10
|
+
import { Trans, useLingui } from '@lingui/react/macro';
|
|
11
|
+
import { endOfDay, endOfMonth, endOfWeek, startOfDay, startOfMonth, startOfWeek, subDays } from 'date-fns';
|
|
12
|
+
import { CalendarIcon } from 'lucide-react';
|
|
13
|
+
import * as React from 'react';
|
|
14
|
+
import { DateRange } from 'react-day-picker';
|
|
15
|
+
|
|
16
|
+
interface DateRangePickerProps {
|
|
17
|
+
className?: string;
|
|
18
|
+
dateRange: DefinedDateRange;
|
|
19
|
+
onDateRangeChange: (range: DefinedDateRange) => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const presets = [
|
|
23
|
+
{
|
|
24
|
+
id: 'today',
|
|
25
|
+
label: <Trans context="date-range">Today</Trans>,
|
|
26
|
+
getValue: () => ({
|
|
27
|
+
from: startOfDay(new Date()),
|
|
28
|
+
to: endOfDay(new Date()),
|
|
29
|
+
}),
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: 'yesterday',
|
|
33
|
+
label: <Trans context="date-range">Yesterday</Trans>,
|
|
34
|
+
getValue: () => ({
|
|
35
|
+
from: startOfDay(subDays(new Date(), 1)),
|
|
36
|
+
to: endOfDay(subDays(new Date(), 1)),
|
|
37
|
+
}),
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
id: 'last-7-days',
|
|
41
|
+
label: <Trans context="date-range">Last 7 days</Trans>,
|
|
42
|
+
getValue: () => ({
|
|
43
|
+
from: startOfDay(subDays(new Date(), 6)),
|
|
44
|
+
to: endOfDay(new Date()),
|
|
45
|
+
}),
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: 'this-week',
|
|
49
|
+
label: <Trans context="date-range">This week</Trans>,
|
|
50
|
+
getValue: () => ({
|
|
51
|
+
from: startOfWeek(new Date(), { weekStartsOn: 1 }),
|
|
52
|
+
to: endOfWeek(new Date(), { weekStartsOn: 1 }),
|
|
53
|
+
}),
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: 'last-30-days',
|
|
57
|
+
label: <Trans context="date-range">Last 30 days</Trans>,
|
|
58
|
+
getValue: () => ({
|
|
59
|
+
from: startOfDay(subDays(new Date(), 29)),
|
|
60
|
+
to: endOfDay(new Date()),
|
|
61
|
+
}),
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: 'month-to-date',
|
|
65
|
+
label: <Trans context="date-range">Month to date</Trans>,
|
|
66
|
+
getValue: () => ({
|
|
67
|
+
from: startOfMonth(new Date()),
|
|
68
|
+
to: endOfDay(new Date()),
|
|
69
|
+
}),
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
id: 'this-month',
|
|
73
|
+
label: <Trans context="date-range">This month</Trans>,
|
|
74
|
+
getValue: () => ({
|
|
75
|
+
from: startOfMonth(new Date()),
|
|
76
|
+
to: endOfMonth(new Date()),
|
|
77
|
+
}),
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: 'last-month',
|
|
81
|
+
label: <Trans context="date-range">Last month</Trans>,
|
|
82
|
+
getValue: () => ({
|
|
83
|
+
from: startOfMonth(subDays(new Date(), 30)),
|
|
84
|
+
to: endOfMonth(subDays(new Date(), 30)),
|
|
85
|
+
}),
|
|
86
|
+
},
|
|
87
|
+
];
|
|
88
|
+
|
|
89
|
+
export function DateRangePicker({ className, dateRange, onDateRangeChange }: DateRangePickerProps) {
|
|
90
|
+
const [open, setOpen] = React.useState(false);
|
|
91
|
+
const { t } = useLingui();
|
|
92
|
+
const { formatDate } = useLocalFormat();
|
|
93
|
+
const locale = useDayPickerLocale();
|
|
94
|
+
// Internal state uses react-day-picker's DateRange type for Calendar compatibility
|
|
95
|
+
const [selectedRange, setSelectedRange] = React.useState<DateRange>({
|
|
96
|
+
from: dateRange.from,
|
|
97
|
+
to: dateRange.to,
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
React.useEffect(() => {
|
|
101
|
+
setSelectedRange({
|
|
102
|
+
from: dateRange.from,
|
|
103
|
+
to: dateRange.to,
|
|
104
|
+
});
|
|
105
|
+
}, [dateRange]);
|
|
106
|
+
|
|
107
|
+
const handleSelect = (range: DateRange | undefined) => {
|
|
108
|
+
if (range?.from) {
|
|
109
|
+
// If no end date is selected, use the from date as the end date
|
|
110
|
+
const to = range.to || range.from;
|
|
111
|
+
const finalRange: DefinedDateRange = {
|
|
112
|
+
from: range.from,
|
|
113
|
+
to: to,
|
|
114
|
+
};
|
|
115
|
+
setSelectedRange({ from: range.from, to });
|
|
116
|
+
onDateRangeChange(finalRange);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const handlePresetClick = (preset: (typeof presets)[number]) => {
|
|
121
|
+
const range = preset.getValue();
|
|
122
|
+
handleSelect(range);
|
|
123
|
+
setOpen(false);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const formatDateRange = () => {
|
|
127
|
+
if (!selectedRange.from) {
|
|
128
|
+
return t`Select date range`;
|
|
129
|
+
}
|
|
130
|
+
if (!selectedRange.to || selectedRange.from === selectedRange.to) {
|
|
131
|
+
return formatDate(selectedRange.from, { dateStyle: 'medium' });
|
|
132
|
+
}
|
|
133
|
+
return `${formatDate(selectedRange.from, { dateStyle: 'medium' })} - ${formatDate(selectedRange.to, { dateStyle: 'medium' })}`;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const isPresetActive = (preset: (typeof presets)[number]) => {
|
|
137
|
+
if (!selectedRange.from || !selectedRange.to) return false;
|
|
138
|
+
const presetRange = preset.getValue();
|
|
139
|
+
return (
|
|
140
|
+
selectedRange.from.getTime() === presetRange.from.getTime() &&
|
|
141
|
+
selectedRange.to.getTime() === presetRange.to.getTime()
|
|
142
|
+
);
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
return (
|
|
146
|
+
<Popover open={open} onOpenChange={setOpen}>
|
|
147
|
+
<PopoverTrigger asChild>
|
|
148
|
+
<Button
|
|
149
|
+
variant="outline"
|
|
150
|
+
className={cn('w-[280px] justify-start text-left font-normal', className)}
|
|
151
|
+
>
|
|
152
|
+
<CalendarIcon className="mr-2 h-4 w-4" />
|
|
153
|
+
{formatDateRange()}
|
|
154
|
+
</Button>
|
|
155
|
+
</PopoverTrigger>
|
|
156
|
+
<PopoverContent className="w-auto p-0" align="start">
|
|
157
|
+
<div className="flex">
|
|
158
|
+
<div className="border-r p-2 space-y-0.5 min-w-0 w-32">
|
|
159
|
+
{presets.map(preset => (
|
|
160
|
+
<Button
|
|
161
|
+
key={preset.id}
|
|
162
|
+
variant={isPresetActive(preset) ? 'default' : 'ghost'}
|
|
163
|
+
size="sm"
|
|
164
|
+
className="w-full justify-start font-normal text-xs h-7 px-2"
|
|
165
|
+
onClick={() => handlePresetClick(preset)}
|
|
166
|
+
>
|
|
167
|
+
{preset.label}
|
|
168
|
+
</Button>
|
|
169
|
+
))}
|
|
170
|
+
</div>
|
|
171
|
+
<div className="p-3">
|
|
172
|
+
<Calendar
|
|
173
|
+
mode="range"
|
|
174
|
+
defaultMonth={selectedRange?.from}
|
|
175
|
+
selected={selectedRange}
|
|
176
|
+
onSelect={handleSelect}
|
|
177
|
+
numberOfMonths={2}
|
|
178
|
+
showOutsideDays={false}
|
|
179
|
+
locale={locale}
|
|
180
|
+
/>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
</PopoverContent>
|
|
184
|
+
</Popover>
|
|
185
|
+
);
|
|
186
|
+
}
|
|
@@ -9,16 +9,18 @@ import {
|
|
|
9
9
|
} from '@/vdb/components/ui/sidebar.js';
|
|
10
10
|
import { useDashboardExtensions } from '@/vdb/framework/extension-api/use-dashboard-extensions.js';
|
|
11
11
|
import { getNavMenuConfig } from '@/vdb/framework/nav-menu/nav-menu-extensions.js';
|
|
12
|
+
import { useDisplayLocale } from '@/vdb/hooks/use-display-locale.js';
|
|
12
13
|
import * as React from 'react';
|
|
13
14
|
import { ChannelSwitcher } from './channel-switcher.js';
|
|
14
15
|
|
|
15
16
|
export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) {
|
|
16
17
|
const { extensionsLoaded } = useDashboardExtensions();
|
|
18
|
+
const { isRTL } = useDisplayLocale();
|
|
17
19
|
const { sections } = getNavMenuConfig();
|
|
18
20
|
|
|
19
21
|
return (
|
|
20
22
|
extensionsLoaded && (
|
|
21
|
-
<Sidebar collapsible="icon" {...props}>
|
|
23
|
+
<Sidebar collapsible="icon" {...props} side={isRTL ? 'right' : 'left'}>
|
|
22
24
|
<SidebarHeader>
|
|
23
25
|
<ChannelSwitcher />
|
|
24
26
|
</SidebarHeader>
|
|
@@ -18,8 +18,8 @@ import { useChannel } from '@/vdb/hooks/use-channel.js';
|
|
|
18
18
|
import { useLocalFormat } from '@/vdb/hooks/use-local-format.js';
|
|
19
19
|
import { useServerConfig } from '@/vdb/hooks/use-server-config.js';
|
|
20
20
|
import { useUserSettings } from '@/vdb/hooks/use-user-settings.js';
|
|
21
|
-
import { Trans } from '@/vdb/lib/trans.js';
|
|
22
21
|
import { cn } from '@/vdb/lib/utils.js';
|
|
22
|
+
import { Trans } from '@lingui/react/macro';
|
|
23
23
|
import { Link } from '@tanstack/react-router';
|
|
24
24
|
import { useEffect, useState } from 'react';
|
|
25
25
|
import { ManageLanguagesDialog } from './manage-languages-dialog.js';
|
|
@@ -99,13 +99,9 @@ export function ChannelSwitcher() {
|
|
|
99
99
|
<ChannelCodeLabel code={displayChannel?.code} />
|
|
100
100
|
</span>
|
|
101
101
|
<span className="truncate text-xs">
|
|
102
|
-
|
|
103
|
-
<
|
|
104
|
-
|
|
105
|
-
</span>
|
|
106
|
-
) : (
|
|
107
|
-
<span>Language: {formatLanguageName(contentLanguage)}</span>
|
|
108
|
-
)}
|
|
102
|
+
<span>
|
|
103
|
+
<Trans>Language: {formatLanguageName(contentLanguage)}</Trans>
|
|
104
|
+
</span>
|
|
109
105
|
</span>
|
|
110
106
|
</div>
|
|
111
107
|
<ChevronsUpDown className="ml-auto" />
|
|
@@ -139,7 +135,7 @@ export function ChannelSwitcher() {
|
|
|
139
135
|
<ChannelCodeLabel code={channel.code} />
|
|
140
136
|
{channel.id === displayChannel?.id && (
|
|
141
137
|
<span className="ml-auto text-xs text-muted-foreground">
|
|
142
|
-
Current
|
|
138
|
+
<Trans context="current channel">Current</Trans>
|
|
143
139
|
</span>
|
|
144
140
|
)}
|
|
145
141
|
</DropdownMenuItem>
|
|
@@ -168,7 +164,9 @@ export function ChannelSwitcher() {
|
|
|
168
164
|
<span>{formatLanguageName(languageCode)}</span>
|
|
169
165
|
{contentLanguage === languageCode && (
|
|
170
166
|
<span className="ml-auto text-xs text-muted-foreground">
|
|
171
|
-
|
|
167
|
+
<Trans context="active language">
|
|
168
|
+
Active
|
|
169
|
+
</Trans>
|
|
172
170
|
</span>
|
|
173
171
|
)}
|
|
174
172
|
</DropdownMenuItem>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Badge } from '@/vdb/components/ui/badge.js';
|
|
2
2
|
import { Button } from '@/vdb/components/ui/button.js';
|
|
3
3
|
import { useUserSettings } from '@/vdb/hooks/use-user-settings.js';
|
|
4
|
-
import { Trans } from '
|
|
4
|
+
import { Trans } from '@lingui/react/macro';
|
|
5
5
|
import { CodeXmlIcon, XIcon } from 'lucide-react';
|
|
6
6
|
|
|
7
7
|
export function DevModeIndicator() {
|
|
@@ -5,11 +5,13 @@ import {
|
|
|
5
5
|
BreadcrumbList,
|
|
6
6
|
BreadcrumbSeparator,
|
|
7
7
|
} from '@/vdb/components/ui/breadcrumb.js';
|
|
8
|
+
import type { NavMenuItem, NavMenuSection } from '@/vdb/framework/nav-menu/nav-menu-extensions.js';
|
|
9
|
+
import { getNavMenuConfig } from '@/vdb/framework/nav-menu/nav-menu-extensions.js';
|
|
10
|
+
import { useDisplayLocale } from '@/vdb/hooks/use-display-locale.js';
|
|
11
|
+
import { useLingui } from '@lingui/react';
|
|
8
12
|
import { Link, useRouter, useRouterState } from '@tanstack/react-router';
|
|
9
13
|
import * as React from 'react';
|
|
10
14
|
import { Fragment } from 'react';
|
|
11
|
-
import { getNavMenuConfig } from '@/vdb/framework/nav-menu/nav-menu-extensions.js';
|
|
12
|
-
import type { NavMenuItem, NavMenuSection } from '@/vdb/framework/nav-menu/nav-menu-extensions.js';
|
|
13
15
|
|
|
14
16
|
export interface BreadcrumbPair {
|
|
15
17
|
label: string | React.ReactElement;
|
|
@@ -24,7 +26,9 @@ export function GeneratedBreadcrumbs() {
|
|
|
24
26
|
const matches = useRouterState({ select: s => s.matches });
|
|
25
27
|
const currentPath = useRouterState({ select: s => s.location.pathname });
|
|
26
28
|
const router = useRouter();
|
|
29
|
+
const { i18n } = useLingui();
|
|
27
30
|
const navMenuConfig = getNavMenuConfig();
|
|
31
|
+
const { bcp47Tag } = useDisplayLocale();
|
|
28
32
|
const basePath = router.basepath || '';
|
|
29
33
|
|
|
30
34
|
const normalizeBreadcrumb = (breadcrumb: any, pathname: string): BreadcrumbPair[] => {
|
|
@@ -51,9 +55,7 @@ export function GeneratedBreadcrumbs() {
|
|
|
51
55
|
const rawCrumbs: BreadcrumbPair[] = React.useMemo(() => {
|
|
52
56
|
return matches
|
|
53
57
|
.filter(match => match.loaderData?.breadcrumb)
|
|
54
|
-
.flatMap(({ pathname, loaderData }) =>
|
|
55
|
-
normalizeBreadcrumb(loaderData.breadcrumb, pathname)
|
|
56
|
-
);
|
|
58
|
+
.flatMap(({ pathname, loaderData }) => normalizeBreadcrumb(loaderData.breadcrumb, pathname));
|
|
57
59
|
}, [matches]);
|
|
58
60
|
|
|
59
61
|
const isBaseRoute = (p: string) => p === basePath || p === `${basePath}/`;
|
|
@@ -119,8 +121,8 @@ export function GeneratedBreadcrumbs() {
|
|
|
119
121
|
);
|
|
120
122
|
const breadcrumbs: BreadcrumbPair[] = React.useMemo(() => {
|
|
121
123
|
const arr = sectionCrumb ? [sectionCrumb, ...pageCrumbs] : pageCrumbs;
|
|
122
|
-
return arr.filter(
|
|
123
|
-
self.findIndex(x => x.path === c.path && x.label === c.label) === i,
|
|
124
|
+
return arr.filter(
|
|
125
|
+
(c, i, self) => self.findIndex(x => x.path === c.path && x.label === c.label) === i,
|
|
124
126
|
);
|
|
125
127
|
}, [sectionCrumb, pageCrumbs]);
|
|
126
128
|
return (
|
|
@@ -130,7 +132,7 @@ export function GeneratedBreadcrumbs() {
|
|
|
130
132
|
<Fragment key={`${path}-${index}`}>
|
|
131
133
|
<BreadcrumbItem className="hidden md:block">
|
|
132
134
|
<BreadcrumbLink asChild>
|
|
133
|
-
<Link to={path}>{label}</Link>
|
|
135
|
+
<Link to={path}>{typeof label === 'string' ? i18n.t(label) : label}</Link>
|
|
134
136
|
</BreadcrumbLink>
|
|
135
137
|
</BreadcrumbItem>
|
|
136
138
|
{index < arr.length - 1 && <BreadcrumbSeparator className="hidden md:block" />}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { CurrencyCode } from '@/vdb/constants.js';
|
|
2
|
+
import { useDisplayLocale } from '@/vdb/hooks/use-display-locale.js';
|
|
2
3
|
import { useLocalFormat } from '@/vdb/hooks/use-local-format.js';
|
|
4
|
+
import { useUiLanguageLoader } from '@/vdb/hooks/use-ui-language-loader.js';
|
|
3
5
|
import { useUserSettings } from '@/vdb/hooks/use-user-settings.js';
|
|
4
|
-
import { Trans } from '
|
|
6
|
+
import { Trans } from '@lingui/react/macro';
|
|
5
7
|
import { useState } from 'react';
|
|
6
8
|
import { uiConfig } from 'virtual:vendure-ui-config';
|
|
7
9
|
import { Button } from '../ui/button.js';
|
|
@@ -11,12 +13,22 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '.
|
|
|
11
13
|
|
|
12
14
|
export function LanguageDialog() {
|
|
13
15
|
const { i18n } = uiConfig;
|
|
16
|
+
const { loadAndActivateLocale } = useUiLanguageLoader();
|
|
14
17
|
const { availableLocales, availableLanguages } = i18n;
|
|
15
18
|
const { settings, setDisplayLanguage, setDisplayLocale } = useUserSettings();
|
|
19
|
+
const { humanReadableLanguageAndLocale } = useDisplayLocale();
|
|
16
20
|
const availableCurrencyCodes = Object.values(CurrencyCode);
|
|
17
|
-
const { formatCurrency, formatLanguageName, formatCurrencyName, formatDate } =
|
|
21
|
+
const { formatCurrency, formatLanguageName, formatRegionName, formatCurrencyName, formatDate } =
|
|
22
|
+
useLocalFormat();
|
|
18
23
|
const [selectedCurrency, setSelectedCurrency] = useState<string>('USD');
|
|
19
24
|
|
|
25
|
+
const orderedAvailableLanguages = availableLanguages.slice().sort((a, b) => a.localeCompare(b));
|
|
26
|
+
const orderedAvailableLocales = availableLocales.slice().sort((a, b) => a.localeCompare(b));
|
|
27
|
+
const handleLanguageChange = async (value: string) => {
|
|
28
|
+
setDisplayLanguage(value);
|
|
29
|
+
void loadAndActivateLocale(value);
|
|
30
|
+
};
|
|
31
|
+
|
|
20
32
|
return (
|
|
21
33
|
<DialogContent>
|
|
22
34
|
<DialogHeader>
|
|
@@ -29,14 +41,15 @@ export function LanguageDialog() {
|
|
|
29
41
|
<Label>
|
|
30
42
|
<Trans>Display language</Trans>
|
|
31
43
|
</Label>
|
|
32
|
-
<Select defaultValue={settings.displayLanguage} onValueChange={
|
|
44
|
+
<Select defaultValue={settings.displayLanguage} onValueChange={handleLanguageChange}>
|
|
33
45
|
<SelectTrigger className="w-full">
|
|
34
46
|
<SelectValue placeholder="Select a language" />
|
|
35
47
|
</SelectTrigger>
|
|
36
48
|
<SelectContent>
|
|
37
|
-
{
|
|
38
|
-
<SelectItem key={language} value={language}>
|
|
39
|
-
{
|
|
49
|
+
{orderedAvailableLanguages.map(language => (
|
|
50
|
+
<SelectItem key={language} value={language} className="flex gap-1">
|
|
51
|
+
<span className="uppercase text-muted-foreground">{language}</span>
|
|
52
|
+
<span>{formatLanguageName(language)}</span>
|
|
40
53
|
</SelectItem>
|
|
41
54
|
))}
|
|
42
55
|
</SelectContent>
|
|
@@ -51,9 +64,10 @@ export function LanguageDialog() {
|
|
|
51
64
|
<SelectValue placeholder="Select a locale" />
|
|
52
65
|
</SelectTrigger>
|
|
53
66
|
<SelectContent>
|
|
54
|
-
{
|
|
55
|
-
<SelectItem key={locale} value={locale}>
|
|
56
|
-
{
|
|
67
|
+
{orderedAvailableLocales.map(locale => (
|
|
68
|
+
<SelectItem key={locale} value={locale} className="flex gap-1">
|
|
69
|
+
<span className="uppercase text-muted-foreground">{locale}</span>
|
|
70
|
+
<span>{formatRegionName(locale)}</span>
|
|
57
71
|
</SelectItem>
|
|
58
72
|
))}
|
|
59
73
|
</SelectContent>
|
|
@@ -62,7 +76,8 @@ export function LanguageDialog() {
|
|
|
62
76
|
</div>
|
|
63
77
|
<div className="bg-sidebar border border-border rounded-md px-6 py-4 space-y-4">
|
|
64
78
|
<span className="font-medium block text-accent-foreground">
|
|
65
|
-
<Trans>Sample Formatting</Trans>:
|
|
79
|
+
<Trans>Sample Formatting</Trans>:{' '}
|
|
80
|
+
<span className="text-muted-foreground">{humanReadableLanguageAndLocale}</span>
|
|
66
81
|
</span>
|
|
67
82
|
<Select defaultValue={selectedCurrency} onValueChange={setSelectedCurrency}>
|
|
68
83
|
<SelectTrigger>
|
|
@@ -77,15 +92,21 @@ export function LanguageDialog() {
|
|
|
77
92
|
</SelectContent>
|
|
78
93
|
</Select>
|
|
79
94
|
<div className="flex flex-col">
|
|
80
|
-
<span className="text-muted-foreground text-sm font-medium">
|
|
95
|
+
<span className="text-muted-foreground text-sm font-medium">
|
|
96
|
+
<Trans>Medium date</Trans>
|
|
97
|
+
</span>
|
|
81
98
|
<span>{formatDate(new Date('2025-03-14'), { dateStyle: 'medium' })}</span>
|
|
82
99
|
</div>
|
|
83
100
|
<div className="flex flex-col">
|
|
84
|
-
<span className="text-muted-foreground text-sm font-medium">
|
|
101
|
+
<span className="text-muted-foreground text-sm font-medium">
|
|
102
|
+
<Trans>Short date</Trans>
|
|
103
|
+
</span>
|
|
85
104
|
<span>{formatDate(new Date('2025-03-14'), { dateStyle: 'short' })}</span>
|
|
86
105
|
</div>
|
|
87
106
|
<div className="flex flex-col">
|
|
88
|
-
<span className="text-muted-foreground text-sm font-medium">
|
|
107
|
+
<span className="text-muted-foreground text-sm font-medium">
|
|
108
|
+
<Trans>Price</Trans>
|
|
109
|
+
</span>
|
|
89
110
|
<span>{formatCurrency(100.0, selectedCurrency)}</span>
|
|
90
111
|
</div>
|
|
91
112
|
</div>
|
|
@@ -17,7 +17,7 @@ import { graphql } from '@/vdb/graphql/graphql.js';
|
|
|
17
17
|
import { useChannel } from '@/vdb/hooks/use-channel.js';
|
|
18
18
|
import { useLocalFormat } from '@/vdb/hooks/use-local-format.js';
|
|
19
19
|
import { usePermissions } from '@/vdb/hooks/use-permissions.js';
|
|
20
|
-
import { Trans } from '
|
|
20
|
+
import { Trans } from '@lingui/react/macro';
|
|
21
21
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
|
22
22
|
import { AlertCircle, Lock } from 'lucide-react';
|
|
23
23
|
import { useEffect, useState } from 'react';
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
NavMenuSectionPlacement,
|
|
16
16
|
} from '@/vdb/framework/nav-menu/nav-menu-extensions.js';
|
|
17
17
|
import { usePermissions } from '@/vdb/hooks/use-permissions.js';
|
|
18
|
+
import { useLingui } from '@lingui/react';
|
|
18
19
|
import { Link, useRouter, useRouterState } from '@tanstack/react-router';
|
|
19
20
|
import { ChevronRight } from 'lucide-react';
|
|
20
21
|
import * as React from 'react';
|
|
@@ -41,6 +42,7 @@ export function NavMain({ items }: Readonly<{ items: Array<NavMenuSection | NavM
|
|
|
41
42
|
const router = useRouter();
|
|
42
43
|
const routerState = useRouterState();
|
|
43
44
|
const { hasPermissions } = usePermissions();
|
|
45
|
+
const { i18n } = useLingui();
|
|
44
46
|
const currentPath = routerState.location.pathname;
|
|
45
47
|
const basePath = router.basepath || '';
|
|
46
48
|
|
|
@@ -183,12 +185,16 @@ export function NavMain({ items }: Readonly<{ items: Array<NavMenuSection | NavM
|
|
|
183
185
|
const renderTopSection = (item: NavMenuSection | NavMenuItem) => {
|
|
184
186
|
if ('url' in item) {
|
|
185
187
|
return (
|
|
186
|
-
<NavItemWrapper key={item.
|
|
188
|
+
<NavItemWrapper key={item.id} locationId={item.id} order={item.order} offset={true}>
|
|
187
189
|
<SidebarMenuItem>
|
|
188
|
-
<SidebarMenuButton
|
|
190
|
+
<SidebarMenuButton
|
|
191
|
+
tooltip={i18n.t(item.title)}
|
|
192
|
+
asChild
|
|
193
|
+
isActive={isPathActive(item.url)}
|
|
194
|
+
>
|
|
189
195
|
<Link to={item.url}>
|
|
190
196
|
{item.icon && <item.icon />}
|
|
191
|
-
<span>{item.title}</span>
|
|
197
|
+
<span>{i18n.t(item.title)}</span>
|
|
192
198
|
</Link>
|
|
193
199
|
</SidebarMenuButton>
|
|
194
200
|
</SidebarMenuItem>
|
|
@@ -197,7 +203,7 @@ export function NavMain({ items }: Readonly<{ items: Array<NavMenuSection | NavM
|
|
|
197
203
|
}
|
|
198
204
|
|
|
199
205
|
return (
|
|
200
|
-
<NavItemWrapper key={item.
|
|
206
|
+
<NavItemWrapper key={item.id} locationId={item.id} order={item.order} offset={true}>
|
|
201
207
|
<Collapsible
|
|
202
208
|
asChild
|
|
203
209
|
open={openTopSectionIds.has(item.id)}
|
|
@@ -208,7 +214,7 @@ export function NavMain({ items }: Readonly<{ items: Array<NavMenuSection | NavM
|
|
|
208
214
|
<CollapsibleTrigger asChild>
|
|
209
215
|
<SidebarMenuButton tooltip={item.title}>
|
|
210
216
|
{item.icon && <item.icon />}
|
|
211
|
-
<span>{item.title}</span>
|
|
217
|
+
<span>{i18n.t(item.title)}</span>
|
|
212
218
|
<ChevronRight className="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" />
|
|
213
219
|
</SidebarMenuButton>
|
|
214
220
|
</CollapsibleTrigger>
|
|
@@ -216,7 +222,7 @@ export function NavMain({ items }: Readonly<{ items: Array<NavMenuSection | NavM
|
|
|
216
222
|
<SidebarMenuSub>
|
|
217
223
|
{item.items?.map(subItem => (
|
|
218
224
|
<NavItemWrapper
|
|
219
|
-
key={subItem.
|
|
225
|
+
key={subItem.id}
|
|
220
226
|
locationId={subItem.id}
|
|
221
227
|
order={subItem.order}
|
|
222
228
|
parentLocationId={item.id}
|
|
@@ -227,7 +233,7 @@ export function NavMain({ items }: Readonly<{ items: Array<NavMenuSection | NavM
|
|
|
227
233
|
isActive={isPathActive(subItem.url)}
|
|
228
234
|
>
|
|
229
235
|
<Link to={subItem.url}>
|
|
230
|
-
<span>{subItem.title}</span>
|
|
236
|
+
<span>{i18n.t(subItem.title)}</span>
|
|
231
237
|
</Link>
|
|
232
238
|
</SidebarMenuSubButton>
|
|
233
239
|
</SidebarMenuSubItem>
|
|
@@ -247,10 +253,14 @@ export function NavMain({ items }: Readonly<{ items: Array<NavMenuSection | NavM
|
|
|
247
253
|
return (
|
|
248
254
|
<NavItemWrapper key={item.title} locationId={item.id} order={item.order} offset={true}>
|
|
249
255
|
<SidebarMenuItem>
|
|
250
|
-
<SidebarMenuButton
|
|
256
|
+
<SidebarMenuButton
|
|
257
|
+
tooltip={i18n.t(item.title)}
|
|
258
|
+
asChild
|
|
259
|
+
isActive={isPathActive(item.url)}
|
|
260
|
+
>
|
|
251
261
|
<Link to={item.url}>
|
|
252
262
|
{item.icon && <item.icon />}
|
|
253
|
-
<span>{item.title}</span>
|
|
263
|
+
<span>{i18n.t(item.title)}</span>
|
|
254
264
|
</Link>
|
|
255
265
|
</SidebarMenuButton>
|
|
256
266
|
</SidebarMenuItem>
|
|
@@ -267,9 +277,9 @@ export function NavMain({ items }: Readonly<{ items: Array<NavMenuSection | NavM
|
|
|
267
277
|
>
|
|
268
278
|
<SidebarMenuItem>
|
|
269
279
|
<CollapsibleTrigger asChild>
|
|
270
|
-
<SidebarMenuButton tooltip={item.title}>
|
|
280
|
+
<SidebarMenuButton tooltip={i18n.t(item.title)}>
|
|
271
281
|
{item.icon && <item.icon />}
|
|
272
|
-
<span>{item.title}</span>
|
|
282
|
+
<span>{i18n.t(item.title)}</span>
|
|
273
283
|
<ChevronRight className="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" />
|
|
274
284
|
</SidebarMenuButton>
|
|
275
285
|
</CollapsibleTrigger>
|
|
@@ -277,7 +287,7 @@ export function NavMain({ items }: Readonly<{ items: Array<NavMenuSection | NavM
|
|
|
277
287
|
<SidebarMenuSub>
|
|
278
288
|
{item.items?.map(subItem => (
|
|
279
289
|
<NavItemWrapper
|
|
280
|
-
key={subItem.title}
|
|
290
|
+
key={i18n.t(subItem.title)}
|
|
281
291
|
locationId={subItem.id}
|
|
282
292
|
order={subItem.order}
|
|
283
293
|
parentLocationId={item.id}
|
|
@@ -288,7 +298,7 @@ export function NavMain({ items }: Readonly<{ items: Array<NavMenuSection | NavM
|
|
|
288
298
|
isActive={isPathActive(subItem.url)}
|
|
289
299
|
>
|
|
290
300
|
<Link to={subItem.url}>
|
|
291
|
-
<span>{subItem.title}</span>
|
|
301
|
+
<span>{i18n.t(subItem.title)}</span>
|
|
292
302
|
</Link>
|
|
293
303
|
</SidebarMenuSubButton>
|
|
294
304
|
</SidebarMenuSubItem>
|