@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.
Files changed (295) hide show
  1. package/README.md +4 -0
  2. package/dist/plugin/api/api-extensions.js +11 -14
  3. package/dist/plugin/api/metrics.resolver.d.ts +2 -2
  4. package/dist/plugin/api/metrics.resolver.js +2 -2
  5. package/dist/plugin/config/metrics-strategies.d.ts +9 -9
  6. package/dist/plugin/config/metrics-strategies.js +6 -6
  7. package/dist/plugin/constants.d.ts +2 -0
  8. package/dist/plugin/constants.js +3 -1
  9. package/dist/plugin/dashboard.plugin.js +13 -0
  10. package/dist/plugin/service/metrics.service.d.ts +3 -3
  11. package/dist/plugin/service/metrics.service.js +37 -53
  12. package/dist/plugin/types.d.ts +9 -12
  13. package/dist/plugin/types.js +7 -11
  14. package/dist/vite/vite-plugin-config.js +13 -9
  15. package/dist/vite/vite-plugin-translations.d.ts +22 -0
  16. package/dist/vite/vite-plugin-translations.js +66 -0
  17. package/dist/vite/vite-plugin-vendure-dashboard.js +10 -8
  18. package/lingui.config.js +25 -2
  19. package/package.json +159 -156
  20. package/src/app/app-providers.tsx +0 -4
  21. package/src/app/common/delete-bulk-action.tsx +6 -5
  22. package/src/app/common/duplicate-bulk-action.tsx +4 -5
  23. package/src/app/common/duplicate-entity-dialog.tsx +1 -1
  24. package/src/app/common/set-document-direction.ts +7 -0
  25. package/src/app/main.tsx +50 -17
  26. package/src/app/routes/_authenticated/_administrators/administrators.tsx +8 -6
  27. package/src/app/routes/_authenticated/_administrators/administrators_.$id.tsx +17 -6
  28. package/src/app/routes/_authenticated/_administrators/components/role-permissions-display.tsx +2 -2
  29. package/src/app/routes/_authenticated/_assets/assets.tsx +1 -1
  30. package/src/app/routes/_authenticated/_assets/assets_.$id.tsx +4 -4
  31. package/src/app/routes/_authenticated/_assets/components/asset-bulk-actions.tsx +8 -6
  32. package/src/app/routes/_authenticated/_assets/components/asset-tag-filter.tsx +1 -1
  33. package/src/app/routes/_authenticated/_assets/components/asset-tags-editor.tsx +1 -1
  34. package/src/app/routes/_authenticated/_assets/components/manage-tags-dialog.tsx +3 -8
  35. package/src/app/routes/_authenticated/_channels/channels.tsx +3 -6
  36. package/src/app/routes/_authenticated/_channels/channels_.$id.tsx +5 -5
  37. package/src/app/routes/_authenticated/_collections/collections.tsx +10 -6
  38. package/src/app/routes/_authenticated/_collections/collections_.$id.tsx +16 -5
  39. package/src/app/routes/_authenticated/_collections/components/collection-bulk-actions.tsx +1 -1
  40. package/src/app/routes/_authenticated/_collections/components/collection-contents-sheet.tsx +1 -1
  41. package/src/app/routes/_authenticated/_collections/components/move-collections-dialog.tsx +6 -6
  42. package/src/app/routes/_authenticated/_countries/countries.graphql.ts +2 -0
  43. package/src/app/routes/_authenticated/_countries/countries.tsx +2 -3
  44. package/src/app/routes/_authenticated/_countries/countries_.$id.tsx +4 -4
  45. package/src/app/routes/_authenticated/_customer-groups/components/customer-group-members-sheet.tsx +1 -1
  46. package/src/app/routes/_authenticated/_customer-groups/components/customer-group-members-table.tsx +4 -4
  47. package/src/app/routes/_authenticated/_customer-groups/customer-groups.tsx +2 -4
  48. package/src/app/routes/_authenticated/_customer-groups/customer-groups_.$id.tsx +13 -6
  49. package/src/app/routes/_authenticated/_customers/components/customer-address-card.tsx +8 -8
  50. package/src/app/routes/_authenticated/_customers/components/customer-address-form.tsx +3 -3
  51. package/src/app/routes/_authenticated/_customers/components/customer-history/customer-history-container.tsx +1 -1
  52. package/src/app/routes/_authenticated/_customers/components/customer-history/customer-history-utils.tsx +1 -1
  53. package/src/app/routes/_authenticated/_customers/components/customer-history/default-customer-history-components.tsx +1 -1
  54. package/src/app/routes/_authenticated/_customers/components/customer-history/use-customer-history.ts +1 -1
  55. package/src/app/routes/_authenticated/_customers/components/customer-status-badge.tsx +1 -1
  56. package/src/app/routes/_authenticated/_customers/customers.graphql.ts +4 -0
  57. package/src/app/routes/_authenticated/_customers/customers.tsx +23 -11
  58. package/src/app/routes/_authenticated/_customers/customers_.$id.tsx +10 -8
  59. package/src/app/routes/_authenticated/_facets/components/edit-facet-value.tsx +1 -1
  60. package/src/app/routes/_authenticated/_facets/components/facet-bulk-actions.tsx +6 -5
  61. package/src/app/routes/_authenticated/_facets/components/facet-values-sheet.tsx +1 -1
  62. package/src/app/routes/_authenticated/_facets/components/facet-values-table.tsx +1 -1
  63. package/src/app/routes/_authenticated/_facets/facets.tsx +5 -5
  64. package/src/app/routes/_authenticated/_facets/facets_.$facetId.values_.$id.tsx +7 -5
  65. package/src/app/routes/_authenticated/_facets/facets_.$id.tsx +18 -6
  66. package/src/app/routes/_authenticated/_global-settings/global-settings.tsx +5 -5
  67. package/src/app/routes/_authenticated/_orders/components/add-manual-payment-dialog.tsx +19 -21
  68. package/src/app/routes/_authenticated/_orders/components/customer-address-selector.tsx +1 -1
  69. package/src/app/routes/_authenticated/_orders/components/edit-order-table.tsx +22 -22
  70. package/src/app/routes/_authenticated/_orders/components/fulfill-order-dialog.tsx +6 -6
  71. package/src/app/routes/_authenticated/_orders/components/fulfillment-details.tsx +15 -9
  72. package/src/app/routes/_authenticated/_orders/components/order-address.tsx +1 -1
  73. package/src/app/routes/_authenticated/_orders/components/order-detail-shared.tsx +11 -9
  74. package/src/app/routes/_authenticated/_orders/components/order-history/default-order-history-components.tsx +1 -1
  75. package/src/app/routes/_authenticated/_orders/components/order-history/order-history-container.tsx +1 -1
  76. package/src/app/routes/_authenticated/_orders/components/order-history/order-history-utils.tsx +1 -1
  77. package/src/app/routes/_authenticated/_orders/components/order-history/use-order-history.ts +1 -1
  78. package/src/app/routes/_authenticated/_orders/components/order-line-custom-fields-form.tsx +1 -1
  79. package/src/app/routes/_authenticated/_orders/components/order-modification-preview-dialog.tsx +4 -4
  80. package/src/app/routes/_authenticated/_orders/components/order-modification-summary.tsx +1 -1
  81. package/src/app/routes/_authenticated/_orders/components/order-table-totals.tsx +27 -27
  82. package/src/app/routes/_authenticated/_orders/components/order-table.tsx +2 -2
  83. package/src/app/routes/_authenticated/_orders/components/order-tax-summary.tsx +1 -1
  84. package/src/app/routes/_authenticated/_orders/components/payment-details.tsx +26 -20
  85. package/src/app/routes/_authenticated/_orders/components/seller-orders-card.tsx +3 -1
  86. package/src/app/routes/_authenticated/_orders/components/settle-refund-dialog.tsx +6 -6
  87. package/src/app/routes/_authenticated/_orders/components/shipping-method-selector.tsx +1 -1
  88. package/src/app/routes/_authenticated/_orders/components/state-transition-control.tsx +1 -1
  89. package/src/app/routes/_authenticated/_orders/components/use-transition-order-to-state.tsx +3 -2
  90. package/src/app/routes/_authenticated/_orders/orders.tsx +5 -9
  91. package/src/app/routes/_authenticated/_orders/orders_.$aggregateOrderId_.seller-orders.$sellerOrderId.tsx +1 -1
  92. package/src/app/routes/_authenticated/_orders/orders_.$id.tsx +1 -1
  93. package/src/app/routes/_authenticated/_orders/orders_.$id_.modify.tsx +4 -4
  94. package/src/app/routes/_authenticated/_orders/orders_.draft.$id.tsx +17 -17
  95. package/src/app/routes/_authenticated/_orders/utils/order-detail-loaders.tsx +1 -1
  96. package/src/app/routes/_authenticated/_payment-methods/payment-methods.tsx +5 -6
  97. package/src/app/routes/_authenticated/_payment-methods/payment-methods_.$id.tsx +13 -6
  98. package/src/app/routes/_authenticated/_product-variants/components/product-variant-bulk-actions.tsx +1 -1
  99. package/src/app/routes/_authenticated/_product-variants/components/variant-price-detail.tsx +1 -1
  100. package/src/app/routes/_authenticated/_product-variants/product-variants.graphql.ts +10 -0
  101. package/src/app/routes/_authenticated/_product-variants/product-variants.tsx +9 -2
  102. package/src/app/routes/_authenticated/_product-variants/product-variants_.$id.tsx +13 -6
  103. package/src/app/routes/_authenticated/_products/components/add-option-group-dialog.tsx +5 -5
  104. package/src/app/routes/_authenticated/_products/components/add-product-variant-dialog.tsx +5 -5
  105. package/src/app/routes/_authenticated/_products/components/assign-facet-values-dialog.tsx +5 -4
  106. package/src/app/routes/_authenticated/_products/components/create-product-options-dialog.tsx +9 -12
  107. package/src/app/routes/_authenticated/_products/components/create-product-variants-dialog.tsx +1 -1
  108. package/src/app/routes/_authenticated/_products/components/create-product-variants.tsx +4 -4
  109. package/src/app/routes/_authenticated/_products/components/option-groups-editor.tsx +1 -1
  110. package/src/app/routes/_authenticated/_products/components/product-bulk-actions.tsx +1 -1
  111. package/src/app/routes/_authenticated/_products/components/product-option-group-badge.tsx +19 -0
  112. package/src/app/routes/_authenticated/_products/components/product-option-select.tsx +3 -3
  113. package/src/app/routes/_authenticated/_products/components/product-options-table.tsx +114 -0
  114. package/src/app/routes/_authenticated/_products/product-option-groups.graphql.ts +103 -0
  115. package/src/app/routes/_authenticated/_products/products.graphql.ts +44 -32
  116. package/src/app/routes/_authenticated/_products/products.tsx +34 -5
  117. package/src/app/routes/_authenticated/_products/products_.$id.tsx +29 -12
  118. package/src/app/routes/_authenticated/_products/products_.$id_.variants.tsx +11 -11
  119. package/src/app/routes/_authenticated/_products/products_.$productId.option-groups.$id.tsx +177 -0
  120. package/src/app/routes/_authenticated/_products/products_.$productId.option-groups.$productOptionGroupId.options_.$id.tsx +208 -0
  121. package/src/app/routes/_authenticated/_profile/profile.tsx +4 -4
  122. package/src/app/routes/_authenticated/_promotions/promotions.tsx +2 -4
  123. package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +16 -9
  124. package/src/app/routes/_authenticated/_roles/components/permissions-table-grid.tsx +1 -1
  125. package/src/app/routes/_authenticated/_roles/roles.tsx +3 -6
  126. package/src/app/routes/_authenticated/_roles/roles_.$id.tsx +4 -6
  127. package/src/app/routes/_authenticated/_sellers/sellers.tsx +3 -4
  128. package/src/app/routes/_authenticated/_sellers/sellers_.$id.tsx +4 -4
  129. package/src/app/routes/_authenticated/_shipping-methods/components/price-display.tsx +5 -5
  130. package/src/app/routes/_authenticated/_shipping-methods/components/shipping-method-test-result-wrapper.tsx +1 -1
  131. package/src/app/routes/_authenticated/_shipping-methods/components/test-address-form.tsx +11 -11
  132. package/src/app/routes/_authenticated/_shipping-methods/components/test-order-builder.tsx +1 -1
  133. package/src/app/routes/_authenticated/_shipping-methods/components/test-shipping-methods-result.tsx +8 -8
  134. package/src/app/routes/_authenticated/_shipping-methods/components/test-shipping-methods-sheet.tsx +1 -1
  135. package/src/app/routes/_authenticated/_shipping-methods/components/test-single-method-result.tsx +8 -8
  136. package/src/app/routes/_authenticated/_shipping-methods/components/test-single-shipping-method-sheet.tsx +4 -4
  137. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods.tsx +2 -3
  138. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods_.$id.tsx +2 -2
  139. package/src/app/routes/_authenticated/_stock-locations/stock-locations.tsx +3 -4
  140. package/src/app/routes/_authenticated/_stock-locations/stock-locations_.$id.tsx +13 -6
  141. package/src/app/routes/_authenticated/_system/healthchecks.tsx +10 -4
  142. package/src/app/routes/_authenticated/_system/job-queue.tsx +10 -13
  143. package/src/app/routes/_authenticated/_system/scheduled-tasks.tsx +18 -16
  144. package/src/app/routes/_authenticated/_tax-categories/tax-categories.tsx +2 -4
  145. package/src/app/routes/_authenticated/_tax-categories/tax-categories_.$id.tsx +13 -6
  146. package/src/app/routes/_authenticated/_tax-rates/tax-rates.tsx +8 -12
  147. package/src/app/routes/_authenticated/_tax-rates/tax-rates_.$id.tsx +6 -4
  148. package/src/app/routes/_authenticated/_zones/components/zone-countries-sheet.tsx +4 -1
  149. package/src/app/routes/_authenticated/_zones/zones.tsx +4 -4
  150. package/src/app/routes/_authenticated/_zones/zones_.$id.tsx +8 -5
  151. package/src/app/routes/_authenticated/index.tsx +46 -25
  152. package/src/app/styles.css +4 -0
  153. package/src/i18n/common-strings.ts +111 -0
  154. package/src/i18n/locales/ar.po +4777 -0
  155. package/src/i18n/locales/cs.po +4777 -0
  156. package/src/i18n/locales/de.po +4299 -1101
  157. package/src/i18n/locales/en.po +3857 -659
  158. package/src/i18n/locales/es.po +4777 -0
  159. package/src/i18n/locales/fa.po +4777 -0
  160. package/src/i18n/locales/fr.po +4777 -0
  161. package/src/i18n/locales/he.po +4777 -0
  162. package/src/i18n/locales/hr.po +4777 -0
  163. package/src/i18n/locales/it.po +4777 -0
  164. package/src/i18n/locales/ja.po +4777 -0
  165. package/src/i18n/locales/ko.po +4628 -0
  166. package/src/i18n/locales/nb.po +4777 -0
  167. package/src/i18n/locales/ne.po +4777 -0
  168. package/src/i18n/locales/nl.po +4628 -0
  169. package/src/i18n/locales/pl.po +4777 -0
  170. package/src/i18n/locales/pt_BR.po +4777 -0
  171. package/src/i18n/locales/pt_PT.po +4777 -0
  172. package/src/i18n/locales/ru.po +4777 -0
  173. package/src/i18n/locales/sv.po +4777 -0
  174. package/src/i18n/locales/tr.po +4777 -0
  175. package/src/i18n/locales/uk.po +4777 -0
  176. package/src/i18n/locales/zh_Hans.po +4777 -0
  177. package/src/i18n/locales/zh_Hant.po +4777 -0
  178. package/src/lib/components/data-display/json.tsx +16 -1
  179. package/src/lib/components/data-input/combination-mode-input.tsx +1 -1
  180. package/src/lib/components/data-input/custom-field-list-input.tsx +11 -7
  181. package/src/lib/components/data-input/customer-group-input.tsx +27 -33
  182. package/src/lib/components/data-input/datetime-input.tsx +40 -1
  183. package/src/lib/components/data-input/default-relation-input.tsx +5 -4
  184. package/src/lib/components/data-input/index.ts +3 -0
  185. package/src/lib/components/data-input/product-multi-selector-input.tsx +14 -14
  186. package/src/lib/components/data-input/relation-selector.tsx +1 -1
  187. package/src/lib/components/data-input/select-with-options.tsx +1 -1
  188. package/src/lib/components/data-input/slug-input.tsx +290 -0
  189. package/src/lib/components/data-table/add-filter-menu.tsx +17 -10
  190. package/src/lib/components/data-table/data-table-bulk-action-item.tsx +45 -8
  191. package/src/lib/components/data-table/data-table-bulk-actions.tsx +4 -4
  192. package/src/lib/components/data-table/data-table-column-header.tsx +13 -8
  193. package/src/lib/components/data-table/data-table-context.tsx +91 -0
  194. package/src/lib/components/data-table/data-table-faceted-filter.tsx +2 -1
  195. package/src/lib/components/data-table/data-table-filter-badge.tsx +9 -5
  196. package/src/lib/components/data-table/data-table-filter-dialog.tsx +1 -1
  197. package/src/lib/components/data-table/data-table-utils.ts +21 -4
  198. package/src/lib/components/data-table/data-table-view-options.tsx +21 -10
  199. package/src/lib/components/data-table/data-table.tsx +146 -94
  200. package/src/lib/components/data-table/filters/data-table-boolean-filter.tsx +4 -4
  201. package/src/lib/components/data-table/global-views-bar.tsx +97 -0
  202. package/src/lib/components/data-table/global-views-sheet.tsx +11 -0
  203. package/src/lib/components/data-table/human-readable-operator.tsx +1 -1
  204. package/src/lib/components/data-table/manage-global-views-button.tsx +26 -0
  205. package/src/lib/components/data-table/my-views-button.tsx +47 -0
  206. package/src/lib/components/data-table/refresh-button.tsx +12 -3
  207. package/src/lib/components/data-table/save-view-button.tsx +41 -0
  208. package/src/lib/components/data-table/save-view-dialog.tsx +113 -0
  209. package/src/lib/components/data-table/use-generated-columns.tsx +13 -8
  210. package/src/lib/components/data-table/user-views-sheet.tsx +11 -0
  211. package/src/lib/components/data-table/views-sheet.tsx +305 -0
  212. package/src/lib/components/date-range-picker.tsx +186 -0
  213. package/src/lib/components/layout/app-sidebar.tsx +3 -1
  214. package/src/lib/components/layout/channel-switcher.tsx +8 -10
  215. package/src/lib/components/layout/dev-mode-indicator.tsx +1 -1
  216. package/src/lib/components/layout/generated-breadcrumbs.tsx +10 -8
  217. package/src/lib/components/layout/language-dialog.tsx +34 -13
  218. package/src/lib/components/layout/manage-languages-dialog.tsx +1 -1
  219. package/src/lib/components/layout/nav-main.tsx +23 -13
  220. package/src/lib/components/layout/nav-user.tsx +19 -23
  221. package/src/lib/components/login/login-form.tsx +1 -1
  222. package/src/lib/components/shared/asset/asset-bulk-actions.tsx +4 -4
  223. package/src/lib/components/shared/asset/asset-focal-point-editor.tsx +1 -1
  224. package/src/lib/components/shared/asset/asset-gallery.tsx +15 -14
  225. package/src/lib/components/shared/assign-to-channel-bulk-action.tsx +11 -11
  226. package/src/lib/components/shared/assign-to-channel-dialog.tsx +6 -5
  227. package/src/lib/components/shared/channel-code-label.tsx +1 -1
  228. package/src/lib/components/shared/channel-selector.tsx +4 -4
  229. package/src/lib/components/shared/configurable-operation-multi-selector.tsx +16 -14
  230. package/src/lib/components/shared/configurable-operation-selector.tsx +1 -1
  231. package/src/lib/components/shared/confirmation-dialog.tsx +8 -8
  232. package/src/lib/components/shared/country-selector.tsx +1 -1
  233. package/src/lib/components/shared/currency-selector.tsx +4 -4
  234. package/src/lib/components/shared/custom-fields-form.tsx +8 -24
  235. package/src/lib/components/shared/customer-address-form.tsx +3 -3
  236. package/src/lib/components/shared/customer-group-selector.tsx +1 -1
  237. package/src/lib/components/shared/customer-selector.tsx +1 -1
  238. package/src/lib/components/shared/error-page.tsx +1 -1
  239. package/src/lib/components/shared/facet-value-selector.tsx +10 -10
  240. package/src/lib/components/shared/history-timeline/history-note-checkbox.tsx +1 -1
  241. package/src/lib/components/shared/history-timeline/history-note-editor.tsx +1 -1
  242. package/src/lib/components/shared/history-timeline/history-note-entry.tsx +1 -1
  243. package/src/lib/components/shared/language-selector.tsx +4 -4
  244. package/src/lib/components/shared/navigation-confirmation.tsx +1 -1
  245. package/src/lib/components/shared/paginated-list-data-table.tsx +64 -34
  246. package/src/lib/components/shared/remove-from-channel-bulk-action.tsx +6 -5
  247. package/src/lib/components/shared/rich-text-editor/image-dialog.tsx +1 -1
  248. package/src/lib/components/shared/rich-text-editor/link-dialog.tsx +1 -1
  249. package/src/lib/components/shared/rich-text-editor/responsive-toolbar.tsx +1 -1
  250. package/src/lib/components/shared/rich-text-editor/table-edit-icons.tsx +1 -1
  251. package/src/lib/components/shared/role-code-label.tsx +1 -1
  252. package/src/lib/components/shared/role-selector.tsx +4 -4
  253. package/src/lib/components/shared/seller-selector.tsx +1 -1
  254. package/src/lib/components/shared/stock-level-label.tsx +3 -5
  255. package/src/lib/components/shared/table-cell/order-table-cell-components.tsx +3 -1
  256. package/src/lib/components/shared/tax-category-selector.tsx +1 -1
  257. package/src/lib/components/shared/translatable-form-field.tsx +15 -15
  258. package/src/lib/components/shared/zone-selector.tsx +1 -1
  259. package/src/lib/components/ui/button.tsx +1 -1
  260. package/src/lib/framework/dashboard-widget/base-widget.tsx +11 -9
  261. package/src/lib/framework/dashboard-widget/latest-orders-widget/index.tsx +35 -6
  262. package/src/lib/framework/dashboard-widget/metrics-widget/index.tsx +18 -12
  263. package/src/lib/framework/dashboard-widget/metrics-widget/metrics-widget.graphql.ts +9 -3
  264. package/src/lib/framework/dashboard-widget/orders-summary/index.tsx +26 -79
  265. package/src/lib/framework/dashboard-widget/widget-filters-context.tsx +35 -0
  266. package/src/lib/framework/defaults.ts +34 -63
  267. package/src/lib/framework/document-introspection/add-custom-fields.spec.ts +319 -9
  268. package/src/lib/framework/document-introspection/add-custom-fields.ts +60 -31
  269. package/src/lib/framework/document-introspection/get-document-structure.spec.ts +1 -159
  270. package/src/lib/framework/document-introspection/include-only-selected-list-fields.spec.ts +1840 -0
  271. package/src/lib/framework/document-introspection/include-only-selected-list-fields.ts +940 -0
  272. package/src/lib/framework/document-introspection/testing-utils.ts +161 -0
  273. package/src/lib/framework/extension-api/display-component-extensions.tsx +2 -0
  274. package/src/lib/framework/extension-api/types/data-table.ts +62 -4
  275. package/src/lib/framework/extension-api/types/navigation.ts +16 -0
  276. package/src/lib/framework/form-engine/utils.ts +34 -0
  277. package/src/lib/framework/layout-engine/page-layout.tsx +36 -36
  278. package/src/lib/framework/page/detail-page.tsx +10 -10
  279. package/src/lib/framework/page/list-page.tsx +289 -4
  280. package/src/lib/framework/page/use-extended-router.tsx +101 -34
  281. package/src/lib/graphql/api.ts +6 -2
  282. package/src/lib/graphql/graphql-env.d.ts +38 -26
  283. package/src/lib/hooks/use-display-locale.ts +40 -0
  284. package/src/lib/hooks/use-dynamic-translations.ts +46 -0
  285. package/src/lib/hooks/use-extended-detail-query.ts +1 -1
  286. package/src/lib/hooks/use-extended-list-query.ts +6 -1
  287. package/src/lib/hooks/use-local-format.ts +15 -1
  288. package/src/lib/hooks/use-saved-views.ts +230 -0
  289. package/src/lib/hooks/use-ui-language-loader.ts +30 -0
  290. package/src/lib/index.ts +15 -0
  291. package/src/lib/lib/load-i18n-messages.ts +17 -0
  292. package/src/lib/lib/trans.tsx +15 -11
  293. package/src/lib/providers/i18n-provider.tsx +7 -14
  294. package/src/lib/types/saved-views.ts +39 -0
  295. package/src/lib/utils/saved-views-utils.ts +40 -0
