@spaceinvoices/react-ui 0.4.3 → 0.4.4

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 (218) hide show
  1. package/cli/dist/index.js +1 -1
  2. package/package.json +1 -1
  3. package/src/common/autocomplete.tsx +18 -2
  4. package/src/components/advance-invoices/create/create-advance-invoice-form.tsx +0 -1
  5. package/src/components/advance-invoices/create/locales/de.ts +2 -0
  6. package/src/components/advance-invoices/create/locales/es.ts +2 -0
  7. package/src/components/advance-invoices/create/locales/fr.ts +2 -0
  8. package/src/components/advance-invoices/create/locales/hr.ts +1 -0
  9. package/src/components/advance-invoices/create/locales/it.ts +2 -0
  10. package/src/components/advance-invoices/create/locales/nl.ts +2 -0
  11. package/src/components/advance-invoices/create/locales/pl.ts +1 -0
  12. package/src/components/advance-invoices/create/locales/pt.ts +1 -0
  13. package/src/components/advance-invoices/create/locales/sl.ts +1 -0
  14. package/src/components/advance-invoices/create/prepare-advance-invoice-submission.ts +0 -1
  15. package/src/components/advance-invoices/list/list-table.tsx +80 -50
  16. package/src/components/advance-invoices/list/locales/de.ts +5 -0
  17. package/src/components/advance-invoices/list/locales/en.ts +4 -0
  18. package/src/components/advance-invoices/list/locales/es.ts +5 -0
  19. package/src/components/advance-invoices/list/locales/fr.ts +5 -0
  20. package/src/components/advance-invoices/list/locales/hr.ts +5 -0
  21. package/src/components/advance-invoices/list/locales/it.ts +5 -0
  22. package/src/components/advance-invoices/list/locales/nl.ts +5 -0
  23. package/src/components/advance-invoices/list/locales/pl.ts +5 -0
  24. package/src/components/advance-invoices/list/locales/pt.ts +5 -0
  25. package/src/components/advance-invoices/list/locales/sl.ts +5 -0
  26. package/src/components/credit-notes/create/create-credit-note-form.tsx +114 -3
  27. package/src/components/credit-notes/create/locales/de.ts +2 -0
  28. package/src/components/credit-notes/create/locales/es.ts +2 -0
  29. package/src/components/credit-notes/create/locales/fr.ts +2 -0
  30. package/src/components/credit-notes/create/locales/hr.ts +1 -0
  31. package/src/components/credit-notes/create/locales/it.ts +2 -0
  32. package/src/components/credit-notes/create/locales/nl.ts +2 -0
  33. package/src/components/credit-notes/create/locales/pl.ts +1 -0
  34. package/src/components/credit-notes/create/locales/pt.ts +1 -0
  35. package/src/components/credit-notes/create/locales/sl.ts +1 -0
  36. package/src/components/credit-notes/credit-notes.hooks.ts +30 -0
  37. package/src/components/credit-notes/list/list-table.tsx +77 -30
  38. package/src/components/credit-notes/list/locales/de.ts +5 -0
  39. package/src/components/credit-notes/list/locales/en.ts +4 -0
  40. package/src/components/credit-notes/list/locales/es.ts +5 -0
  41. package/src/components/credit-notes/list/locales/fr.ts +5 -0
  42. package/src/components/credit-notes/list/locales/hr.ts +5 -0
  43. package/src/components/credit-notes/list/locales/it.ts +5 -0
  44. package/src/components/credit-notes/list/locales/nl.ts +5 -0
  45. package/src/components/credit-notes/list/locales/pl.ts +5 -0
  46. package/src/components/credit-notes/list/locales/pt.ts +5 -0
  47. package/src/components/credit-notes/list/locales/sl.ts +5 -0
  48. package/src/components/customers/customer-list-table/customer-list-table.tsx +0 -3
  49. package/src/components/customers/customer-list-table/locales/de.ts +1 -0
  50. package/src/components/customers/customer-list-table/locales/es.ts +1 -0
  51. package/src/components/customers/customer-list-table/locales/fr.ts +1 -0
  52. package/src/components/customers/customer-list-table/locales/hr.ts +1 -0
  53. package/src/components/customers/customer-list-table/locales/it.ts +1 -0
  54. package/src/components/customers/customer-list-table/locales/nl.ts +1 -0
  55. package/src/components/customers/customer-list-table/locales/pl.ts +1 -0
  56. package/src/components/customers/customer-list-table/locales/pt.ts +1 -0
  57. package/src/components/customers/customer-list-table/locales/sl.ts +1 -0
  58. package/src/components/delivery-notes/list/list-row-actions.tsx +20 -1
  59. package/src/components/delivery-notes/list/list-table.tsx +41 -8
  60. package/src/components/delivery-notes/list/locales/de.ts +4 -0
  61. package/src/components/delivery-notes/list/locales/en.ts +2 -0
  62. package/src/components/delivery-notes/list/locales/es.ts +4 -0
  63. package/src/components/delivery-notes/list/locales/fr.ts +4 -0
  64. package/src/components/delivery-notes/list/locales/hr.ts +4 -0
  65. package/src/components/delivery-notes/list/locales/it.ts +4 -0
  66. package/src/components/delivery-notes/list/locales/nl.ts +4 -0
  67. package/src/components/delivery-notes/list/locales/pl.ts +4 -0
  68. package/src/components/delivery-notes/list/locales/pt.ts +4 -0
  69. package/src/components/delivery-notes/list/locales/sl.ts +4 -0
  70. package/src/components/documents/create/document-details-section.tsx +41 -27
  71. package/src/components/documents/create/linked-documents-info.tsx +82 -0
  72. package/src/components/documents/create/live-preview.tsx +1 -1
  73. package/src/components/documents/types.ts +2 -2
  74. package/src/components/documents/view/document-activities-list.tsx +65 -47
  75. package/src/components/documents/view/document-details-card.tsx +99 -74
  76. package/src/components/documents/view/document-payments-list.tsx +99 -65
  77. package/src/components/documents/view/document-relations-list.tsx +43 -28
  78. package/src/components/documents/view/document-sidebar.tsx +151 -0
  79. package/src/components/documents/view/index.ts +2 -0
  80. package/src/components/documents/view/locales/de.ts +2 -0
  81. package/src/components/documents/view/locales/es.ts +2 -0
  82. package/src/components/documents/view/locales/fr.ts +2 -0
  83. package/src/components/documents/view/locales/hr.ts +2 -0
  84. package/src/components/documents/view/locales/it.ts +2 -0
  85. package/src/components/documents/view/locales/nl.ts +2 -0
  86. package/src/components/documents/view/locales/pl.ts +2 -0
  87. package/src/components/documents/view/locales/pt.ts +2 -0
  88. package/src/components/documents/view/locales/sl.ts +2 -0
  89. package/src/components/documents/view/use-document-download.ts +3 -2
  90. package/src/components/entities/create-entity-form.tsx +165 -13
  91. package/src/components/entities/entity-settings-form/entity-settings-form.tsx +101 -1
  92. package/src/components/entities/entity-settings-form/locales/de.ts +9 -0
  93. package/src/components/entities/entity-settings-form/locales/es.ts +9 -0
  94. package/src/components/entities/entity-settings-form/locales/fr.ts +9 -0
  95. package/src/components/entities/entity-settings-form/locales/hr.ts +9 -0
  96. package/src/components/entities/entity-settings-form/locales/it.ts +9 -0
  97. package/src/components/entities/entity-settings-form/locales/nl.ts +9 -0
  98. package/src/components/entities/entity-settings-form/locales/pl.ts +9 -0
  99. package/src/components/entities/entity-settings-form/locales/pt.ts +9 -0
  100. package/src/components/entities/entity-settings-form/locales/sl.ts +9 -0
  101. package/src/components/entities/fina-settings-form/fina-settings-form.tsx +6 -6
  102. package/src/components/entities/fina-settings-form/locales/de.ts +2 -2
  103. package/src/components/entities/fina-settings-form/locales/en.ts +2 -2
  104. package/src/components/entities/fina-settings-form/locales/es.ts +2 -2
  105. package/src/components/entities/fina-settings-form/locales/fr.ts +2 -2
  106. package/src/components/entities/fina-settings-form/locales/hr.ts +2 -2
  107. package/src/components/entities/fina-settings-form/locales/it.ts +2 -2
  108. package/src/components/entities/fina-settings-form/locales/nl.ts +2 -2
  109. package/src/components/entities/fina-settings-form/locales/pl.ts +2 -2
  110. package/src/components/entities/fina-settings-form/locales/pt.ts +2 -2
  111. package/src/components/entities/fina-settings-form/locales/sl.ts +2 -2
  112. package/src/components/entities/furs-settings-form/locales/en.ts +0 -1
  113. package/src/components/entities/settings/pdf-template-selector/locales/de.ts +3 -1
  114. package/src/components/entities/settings/pdf-template-selector/locales/es.ts +3 -1
  115. package/src/components/entities/settings/pdf-template-selector/locales/fr.ts +4 -1
  116. package/src/components/entities/settings/pdf-template-selector/locales/hr.ts +4 -1
  117. package/src/components/entities/settings/pdf-template-selector/locales/it.ts +3 -1
  118. package/src/components/entities/settings/pdf-template-selector/locales/nl.ts +3 -1
  119. package/src/components/entities/settings/pdf-template-selector/locales/pl.ts +3 -1
  120. package/src/components/entities/settings/pdf-template-selector/locales/pt.ts +3 -1
  121. package/src/components/entities/settings/pdf-template-selector/locales/sl.ts +3 -1
  122. package/src/components/entities/settings/pdf-template-selector/pdf-template-cards.tsx +1 -0
  123. package/src/components/estimates/create/create-estimate-form.tsx +29 -2
  124. package/src/components/estimates/list/list-table.tsx +3 -6
  125. package/src/components/estimates/list/locales/de.ts +1 -0
  126. package/src/components/estimates/list/locales/es.ts +1 -0
  127. package/src/components/estimates/list/locales/fr.ts +1 -0
  128. package/src/components/estimates/list/locales/hr.ts +1 -0
  129. package/src/components/estimates/list/locales/it.ts +1 -0
  130. package/src/components/estimates/list/locales/nl.ts +1 -0
  131. package/src/components/estimates/list/locales/pl.ts +1 -0
  132. package/src/components/estimates/list/locales/pt.ts +1 -0
  133. package/src/components/estimates/list/locales/sl.ts +1 -0
  134. package/src/components/export/document-export-form.tsx +9 -2
  135. package/src/components/export/index.ts +2 -0
  136. package/src/components/export/sales-per-item-export-form.tsx +223 -0
  137. package/src/components/invoices/create/create-invoice-form.tsx +48 -1
  138. package/src/components/invoices/create/locales/de.ts +11 -0
  139. package/src/components/invoices/create/locales/es.ts +11 -0
  140. package/src/components/invoices/create/locales/fr.ts +11 -0
  141. package/src/components/invoices/create/locales/hr.ts +10 -0
  142. package/src/components/invoices/create/locales/it.ts +11 -0
  143. package/src/components/invoices/create/locales/nl.ts +11 -0
  144. package/src/components/invoices/create/locales/pl.ts +10 -0
  145. package/src/components/invoices/create/locales/pt.ts +10 -0
  146. package/src/components/invoices/create/locales/sl.ts +10 -0
  147. package/src/components/invoices/invoices-furs.hooks.ts +4 -1
  148. package/src/components/invoices/list/list-table.tsx +77 -31
  149. package/src/components/invoices/list/locales/de.ts +5 -0
  150. package/src/components/invoices/list/locales/en.ts +4 -0
  151. package/src/components/invoices/list/locales/es.ts +5 -0
  152. package/src/components/invoices/list/locales/fr.ts +5 -0
  153. package/src/components/invoices/list/locales/hr.ts +5 -0
  154. package/src/components/invoices/list/locales/it.ts +5 -0
  155. package/src/components/invoices/list/locales/nl.ts +5 -0
  156. package/src/components/invoices/list/locales/pl.ts +5 -0
  157. package/src/components/invoices/list/locales/pt.ts +5 -0
  158. package/src/components/invoices/list/locales/sl.ts +5 -0
  159. package/src/components/invoices/view/fiscalization-status-card.tsx +42 -24
  160. package/src/components/items/item-combobox.tsx +5 -3
  161. package/src/components/items/item-list-table/item-list-header.tsx +4 -17
  162. package/src/components/items/item-list-table/item-list-table.tsx +3 -3
  163. package/src/components/items/item-list-table/locales/de.ts +1 -0
  164. package/src/components/items/item-list-table/locales/es.ts +1 -0
  165. package/src/components/items/item-list-table/locales/fr.ts +1 -0
  166. package/src/components/items/item-list-table/locales/hr.ts +1 -0
  167. package/src/components/items/item-list-table/locales/it.ts +1 -0
  168. package/src/components/items/item-list-table/locales/nl.ts +1 -0
  169. package/src/components/items/item-list-table/locales/pl.ts +1 -0
  170. package/src/components/items/item-list-table/locales/pt.ts +1 -0
  171. package/src/components/items/item-list-table/locales/sl.ts +1 -0
  172. package/src/components/payments/list/list-table.tsx +0 -4
  173. package/src/components/payments/list/locales/de.ts +1 -0
  174. package/src/components/payments/list/locales/es.ts +1 -0
  175. package/src/components/payments/list/locales/fr.ts +1 -0
  176. package/src/components/payments/list/locales/hr.ts +1 -0
  177. package/src/components/payments/list/locales/it.ts +1 -0
  178. package/src/components/payments/list/locales/nl.ts +1 -0
  179. package/src/components/payments/list/locales/pl.ts +1 -0
  180. package/src/components/payments/list/locales/pt.ts +1 -0
  181. package/src/components/payments/list/locales/sl.ts +1 -0
  182. package/src/components/recurring-invoices/list/list-table.tsx +0 -7
  183. package/src/components/recurring-invoices/list/locales/de.ts +1 -0
  184. package/src/components/recurring-invoices/list/locales/es.ts +1 -0
  185. package/src/components/recurring-invoices/list/locales/fr.ts +1 -0
  186. package/src/components/recurring-invoices/list/locales/hr.ts +1 -0
  187. package/src/components/recurring-invoices/list/locales/it.ts +1 -0
  188. package/src/components/recurring-invoices/list/locales/nl.ts +1 -0
  189. package/src/components/recurring-invoices/list/locales/pl.ts +1 -0
  190. package/src/components/recurring-invoices/list/locales/pt.ts +1 -0
  191. package/src/components/recurring-invoices/list/locales/sl.ts +1 -0
  192. package/src/components/request-logs/request-log-list-table.tsx +0 -3
  193. package/src/components/table/README.md +14 -121
  194. package/src/components/table/data-table.tsx +22 -37
  195. package/src/components/table/hooks/use-table-state.ts +3 -27
  196. package/src/components/table/index.ts +0 -2
  197. package/src/components/table/selection-toolbar.tsx +35 -1
  198. package/src/components/table/table-empty-state.tsx +6 -3
  199. package/src/components/table/table-no-results.tsx +10 -5
  200. package/src/components/table/types.ts +0 -5
  201. package/src/components/taxes/tax-list-table/locales/de.ts +1 -0
  202. package/src/components/taxes/tax-list-table/locales/es.ts +1 -0
  203. package/src/components/taxes/tax-list-table/locales/fr.ts +1 -0
  204. package/src/components/taxes/tax-list-table/locales/hr.ts +1 -0
  205. package/src/components/taxes/tax-list-table/locales/it.ts +1 -0
  206. package/src/components/taxes/tax-list-table/locales/nl.ts +1 -0
  207. package/src/components/taxes/tax-list-table/locales/pl.ts +1 -0
  208. package/src/components/taxes/tax-list-table/locales/pt.ts +1 -0
  209. package/src/components/taxes/tax-list-table/locales/sl.ts +1 -0
  210. package/src/components/taxes/tax-list-table/tax-list-header.tsx +3 -14
  211. package/src/components/taxes/tax-list-table/tax-list-table.tsx +3 -3
  212. package/src/components/ui/popover.tsx +3 -1
  213. package/src/components/ui/tooltip.tsx +3 -1
  214. package/src/generated/schemas/index.ts +1 -1
  215. package/src/hooks/use-duplicate-document.ts +40 -5
  216. package/src/lib/fiscalization.ts +12 -0
  217. package/src/lib/schemas/advance-invoice.ts +0 -1
  218. package/src/components/table/sortable-header.tsx +0 -56
