@spaceinvoices/react-ui 0.4.8 → 0.4.11

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 (276) hide show
  1. package/README.md +24 -8
  2. package/cli/dist/index.js +89 -26
  3. package/package.json +4 -1
  4. package/spaceinvoices.schema.json +6 -1
  5. package/src/common/autocomplete.tsx +69 -6
  6. package/src/components/advance-invoices/create/create-advance-invoice-form.tsx +124 -285
  7. package/src/components/advance-invoices/list/list-table.tsx +10 -3
  8. package/src/components/advance-invoices/list/locales/de.ts +2 -0
  9. package/src/components/advance-invoices/list/locales/en.ts +1 -0
  10. package/src/components/advance-invoices/list/locales/es.ts +1 -0
  11. package/src/components/advance-invoices/list/locales/fr.ts +1 -0
  12. package/src/components/advance-invoices/list/locales/hr.ts +1 -0
  13. package/src/components/advance-invoices/list/locales/it.ts +1 -0
  14. package/src/components/advance-invoices/list/locales/nl.ts +1 -0
  15. package/src/components/advance-invoices/list/locales/pl.ts +1 -0
  16. package/src/components/advance-invoices/list/locales/pt.ts +1 -0
  17. package/src/components/advance-invoices/list/locales/sl.ts +1 -0
  18. package/src/components/advance-invoices/list/use-advance-invoice-download.ts +1 -12
  19. package/src/components/credit-notes/create/create-credit-note-form.tsx +116 -238
  20. package/src/components/credit-notes/list/list-table.tsx +6 -3
  21. package/src/components/credit-notes/list/use-credit-note-download.ts +1 -12
  22. package/src/components/customers/customer-autocomplete.tsx +64 -11
  23. package/src/components/customers/customer-list-table/customer-list-table.tsx +3 -2
  24. package/src/components/dashboard/collection-rate-card/collection-rate-card.tsx +9 -1
  25. package/src/components/dashboard/collection-rate-card/locales/bg.ts +3 -0
  26. package/src/components/dashboard/collection-rate-card/locales/cs.ts +3 -0
  27. package/src/components/dashboard/collection-rate-card/locales/et.ts +3 -0
  28. package/src/components/dashboard/collection-rate-card/locales/fi.ts +3 -0
  29. package/src/components/dashboard/collection-rate-card/locales/is.ts +3 -0
  30. package/src/components/dashboard/collection-rate-card/locales/nb.ts +3 -0
  31. package/src/components/dashboard/collection-rate-card/locales/sk.ts +3 -0
  32. package/src/components/dashboard/collection-rate-card/locales/sv.ts +3 -0
  33. package/src/components/dashboard/invoice-status-chart/invoice-status-chart.tsx +10 -2
  34. package/src/components/dashboard/invoice-status-chart/locales/bg.ts +10 -0
  35. package/src/components/dashboard/invoice-status-chart/locales/cs.ts +10 -0
  36. package/src/components/dashboard/invoice-status-chart/locales/de.ts +1 -0
  37. package/src/components/dashboard/invoice-status-chart/locales/es.ts +1 -0
  38. package/src/components/dashboard/invoice-status-chart/locales/et.ts +10 -0
  39. package/src/components/dashboard/invoice-status-chart/locales/fi.ts +10 -0
  40. package/src/components/dashboard/invoice-status-chart/locales/fr.ts +1 -0
  41. package/src/components/dashboard/invoice-status-chart/locales/hr.ts +1 -0
  42. package/src/components/dashboard/invoice-status-chart/locales/is.ts +10 -0
  43. package/src/components/dashboard/invoice-status-chart/locales/it.ts +1 -0
  44. package/src/components/dashboard/invoice-status-chart/locales/nb.ts +10 -0
  45. package/src/components/dashboard/invoice-status-chart/locales/nl.ts +1 -0
  46. package/src/components/dashboard/invoice-status-chart/locales/pl.ts +1 -0
  47. package/src/components/dashboard/invoice-status-chart/locales/pt.ts +1 -0
  48. package/src/components/dashboard/invoice-status-chart/locales/sk.ts +10 -0
  49. package/src/components/dashboard/invoice-status-chart/locales/sl.ts +1 -0
  50. package/src/components/dashboard/invoice-status-chart/locales/sv.ts +10 -0
  51. package/src/components/dashboard/payment-methods-chart/locales/bg.ts +12 -0
  52. package/src/components/dashboard/payment-methods-chart/locales/cs.ts +12 -0
  53. package/src/components/dashboard/payment-methods-chart/locales/et.ts +12 -0
  54. package/src/components/dashboard/payment-methods-chart/locales/fi.ts +12 -0
  55. package/src/components/dashboard/payment-methods-chart/locales/is.ts +12 -0
  56. package/src/components/dashboard/payment-methods-chart/locales/nb.ts +12 -0
  57. package/src/components/dashboard/payment-methods-chart/locales/sk.ts +12 -0
  58. package/src/components/dashboard/payment-methods-chart/locales/sv.ts +12 -0
  59. package/src/components/dashboard/payment-methods-chart/payment-methods-chart.tsx +9 -1
  60. package/src/components/dashboard/payment-trend-chart/locales/bg.ts +6 -0
  61. package/src/components/dashboard/payment-trend-chart/locales/cs.ts +6 -0
  62. package/src/components/dashboard/payment-trend-chart/locales/de.ts +1 -0
  63. package/src/components/dashboard/payment-trend-chart/locales/es.ts +1 -0
  64. package/src/components/dashboard/payment-trend-chart/locales/et.ts +6 -0
  65. package/src/components/dashboard/payment-trend-chart/locales/fi.ts +6 -0
  66. package/src/components/dashboard/payment-trend-chart/locales/fr.ts +1 -0
  67. package/src/components/dashboard/payment-trend-chart/locales/hr.ts +1 -0
  68. package/src/components/dashboard/payment-trend-chart/locales/is.ts +6 -0
  69. package/src/components/dashboard/payment-trend-chart/locales/it.ts +1 -0
  70. package/src/components/dashboard/payment-trend-chart/locales/nb.ts +6 -0
  71. package/src/components/dashboard/payment-trend-chart/locales/nl.ts +1 -0
  72. package/src/components/dashboard/payment-trend-chart/locales/pl.ts +1 -0
  73. package/src/components/dashboard/payment-trend-chart/locales/pt.ts +1 -0
  74. package/src/components/dashboard/payment-trend-chart/locales/sk.ts +6 -0
  75. package/src/components/dashboard/payment-trend-chart/locales/sl.ts +1 -0
  76. package/src/components/dashboard/payment-trend-chart/locales/sv.ts +6 -0
  77. package/src/components/dashboard/payment-trend-chart/payment-trend-chart.tsx +15 -8
  78. package/src/components/dashboard/revenue-trend-chart/locales/bg.ts +6 -0
  79. package/src/components/dashboard/revenue-trend-chart/locales/cs.ts +6 -0
  80. package/src/components/dashboard/revenue-trend-chart/locales/de.ts +1 -0
  81. package/src/components/dashboard/revenue-trend-chart/locales/es.ts +1 -0
  82. package/src/components/dashboard/revenue-trend-chart/locales/et.ts +6 -0
  83. package/src/components/dashboard/revenue-trend-chart/locales/fi.ts +6 -0
  84. package/src/components/dashboard/revenue-trend-chart/locales/fr.ts +1 -0
  85. package/src/components/dashboard/revenue-trend-chart/locales/hr.ts +1 -0
  86. package/src/components/dashboard/revenue-trend-chart/locales/is.ts +6 -0
  87. package/src/components/dashboard/revenue-trend-chart/locales/it.ts +1 -0
  88. package/src/components/dashboard/revenue-trend-chart/locales/nb.ts +6 -0
  89. package/src/components/dashboard/revenue-trend-chart/locales/nl.ts +1 -0
  90. package/src/components/dashboard/revenue-trend-chart/locales/pl.ts +1 -0
  91. package/src/components/dashboard/revenue-trend-chart/locales/pt.ts +1 -0
  92. package/src/components/dashboard/revenue-trend-chart/locales/sk.ts +6 -0
  93. package/src/components/dashboard/revenue-trend-chart/locales/sl.ts +1 -0
  94. package/src/components/dashboard/revenue-trend-chart/locales/sv.ts +6 -0
  95. package/src/components/dashboard/revenue-trend-chart/revenue-trend-chart.tsx +15 -8
  96. package/src/components/dashboard/tax-collected-card/locales.ts +110 -0
  97. package/src/components/dashboard/tax-collected-card/tax-collected-card.tsx +8 -2
  98. package/src/components/dashboard/tax-collected-card/use-tax-collected.ts +4 -4
  99. package/src/components/dashboard/top-customers-chart/locales/bg.ts +7 -0
  100. package/src/components/dashboard/top-customers-chart/locales/cs.ts +7 -0
  101. package/src/components/dashboard/top-customers-chart/locales/de.ts +2 -0
  102. package/src/components/dashboard/top-customers-chart/locales/es.ts +2 -0
  103. package/src/components/dashboard/top-customers-chart/locales/et.ts +7 -0
  104. package/src/components/dashboard/top-customers-chart/locales/fi.ts +7 -0
  105. package/src/components/dashboard/top-customers-chart/locales/fr.ts +2 -0
  106. package/src/components/dashboard/top-customers-chart/locales/hr.ts +2 -0
  107. package/src/components/dashboard/top-customers-chart/locales/is.ts +7 -0
  108. package/src/components/dashboard/top-customers-chart/locales/it.ts +2 -0
  109. package/src/components/dashboard/top-customers-chart/locales/nb.ts +7 -0
  110. package/src/components/dashboard/top-customers-chart/locales/nl.ts +2 -0
  111. package/src/components/dashboard/top-customers-chart/locales/pl.ts +2 -0
  112. package/src/components/dashboard/top-customers-chart/locales/pt.ts +2 -0
  113. package/src/components/dashboard/top-customers-chart/locales/sk.ts +7 -0
  114. package/src/components/dashboard/top-customers-chart/locales/sl.ts +2 -0
  115. package/src/components/dashboard/top-customers-chart/locales/sv.ts +7 -0
  116. package/src/components/dashboard/top-customers-chart/top-customers-chart.tsx +23 -12
  117. package/src/components/delivery-notes/create/create-delivery-note-form.tsx +33 -20
  118. package/src/components/delivery-notes/list/list-table.tsx +22 -13
  119. package/src/components/delivery-notes/list/locales/de.ts +2 -0
  120. package/src/components/delivery-notes/list/locales/en.ts +1 -0
  121. package/src/components/delivery-notes/list/locales/es.ts +1 -0
  122. package/src/components/delivery-notes/list/locales/fr.ts +1 -0
  123. package/src/components/delivery-notes/list/locales/hr.ts +1 -0
  124. package/src/components/delivery-notes/list/locales/it.ts +1 -0
  125. package/src/components/delivery-notes/list/locales/nl.ts +1 -0
  126. package/src/components/delivery-notes/list/locales/pl.ts +1 -0
  127. package/src/components/delivery-notes/list/locales/pt.ts +1 -0
  128. package/src/components/delivery-notes/list/locales/sl.ts +1 -0
  129. package/src/components/delivery-notes/list/use-delivery-note-download.ts +1 -12
  130. package/src/components/documents/create/document-add-item-form.tsx +28 -16
  131. package/src/components/documents/create/document-add-item-tax-rate-field.tsx +12 -2
  132. package/src/components/documents/create/document-items-section.tsx +70 -39
  133. package/src/components/documents/create/document-recipient-section.tsx +10 -1
  134. package/src/components/documents/create/live-preview.tsx +113 -15
  135. package/src/components/documents/create/prepare-document-submission.ts +35 -16
  136. package/src/components/documents/create/use-document-customer-form.ts +14 -3
  137. package/src/components/documents/documents.hooks.ts +7 -2
  138. package/src/components/documents/shared/document-preview-display.tsx +136 -67
  139. package/src/components/documents/shared/scaled-document-preview.tsx +45 -5
  140. package/src/components/documents/view/document-actions-bar.tsx +284 -182
  141. package/src/components/documents/view/document-activities-list.tsx +3 -0
  142. package/src/components/documents/view/document-payments-list.tsx +3 -0
  143. package/src/components/documents/view/locales/de.ts +8 -0
  144. package/src/components/documents/view/locales/es.ts +8 -0
  145. package/src/components/documents/view/locales/fr.ts +8 -0
  146. package/src/components/documents/view/locales/hr.ts +8 -0
  147. package/src/components/documents/view/locales/it.ts +8 -0
  148. package/src/components/documents/view/locales/nl.ts +8 -0
  149. package/src/components/documents/view/locales/pl.ts +8 -0
  150. package/src/components/documents/view/locales/pt.ts +8 -0
  151. package/src/components/documents/view/locales/sl.ts +8 -0
  152. package/src/components/documents/view/use-document-download.ts +14 -25
  153. package/src/components/entities/create-entity-form.tsx +101 -16
  154. package/src/components/entities/entity-settings-form/entity-settings-form.tsx +10 -10
  155. package/src/components/entities/entity-settings-form/locales/de.ts +10 -0
  156. package/src/components/entities/entity-settings-form/locales/es.ts +10 -0
  157. package/src/components/entities/entity-settings-form/locales/fr.ts +10 -0
  158. package/src/components/entities/entity-settings-form/locales/hr.ts +10 -0
  159. package/src/components/entities/entity-settings-form/locales/it.ts +10 -0
  160. package/src/components/entities/entity-settings-form/locales/nl.ts +10 -0
  161. package/src/components/entities/entity-settings-form/locales/pl.ts +10 -0
  162. package/src/components/entities/entity-settings-form/locales/pt.ts +10 -0
  163. package/src/components/entities/entity-settings-form/locales/sl.ts +10 -0
  164. package/src/components/entities/fina-settings-form/fina-operator-required-dialog.tsx +3 -3
  165. package/src/components/entities/fina-settings-form/fina-settings-form.tsx +78 -124
  166. package/src/components/entities/fina-settings-form/sections/certificate-settings-section.tsx +8 -1
  167. package/src/components/entities/fina-settings-form/sections/premises-management-section.tsx +14 -2
  168. package/src/components/entities/fina-settings-form/sections/register-premise-dialog.tsx +7 -2
  169. package/src/components/entities/furs-settings-form/furs-settings-form.tsx +56 -130
  170. package/src/components/entities/furs-settings-form/sections/certificate-settings-section.tsx +8 -1
  171. package/src/components/entities/furs-settings-form/sections/enable-fiscalization-section.tsx +1 -0
  172. package/src/components/entities/furs-settings-form/sections/general-settings-section.tsx +15 -2
  173. package/src/components/entities/furs-settings-form/sections/premises-management-section.tsx +20 -3
  174. package/src/components/entities/furs-settings-form/sections/register-premise-dialog.tsx +38 -12
  175. package/src/components/entities/settings/defaults-settings-form.tsx +6 -6
  176. package/src/components/entities/settings/eslog-settings-form.tsx +13 -1
  177. package/src/components/entities/settings/pdf-template-selector/demo-invoice-data.ts +3 -22
  178. package/src/components/entities/shared/fiscalization-step-flow.ts +77 -0
  179. package/src/components/entities/shared/fiscalization-step-tabs.tsx +71 -0
  180. package/src/components/estimates/create/create-estimate-form.tsx +34 -21
  181. package/src/components/estimates/list/list-table.tsx +23 -14
  182. package/src/components/estimates/list/locales/de.ts +2 -0
  183. package/src/components/estimates/list/locales/en.ts +1 -0
  184. package/src/components/estimates/list/locales/es.ts +1 -0
  185. package/src/components/estimates/list/locales/fr.ts +1 -0
  186. package/src/components/estimates/list/locales/hr.ts +1 -0
  187. package/src/components/estimates/list/locales/it.ts +1 -0
  188. package/src/components/estimates/list/locales/nl.ts +1 -0
  189. package/src/components/estimates/list/locales/pl.ts +1 -0
  190. package/src/components/estimates/list/locales/pt.ts +1 -0
  191. package/src/components/estimates/list/locales/sl.ts +1 -0
  192. package/src/components/estimates/list/use-estimate-download.ts +1 -12
  193. package/src/components/export/document-export-form.tsx +33 -7
  194. package/src/components/export/sales-per-item-export-form.tsx +23 -7
  195. package/src/components/invoices/create/create-invoice-form.tsx +295 -329
  196. package/src/components/invoices/create/prepare-invoice-submission.ts +0 -8
  197. package/src/components/invoices/list/list-table.tsx +7 -4
  198. package/src/components/invoices/list/use-invoice-download.ts +1 -11
  199. package/src/components/invoices/send-email-dialog/locales/de.ts +20 -0
  200. package/src/components/invoices/send-email-dialog/locales/es.ts +20 -0
  201. package/src/components/invoices/send-email-dialog/locales/fr.ts +20 -0
  202. package/src/components/invoices/send-email-dialog/locales/hr.ts +20 -0
  203. package/src/components/invoices/send-email-dialog/locales/it.ts +20 -0
  204. package/src/components/invoices/send-email-dialog/locales/nl.ts +20 -0
  205. package/src/components/invoices/send-email-dialog/locales/pl.ts +20 -0
  206. package/src/components/invoices/send-email-dialog/locales/pt.ts +20 -0
  207. package/src/components/invoices/send-email-dialog/locales/sl.ts +20 -0
  208. package/src/components/invoices/send-email-dialog/send-email-dialog.tsx +77 -8
  209. package/src/components/invoices/view/eslog-info-display.tsx +17 -1
  210. package/src/components/invoices/view/fiscalization-status-card.tsx +7 -3
  211. package/src/components/items/item-combobox.tsx +26 -6
  212. package/src/components/items/item-list-table/item-list-table.tsx +5 -2
  213. package/src/components/payments/create-payment-form/index.ts +1 -0
  214. package/src/components/payments/list/list-table.tsx +14 -4
  215. package/src/components/recurring-invoices/list/list-table.tsx +7 -4
  216. package/src/components/request-logs/locales.ts +412 -0
  217. package/src/components/request-logs/request-log-detail.tsx +37 -21
  218. package/src/components/request-logs/request-log-list-table.tsx +57 -11
  219. package/src/components/table/data-table.tsx +5 -2
  220. package/src/components/table/date-cell.tsx +3 -1
  221. package/src/components/table/filter-bar.tsx +14 -2
  222. package/src/components/table/hooks/use-table-query.ts +1 -1
  223. package/src/components/table/locales.ts +1116 -0
  224. package/src/components/table/search-input.tsx +12 -3
  225. package/src/components/table/selection-toolbar.tsx +23 -6
  226. package/src/components/table/table-empty-state.tsx +43 -3
  227. package/src/components/table/table-no-results.tsx +3 -3
  228. package/src/components/table/table-pagination.tsx +4 -3
  229. package/src/components/table/types.ts +1 -0
  230. package/src/components/tax-reports/index.ts +1 -0
  231. package/src/components/tax-reports/kir-export-form.tsx +46 -8
  232. package/src/components/tax-reports/slovenia-tax-profile-step.tsx +191 -0
  233. package/src/components/tax-reports/slovenia-yearly-export-form.tsx +509 -0
  234. package/src/components/tax-reports/slovenia-yearly-review-step.tsx +253 -0
  235. package/src/components/tax-reports/slovenia-yearly-summary.tsx +19 -0
  236. package/src/components/taxes/tax-list-table/tax-list-table.tsx +3 -2
  237. package/src/components/ui/sidebar.tsx +3 -2
  238. package/src/components/ui/sticky-form-footer.tsx +7 -1
  239. package/src/components/webhook-logs/index.ts +6 -0
  240. package/src/components/webhook-logs/locales.ts +392 -0
  241. package/src/components/webhook-logs/webhook-delivery-detail.tsx +255 -0
  242. package/src/components/webhook-logs/webhook-delivery-list-table.tsx +278 -0
  243. package/src/components/wl-subscription/index.ts +1 -0
  244. package/src/components/wl-subscription/locked-feature.tsx +1 -0
  245. package/src/components/wl-subscription/paywall.tsx +193 -0
  246. package/src/components/wl-subscription/upgrade-modal.tsx +93 -29
  247. package/src/generate-schemas.ts +12 -7
  248. package/src/generated/schemas/customer.ts +2 -0
  249. package/src/generated/schemas/entity.ts +134 -0
  250. package/src/generated/schemas/exportsloveniayearlynormiranireport_body.ts +27 -0
  251. package/src/generated/schemas/index.ts +2 -0
  252. package/src/generated/schemas/me.ts +20 -1
  253. package/src/generated/schemas/renderadvanceinvoicepreview_body.ts +40 -34
  254. package/src/generated/schemas/rendercreditnotepreview_body.ts +42 -36
  255. package/src/generated/schemas/renderdeliverynotepreview_body.ts +23 -13
  256. package/src/generated/schemas/renderestimatepreview_body.ts +23 -13
  257. package/src/generated/schemas/renderinvoicepreview_body.ts +40 -34
  258. package/src/generated/schemas/sendemail_body.ts +44 -0
  259. package/src/generated/schemas/sloveniataxprofile.ts +42 -0
  260. package/src/generated/schemas/startpdfexport_body.ts +91 -1
  261. package/src/generated/schemas/webhook.ts +10 -0
  262. package/src/hooks/use-duplicate-document.ts +51 -13
  263. package/src/hooks/use-eslog-validation.ts +59 -0
  264. package/src/hooks/use-premise-selection.ts +186 -0
  265. package/src/lib/browser-cookies.ts +4 -4
  266. package/src/lib/date-fns-locale.ts +48 -0
  267. package/src/lib/fiscalization-options.ts +81 -0
  268. package/src/lib/locale.ts +38 -0
  269. package/src/lib/template-variables.tsx +1 -1
  270. package/src/lib/translation.ts +14 -3
  271. package/src/providers/entities-context.tsx +1 -0
  272. package/src/providers/entities-provider.tsx +102 -3
  273. package/src/providers/form-footer-context.tsx +37 -4
  274. package/src/providers/sdk-provider.tsx +7 -2
  275. package/src/providers/white-label-provider.tsx +4 -1
  276. package/src/providers/wl-subscription-provider.tsx +90 -3