@@ -6,16 +6,20 @@ import {
6
6
  } from '@/vdb/components/shared/table-cell/order-table-cell-components.js';
7
7
  import { Button } from '@/vdb/components/ui/button.js';
8
8
  import { useLocalFormat } from '@/vdb/hooks/use-local-format.js';
9
+ import { useLingui } from '@lingui/react/macro';
9
10
  import { Link } from '@tanstack/react-router';
10
11
  import { ColumnFiltersState, SortingState } from '@tanstack/react-table';
11
12
  import { formatRelative } from 'date-fns';
12
- import { useState } from 'react';
13
+ import { useEffect, useState } from 'react';
13
14
  import { DashboardBaseWidget } from '../base-widget.js';
15
+ import { useWidgetFilters } from '../widget-filters-context.js';
14
16
  import { latestOrdersQuery } from './latest-orders-widget.graphql.js';
15
17
 
16
18
  export const WIDGET_ID = 'latest-orders-widget';
17
19
 
18
20
  export function LatestOrdersWidget() {
21
+ const { t } = useLingui();
22
+ const { dateRange } = useWidgetFilters();
19
23
  const [sorting, setSorting] = useState<SortingState>([
20
24
  {
21
25
  id: 'orderPlacedAt',
@@ -24,11 +28,36 @@ export function LatestOrdersWidget() {
24
28
  ]);
25
29
  const [page, setPage] = useState(1);
26
30
  const [pageSize, setPageSize] = useState(10);
27
- const [filters, setFilters] = useState<ColumnFiltersState>([]);
31
+ const [filters, setFilters] = useState<ColumnFiltersState>([
32
+ {
33
+ id: 'orderPlacedAt',
34
+ value: {
35
+ between: {
36
+ start: dateRange.from.toISOString(),
37
+ end: dateRange.to.toISOString(),
38
+ },
39
+ },
40
+ },
41
+ ]);
28
42
  const { formatCurrency } = useLocalFormat();
29
43
 
44
+ // Update filters when date range changes
45
+ useEffect(() => {
46
+ setFilters([
47
+ {
48
+ id: 'orderPlacedAt',
49
+ value: {
50
+ between: {
51
+ start: dateRange.from.toISOString(),
52
+ end: dateRange.to.toISOString(),
53
+ },
54
+ },
55
+ },
56
+ ]);
57
+ }, [dateRange]);
58
+
30
59
  return (
31
- <DashboardBaseWidget id={WIDGET_ID} title="Latest Orders" description="Your latest orders">
60
+ <DashboardBaseWidget id={WIDGET_ID} title={t`Latest Orders`} description={t`Your latest orders`}>
32
61
  <PaginatedListDataTable
33
62
  page={page}
34
63
  transformVariables={variables => ({
@@ -48,7 +77,7 @@ export function LatestOrdersWidget() {
48
77
  })}
49
78
  customizeColumns={{
50
79
  code: {
51
- header: 'Code',
80
+ header: t`Code`,
52
81
  cell: ({ row }) => {
53
82
  return (
54
83
  <Button variant="ghost" asChild>
@@ -58,7 +87,7 @@ export function LatestOrdersWidget() {
58
87
  },
59
88
  },
60
89
  orderPlacedAt: {
61
- header: 'Placed At',
90
+ header: t`Placed At`,
62
91
  cell: ({ row }) => {
63
92
  return (
64
93
  <span className="capitalize">
@@ -68,7 +97,7 @@ export function LatestOrdersWidget() {
68
97
  },
69
98
  },
70
99
  total: {
71
- header: 'Total',
100
+ header: t`Total`,
72
101
  cell: OrderMoneyCell,
73
102
  },
74
103
  totalWithTax: { cell: OrderMoneyCell },
@@ -3,10 +3,13 @@ import { Tabs, TabsList, TabsTrigger } from '@/vdb/components/ui/tabs.js';
3
3
  import { api } from '@/vdb/graphql/api.js';
4
4
  import { useChannel } from '@/vdb/hooks/use-channel.js';
5
5
  import { useLocalFormat } from '@/vdb/hooks/use-local-format.js';
6
+ import { Trans } from '@lingui/react/macro';
7
+ import { useLingui } from '@lingui/react/macro';
6
8
  import { useQuery } from '@tanstack/react-query';
7
9
  import { RefreshCw } from 'lucide-react';
8
10
  import { useMemo, useState } from 'react';
9
11
  import { DashboardBaseWidget } from '../base-widget.js';
12
+ import { useWidgetFilters } from '../widget-filters-context.js';
10
13
  import { MetricsChart } from './chart.js';
11
14
  import { orderChartDataQuery } from './metrics-widget.graphql.js';
12
15
 
@@ -17,53 +20,56 @@ enum DATA_TYPES {
17
20
  }
18
21
 
19
22
  export function MetricsWidget() {
23
+ const { t } = useLingui();
20
24
  const { formatDate, formatCurrency } = useLocalFormat();
21
25
  const { activeChannel } = useChannel();
26
+ const { dateRange } = useWidgetFilters();
22
27
  const [dataType, setDataType] = useState<DATA_TYPES>(DATA_TYPES.OrderTotal);
23
28
 
24
- const { data, isRefetching, refetch } = useQuery({
25
- queryKey: ['dashboard-order-metrics', dataType],
29
+ const { data, refetch, isRefetching } = useQuery({
30
+ queryKey: ['dashboard-order-metrics', dataType, dateRange],
26
31
  queryFn: () => {
27
32
  return api.query(orderChartDataQuery, {
28
33
  types: [dataType],
29
34
  refresh: true,
35
+ startDate: dateRange.from.toISOString(),
36
+ endDate: dateRange.to.toISOString(),
30
37
  });
31
38
  },
32
39
  });
33
40
 
34
41
  const chartData = useMemo(() => {
35
- const entry = data?.metricSummary.at(0);
42
+ const entry = data?.dashboardMetricSummary.at(0);
36
43
  if (!entry) {
37
44
  return undefined;
38
45
  }
39
46
 
40
- const { interval, type, entries } = entry;
47
+ const { type, entries } = entry;
41
48
 
42
- const values = entries.map(({ label, value }) => ({
49
+ const values = entries.map(({ label, value }: { label: string; value: number }) => ({
43
50
  name: formatDate(label, { month: 'short', day: 'numeric' }),
44
51
  sales: value,
45
52
  }));
46
53
 
47
54
  return {
48
55
  values,
49
- interval,
50
56
  type,
51
57
  };
52
- }, [data]);
58
+ }, [data, formatDate]);
53
59
 
54
60
  return (
55
61
  <DashboardBaseWidget
56
62
  id="metrics-widget"
57
- title="Metrics"
58
- description="Order metrics"
63
+ title={t`Metrics`}
64
+ description={t`Order metrics`}
59
65
  actions={
60
66
  <div className="flex gap-1">
61
67
  <Tabs defaultValue={dataType} onValueChange={value => setDataType(value as DATA_TYPES)}>
62
68
  <TabsList>
63
- <TabsTrigger value={DATA_TYPES.OrderCount}>Order Count</TabsTrigger>
64
- <TabsTrigger value={DATA_TYPES.OrderTotal}>Order Total</TabsTrigger>
69
+ <TabsTrigger value={DATA_TYPES.OrderCount}><Trans>Order Count</Trans></TabsTrigger>
70
+ <TabsTrigger value={DATA_TYPES.OrderTotal}><Trans>Order Total</Trans></TabsTrigger>
65
71
  <TabsTrigger value={DATA_TYPES.AverageOrderValue}>
66
- Average Order Value
72
+ <Trans>Average Order Value</Trans>
67
73
  </TabsTrigger>
68
74
  </TabsList>
69
75
  </Tabs>
@@ -1,9 +1,15 @@
1
1
  import { graphql } from '@/vdb/graphql/graphql.js';
2
2
 
3
3
  export const orderChartDataQuery = graphql(`
4
- query GetOrderChartData($refresh: Boolean, $types: [MetricType!]!) {
5
- metricSummary(input: { interval: Daily, types: $types, refresh: $refresh }) {
6
- interval
4
+ query GetOrderChartData(
5
+ $refresh: Boolean
6
+ $types: [DashboardMetricType!]!
7
+ $startDate: DateTime!
8
+ $endDate: DateTime!
9
+ ) {
10
+ dashboardMetricSummary(
11
+ input: { types: $types, refresh: $refresh, startDate: $startDate, endDate: $endDate }
12
+ ) {
7
13
  type
8
14
  entries {
9
15
  label
@@ -1,21 +1,16 @@
1
1
  import { AnimatedCurrency, AnimatedNumber } from '@/vdb/components/shared/animated-number.js';
2
- import { Tabs, TabsList, TabsTrigger } from '@/vdb/components/ui/tabs.js';
3
2
  import { api } from '@/vdb/graphql/api.js';
3
+ import { Trans } from '@lingui/react/macro';
4
+ import { useLingui } from '@lingui/react/macro';
4
5
  import { useQuery } from '@tanstack/react-query';
5
- import { endOfDay, endOfMonth, startOfDay, startOfMonth, subDays, subMonths } from 'date-fns';
6
- import { useMemo, useState } from 'react';
6
+ import { differenceInDays, subDays } from 'date-fns';
7
+ import { useMemo } from 'react';
7
8
  import { DashboardBaseWidget } from '../base-widget.js';
9
+ import { useWidgetFilters } from '../widget-filters-context.js';
8
10
  import { orderSummaryQuery } from './order-summary-widget.graphql.js';
9
11
 
10
12
  const WIDGET_ID = 'orders-summary-widget';
11
13
 
12
- enum Range {
13
- Today = 'today',
14
- Yesterday = 'yesterday',
15
- ThisWeek = 'thisWeek',
16
- ThisMonth = 'thisMonth',
17
- }
18
-
19
14
  interface PercentageChangeProps {
20
15
  value: number;
21
16
  }
@@ -34,63 +29,25 @@ function PercentageChange({ value }: PercentageChangeProps) {
34
29
  }
35
30
 
36
31
  export function OrdersSummaryWidget() {
37
- const [range, setRange] = useState<Range>(Range.Today);
32
+ const { t } = useLingui();
33
+ const { dateRange } = useWidgetFilters();
38
34
 
39
35
  const variables = useMemo(() => {
40
- const now = new Date();
41
-
42
- switch (range) {
43
- case Range.Today: {
44
- const today = now;
45
- const yesterday = subDays(now, 1);
46
-
47
- return {
48
- start: startOfDay(today).toISOString(),
49
- end: endOfDay(today).toISOString(),
50
- previousStart: startOfDay(yesterday).toISOString(),
51
- previousEnd: endOfDay(yesterday).toISOString(),
52
- };
53
- }
54
- case Range.Yesterday: {
55
- const yesterday = subDays(now, 1);
56
- const dayBeforeYesterday = subDays(now, 2);
57
-
58
- return {
59
- start: startOfDay(yesterday).toISOString(),
60
- end: endOfDay(yesterday).toISOString(),
61
- previousStart: startOfDay(dayBeforeYesterday).toISOString(),
62
- previousEnd: endOfDay(dayBeforeYesterday).toISOString(),
63
- };
64
- }
65
- case Range.ThisWeek: {
66
- const today = now;
67
- const sixDaysAgo = subDays(now, 6);
68
- const sevenDaysAgo = subDays(now, 7);
69
- const thirteenDaysAgo = subDays(now, 13);
70
-
71
- return {
72
- start: startOfDay(sixDaysAgo).toISOString(),
73
- end: endOfDay(today).toISOString(),
74
- previousStart: startOfDay(thirteenDaysAgo).toISOString(),
75
- previousEnd: endOfDay(sevenDaysAgo).toISOString(),
76
- };
77
- }
78
- case Range.ThisMonth: {
79
- const lastMonth = subMonths(now, 1);
80
- const twoMonthsAgo = subMonths(now, 2);
81
-
82
- return {
83
- start: startOfMonth(lastMonth).toISOString(),
84
- end: endOfMonth(lastMonth).toISOString(),
85
- previousStart: startOfMonth(twoMonthsAgo).toISOString(),
86
- previousEnd: endOfMonth(twoMonthsAgo).toISOString(),
87
- };
88
- }
89
- }
90
- }, [range]);
36
+ const rangeLength = differenceInDays(dateRange.to, dateRange.from) + 1;
37
+ // For the previous period, we go back by the same range length
38
+ const previousStart = subDays(dateRange.from, rangeLength);
39
+ const previousEnd = subDays(dateRange.to, rangeLength);
40
+
41
+ return {
42
+ start: dateRange.from.toISOString(),
43
+ end: dateRange.to.toISOString(),
44
+ previousStart: previousStart.toISOString(),
45
+ previousEnd: previousEnd.toISOString(),
46
+ };
47
+ }, [dateRange]);
91
48
 
92
49
  const { data } = useQuery({
93
- queryKey: ['orders-summary', range],
50
+ queryKey: ['orders-summary', dateRange],
94
51
  queryFn: () =>
95
52
  api.query(orderSummaryQuery, {
96
53
  start: variables.start,
@@ -99,7 +56,7 @@ export function OrdersSummaryWidget() {
99
56
  });
100
57
 
101
58
  const { data: previousData } = useQuery({
102
- queryKey: ['orders-summary', 'previous', range],
59
+ queryKey: ['orders-summary', 'previous', dateRange],
103
60
  queryFn: () =>
104
61
  api.query(orderSummaryQuery, {
105
62
  start: variables.previousStart,
@@ -124,23 +81,13 @@ export function OrdersSummaryWidget() {
124
81
  return (
125
82
  <DashboardBaseWidget
126
83
  id={WIDGET_ID}
127
- title="Orders Summary"
128
- description="Your orders summary"
129
- actions={
130
- <Tabs defaultValue={range} onValueChange={value => setRange(value as Range)}>
131
- <TabsList>
132
- <TabsTrigger value={Range.Today}>Today</TabsTrigger>
133
- <TabsTrigger value={Range.Yesterday}>Yesterday</TabsTrigger>
134
- <TabsTrigger value={Range.ThisWeek}>This Week</TabsTrigger>
135
- <TabsTrigger value={Range.ThisMonth}>This Month</TabsTrigger>
136
- </TabsList>
137
- </Tabs>
138
- }
84
+ title={t`Orders Summary`}
85
+ description={t`Your orders summary`}
139
86
  >
140
87
  <div className="@container h-full">
141
88
  <div className="flex flex-col h-full @md:flex-row gap-8 items-center justify-center @md:justify-evenly text-center tabular-nums">
142
89
  <div className="flex flex-col lg:gap-2">
143
- <p className="lg:text-lg text-muted-foreground">Total Orders</p>
90
+ <p className="lg:text-lg text-muted-foreground"><Trans>Total Orders</Trans></p>
144
91
  <p className="text-xl @md:text-3xl font-semibold">
145
92
  <AnimatedNumber
146
93
  animationConfig={{ mass: 0.01, stiffness: 90, damping: 3 }}
@@ -150,7 +97,7 @@ export function OrdersSummaryWidget() {
150
97
  <PercentageChange value={orderChange} />
151
98
  </div>
152
99
  <div className="flex flex-col lg:gap-2">
153
- <p className="lg:text-lg text-muted-foreground">Total Revenue</p>
100
+ <p className="lg:text-lg text-muted-foreground"><Trans>Total Revenue</Trans></p>
154
101
  <p className="text-xl @md:text-3xl font-semibold">
155
102
  <AnimatedCurrency
156
103
  animationConfig={{ mass: 0.01, stiffness: 90, damping: 3 }}
@@ -163,4 +110,4 @@ export function OrdersSummaryWidget() {
163
110
  </div>
164
111
  </DashboardBaseWidget>
165
112
  );
166
- }
113
+ }
@@ -0,0 +1,35 @@
1
+ 'use client';
2
+
3
+ import { useLingui } from '@lingui/react/macro';
4
+ import { createContext, useContext, PropsWithChildren } from 'react';
5
+
6
+ export interface DefinedDateRange {
7
+ from: Date;
8
+ to: Date;
9
+ }
10
+
11
+ export interface WidgetFilters {
12
+ dateRange: DefinedDateRange;
13
+ }
14
+
15
+ const WidgetFiltersContext = createContext<WidgetFilters | undefined>(undefined);
16
+
17
+ export function WidgetFiltersProvider({
18
+ children,
19
+ filters
20
+ }: PropsWithChildren<{ filters: WidgetFilters }>) {
21
+ return (
22
+ <WidgetFiltersContext.Provider value={filters}>
23
+ {children}
24
+ </WidgetFiltersContext.Provider>
25
+ );
26
+ }
27
+
28
+ export function useWidgetFilters() {
29
+ const { t } = useLingui();
30
+ const context = useContext(WidgetFiltersContext);
31
+ if (context === undefined) {
32
+ throw new Error(t`useWidgetFilters must be used within a WidgetFiltersProvider`);
33
+ }
34
+ return context;
35
+ }