@@ -6,7 +6,6 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@
6
6
  import { FilterBar } from "./filter-bar";
7
7
  import { useTableQuery } from "./hooks/use-table-query";
8
8
  import { useTableState } from "./hooks/use-table-state";
9
- import { SortableHeader } from "./sortable-header";
10
9
  import { TableEmptyState } from "./table-empty-state";
11
10
  import { TableNoResults } from "./table-no-results";
12
11
  import { Pagination } from "./table-pagination";
@@ -22,8 +21,6 @@ export type DataTableProps<T> = {
22
21
  onFetch: (params: TableQueryParams) => Promise<TableQueryResponse<T>>;
23
22
  /** Resource name for empty states (e.g., "customer", "invoice") */
24
23
  resourceName: string;
25
- /** Default sort order (e.g., "-id", "name") */
26
- defaultOrderBy?: string;
27
24
  /** Initial/external query parameters */
28
25
  queryParams?: TableQueryParams;
29
26
  /** Callback when params change (for external state management) */
@@ -36,12 +33,14 @@ export type DataTableProps<T> = {
36
33
  createNewLink?: string;
37
34
  /** Custom trigger for create action */
38
35
  createNewTrigger?: ReactNode;
36
+ /** Callback for "Create new" click — enables client-side navigation instead of full page reload */
37
+ onCreateNew?: () => void;
39
38
  /** Optional row click handler */
40
39
  onRowClick?: (item: T) => void;
41
40
  /** Custom row renderer (overrides default cell rendering) */
42
41
  renderRow?: (item: T) => ReactNode;
43
42
  /** Custom header renderer (overrides default header) */
44
- renderHeader?: (props: { orderBy?: string; onSort?: (order: string | null) => void }) => ReactNode;
43
+ renderHeader?: () => ReactNode;
45
44
  /** Filter configuration (date fields, status filter) */
46
45
  filterConfig?: FilterConfig;
47
46
  /** Translation function */
@@ -55,7 +54,7 @@ export type DataTableProps<T> = {
55
54
  /** Callback when selection changes */
56
55
  onSelectionChange?: (selectedIds: Set<string>) => void;
57
56
  /** Content to render in selection toolbar (shown when items selected) */
58
- selectionToolbar?: (selectedCount: number) => ReactNode;
57
+ selectionToolbar?: (selectedCount: number, data: T[]) => ReactNode;
59
58
  };
60
59
 
61
60
  /**
@@ -66,13 +65,13 @@ export function DataTable<T extends { id: string }>({
66
65
  cacheKey,
67
66
  onFetch,
68
67
  resourceName,
69
- defaultOrderBy = "-id",
70
68
  queryParams,
71
69
  onChangeParams,
72
70
  disableUrlSync,
73
71
  entityId,
74
72
  createNewLink,
75
73
  createNewTrigger,
74
+ onCreateNew,
76
75
  onRowClick,
77
76
  renderRow,
78
77
  renderHeader,
@@ -94,14 +93,12 @@ export function DataTable<T extends { id: string }>({
94
93
  );
95
94
  const [filterPanelOpen, setFilterPanelOpen] = useState(hasInitialFilters);
96
95
 
97
- // Manage table state (sort, search, pagination, filters)
98
- const { params, apiParams, filterState, handleSort, handleSearch, handlePageChange, handleFilterChange } =
99
- useTableState({
100
- initialParams: queryParams,
101
- defaultOrderBy,
102
- onChangeParams,
103
- disableUrlSync,
104
- });
96
+ // Manage table state (search, pagination, filters)
97
+ const { params, apiParams, filterState, handleSearch, handlePageChange, handleFilterChange } = useTableState({
98
+ initialParams: queryParams,
99
+ onChangeParams,
100
+ disableUrlSync,
101
+ });
105
102
 
106
103
  // Fetch table data (use apiParams which has the query JSON for API)
107
104
  const { data: queryResult, isFetching } = useTableQuery<T>({
@@ -121,6 +118,12 @@ export function DataTable<T extends { id: string }>({
121
118
  params.filter_http_status,
122
119
  );
123
120
 
121
+ // Combined clear handler for both search and filters
122
+ const handleClearAll = useCallback(() => {
123
+ handleSearch(null);
124
+ handleFilterChange(null);
125
+ }, [handleSearch, handleFilterChange]);
126
+
124
127
  // Selection helpers
125
128
  const pageIds = useMemo(() => data.map((item) => item.id), [data]);
126
129
  const selectedCount = selectedIds?.size ?? 0;
@@ -186,6 +189,7 @@ export function DataTable<T extends { id: string }>({
186
189
  resource={resourceName}
187
190
  createNewLink={createNewLink}
188
191
  createNewTrigger={createNewTrigger}
192
+ onCreateNew={onCreateNew}
189
193
  t={t}
190
194
  />
191
195
  );
@@ -207,19 +211,17 @@ export function DataTable<T extends { id: string }>({
207
211
 
208
212
  {selectable && selectedCount > 0 && selectionToolbar && (
209
213
  <div className="flex items-center gap-3 rounded-lg border bg-muted/50 px-4 py-2">
210
- {selectionToolbar(selectedCount)}
214
+ {selectionToolbar(selectedCount, data)}
211
215
  </div>
212
216
  )}
213
217
 
214
218
  <div className="rounded-lg border">
215
219
  <Table>
216
220
  {renderHeader ? (
217
- renderHeader({ orderBy: params.order_by, onSort: handleSort })
221
+ renderHeader()
218
222
  ) : (
219
223
  <DefaultTableHeader
220
224
  columns={columns}
221
- orderBy={params.order_by}
222
- onSort={handleSort}
223
225
  selectable={selectable}
224
226
  allPageSelected={allPageSelected}
225
227
  somePageSelected={somePageSelected}
@@ -249,7 +251,7 @@ export function DataTable<T extends { id: string }>({
249
251
  );
250
252
  })
251
253
  ) : (
252
- <TableNoResults resource={resourceName} search={handleSearch} t={t} />
254
+ <TableNoResults resource={resourceName} search={handleSearch} onClear={handleClearAll} t={t} />
253
255
  )}
254
256
  </TableBody>
255
257
  </Table>
@@ -271,16 +273,12 @@ export function DataTable<T extends { id: string }>({
271
273
  */
272
274
  const DefaultTableHeader = memo(function DefaultTableHeader<T>({
273
275
  columns,
274
- orderBy,
275
- onSort,
276
276
  selectable,
277
277
  allPageSelected,
278
278
  somePageSelected,
279
279
  onToggleAll,
280
280
  }: {
281
281
  columns: Column<T>[];
282
- orderBy?: string;
283
- onSort?: (order: string | null) => void;
284
282
  selectable?: boolean;
285
283
  allPageSelected?: boolean;
286
284
  somePageSelected?: boolean;
@@ -300,18 +298,7 @@ const DefaultTableHeader = memo(function DefaultTableHeader<T>({
300
298
  )}
301
299
  {columns.map((column) => (
302
300
  <TableHead key={column.id} className={column.className} style={{ textAlign: column.align }}>
303
- {column.sortable ? (
304
- <SortableHeader
305
- field={column.sortField ?? column.id}
306
- currentOrder={orderBy}
307
- onSort={onSort}
308
- align={column.align}
309
- >
310
- {column.header}
311
- </SortableHeader>
312
- ) : (
313
- column.header
314
- )}
301
+ {column.header}
315
302
  </TableHead>
316
303
  ))}
317
304
  </TableRow>
@@ -319,8 +306,6 @@ const DefaultTableHeader = memo(function DefaultTableHeader<T>({
319
306
  );
320
307
  }) as <T>(props: {
321
308
  columns: Column<T>[];
322
- orderBy?: string;
323
- onSort?: (order: string | null) => void;
324
309
  selectable?: boolean;
325
310
  allPageSelected?: boolean;
326
311
  somePageSelected?: boolean;
@@ -3,7 +3,6 @@ import type { FilterState, HttpMethodFilter, HttpStatusCodeFilter, StatusFilter,
3
3
 
4
4
  type UseTableStateProps = {
5
5
  initialParams?: TableQueryParams;
6
- defaultOrderBy?: string;
7
6
  onChangeParams?: (params: TableQueryParams) => void;
8
7
  /** When true, disables URL sync entirely (for embedded tables like dashboard) */
9
8
  disableUrlSync?: boolean;
@@ -115,17 +114,11 @@ export function buildQueryFromFilterState(state: FilterState | null): string | u
115
114
  }
116
115
 
117
116
  /**
118
- * Manages table state (sorting, search, pagination) with optional URL sync
117
+ * Manages table state (search, pagination, filters) with optional URL sync
119
118
  */
120
- export function useTableState({
121
- initialParams = {},
122
- defaultOrderBy = "-id",
123
- onChangeParams,
124
- disableUrlSync = false,
125
- }: UseTableStateProps) {
119
+ export function useTableState({ initialParams = {}, onChangeParams, disableUrlSync = false }: UseTableStateProps) {
126
120
  const [params, setParams] = useState<TableQueryParams>({
127
121
  ...initialParams,
128
- order_by: initialParams.order_by ?? defaultOrderBy,
129
122
  });
130
123
 
131
124
  // Use ref for onChangeParams to keep it stable
@@ -147,10 +140,9 @@ export function useTableState({
147
140
  isUpdatingFromInitialRef.current = true;
148
141
  setParams({
149
142
  ...initialParams,
150
- order_by: initialParams.order_by ?? defaultOrderBy,
151
143
  });
152
144
  }
153
- }, [initialParams, defaultOrderBy]);
145
+ }, [initialParams]);
154
146
 
155
147
  // Sync params to parent or URL when they change
156
148
  useEffect(() => {
@@ -185,21 +177,6 @@ export function useTableState({
185
177
  }
186
178
  }, [params, disableUrlSync]);
187
179
 
188
- /**
189
- * Handle sort change
190
- */
191
- const handleSort = useCallback(
192
- (order: string | null) => {
193
- setParams((prevParams) => ({
194
- ...prevParams,
195
- order_by: order ?? defaultOrderBy,
196
- prev_cursor: undefined,
197
- next_cursor: undefined,
198
- }));
199
- },
200
- [defaultOrderBy],
201
- );
202
-
203
180
  /**
204
181
  * Handle search change
205
182
  */
@@ -285,7 +262,6 @@ export function useTableState({
285
262
  params,
286
263
  apiParams,
287
264
  filterState,
288
- handleSort,
289
265
  handleSearch,
290
266
  handlePageChange,
291
267
  handleFilterChange,
@@ -2,7 +2,6 @@
2
2
  * Table Component Library
3
3
  *
4
4
  * A comprehensive, type-safe table system with built-in:
5
- * - Sorting (client and server-side)
6
5
  * - Search/filtering
7
6
  * - Cursor-based pagination
8
7
  * - Loading states
@@ -20,7 +19,6 @@ export { useTableQuery } from "./hooks/use-table-query";
20
19
  export { useTableState } from "./hooks/use-table-state";
21
20
  // Supporting components
22
21
  export { SearchInput } from "./search-input";
23
- export { SortableHeader } from "./sortable-header";
24
22
  export { TableEmptyState } from "./table-empty-state";
25
23
  export { TableNoResults } from "./table-no-results";
26
24
  export { Pagination } from "./table-pagination";
@@ -1,9 +1,14 @@
1
- import { FileDown, X } from "lucide-react";
1
+ import { FileDown, FileText, RefreshCw, X } from "lucide-react";
2
2
  import { Button } from "@/ui/components/ui/button";
3
+ import { Tooltip, TooltipContent, TooltipTrigger } from "@/ui/components/ui/tooltip";
3
4
 
4
5
  type SelectionToolbarProps = {
5
6
  selectedCount: number;
6
7
  onExportPdfs?: () => void;
8
+ onCopyToInvoice?: () => void;
9
+ onRetryFiscalization?: () => void;
10
+ retryFiscalizationDisabled?: boolean;
11
+ retryFiscalizationTooltip?: string;
7
12
  onDeselectAll?: () => void;
8
13
  t?: (key: string) => string;
9
14
  };
@@ -11,6 +16,10 @@ type SelectionToolbarProps = {
11
16
  export function SelectionToolbar({
12
17
  selectedCount,
13
18
  onExportPdfs,
19
+ onCopyToInvoice,
20
+ onRetryFiscalization,
21
+ retryFiscalizationDisabled,
22
+ retryFiscalizationTooltip,
14
23
  onDeselectAll,
15
24
  t = (key) => key,
16
25
  }: SelectionToolbarProps) {
@@ -25,6 +34,31 @@ export function SelectionToolbar({
25
34
  {t("Export PDFs")}
26
35
  </Button>
27
36
  )}
37
+ {onCopyToInvoice && (
38
+ <Button variant="outline" size="sm" onClick={onCopyToInvoice}>
39
+ <FileText className="mr-1.5 size-4" />
40
+ {t("Copy to Invoice")}
41
+ </Button>
42
+ )}
43
+ {onRetryFiscalization &&
44
+ (retryFiscalizationDisabled && retryFiscalizationTooltip ? (
45
+ <Tooltip>
46
+ <TooltipTrigger>
47
+ <span>
48
+ <Button variant="outline" size="sm" disabled>
49
+ <RefreshCw className="mr-1.5 size-4" />
50
+ {t("Retry Fiscalization")}
51
+ </Button>
52
+ </span>
53
+ </TooltipTrigger>
54
+ <TooltipContent>{retryFiscalizationTooltip}</TooltipContent>
55
+ </Tooltip>
56
+ ) : (
57
+ <Button variant="outline" size="sm" onClick={onRetryFiscalization}>
58
+ <RefreshCw className="mr-1.5 size-4" />
59
+ {t("Retry Fiscalization")}
60
+ </Button>
61
+ ))}
28
62
  {onDeselectAll && (
29
63
  <Button variant="ghost" size="sm" onClick={onDeselectAll}>
30
64
  <X className="mr-1.5 size-4" />
@@ -6,6 +6,8 @@ type TableEmptyStateProps = {
6
6
  resource: string;
7
7
  createNewLink?: string;
8
8
  createNewTrigger?: React.ReactNode;
9
+ /** Callback for "Create new" click — enables client-side navigation instead of full page reload */
10
+ onCreateNew?: () => void;
9
11
  /** Number of rows to calculate height (default: 10) */
10
12
  rows?: number;
11
13
  /** Translation function */
@@ -21,6 +23,7 @@ const ROW_HEIGHT = 53;
21
23
  export function TableEmptyState({
22
24
  createNewLink,
23
25
  createNewTrigger,
26
+ onCreateNew,
24
27
  rows = 10,
25
28
  t = (key) => key,
26
29
  }: TableEmptyStateProps) {
@@ -32,13 +35,13 @@ export function TableEmptyState({
32
35
  <Sprout size={70} strokeWidth={0.35} className="text-muted-foreground" />
33
36
  <div className="space-y-1 text-center">
34
37
  <p className="font-light text-lg text-muted-foreground">{t("Your list is empty")}</p>
35
- {(createNewLink || createNewTrigger) && (
38
+ {(createNewLink || createNewTrigger || onCreateNew) && (
36
39
  <p className="text-muted-foreground text-sm">{t("Get started by creating your first entry")}</p>
37
40
  )}
38
41
  </div>
39
42
  {createNewLink && (
40
- <Button variant="default" size="sm" asChild>
41
- <a href={createNewLink}>{t("Create new")}</a>
43
+ <Button variant="default" size="sm" {...(onCreateNew ? { onClick: onCreateNew } : { asChild: true })}>
44
+ {onCreateNew ? t("Create new") : <a href={createNewLink}>{t("Create new")}</a>}
42
45
  </Button>
43
46
  )}
44
47
  {createNewTrigger && !createNewLink && <div>{createNewTrigger}</div>}
@@ -6,6 +6,8 @@ import { TableCell, TableRow } from "@/ui/components/ui/table";
6
6
  type TableNoResultsProps = {
7
7
  resource: string;
8
8
  search?: (value: null) => void;
9
+ /** Combined clear handler for both search and filters */
10
+ onClear?: () => void;
9
11
  /** Number of rows to calculate height (default: 10) */
10
12
  rows?: number;
11
13
  /** Translation function */
@@ -18,10 +20,13 @@ const ROW_HEIGHT = 53;
18
20
  /**
19
21
  * No results message shown when search returns empty
20
22
  */
21
- export function TableNoResults({ search, rows = 10, t = (key) => key }: TableNoResultsProps) {
23
+ export function TableNoResults({ search, onClear, rows = 10, t = (key) => key }: TableNoResultsProps) {
22
24
  // Calculate height based on row count (min 150px)
23
25
  const height = Math.max(rows * ROW_HEIGHT, 150);
24
26
 
27
+ const handleClear = onClear ?? (search ? () => search(null) : undefined);
28
+ const clearLabel = onClear ? t("Clear all") : t("Clear search");
29
+
25
30
  return (
26
31
  <TableRow className="hover:bg-transparent">
27
32
  <TableCell colSpan={100} className="text-center align-middle" style={{ height }}>
@@ -29,11 +34,11 @@ export function TableNoResults({ search, rows = 10, t = (key) => key }: TableNoR
29
34
  <FileX size={32} strokeWidth={1.5} className="text-muted-foreground" />
30
35
  <div className="space-y-1">
31
36
  <p className="font-medium text-muted-foreground">{t("No results found")}</p>
32
- {search && <p className="text-muted-foreground text-sm">{t("Try adjusting your search criteria")}</p>}
37
+ {handleClear && <p className="text-muted-foreground text-sm">{t("Try adjusting your search criteria")}</p>}
33
38
  </div>
34
- {search && (
35
- <Button variant="link" size="sm" onClick={() => search(null)} className="underline">
36
- {t("Clear search")}
39
+ {handleClear && (
40
+ <Button variant="link" size="sm" onClick={handleClear} className="underline">
41
+ {clearLabel}
37
42
  </Button>
38
43
  )}
39
44
  </div>
@@ -10,10 +10,6 @@ export type Column<T> = {
10
10
  header: ReactNode;
11
11
  /** Cell renderer function - returns content for each row. Optional when using renderRow. */
12
12
  cell?: (item: T) => ReactNode;
13
- /** Field name for sorting (if different from id) */
14
- sortField?: string;
15
- /** Whether this column is sortable */
16
- sortable?: boolean;
17
13
  /** Text alignment */
18
14
  align?: "left" | "center" | "right";
19
15
  /** Optional CSS class for the column */
@@ -24,7 +20,6 @@ export type Column<T> = {
24
20
  * Query parameters for table data fetching
25
21
  */
26
22
  export type TableQueryParams = {
27
- order_by?: string;
28
23
  search?: string;
29
24
  prev_cursor?: string;
30
25
  next_cursor?: string;
@@ -14,4 +14,5 @@ export default {
14
14
  "No results found": "Keine Steuern gefunden",
15
15
  "Try adjusting your search criteria": "Versuchen Sie, Ihre Suchkriterien anzupassen",
16
16
  "Clear search": "Suche zurücksetzen",
17
+ "Clear all": "Alles zurücksetzen",
17
18
  };
@@ -14,4 +14,5 @@ export default {
14
14
  "No results found": "No se encontraron impuestos",
15
15
  "Try adjusting your search criteria": "Intente ajustar sus criterios de búsqueda",
16
16
  "Clear search": "Limpiar búsqueda",
17
+ "Clear all": "Borrar todo",
17
18
  };
@@ -14,4 +14,5 @@ export default {
14
14
  "No results found": "Aucune taxe trouvée",
15
15
  "Try adjusting your search criteria": "Essayez de modifier vos critères de recherche",
16
16
  "Clear search": "Effacer la recherche",
17
+ "Clear all": "Tout effacer",
17
18
  };
@@ -14,4 +14,5 @@ export default {
14
14
  "No results found": "Nisu pronađeni porezi",
15
15
  "Try adjusting your search criteria": "Pokušajte prilagoditi kriterije pretrage",
16
16
  "Clear search": "Očisti pretragu",
17
+ "Clear all": "Očisti sve",
17
18
  };
@@ -14,4 +14,5 @@ export default {
14
14
  "No results found": "Nessuna tassa trovata",
15
15
  "Try adjusting your search criteria": "Prova a modificare i criteri di ricerca",
16
16
  "Clear search": "Cancella ricerca",
17
+ "Clear all": "Cancella tutto",
17
18
  };
@@ -14,4 +14,5 @@ export default {
14
14
  "No results found": "Geen belastingen gevonden",
15
15
  "Try adjusting your search criteria": "Probeer uw zoekcriteria aan te passen",
16
16
  "Clear search": "Zoekopdracht wissen",
17
+ "Clear all": "Alles wissen",
17
18
  };
@@ -14,4 +14,5 @@ export default {
14
14
  "No results found": "Nie znaleziono podatków",
15
15
  "Try adjusting your search criteria": "Spróbuj dostosować kryteria wyszukiwania",
16
16
  "Clear search": "Wyczyść wyszukiwanie",
17
+ "Clear all": "Wyczyść wszystko",
17
18
  };
@@ -14,4 +14,5 @@ export default {
14
14
  "No results found": "Nenhum imposto encontrado",
15
15
  "Try adjusting your search criteria": "Tente ajustar os seus critérios de pesquisa",
16
16
  "Clear search": "Limpar pesquisa",
17
+ "Clear all": "Limpar tudo",
17
18
  };
@@ -14,4 +14,5 @@ export default {
14
14
  "No results found": "Ni najdenih davkov",
15
15
  "Try adjusting your search criteria": "Poskusite prilagoditi iskalne kriterije",
16
16
  "Clear search": "Počisti iskanje",
17
+ "Clear all": "Počisti vse",
17
18
  };
@@ -1,27 +1,16 @@
1
1
  import { TableHead, TableHeader, TableRow } from "@/ui/components/ui/table";
2
- import { SortableHeader } from "../../table/sortable-header";
3
2
 
4
3
  type TaxListHeaderProps = {
5
- orderBy?: string;
6
- onSort?: (order: string | null) => void;
7
4
  t: (key: string) => string;
8
5
  };
9
6
 
10
- export default function TaxListHeader({ orderBy, onSort, t }: TaxListHeaderProps) {
7
+ export default function TaxListHeader({ t }: TaxListHeaderProps) {
11
8
  return (
12
9
  <TableHeader>
13
10
  <TableRow>
14
- <TableHead>
15
- <SortableHeader field="name" currentOrder={orderBy} onSort={onSort}>
16
- {t("Name")}
17
- </SortableHeader>
18
- </TableHead>
11
+ <TableHead>{t("Name")}</TableHead>
19
12
  <TableHead>{t("Tax Rates")}</TableHead>
20
- <TableHead>
21
- <SortableHeader field="created_at" currentOrder={orderBy} onSort={onSort}>
22
- {t("Created")}
23
- </SortableHeader>
24
- </TableHead>
13
+ <TableHead>{t("Created")}</TableHead>
25
14
  <TableHead className="text-right" />
26
15
  </TableRow>
27
16
  </TableHeader>
@@ -58,15 +58,15 @@ export default function TaxListTable({
58
58
  return (
59
59
  <DataTable
60
60
  columns={[
61
- { id: "name", header: t("Name"), sortable: true },
61
+ { id: "name", header: t("Name") },
62
62
  { id: "tax_rates", header: t("Tax Rates") },
63
- { id: "created_at", header: t("Created"), sortable: true },
63
+ { id: "created_at", header: t("Created") },
64
64
  { id: "actions", header: "", align: "right" },
65
65
  ]}
66
66
  renderRow={(tax) => (
67
67
  <TaxListRow tax={tax} key={tax.id} onRowClick={(tax) => onRowClick?.(tax)} onView={onView} t={t} />
68
68
  )}
69
- renderHeader={(headerProps) => <TaxListHeader orderBy={headerProps.orderBy} onSort={headerProps.onSort} t={t} />}
69
+ renderHeader={() => <TaxListHeader t={t} />}
70
70
  queryParams={queryParams}
71
71
  resourceName="tax"
72
72
  cacheKey={TAXES_CACHE_KEY}
@@ -37,11 +37,12 @@ function PopoverContent({
37
37
  alignOffset = 0,
38
38
  side = "bottom",
39
39
  sideOffset = 4,
40
+ positionMethod = "fixed",
40
41
  ...props
41
42
  }: PopoverPrimitive.Popup.Props &
42
43
  Pick<
43
44
  PopoverPrimitive.Positioner.Props,
44
- "align" | "alignOffset" | "side" | "sideOffset"
45
+ "align" | "alignOffset" | "side" | "sideOffset" | "positionMethod"
45
46
  >) {
46
47
  return (
47
48
  <PopoverPrimitive.Portal>
@@ -50,6 +51,7 @@ function PopoverContent({
50
51
  alignOffset={alignOffset}
51
52
  side={side}
52
53
  sideOffset={sideOffset}
54
+ positionMethod={positionMethod}
53
55
  className="isolate z-50"
54
56
  >
55
57
  <PopoverPrimitive.Popup
@@ -54,12 +54,13 @@ function TooltipContent({
54
54
  sideOffset = 4,
55
55
  align = "center",
56
56
  alignOffset = 0,
57
+ positionMethod = "fixed",
57
58
  children,
58
59
  ...props
59
60
  }: TooltipPrimitive.Popup.Props &
60
61
  Pick<
61
62
  TooltipPrimitive.Positioner.Props,
62
- "align" | "alignOffset" | "side" | "sideOffset"
63
+ "align" | "alignOffset" | "side" | "sideOffset" | "positionMethod"
63
64
  >) {
64
65
  return (
65
66
  <TooltipPrimitive.Portal>
@@ -68,6 +69,7 @@ function TooltipContent({
68
69
  alignOffset={alignOffset}
69
70
  side={side}
70
71
  sideOffset={sideOffset}
72
+ positionMethod={positionMethod}
71
73
  className="isolate z-50"
72
74
  >
73
75
  <TooltipPrimitive.Popup
@@ -13,8 +13,8 @@ export * from './customadvanceinvoice';
13
13
  export * from './customcreditnote';
14
14
  export * from './customer';
15
15
  export * from './customestimate';
16
- export * from './deliverynote';
17
16
  export * from './custominvoice';
17
+ export * from './deliverynote';
18
18
  export * from './entity';
19
19
  export * from './entityuserrole';
20
20
  export * from './estimate';