@@ -5,17 +5,20 @@ import { Check, Copy } from "lucide-react";
5
5
  import { useState } from "react";
6
6
  import { Button } from "@/ui/components/ui/button";
7
7
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/ui/components/ui/tabs";
8
+ import { getDateFnsLocale } from "@/ui/lib/date-fns-locale";
8
9
  import { cn } from "../../lib/utils";
9
10
  import type { RequestLogResponse } from "./request-log-list-table";
10
11
 
11
- type TranslationFn = (key: string, fallback: string) => string;
12
+ type TranslationFn = (key: string) => string;
12
13
 
13
- const defaultT: TranslationFn = (_key, fallback) => fallback;
14
+ const defaultT: TranslationFn = (key) => key;
14
15
 
15
16
  export interface RequestLogDetailProps {
16
17
  log: RequestLogResponse;
17
- /** Translation function - defaults to returning fallback */
18
+ /** Translation function - defaults to identity */
18
19
  t?: TranslationFn;
20
+ /** Locale used for relative date formatting */
21
+ locale?: string;
19
22
  }
20
23
 
21
24
  /**
@@ -39,7 +42,7 @@ function unwrapResponseData(data: unknown): unknown {
39
42
  return data;
40
43
  }
41
44
 
42
- function JsonViewer({ data, label }: { data: unknown; label: string }) {
45
+ function JsonViewer({ data, noDataLabel, t }: { data: unknown; noDataLabel: string; t: TranslationFn }) {
43
46
  const [copied, setCopied] = useState(false);
44
47
  // Unwrap { text: "json" } format if present
45
48
  const unwrappedData = unwrapResponseData(data);
@@ -59,7 +62,7 @@ function JsonViewer({ data, label }: { data: unknown; label: string }) {
59
62
  ) {
60
63
  return (
61
64
  <div className="rounded-lg border bg-muted/30 p-4 text-center text-muted-foreground text-sm">
62
- No {label.toLowerCase()} data
65
+ {t(noDataLabel)}
63
66
  </div>
64
67
  );
65
68
  }
@@ -71,7 +74,7 @@ function JsonViewer({ data, label }: { data: unknown; label: string }) {
71
74
  size="sm"
72
75
  className="absolute top-2 right-2 h-8 w-8 p-0"
73
76
  onClick={handleCopy}
74
- title="Copy to clipboard"
77
+ title={t("Copy to clipboard")}
75
78
  >
76
79
  {copied ? <Check className="h-4 w-4 text-green-500" /> : <Copy className="h-4 w-4" />}
77
80
  </Button>
@@ -140,8 +143,9 @@ function JsonHighlight({ json }: { json: string }) {
140
143
  );
141
144
  }
142
145
 
143
- export function RequestLogDetail({ log, t = defaultT }: RequestLogDetailProps) {
146
+ export function RequestLogDetail({ log, t = defaultT, locale }: RequestLogDetailProps) {
144
147
  const createdAt = new Date(log.created_at);
148
+ const dateLocale = getDateFnsLocale(locale);
145
149
  const statusCode = log.res_status ? Number.parseInt(log.res_status, 10) : 0;
146
150
 
147
151
  let statusColor = "text-gray-500";
@@ -166,7 +170,7 @@ export function RequestLogDetail({ log, t = defaultT }: RequestLogDetailProps) {
166
170
  </span>
167
171
  <div className="text-muted-foreground text-sm">
168
172
  <time dateTime={log.created_at} title={format(createdAt, "PPpp")}>
169
- {formatDistanceToNow(createdAt, { addSuffix: true })}
173
+ {formatDistanceToNow(createdAt, { addSuffix: true, locale: dateLocale })}
170
174
  </time>
171
175
  <span className="mx-2">•</span>
172
176
  <span>{format(createdAt, "PPpp")}</span>
@@ -174,23 +178,29 @@ export function RequestLogDetail({ log, t = defaultT }: RequestLogDetailProps) {
174
178
  </div>
175
179
 
176
180
  {/* Metadata */}
