@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
@@ -16,7 +16,7 @@ import {
16
16
  import { Input } from '@/vdb/components/ui/input.js';
17
17
  import { ScrollArea } from '@/vdb/components/ui/scroll-area.js';
18
18
  import { api } from '@/vdb/graphql/api.js';
19
- import { Trans, useLingui } from '@/vdb/lib/trans.js';
19
+ import { Trans, useLingui } from '@lingui/react/macro';
20
20
  import { ChevronRight, Folder, FolderOpen, Search } from 'lucide-react';
21
21
 
22
22
  import { collectionListForMoveDocument, moveCollectionDocument } from '../collections.graphql.js';
@@ -217,7 +217,7 @@ export function MoveCollectionsDialog({
217
217
  const debouncedSearchTerm = useDebounce(searchTerm, 300);
218
218
  const collectionNameCache = useRef<Map<string, string>>(new Map());
219
219
  const queryClient = useQueryClient();
220
- const { i18n } = useLingui();
220
+ const { t } = useLingui();
221
221
  const collectionForMoveKey = ['collectionsForMove', debouncedSearchTerm];
222
222
  const childCollectionsForMoveKey = (collectionId?: string) =>
223
223
  collectionId ? ['childCollectionsForMove', collectionId] : ['childCollectionsForMove'];
@@ -280,14 +280,14 @@ export function MoveCollectionsDialog({
280
280
  const moveCollectionsMutation = useMutation({
281
281
  mutationFn: api.mutate(moveCollectionDocument),
282
282
  onSuccess: () => {
283
- toast.success(i18n.t('Collections moved successfully'));
283
+ toast.success(t`Collections moved successfully`);
284
284
  queryClient.invalidateQueries({ queryKey: collectionForMoveKey });
285
285
  queryClient.invalidateQueries({ queryKey: childCollectionsForMoveKey() });
286
286
  onSuccess?.();
287
287
  onOpenChange(false);
288
288
  },
289
289
  onError: error => {
290
- toast.error(i18n.t('Failed to move collections'));
290
+ toast.error(t`Failed to move collections`);
291
291
  console.error('Move collections error:', error);
292
292
  },
293
293
  });
@@ -305,7 +305,7 @@ export function MoveCollectionsDialog({
305
305
 
306
306
  const handleMove = () => {
307
307
  if (!selectedCollectionId) {
308
- toast.error(i18n.t('Please select a target collection'));
308
+ toast.error(t`Please select a target collection`);
309
309
  return;
310
310
  }
311
311
  // Move to a specific parent using moveCollection
@@ -363,7 +363,7 @@ export function MoveCollectionsDialog({
363
363
  <div className="relative mb-3">
364
364
  <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" />
365
365
  <Input
366
- placeholder={i18n.t('Filter by collection name')}
366
+ placeholder={t`Filter by collection name`}
367
367
  value={searchTerm}
368
368
  onChange={e => setSearchTerm(e.target.value)}
369
369
  className="pl-10"
@@ -3,6 +3,8 @@ import { graphql } from '@/vdb/graphql/graphql.js';
3
3
  export const countryItemFragment = graphql(`
4
4
  fragment CountryItem on Country {
5
5
  id
6
+ createdAt
7
+ updatedAt
6
8
  name
7
9
  code
8
10
  enabled
@@ -3,7 +3,7 @@ import { PermissionGuard } from '@/vdb/components/shared/permission-guard.js';
3
3
  import { Button } from '@/vdb/components/ui/button.js';
4
4
  import { PageActionBarRight } from '@/vdb/framework/layout-engine/page-layout.js';
5
5
  import { ListPage } from '@/vdb/framework/page/list-page.js';
6
- import { Trans } from '@/vdb/lib/trans.js';
6
+ import { Trans } from '@lingui/react/macro';
7
7
  import { createFileRoute, Link } from '@tanstack/react-router';
8
8
  import { PlusIcon } from 'lucide-react';
9
9
  import { DeleteCountriesBulkAction } from './components/country-bulk-actions.js';
@@ -20,7 +20,7 @@ function CountryListPage() {
20
20
  pageId="country-list"
21
21
  listQuery={countriesListQuery}
22
22
  route={Route}
23
- title="Countries"
23
+ title={<Trans>Countries</Trans>}
24
24
  defaultVisibility={{
25
25
  name: true,
26
26
  code: true,
@@ -47,7 +47,6 @@ function CountryListPage() {
47
47
  }}
48
48
  customizeColumns={{
49
49
  name: {
50
- header: 'Name',
51
50
  cell: ({ row }) => <DetailPageButton id={row.original.id} label={row.original.name} />,
52
51
  },
53
52
  }}
@@ -18,7 +18,7 @@ import {
18
18
  } from '@/vdb/framework/layout-engine/page-layout.js';
19
19
  import { detailPageRouteLoader } from '@/vdb/framework/page/detail-page-route-loader.js';
20
20
  import { useDetailPage } from '@/vdb/framework/page/use-detail-page.js';
21
- import { Trans, useLingui } from '@/vdb/lib/trans.js';
21
+ import { Trans, useLingui } from '@lingui/react/macro';
22
22
  import { createFileRoute, useNavigate } from '@tanstack/react-router';
23
23
  import { toast } from 'sonner';
24
24
  import { countryDetailDocument, createCountryDocument, updateCountryDocument } from './countries.graphql.js';
@@ -42,7 +42,7 @@ function CountryDetailPage() {
42
42
  const params = Route.useParams();
43
43
  const navigate = useNavigate();
44
44
  const creatingNewEntity = params.id === NEW_ENTITY_PATH;
45
- const { i18n } = useLingui();
45
+ const { t } = useLingui();
46
46
 
47
47
  const { form, submitHandler, entity, isPending, resetForm } = useDetailPage({
48
48
  pageId,
@@ -61,14 +61,14 @@ function CountryDetailPage() {
61
61
  },
62
62
  params: { id: params.id },
63
63
  onSuccess: async data => {
64
- toast(i18n.t(creatingNewEntity ? 'Successfully created country' : 'Successfully updated country'));
64
+ toast(creatingNewEntity ? t`Successfully created country` : t`Successfully updated country`);
65
65
  form.reset(form.getValues());
66
66
  if (creatingNewEntity) {
67
67
  await navigate({ to: `../$id`, params: { id: data.id } });
68
68
  }
69
69
  },
70
70
  onError: err => {
71
- toast(i18n.t(creatingNewEntity ? 'Failed to create country' : 'Failed to update country'), {
71
+ toast(creatingNewEntity ? t`Failed to create country` : t`Failed to update country`, {
72
72
  description: err instanceof Error ? err.message : 'Unknown error',
73
73
  });
74
74
  },
@@ -7,7 +7,7 @@ import {
7
7
  SheetTitle,
8
8
  SheetTrigger,
9
9
  } from '@/vdb/components/ui/sheet.js';
10
- import { Trans } from '@/vdb/lib/trans.js';
10
+ import { Trans } from '@lingui/react/macro';
11
11
  import { PanelLeftOpen } from 'lucide-react';
12
12
  import { CustomerGroupMembersTable } from './customer-group-members-table.js';
13
13
 
@@ -7,7 +7,7 @@ import { Button } from '@/vdb/components/ui/button.js';
7
7
  import { addCustomFields } from '@/vdb/framework/document-introspection/add-custom-fields.js';
8
8
  import { api } from '@/vdb/graphql/api.js';
9
9
  import { graphql } from '@/vdb/graphql/graphql.js';
10
- import { Trans, useLingui } from '@/vdb/lib/trans.js';
10
+ import { Trans, useLingui } from '@lingui/react/macro';
11
11
  import { useMutation, useQueryClient } from '@tanstack/react-query';
12
12
  import { Link } from '@tanstack/react-router';
13
13
  import { ColumnFiltersState, SortingState } from '@tanstack/react-table';
@@ -46,19 +46,19 @@ export function CustomerGroupMembersTable({
46
46
  const [page, setPage] = useState(1);
47
47
  const [pageSize, setPageSize] = useState(10);
48
48
  const [filters, setFilters] = useState<ColumnFiltersState>([]);
49
- const { i18n } = useLingui();
49
+ const { t } = useLingui();
50
50
  const queryClient = useQueryClient();
51
51
 
52
52
  const { mutate: addCustomerToGroup } = useMutation({
53
53
  mutationFn: api.mutate(addCustomerToGroupDocument),
54
54
  onSuccess: () => {
55
- toast.success(i18n.t('Customer added to group'));
55
+ toast.success(t`Customer added to group`);
56
56
  queryClient.invalidateQueries({
57
57
  queryKey: [PaginatedListDataTableKey, customerGroupMemberListDocument],
58
58
  });
59
59
  },
60
60
  onError: () => {
61
- toast.error(i18n.t('Failed to add customer to group'));
61
+ toast.error(t`Failed to add customer to group`);
62
62
  },
63
63
  });
64
64
 
@@ -3,7 +3,7 @@ import { PermissionGuard } from '@/vdb/components/shared/permission-guard.js';
3
3
  import { Button } from '@/vdb/components/ui/button.js';
4
4
  import { PageActionBarRight } from '@/vdb/framework/layout-engine/page-layout.js';
5
5
  import { ListPage } from '@/vdb/framework/page/list-page.js';
6
- import { Trans } from '@/vdb/lib/trans.js';
6
+ import { Trans } from '@lingui/react/macro';
7
7
  import { createFileRoute, Link } from '@tanstack/react-router';
8
8
  import { PlusIcon } from 'lucide-react';
9
9
  import { DeleteCustomerGroupsBulkAction } from './components/customer-group-bulk-actions.js';
@@ -19,16 +19,14 @@ function CustomerGroupListPage() {
19
19
  return (
20
20
  <ListPage
21
21
  pageId="customer-group-list"
22
- title="Customer Groups"
22
+ title={<Trans>Customer Groups</Trans>}
23
23
  listQuery={customerGroupListDocument}
24
24
  route={Route}
25
25
  customizeColumns={{
26
26
  name: {
27
- header: 'Name',
28
27
  cell: ({ row }) => <DetailPageButton id={row.original.id} label={row.original.name} />,
29
28
  },
30
29
  customers: {
31
- header: () => <Trans>Values</Trans>,
32
30
  cell: ({ cell }) => {
33
31
  const value = cell.getValue();
34
32
  if (!value) {
@@ -16,7 +16,7 @@ import {
16
16
  } from '@/vdb/framework/layout-engine/page-layout.js';
17
17
  import { detailPageRouteLoader } from '@/vdb/framework/page/detail-page-route-loader.js';
18
18
  import { useDetailPage } from '@/vdb/framework/page/use-detail-page.js';
19
- import { Trans, useLingui } from '@/vdb/lib/trans.js';
19
+ import { Trans, useLingui } from '@lingui/react/macro';
20
20
  import { createFileRoute, useNavigate } from '@tanstack/react-router';
21
21
  import { toast } from 'sonner';
22
22
  import { CustomerGroupMembersTable } from './components/customer-group-members-table.js';
@@ -45,7 +45,7 @@ function CustomerGroupDetailPage() {
45
45
  const params = Route.useParams();
46
46
  const navigate = useNavigate();
47
47
  const creatingNewEntity = params.id === NEW_ENTITY_PATH;
48
- const { i18n } = useLingui();
48
+ const { t } = useLingui();
49
49
 
50
50
  const { form, submitHandler, entity, isPending, resetForm } = useDetailPage({
51
51
  pageId,
@@ -61,16 +61,23 @@ function CustomerGroupDetailPage() {
61
61
  },
62
62
  params: { id: params.id },
63
63
  onSuccess: async data => {
64
- toast.success(i18n.t(creatingNewEntity ? 'Successfully created customer group' : 'Successfully updated customer group'));
64
+ toast.success(
65
+ creatingNewEntity
66
+ ? t`Successfully created customer group`
67
+ : t`Successfully updated customer group`,
68
+ );
65
69
  resetForm();
66
70
  if (creatingNewEntity && data?.id) {
67
71
  await navigate({ to: `../$id`, params: { id: data.id } });
68
72
  }
69
73
  },
70
74
  onError: err => {
71
- toast.error(i18n.t(creatingNewEntity ? 'Failed to create customer group' : 'Failed to update customer group'), {
72
- description: err instanceof Error ? err.message : 'Unknown error',
73
- });
75
+ toast.error(
76
+ creatingNewEntity ? t`Failed to create customer group` : t`Failed to update customer group`,
77
+ {
78
+ description: err instanceof Error ? err.message : 'Unknown error',
79
+ },
80
+ );
74
81
  },
75
82
  });
76
83
 
@@ -11,7 +11,7 @@ import {
11
11
  DialogTrigger,
12
12
  } from '@/vdb/components/ui/dialog.js';
13
13
  import { api } from '@/vdb/graphql/api.js';
14
- import { Trans, useLingui } from '@/vdb/lib/trans.js';
14
+ import { Trans, useLingui } from '@lingui/react/macro';
15
15
  import { useMutation } from '@tanstack/react-query';
16
16
  import { EditIcon, TrashIcon } from 'lucide-react';
17
17
  import { useState } from 'react';
@@ -37,15 +37,15 @@ export function CustomerAddressCard({
37
37
  onDelete?: () => void;
38
38
  }) {
39
39
  const [open, setOpen] = useState(false);
40
- const { i18n } = useLingui();
40
+ const { t } = useLingui();
41
41
  const { mutate: deleteAddress } = useMutation({
42
42
  mutationFn: api.mutate(deleteCustomerAddressDocument),
43
43
  onSuccess: () => {
44
- toast.success(i18n.t('Address deleted successfully'));
44
+ toast.success(t`Address deleted successfully`);
45
45
  onDelete?.();
46
46
  },
47
47
  onError: () => {
48
- toast.error(i18n.t('Failed to delete address'));
48
+ toast.error(t`Failed to delete address`);
49
49
  },
50
50
  });
51
51
 
@@ -53,11 +53,11 @@ export function CustomerAddressCard({
53
53
  const { mutate: updateAddress } = useMutation({
54
54
  mutationFn: api.mutate(updateCustomerAddressDocument),
55
55
  onSuccess: () => {
56
- toast.success(i18n.t('Address updated successfully'));
56
+ toast.success(t`Address updated successfully`);
57
57
  onUpdate?.();
58
58
  },
59
59
  onError: error => {
60
- toast.error(i18n.t('Failed to update address'));
60
+ toast.error(t`Failed to update address`);
61
61
  console.error('Error updating address:', error);
62
62
  },
63
63
  });
@@ -138,8 +138,8 @@ export function CustomerAddressCard({
138
138
  )}
139
139
  {deletable && (
140
140
  <ConfirmationDialog
141
- title={i18n.t('Delete Address')}
142
- description={i18n.t('Are you sure you want to delete this address?')}
141
+ title={t`Delete Address`}
142
+ description={t`Are you sure you want to delete this address?`}
143
143
  onConfirm={() => {
144
144
  deleteAddress({ id: address.id });
145
145
  onDelete?.();
@@ -13,8 +13,8 @@ import { Input } from '@/vdb/components/ui/input.js';
13
13
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/vdb/components/ui/select.js';
14
14
  import { api } from '@/vdb/graphql/api.js';
15
15
  import { graphql, ResultOf } from '@/vdb/graphql/graphql.js';
16
- import { Trans, useLingui } from '@/vdb/lib/trans.js';
17
16
  import { zodResolver } from '@hookform/resolvers/zod';
17
+ import { Trans, useLingui } from '@lingui/react/macro';
18
18
  import { useQuery } from '@tanstack/react-query';
19
19
  import { useForm } from 'react-hook-form';
20
20
  import { z } from 'zod';
@@ -59,7 +59,7 @@ interface CustomerAddressFormProps {
59
59
  }
60
60
 
61
61
  export function CustomerAddressForm({ address, onSubmit, onCancel }: Readonly<CustomerAddressFormProps>) {
62
- const { i18n } = useLingui();
62
+ const { t } = useLingui();
63
63
 
64
64
  // Fetch available countries
65
65
  const { data: countriesData, isLoading: isLoadingCountries } = useQuery({
@@ -246,7 +246,7 @@ export function CustomerAddressForm({ address, onSubmit, onCancel }: Readonly<Cu
246
246
  >
247
247
  <FormControl>
248
248
  <SelectTrigger>
249
- <SelectValue placeholder={i18n.t('Select a country')} />
249
+ <SelectValue placeholder={t`Select a country`} />
250
250
  </SelectTrigger>
251
251
  </FormControl>
252
252
  <SelectContent>
@@ -1,7 +1,7 @@
1
1
  import { Alert, AlertDescription } from '@/vdb/components/ui/alert.js';
2
2
  import { Button } from '@/vdb/components/ui/button.js';
3
3
  import { Skeleton } from '@/vdb/components/ui/skeleton.js';
4
- import { Trans } from '@/vdb/lib/trans.js';
4
+ import { Trans } from '@lingui/react/macro';
5
5
  import { TriangleAlert } from 'lucide-react';
6
6
  import { CustomerHistory } from './customer-history.js';
7
7
  import { useCustomerHistory } from './use-customer-history.js';
@@ -1,5 +1,5 @@
1
1
  import { HistoryEntryItem } from '@/vdb/framework/extension-api/types/index.js';
2
- import { Trans } from '@/vdb/lib/trans.js';
2
+ import { Trans } from '@lingui/react/macro';
3
3
  import { CheckIcon, Edit3, KeyIcon, Mail, MapPin, SquarePen, User, UserCheck, Users } from 'lucide-react';
4
4
  import { CustomerHistoryCustomerDetail } from './customer-history-types.js';
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { HistoryEntry, HistoryEntryProps } from '@/vdb/framework/history-entry/history-entry.js';
2
- import { Trans } from '@/vdb/lib/trans.js';
2
+ import { Trans } from '@lingui/react/macro';
3
3
 
4
4
  export function CustomerRegisteredOrVerifiedComponent(props: Readonly<HistoryEntryProps>) {
5
5
  const { entry } = props;
@@ -1,6 +1,6 @@
1
1
  import { api } from '@/vdb/graphql/api.js';
2
2
  import { graphql, ResultOf } from '@/vdb/graphql/graphql.js';
3
- import { useLingui } from '@/vdb/lib/trans.js';
3
+ import { useLingui } from '@lingui/react/macro';
4
4
  import { useInfiniteQuery, useMutation } from '@tanstack/react-query';
5
5
  import { useState } from 'react';
6
6
  import { toast } from 'sonner';
@@ -1,5 +1,5 @@
1
1
  import { Badge } from '@/vdb/components/ui/badge.js';
2
- import { Trans } from '@/vdb/lib/trans.js';
2
+ import { Trans } from '@lingui/react/macro';
3
3
  import { BadgeCheck, BadgeX } from 'lucide-react';
4
4
 
5
5
  export type CustomerStatus = 'guest' | 'registered' | 'verified';
@@ -10,6 +10,10 @@ export const customerListDocument = graphql(`
10
10
  firstName
11
11
  lastName
12
12
  emailAddress
13
+ groups {
14
+ id
15
+ name
16
+ }
13
17
  user {
14
18
  id
15
19
  verified
@@ -1,9 +1,10 @@
1
1
  import { DetailPageButton } from '@/vdb/components/shared/detail-page-button.js';
2
2
  import { PermissionGuard } from '@/vdb/components/shared/permission-guard.js';
3
+ import { Badge } from '@/vdb/components/ui/badge.js';
3
4
  import { Button } from '@/vdb/components/ui/button.js';
4
5
  import { PageActionBarRight } from '@/vdb/framework/layout-engine/page-layout.js';
5
6
  import { ListPage } from '@/vdb/framework/page/list-page.js';
6
- import { Trans } from '@/vdb/lib/trans.js';
7
+ import { Trans } from '@lingui/react/macro';
7
8
  import { createFileRoute, Link } from '@tanstack/react-router';
8
9
  import { PlusIcon } from 'lucide-react';
9
10
  import { DeleteCustomersBulkAction } from './components/customer-bulk-actions.js';
@@ -18,7 +19,7 @@ export const Route = createFileRoute('/_authenticated/_customers/customers')({
18
19
  function CustomerListPage() {
19
20
  return (
20
21
  <ListPage
21
- title="Customers"
22
+ title={<Trans>Customers</Trans>}
22
23
  pageId="customer-list"
23
24
  listQuery={customerListDocument}
24
25
  onSearchTermChange={searchTerm => {
@@ -42,16 +43,29 @@ function CustomerListPage() {
42
43
  route={Route}
43
44
  customizeColumns={{
44
45
  user: {
45
- header: 'Status',
46
- cell: ({ cell }) => {
47
- const value = cell.getValue();
46
+ header: () => <Trans>Status</Trans>,
47
+ cell: ({ row }) => {
48
+ const value = row.original.user;
48
49
  return <CustomerStatusBadge user={value} />;
49
50
  },
50
51
  },
52
+ groups: {
53
+ cell: ({ row }) => {
54
+ return row.original.groups?.map(g => (
55
+ <Badge variant="secondary" key={g.id}>
56
+ {g.name}
57
+ </Badge>
58
+ ));
59
+ },
60
+ },
51
61
  }}
52
62
  additionalColumns={{
53
63
  name: {
54
- header: 'Name',
64
+ id: 'name',
65
+ meta: {
66
+ dependencies: ['id', 'firstName', 'lastName'],
67
+ },
68
+ header: () => <Trans>Name</Trans>,
55
69
  cell: ({ row }) => {
56
70
  const value = `${row.original.firstName} ${row.original.lastName}`;
57
71
  return <DetailPageButton id={row.original.id} label={value} />;
@@ -60,11 +74,9 @@ function CustomerListPage() {
60
74
  }}
61
75
  defaultColumnOrder={['name', 'emailAddress', 'user', 'createdAt']}
62
76
  defaultVisibility={{
63
- id: false,
64
- createdAt: false,
65
- updatedAt: false,
66
- firstName: false,
67
- lastName: false,
77
+ name: true,
78
+ emailAddress: true,
79
+ user: true,
68
80
  }}
69
81
  bulkActions={[
70
82
  {
@@ -27,7 +27,7 @@ import {
27
27
  import { detailPageRouteLoader } from '@/vdb/framework/page/detail-page-route-loader.js';
28
28
  import { useDetailPage } from '@/vdb/framework/page/use-detail-page.js';
29
29
  import { api } from '@/vdb/graphql/api.js';
30
- import { Trans, useLingui } from '@/vdb/lib/trans.js';
30
+ import { Trans, useLingui } from '@lingui/react/macro';
31
31
  import { useMutation } from '@tanstack/react-query';
32
32
  import { createFileRoute, useNavigate } from '@tanstack/react-router';
33
33
  import { Plus } from 'lucide-react';
@@ -66,7 +66,7 @@ function CustomerDetailPage() {
66
66
  const params = Route.useParams();
67
67
  const navigate = useNavigate();
68
68
  const creatingNewEntity = params.id === NEW_ENTITY_PATH;
69
- const { i18n } = useLingui();
69
+ const { t } = useLingui();
70
70
  const [newAddressOpen, setNewAddressOpen] = useState(false);
71
71
 
72
72
  const { form, submitHandler, entity, isPending, refreshEntity, resetForm } = useDetailPage({
@@ -89,19 +89,21 @@ function CustomerDetailPage() {
89
89
  params: { id: params.id },
90
90
  onSuccess: async data => {
91
91
  if (data.__typename === 'Customer') {
92
- toast.success(i18n.t(creatingNewEntity ? 'Successfully created customer' : 'Successfully updated customer'));
92
+ toast.success(
93
+ creatingNewEntity ? t`Successfully created customer` : t`Successfully updated customer`,
94
+ );
93
95
  resetForm();
94
96
  if (creatingNewEntity) {
95
97
  await navigate({ to: `../$id`, params: { id: data.id } });
96
98
  }
97
99
  } else {
98
- toast.error(i18n.t(creatingNewEntity ? 'Failed to create customer' : 'Failed to update customer'), {
100
+ toast.error(creatingNewEntity ? t`Failed to create customer` : t`Failed to update customer`, {
99
101
  description: data.message,
100
102
  });
101
103
  }
102
104
  },
103
105
  onError: err => {
104
- toast.error(i18n.t(creatingNewEntity ? 'Failed to create customer' : 'Failed to update customer'), {
106
+ toast.error(creatingNewEntity ? t`Failed to create customer` : t`Failed to update customer`, {
105
107
  description: err instanceof Error ? err.message : 'Unknown error',
106
108
  });
107
109
  },
@@ -114,7 +116,7 @@ function CustomerDetailPage() {
114
116
  refreshEntity();
115
117
  },
116
118
  onError: () => {
117
- toast.error(i18n.t('Failed to create address'));
119
+ toast.error(t`Failed to create address`);
118
120
  },
119
121
  });
120
122
 
@@ -124,7 +126,7 @@ function CustomerDetailPage() {
124
126
  refreshEntity();
125
127
  },
126
128
  onError: () => {
127
- toast(i18n.t('Failed to add customer to group'));
129
+ toast(t`Failed to add customer to group`);
128
130
  },
129
131
  });
130
132
 
@@ -134,7 +136,7 @@ function CustomerDetailPage() {
134
136
  refreshEntity();
135
137
  },
136
138
  onError: () => {
137
- toast(i18n.t('Failed to remove customer from group'));
139
+ toast(t`Failed to remove customer from group`);
138
140
  },
139
141
  });
140
142
 
@@ -5,7 +5,7 @@ import { Input } from '@/vdb/components/ui/input.js';
5
5
  import { api } from '@/vdb/graphql/api.js';
6
6
  import { graphql } from '@/vdb/graphql/graphql.js';
7
7
  import { useUserSettings } from '@/vdb/hooks/use-user-settings.js';
8
- import { Trans } from '@/vdb/lib/trans.js';
8
+ import { Trans } from '@lingui/react/macro';
9
9
  import { useMutation, useQuery } from '@tanstack/react-query';
10
10
  import { useForm } from 'react-hook-form';
11
11
 
@@ -6,7 +6,7 @@ import { BulkActionComponent } from '@/vdb/framework/extension-api/types/data-ta
6
6
  import { api } from '@/vdb/graphql/api.js';
7
7
  import { ResultOf } from '@/vdb/graphql/graphql.js';
8
8
  import { useChannel } from '@/vdb/hooks/use-channel.js';
9
- import { useLingui } from '@/vdb/lib/trans.js';
9
+ import { useLingui } from '@lingui/react/macro';
10
10
  import { DeleteBulkAction } from '../../../../common/delete-bulk-action.js';
11
11
  import { DuplicateBulkAction } from '../../../../common/duplicate-bulk-action.js';
12
12
 
@@ -46,7 +46,7 @@ export const AssignFacetsToChannelBulkAction: BulkActionComponent<any> = ({ sele
46
46
 
47
47
  export const RemoveFacetsFromChannelBulkAction: BulkActionComponent<any> = ({ selection, table }) => {
48
48
  const { activeChannel } = useChannel();
49
- const { i18n } = useLingui();
49
+ const { t } = useLingui();
50
50
 
51
51
  return (
52
52
  <RemoveFromChannelBulkAction
@@ -68,15 +68,16 @@ export const RemoveFacetsFromChannelBulkAction: BulkActionComponent<any> = ({ se
68
68
  if ('id' in item) {
69
69
  // Do nothing
70
70
  } else if ('message' in item) {
71
- errors.push(item.message);
72
- toast.error(i18n.t(`Failed to remove facet from channel: ${item.message}`));
71
+ const message = item.message;
72
+ errors.push(message);
73
+ toast.error(t`Failed to remove facet from channel: ${message}`);
73
74
  }
74
75
  }
75
76
 
76
77
  const successCount = selection.length - errors.length;
77
78
 
78
79
  if (successCount > 0) {
79
- toast.success(i18n.t(`Successfully removed ${successCount} facets from channel`));
80
+ toast.success(t`Successfully removed ${successCount} facets from channel`);
80
81
  }
81
82
  }
82
83
  }}
@@ -7,7 +7,7 @@ import {
7
7
  SheetTitle,
8
8
  SheetTrigger,
9
9
  } from '@/vdb/components/ui/sheet.js';
10
- import { Trans } from '@/vdb/lib/trans.js';
10
+ import { Trans } from '@lingui/react/macro';
11
11
  import { PanelLeftOpen } from 'lucide-react';
12
12
  import { FacetValuesTable } from './facet-values-table.js';
13
13
 
@@ -2,7 +2,7 @@ import { DetailPageButton } from '@/vdb/components/shared/detail-page-button.js'
2
2
  import { PaginatedListDataTable } from '@/vdb/components/shared/paginated-list-data-table.js';
3
3
  import { addCustomFields } from '@/vdb/framework/document-introspection/add-custom-fields.js';
4
4
  import { graphql } from '@/vdb/graphql/graphql.js';
5
- import { Trans } from '@/vdb/lib/trans.js';
5
+ import { Trans } from '@lingui/react/macro';
6
6
  import { Link } from '@tanstack/react-router';
7
7
  import { Button } from '@/vdb/components/ui/button.js';
8
8
  import { ColumnFiltersState, SortingState } from '@tanstack/react-table';
@@ -1,3 +1,4 @@
1
+ import { DataTableCellComponent } from '@/vdb/components/data-table/types.js';
1
2
  import { DetailPageButton } from '@/vdb/components/shared/detail-page-button.js';
2
3
  import { FacetValueChip } from '@/vdb/components/shared/facet-value-chip.js';
3
4
  import { PermissionGuard } from '@/vdb/components/shared/permission-guard.js';
@@ -5,7 +6,7 @@ import { Badge } from '@/vdb/components/ui/badge.js';
5
6
  import { Button } from '@/vdb/components/ui/button.js';
6
7
  import { PageActionBarRight } from '@/vdb/framework/layout-engine/page-layout.js';
7
8
  import { ListPage } from '@/vdb/framework/page/list-page.js';
8
- import { Trans } from '@/vdb/lib/trans.js';
9
+ import { Trans } from '@lingui/react/macro';
9
10
  import { createFileRoute, Link } from '@tanstack/react-router';
10
11
  import { ResultOf } from 'gql.tada';
11
12
  import { PlusIcon } from 'lucide-react';
@@ -16,8 +17,7 @@ import {
16
17
  RemoveFacetsFromChannelBulkAction,
17
18
  } from './components/facet-bulk-actions.js';
18
19
  import { FacetValuesSheet } from './components/facet-values-sheet.js';
19
- import { deleteFacetDocument, facetListDocument } from './facets.graphql.js';
20
- import { DataTableCellComponent } from '@/vdb/components/data-table/types.js';
20
+ import { facetListDocument } from './facets.graphql.js';
21
21
 
22
22
  export const Route = createFileRoute('/_authenticated/_facets/facets')({
23
23
  component: FacetListPage,
@@ -61,7 +61,7 @@ function FacetListPage() {
61
61
  return (
62
62
  <ListPage
63
63
  pageId="facet-list"
64
- title="Facets"
64
+ title={<Trans>Facets</Trans>}
65
65
  listQuery={facetListDocument}
66
66
  defaultVisibility={{
67
67
  name: true,
@@ -70,7 +70,7 @@ function FacetListPage() {
70
70
  }}
71
71
  customizeColumns={{
72
72
  name: {
73
- header: () => <Trans>Facet Name</Trans>,
73
+ id: 'name',
74
74
  cell: ({ row }) => <DetailPageButton id={row.original.id} label={row.original.name} />,
75
75
  },
76
76
  isPrivate: {