177
- {(log.resource_type || log.resource_id || log.action) && (
181
+ {(log.client_name || log.resource_type || log.resource_id || log.action) && (
178
182
  <div className="flex flex-wrap gap-4 text-sm">
183
+ {log.client_name && (
184
+ <div>
185
+ <span className="text-muted-foreground">{t("Client")}:</span>{" "}
186
+ <code className="rounded bg-muted px-1.5 py-0.5 font-mono text-xs">{log.client_name}</code>
187
+ </div>
188
+ )}
179
189
  {log.resource_type && (
180
190
  <div>
181
- <span className="text-muted-foreground">{t("request-logs.detail.resource-type", "Resource")}:</span>{" "}
191
+ <span className="text-muted-foreground">{t("Resource")}:</span>{" "}
182
192
  <span className="font-medium">{log.resource_type}</span>
183
193
  </div>
184
194
  )}
185
195
  {log.resource_id && (
186
196
  <div>
187
- <span className="text-muted-foreground">{t("request-logs.detail.resource-id", "ID")}:</span>{" "}
197
+ <span className="text-muted-foreground">{t("ID")}:</span>{" "}
188
198
  <code className="rounded bg-muted px-1.5 py-0.5 font-mono text-xs">{log.resource_id}</code>
189
199
  </div>
190
200
  )}
191
201
  {log.action && (
192
202
  <div>
193
- <span className="text-muted-foreground">{t("request-logs.detail.action", "Action")}:</span>{" "}
203
+ <span className="text-muted-foreground">{t("Action")}:</span>{" "}
194
204
  <span className="font-medium">{log.action}</span>
195
205
  </div>
196
206
  )}
@@ -200,18 +210,18 @@ export function RequestLogDetail({ log, t = defaultT }: RequestLogDetailProps) {
200
210
  {/* Tabs for Request/Response/Headers */}
201
211
  <Tabs defaultValue="request" className="w-full">
202
212
  <TabsList className="grid w-full grid-cols-3">
203
- <TabsTrigger value="request">{t("request-logs.detail.request", "Request")}</TabsTrigger>
204
- <TabsTrigger value="response">{t("request-logs.detail.response", "Response")}</TabsTrigger>
205
- <TabsTrigger value="headers">{t("request-logs.detail.headers", "Headers")}</TabsTrigger>
213
+ <TabsTrigger value="request">{t("Request")}</TabsTrigger>
214
+ <TabsTrigger value="response">{t("Response")}</TabsTrigger>
215
+ <TabsTrigger value="headers">{t("Headers")}</TabsTrigger>
206
216
  </TabsList>
207
217
  <TabsContent value="request" className="mt-4">
208
- <JsonViewer data={log.req_body} label="Request body" />
218
+ <JsonViewer data={log.req_body} noDataLabel="No request body data" t={t} />
209
219
  </TabsContent>
210
220
  <TabsContent value="response" className="mt-4">
211
- <JsonViewer data={log.res_body} label="Response body" />
221
+ <JsonViewer data={log.res_body} noDataLabel="No response body data" t={t} />
212
222
  </TabsContent>
213
223
  <TabsContent value="headers" className="mt-4">
214
- <JsonViewer data={log.headers} label="Headers" />
224
+ <JsonViewer data={log.headers} noDataLabel="No headers data" t={t} />
215
225
  </TabsContent>
216
226
  </Tabs>
217
227
 
@@ -221,7 +231,7 @@ export function RequestLogDetail({ log, t = defaultT }: RequestLogDetailProps) {
221
231
  );
222
232
  }
223
233
 
224
- function RequestIdDisplay({ requestId, t }: { requestId: string; t: (key: string, fallback: string) => string }) {
234
+ function RequestIdDisplay({ requestId, t }: { requestId: string; t: TranslationFn }) {
225
235
  const [copied, setCopied] = useState(false);
226
236
 
227
237
  const handleCopy = async () => {
@@ -232,9 +242,15 @@ function RequestIdDisplay({ requestId, t }: { requestId: string; t: (key: string
232
242
 
233
243
  return (
234
244
  <div className="flex items-center gap-2 border-t pt-4 text-muted-foreground text-xs">
235
- <span>{t("request-logs.detail.request-id", "Request ID")}:</span>
245
+ <span>{t("Request ID")}:</span>
236
246
  <code className="font-mono">{requestId}</code>
237
- <Button variant="ghost" size="sm" className="h-6 w-6 p-0" onClick={handleCopy} title="Copy to clipboard">
247
+ <Button
248
+ variant="ghost"
249
+ size="sm"
250
+ className="h-6 w-6 p-0"
251
+ onClick={handleCopy}
252
+ title={t("Copy to clipboard")}
253
+ >
238
254
  {copied ? <Check className="h-3 w-3 text-green-500" /> : <Copy className="h-3 w-3" />}
239
255
  </Button>
240
256
  </div>
@@ -1,14 +1,21 @@
1
1
  "use client";
2
2
 
3
+ import { getClientHeaders } from "@spaceinvoices/js-sdk";
3
4
  import { formatDistanceToNow } from "date-fns";
4
5
  import { useCallback, useMemo } from "react";
6
+ import { Label } from "@/ui/components/ui/label";
7
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/ui/components/ui/select";
5
8
  import { Sheet, SheetContent, SheetHeader, SheetTitle } from "@/ui/components/ui/sheet";
6
9
  import { Tooltip, TooltipContent, TooltipTrigger } from "@/ui/components/ui/tooltip";
7
10
  import { AUTH_COOKIES } from "@/ui/lib/auth";
8
11
  import { getCookie } from "@/ui/lib/browser-cookies";
12
+ import { getDateFnsLocale } from "@/ui/lib/date-fns-locale";
13
+ import { createTranslation } from "@/ui/lib/translation";
9
14
  import { cn } from "@/ui/lib/utils";
10
15
  import { DataTable } from "../table/data-table";
16
+ import { withTableTranslations } from "../table/locales";
11
17
  import type { Column, FilterConfig, ListTableProps, TableQueryParams, TableQueryResponse } from "../table/types";
18
+ import translations from "./locales";
12
19
  import { RequestLogDetail } from "./request-log-detail";
13
20
 
14
21
  // Request log response type (internal endpoint, not in SDK)
@@ -22,6 +29,7 @@ export interface RequestLogResponse {
22
29
  resource_type: string | null;
23
30
  resource_id: string | null;
24
31
  action: string | null;
32
+ client_name: string | null;
25
33
  req_body: Record<string, unknown> | null;
26
34
  res_body: Record<string, unknown> | null;
27
35
  headers: Record<string, unknown> | null;
@@ -38,6 +46,7 @@ const getApiBaseUrl = () => {
38
46
  };
39
47
 
40
48
  export const REQUEST_LOGS_CACHE_KEY = "request-logs";
49
+ const mergedTranslations = withTableTranslations(translations);
41
50
 
42
51
  const METHOD_COLORS: Record<string, string> = {
43
52
  GET: "bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300",
@@ -82,6 +91,10 @@ type RequestLogListTableProps = ListTableProps<RequestLogResponse> & {
82
91
  selectedLog?: RequestLogResponse | null;
83
92
  /** Callback when a log is selected */
84
93
  onSelectLog?: (log: RequestLogResponse | null) => void;
94
+ /** Translation function */
95
+ t?: (key: string) => string;
96
+ /** Locale used for relative date formatting */
97
+ locale?: string;
85
98
  };
86
99
 
87
100
  export function RequestLogListTable({
@@ -92,7 +105,11 @@ export function RequestLogListTable({
92
105
  showEntityColumn = false,
93
106
  selectedLog,
94
107
  onSelectLog,
108
+ t = (key) => key,
109
+ locale,
95
110
  }: RequestLogListTableProps) {
111
+ const translate = createTranslation({ t, locale, translations: mergedTranslations });
112
+
96
113
  // Custom fetch function that handles both entity-scoped and account-scoped queries
97
114
  // Don't use useTableFetch since we need special handling for environment
98
115
  const handleFetch = useCallback(
@@ -124,6 +141,7 @@ export function RequestLogListTable({
124
141
 
125
142
  // HTTP status code filter
126
143
  if (params.filter_http_status) queryParamsUrl.set("status", params.filter_http_status);
144
+ if (params.filter_client_name) queryParamsUrl.set("client_name", params.filter_client_name);
127
145
 
128
146
  // Date filters
129
147
  if (params.filter_date_from) queryParamsUrl.set("date_from", params.filter_date_from);
@@ -133,6 +151,7 @@ export function RequestLogListTable({
133
151
  const response = await fetch(`${apiBaseUrl}/request-logs?${queryParamsUrl.toString()}`, {
134
152
  headers: {
135
153
  Authorization: `Bearer ${token}`,
154
+ ...getClientHeaders("ui"),
136
155
  "Content-Type": "application/json",
137
156
  },
138
157
  });
@@ -147,6 +166,7 @@ export function RequestLogListTable({
147
166
  );
148
167
 
149
168
  const columns: Column<RequestLogResponse>[] = useMemo(() => {
169
+ const dateLocale = getDateFnsLocale(locale);
150
170
  const cols: Column<RequestLogResponse>[] = [
151
171
  {
152
172
  id: "status_dot",
@@ -156,19 +176,19 @@ export function RequestLogListTable({
156
176
  },
157
177
  {
158
178
  id: "res_status",
159
- header: "Status",
179
+ header: translate("Status"),
160
180
  className: "w-16",
161
181
  cell: (log) => <span className="font-mono text-muted-foreground text-sm">{log.res_status || "—"}</span>,
162
182
  },
163
183
  {
164
184
  id: "method",
165
- header: "Method",
185
+ header: translate("Method"),
166
186
  className: "w-20",
167
187
  cell: (log) => <MethodBadge method={log.method} />,
168
188
  },
169
189
  {
170
190
  id: "path",
171
- header: "Path",
191
+ header: translate("Path"),
172
192
  cell: (log) => <span className="truncate font-mono text-sm">{log.path}</span>,
173
193
  },
174
194
  ];
@@ -176,7 +196,7 @@ export function RequestLogListTable({
176
196
  if (showEntityColumn) {
177
197
  cols.push({
178
198
  id: "entity_id",
179
- header: "Entity",
199
+ header: translate("Entity"),
180
200
  className: "hidden md:table-cell",
181
201
  cell: (log) => (
182
202
  <Tooltip>
@@ -192,14 +212,14 @@ export function RequestLogListTable({
192
212
  {log.entity_id}
193
213
  </button>
194
214
  </TooltipTrigger>
195
- <TooltipContent>Copy</TooltipContent>
215
+ <TooltipContent>{translate("Copy")}</TooltipContent>
196
216
  </Tooltip>
197
217
  ),
198
218
  });
199
219
  } else {
200
220
  cols.push({
201
221
  id: "resource_id",
202
- header: "Resource",
222
+ header: translate("Resource"),
203
223
  className: "hidden sm:table-cell",
204
224
  cell: (log) => <span className="text-muted-foreground text-xs">{log.resource_id || "—"}</span>,
205
225
  });
@@ -207,20 +227,20 @@ export function RequestLogListTable({
207
227
 
208
228
  cols.push({
209
229
  id: "created_at",
210
- header: "Time",
230
+ header: translate("Time"),
211
231
  align: "right",
212
232
  cell: (log) => (
213
233
  <span className="text-muted-foreground text-xs">
214
- {formatDistanceToNow(new Date(log.created_at), { addSuffix: true })}
234
+ {formatDistanceToNow(new Date(log.created_at), { addSuffix: true, locale: dateLocale })}
215
235
  </span>
216
236
  ),
217
237
  });
218
238
 
219
239
  return cols;
220
- }, [showEntityColumn]);
240
+ }, [locale, showEntityColumn, translate]);
221
241
 
222
242
  const filterConfig: FilterConfig = {
223
- dateFields: [{ id: "created_at", label: "Date" }],
243
+ dateFields: [{ id: "created_at", label: translate("Date") }],
224
244
  httpMethodFilter: true,
225
245
  httpStatusCodeFilter: true,
226
246
  };
@@ -231,6 +251,31 @@ export function RequestLogListTable({
231
251
 
232
252
  return (
233
253
  <>
254
+ <div className="space-y-2">
255
+ <Label htmlFor="request-log-client-filter">{translate("Client")}</Label>
256
+ <Select
257
+ value={queryParams?.filter_client_name ?? "all"}
258
+ onValueChange={(value) =>
259
+ onChangeParams?.({
260
+ ...queryParams,
261
+ filter_client_name: !value || value === "all" ? undefined : value,
262
+ prev_cursor: undefined,
263
+ next_cursor: undefined,
264
+ })
265
+ }
266
+ >
267
+ <SelectTrigger id="request-log-client-filter" className="w-full sm:w-56">
268
+ <SelectValue placeholder={translate("All clients")} />
269
+ </SelectTrigger>
270
+ <SelectContent>
271
+ <SelectItem value="all">{translate("All clients")}</SelectItem>
272
+ <SelectItem value="web">web</SelectItem>
273
+ <SelectItem value="ui">ui</SelectItem>
274
+ <SelectItem value="mobile">mobile</SelectItem>
275
+ <SelectItem value="js-sdk">js-sdk</SelectItem>
276
+ </SelectContent>
277
+ </Select>
278
+ </div>
234
279
  <DataTable
235
280
  columns={columns}
236
281
  cacheKey={cacheKey}
@@ -241,6 +286,7 @@ export function RequestLogListTable({
241
286
  entityId={entityId}
242
287
  filterConfig={filterConfig}
243
288
  onRowClick={(log) => onSelectLog?.(log)}
289
+ t={translate}
244
290
  />
245
291
 
246
292
  <Sheet open={!!selectedLog} onOpenChange={(open) => !open && onSelectLog?.(null)}>
@@ -255,7 +301,7 @@ export function RequestLogListTable({
255
301
  )}
256
302
  </SheetTitle>
257
303
  </SheetHeader>
258
- {selectedLog && <RequestLogDetail log={selectedLog} />}
304
+ {selectedLog && <RequestLogDetail log={selectedLog} t={translate} locale={locale} />}
259
305
  </SheetContent>
260
306
  </Sheet>
261
307
  </>
@@ -89,7 +89,8 @@ export function DataTable<T extends { id: string }>({
89
89
  queryParams?.filter_date_to ||
90
90
  queryParams?.filter_status ||
91
91
  queryParams?.filter_method ||
92
- queryParams?.filter_http_status,
92
+ queryParams?.filter_http_status ||
93
+ queryParams?.filter_client_name,
93
94
  );
94
95
  const [filterPanelOpen, setFilterPanelOpen] = useState(hasInitialFilters);
95
96
 
@@ -115,7 +116,8 @@ export function DataTable<T extends { id: string }>({
115
116
  params.filter_date_to ||
116
117
  params.filter_status ||
117
118
  params.filter_method ||
118
- params.filter_http_status,
119
+ params.filter_http_status ||
120
+ params.filter_client_name,
119
121
  );
120
122
 
121
123
  // Combined clear handler for both search and filters
@@ -261,6 +263,7 @@ export function DataTable<T extends { id: string }>({
261
263
  prevCursor={queryResult?.pagination.prev_cursor}
262
264
  nextCursor={queryResult?.pagination.next_cursor}
263
265
  onPageChange={handlePageChange}
266
+ t={t}
264
267
  />
265
268
  </div>
266
269
  </div>
@@ -1,6 +1,7 @@
1
1
  type FormattedDateProps = {
2
2
  date: string | number | Date | null | undefined;
3
3
  format?: Intl.DateTimeFormatOptions;
4
+ locale?: string;
4
5
  };
5
6
 
6
7
  /**
@@ -13,6 +14,7 @@ export function FormattedDate({
13
14
  month: "short",
14
15
  day: "numeric",
15
16
  },
17
+ locale,
16
18
  }: FormattedDateProps) {
17
19
  if (!date) {
18
20
  return <span className="text-muted-foreground">—</span>;
@@ -27,7 +29,7 @@ export function FormattedDate({
27
29
  return <span className="text-destructive">{String(date)}</span>;
28
30
  }
29
31
 
30
- return <>{dateObj.toLocaleDateString(undefined, format)}</>;
32
+ return <>{dateObj.toLocaleDateString(locale, format)}</>;
31
33
  } catch (error) {
32
34
  console.error("Error formatting date:", error);
33
35
  return <span className="text-destructive">{String(date)}</span>;
@@ -54,7 +54,13 @@ export function FilterBar({
54
54
  // No filters configured, just show search
55
55
  return (
56
56
  <div className="px-4 pt-4">
57
- <SearchInput initialValue={searchValue} onSearch={onSearch} placeholder={t("Search...")} />
57
+ <SearchInput
58
+ initialValue={searchValue}
59
+ onSearch={onSearch}
60
+ placeholder={t("Search...")}
61
+ ariaLabel={t("Search")}
62
+ clearAriaLabel={t("Clear search")}
63
+ />
58
64
  </div>
59
65
  );
60
66
  }
@@ -62,7 +68,13 @@ export function FilterBar({
62
68
  return (
63
69
  <Collapsible open={isOpen} onOpenChange={onToggle} className="px-4 pt-4">
64
70
  <div className="flex items-center gap-2">
65
- <SearchInput initialValue={searchValue} onSearch={onSearch} placeholder={t("Search...")} />
71
+ <SearchInput
72
+ initialValue={searchValue}
73
+ onSearch={onSearch}
74
+ placeholder={t("Search...")}
75
+ ariaLabel={t("Search")}
76
+ clearAriaLabel={t("Clear search")}
77
+ />
66
78
  <CollapsibleTrigger asChild>
67
79
  <Button variant="outline" size="sm" className="h-8 gap-1.5">
68
80
  <FilterIcon className="h-3.5 w-3.5" />
@@ -28,7 +28,7 @@ export function useTableQuery<T>({ cacheKey, fetchFn, params, entityId, enabled
28
28
  queryKey,
29
29
  queryFn: () => fetchFn({ ...params, entity_id: entityId }),
30
30
  staleTime: 1000 * 60 * 2, // Data is fresh for 2 minutes (unless invalidated)
31
- gcTime: 1000 * 60 * 30, // Keep in cache for 30 minutes
31
+ gcTime: 1000 * 60 * 10, // Keep table variants around for a short session without retaining them all day
32
32
  refetchOnMount: true, // Refetch when mounting if data is stale (including when invalidated)
33
33
  refetchOnWindowFocus: false, // Don't refetch on window focus
34
34
  refetchOnReconnect: true, // Refetch on reconnect