@spaceinvoices/react-ui 0.4.1 → 0.4.2

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 (191) hide show
  1. package/cli/dist/index.js +1 -1
  2. package/package.json +1 -1
  3. package/registry.json +25 -0
  4. package/src/components/advance-invoices/advance-invoices.hooks.ts +32 -2
  5. package/src/components/advance-invoices/create/create-advance-invoice-form.tsx +109 -4
  6. package/src/components/advance-invoices/create/locales/de.ts +2 -0
  7. package/src/components/advance-invoices/create/locales/es.ts +2 -0
  8. package/src/components/advance-invoices/create/locales/fr.ts +2 -0
  9. package/src/components/advance-invoices/create/locales/hr.ts +2 -0
  10. package/src/components/advance-invoices/create/locales/it.ts +2 -0
  11. package/src/components/advance-invoices/create/locales/nl.ts +2 -0
  12. package/src/components/advance-invoices/create/locales/pl.ts +2 -0
  13. package/src/components/advance-invoices/create/locales/pt.ts +2 -0
  14. package/src/components/advance-invoices/create/locales/sl.ts +2 -0
  15. package/src/components/advance-invoices/create/prepare-advance-invoice-submission.ts +17 -0
  16. package/src/components/advance-invoices/list/list-row-actions.tsx +3 -6
  17. package/src/components/advance-invoices/list/list-table.tsx +45 -2
  18. package/src/components/advance-invoices/list/locales/de.ts +3 -0
  19. package/src/components/advance-invoices/list/locales/en.ts +3 -0
  20. package/src/components/advance-invoices/list/locales/es.ts +3 -0
  21. package/src/components/advance-invoices/list/locales/fr.ts +3 -0
  22. package/src/components/advance-invoices/list/locales/hr.ts +3 -0
  23. package/src/components/advance-invoices/list/locales/it.ts +3 -0
  24. package/src/components/advance-invoices/list/locales/nl.ts +3 -0
  25. package/src/components/advance-invoices/list/locales/pl.ts +3 -0
  26. package/src/components/advance-invoices/list/locales/pt.ts +3 -0
  27. package/src/components/advance-invoices/list/locales/sl.ts +3 -0
  28. package/src/components/credit-notes/create/create-credit-note-form.tsx +177 -6
  29. package/src/components/credit-notes/create/locales/de.ts +8 -0
  30. package/src/components/credit-notes/create/locales/es.ts +8 -0
  31. package/src/components/credit-notes/create/locales/fr.ts +7 -0
  32. package/src/components/credit-notes/create/locales/hr.ts +7 -0
  33. package/src/components/credit-notes/create/locales/it.ts +9 -0
  34. package/src/components/credit-notes/create/locales/nl.ts +7 -0
  35. package/src/components/credit-notes/create/locales/pl.ts +7 -0
  36. package/src/components/credit-notes/create/locales/pt.ts +7 -0
  37. package/src/components/credit-notes/create/locales/sl.ts +7 -0
  38. package/src/components/credit-notes/credit-notes.hooks.ts +30 -0
  39. package/src/components/credit-notes/list/list-row-actions.tsx +3 -6
  40. package/src/components/credit-notes/list/list-table.tsx +45 -2
  41. package/src/components/credit-notes/list/locales/de.ts +3 -0
  42. package/src/components/credit-notes/list/locales/en.ts +3 -0
  43. package/src/components/credit-notes/list/locales/es.ts +3 -0
  44. package/src/components/credit-notes/list/locales/fr.ts +3 -0
  45. package/src/components/credit-notes/list/locales/hr.ts +3 -0
  46. package/src/components/credit-notes/list/locales/it.ts +3 -0
  47. package/src/components/credit-notes/list/locales/nl.ts +3 -0
  48. package/src/components/credit-notes/list/locales/pl.ts +3 -0
  49. package/src/components/credit-notes/list/locales/pt.ts +3 -0
  50. package/src/components/credit-notes/list/locales/sl.ts +3 -0
  51. package/src/components/customers/create-customer-form/create-customer-form.tsx +0 -1
  52. package/src/components/documents/create/document-details-section.tsx +67 -1
  53. package/src/components/documents/create/mark-as-paid-section.tsx +11 -2
  54. package/src/components/documents/view/document-actions-bar.tsx +30 -0
  55. package/src/components/documents/view/locales/de.ts +5 -0
  56. package/src/components/documents/view/locales/es.ts +5 -0
  57. package/src/components/documents/view/locales/fr.ts +5 -0
  58. package/src/components/documents/view/locales/hr.ts +5 -0
  59. package/src/components/documents/view/locales/it.ts +5 -0
  60. package/src/components/documents/view/locales/nl.ts +5 -0
  61. package/src/components/documents/view/locales/pl.ts +5 -0
  62. package/src/components/documents/view/locales/pt.ts +5 -0
  63. package/src/components/documents/view/locales/sl.ts +5 -0
  64. package/src/components/entities/create-entity-form.tsx +1 -1
  65. package/src/components/entities/entity-settings-form/entity-settings-form.tsx +2 -3
  66. package/src/components/entities/entity-settings-form/locales/es.ts +2 -0
  67. package/src/components/entities/entity-settings-form/locales/fr.ts +2 -0
  68. package/src/components/entities/entity-settings-form/locales/hr.ts +2 -0
  69. package/src/components/entities/entity-settings-form/locales/it.ts +2 -0
  70. package/src/components/entities/entity-settings-form/locales/nl.ts +2 -0
  71. package/src/components/entities/entity-settings-form/locales/pl.ts +2 -0
  72. package/src/components/entities/entity-settings-form/locales/pt.ts +2 -0
  73. package/src/components/entities/fina-settings-form/fina-operator-required-dialog.tsx +109 -0
  74. package/src/components/entities/fina-settings-form/fina-settings-form.tsx +365 -35
  75. package/src/components/entities/fina-settings-form/fina-settings.hooks.ts +101 -20
  76. package/src/components/entities/fina-settings-form/index.ts +1 -0
  77. package/src/components/entities/fina-settings-form/locales/de.ts +54 -34
  78. package/src/components/entities/fina-settings-form/locales/en.ts +51 -34
  79. package/src/components/entities/fina-settings-form/locales/es.ts +50 -34
  80. package/src/components/entities/fina-settings-form/locales/fr.ts +50 -34
  81. package/src/components/entities/fina-settings-form/locales/hr.ts +50 -34
  82. package/src/components/entities/fina-settings-form/locales/it.ts +50 -34
  83. package/src/components/entities/fina-settings-form/locales/nl.ts +50 -34
  84. package/src/components/entities/fina-settings-form/locales/pl.ts +50 -34
  85. package/src/components/entities/fina-settings-form/locales/pt.ts +50 -34
  86. package/src/components/entities/fina-settings-form/locales/sl.ts +50 -34
  87. package/src/components/entities/fina-settings-form/sections/certificate-settings-section.tsx +18 -0
  88. package/src/components/entities/fina-settings-form/sections/premises-management-section.tsx +64 -89
  89. package/src/components/entities/fina-settings-form/sections/register-premise-dialog.tsx +51 -323
  90. package/src/components/entities/furs-settings-form/furs-operator-required-dialog.tsx +106 -0
  91. package/src/components/entities/furs-settings-form/furs-settings-form.tsx +24 -10
  92. package/src/components/entities/furs-settings-form/furs-settings.hooks.ts +5 -9
  93. package/src/components/entities/furs-settings-form/index.ts +1 -0
  94. package/src/components/entities/furs-settings-form/locales/de.ts +27 -3
  95. package/src/components/entities/furs-settings-form/locales/en.ts +17 -3
  96. package/src/components/entities/furs-settings-form/locales/es.ts +26 -3
  97. package/src/components/entities/furs-settings-form/locales/fr.ts +26 -3
  98. package/src/components/entities/furs-settings-form/locales/hr.ts +26 -3
  99. package/src/components/entities/furs-settings-form/locales/it.ts +26 -3
  100. package/src/components/entities/furs-settings-form/locales/nl.ts +26 -3
  101. package/src/components/entities/furs-settings-form/locales/pl.ts +26 -3
  102. package/src/components/entities/furs-settings-form/locales/pt.ts +26 -3
  103. package/src/components/entities/furs-settings-form/locales/sl.ts +16 -3
  104. package/src/components/entities/furs-settings-form/sections/certificate-settings-section.tsx +22 -0
  105. package/src/components/entities/furs-settings-form/sections/general-settings-section.tsx +15 -2
  106. package/src/components/entities/furs-settings-form/sections/register-premise-dialog.tsx +14 -2
  107. package/src/components/entities/settings/tax-rules-settings-form.tsx +4 -4
  108. package/src/components/estimates/list/list-row-actions.tsx +3 -7
  109. package/src/components/estimates/list/list-table.tsx +35 -2
  110. package/src/components/estimates/list/locales/de.ts +3 -0
  111. package/src/components/estimates/list/locales/en.ts +3 -0
  112. package/src/components/estimates/list/locales/es.ts +3 -0
  113. package/src/components/estimates/list/locales/fr.ts +3 -0
  114. package/src/components/estimates/list/locales/hr.ts +3 -0
  115. package/src/components/estimates/list/locales/it.ts +3 -0
  116. package/src/components/estimates/list/locales/nl.ts +3 -0
  117. package/src/components/estimates/list/locales/pl.ts +3 -0
  118. package/src/components/estimates/list/locales/pt.ts +3 -0
  119. package/src/components/estimates/list/locales/sl.ts +3 -0
  120. package/src/components/export/document-export-form.tsx +34 -34
  121. package/src/components/invoices/create/create-invoice-form.tsx +107 -5
  122. package/src/components/invoices/create/prepare-invoice-submission.ts +17 -0
  123. package/src/components/invoices/invoices.hooks.ts +32 -2
  124. package/src/components/invoices/list/list-row-actions.tsx +23 -8
  125. package/src/components/invoices/list/list-table.tsx +53 -2
  126. package/src/components/invoices/list/locales/de.ts +4 -0
  127. package/src/components/invoices/list/locales/en.ts +4 -0
  128. package/src/components/invoices/list/locales/es.ts +4 -0
  129. package/src/components/invoices/list/locales/fr.ts +4 -0
  130. package/src/components/invoices/list/locales/hr.ts +4 -0
  131. package/src/components/invoices/list/locales/it.ts +4 -0
  132. package/src/components/invoices/list/locales/nl.ts +4 -0
  133. package/src/components/invoices/list/locales/pl.ts +4 -0
  134. package/src/components/invoices/list/locales/pt.ts +4 -0
  135. package/src/components/invoices/list/locales/sl.ts +4 -0
  136. package/src/components/invoices/view/fiscalization-status-card.tsx +4 -1
  137. package/src/components/items/item-list-table/item-list-row-actions.tsx +3 -7
  138. package/src/components/items/item-list-table/item-list-row.tsx +3 -2
  139. package/src/components/items/item-list-table/item-list-table.tsx +5 -1
  140. package/src/components/recurring-invoices/create-recurring-invoice-form/create-recurring-invoice-form.tsx +418 -0
  141. package/src/components/recurring-invoices/create-recurring-invoice-form/locales/de.ts +45 -0
  142. package/src/components/recurring-invoices/create-recurring-invoice-form/locales/es.ts +44 -0
  143. package/src/components/recurring-invoices/create-recurring-invoice-form/locales/fr.ts +44 -0
  144. package/src/components/recurring-invoices/create-recurring-invoice-form/locales/hr.ts +44 -0
  145. package/src/components/recurring-invoices/create-recurring-invoice-form/locales/it.ts +44 -0
  146. package/src/components/recurring-invoices/create-recurring-invoice-form/locales/nl.ts +44 -0
  147. package/src/components/recurring-invoices/create-recurring-invoice-form/locales/pl.ts +44 -0
  148. package/src/components/recurring-invoices/create-recurring-invoice-form/locales/pt.ts +44 -0
  149. package/src/components/recurring-invoices/create-recurring-invoice-form/locales/sl.ts +44 -0
  150. package/src/components/recurring-invoices/index.ts +3 -0
  151. package/src/components/recurring-invoices/list/index.ts +2 -0
  152. package/src/components/recurring-invoices/list/list-row-actions.tsx +139 -0
  153. package/src/components/recurring-invoices/list/list-table.tsx +179 -0
  154. package/src/components/recurring-invoices/list/locales/de.ts +27 -0
  155. package/src/components/recurring-invoices/list/locales/en.ts +5 -0
  156. package/src/components/recurring-invoices/list/locales/es.ts +27 -0
  157. package/src/components/recurring-invoices/list/locales/fr.ts +27 -0
  158. package/src/components/recurring-invoices/list/locales/hr.ts +27 -0
  159. package/src/components/recurring-invoices/list/locales/it.ts +27 -0
  160. package/src/components/recurring-invoices/list/locales/nl.ts +27 -0
  161. package/src/components/recurring-invoices/list/locales/pl.ts +27 -0
  162. package/src/components/recurring-invoices/list/locales/pt.ts +27 -0
  163. package/src/components/recurring-invoices/list/locales/sl.ts +27 -0
  164. package/src/components/recurring-invoices/recurring-invoices.hooks.ts +28 -0
  165. package/src/components/table/data-table.tsx +122 -5
  166. package/src/components/table/selection-toolbar.tsx +36 -0
  167. package/src/components/tax-reports/kir-export-form.tsx +75 -55
  168. package/src/components/taxes/tax-list-table/tax-list-row-actions.tsx +3 -6
  169. package/src/components/taxes/tax-list-table/tax-list-row.tsx +3 -2
  170. package/src/components/taxes/tax-list-table/tax-list-table.tsx +5 -1
  171. package/src/components/ui/checkbox.tsx +5 -5
  172. package/src/generate-schemas.ts +45 -18
  173. package/src/generated/schemas/authorizeshopify_body.ts +22 -0
  174. package/src/generated/schemas/creditnote.ts +0 -2
  175. package/src/generated/schemas/entity.ts +1 -1
  176. package/src/generated/schemas/index.ts +39 -28
  177. package/src/generated/schemas/order.ts +127 -0
  178. package/src/generated/schemas/orderintegration.ts +51 -0
  179. package/src/generated/schemas/payment.ts +2 -0
  180. package/src/generated/schemas/recurringinvoice.ts +61 -0
  181. package/src/generated/schemas/renderadvanceinvoicepreview_body.ts +107 -140
  182. package/src/generated/schemas/rendercreditnotepreview_body.ts +108 -141
  183. package/src/generated/schemas/renderestimatepreview_body.ts +78 -82
  184. package/src/generated/schemas/renderinvoicepreview_body.ts +108 -141
  185. package/src/generated/schemas/webhook.ts +42 -0
  186. package/src/lib/furs-error-utils.ts +36 -0
  187. package/src/lib/schemas/advance-invoice.ts +3 -3
  188. package/src/lib/schemas/credit-note.ts +3 -3
  189. package/src/lib/schemas/estimate.ts +3 -3
  190. package/src/lib/schemas/invoice.ts +3 -3
  191. package/src/providers/white-label-provider.tsx +3 -0
package/cli/dist/index.js CHANGED
@@ -870,7 +870,7 @@ async function list(options = {}) {
870
870
 
871
871
  // cli/src/index.ts
872
872
  var program = new Command();
873
- program.name("spaceinvoices-ui").description("CLI for adding Space Invoices React UI components to your project").version("0.4.1");
873
+ program.name("spaceinvoices-ui").description("CLI for adding Space Invoices React UI components to your project").version("0.4.2");
874
874
  program.option("--local <path>", "Use local registry from specified path (for development)");
875
875
  program.command("init").description("Initialize Space Invoices UI in your project").option("-y, --yes", "Skip prompts and use defaults").option("-f, --force", "Overwrite existing configuration").option("--cwd <path>", "Working directory (defaults to current directory)").action(async (options) => {
876
876
  const globalOpts = program.opts();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@spaceinvoices/react-ui",
3
3
  "type": "module",
4
- "version": "0.4.1",
4
+ "version": "0.4.2",
5
5
  "private": false,
6
6
  "license": "MIT",
7
7
  "description": "Space Invoices UI components - copy-paste distribution with CLI support",
package/registry.json CHANGED
@@ -206,6 +206,7 @@
206
206
  "components/table/types.ts",
207
207
  "components/table/hooks/use-table-fetch.ts",
208
208
  "components/table/hooks/use-table-state.ts",
209
+ "components/table/selection-toolbar.tsx",
209
210
  "components/table/index.ts"
210
211
  ],
211
212
  "dependencies": ["ui/table", "ui/skeleton", "ui/button", "ui/input"],
@@ -530,6 +531,30 @@
530
531
  "dependencies": ["ui/card", "dashboard/loading-card"],
531
532
  "providers": ["sdk-provider"],
532
533
  "utils": ["translation"]
534
+ },
535
+ "recurring-invoices/create-recurring-invoice-form": {
536
+ "name": "Create Recurring Invoice Form",
537
+ "category": "feature",
538
+ "files": [
539
+ "components/recurring-invoices/create-recurring-invoice-form/create-recurring-invoice-form.tsx",
540
+ "components/recurring-invoices/recurring-invoices.hooks.ts"
541
+ ],
542
+ "dependencies": ["form/form-input", "ui/form", "ui/card", "customers/customer-combobox"],
543
+ "providers": ["sdk-provider", "entities-provider"],
544
+ "utils": ["translation", "hooks"],
545
+ "schemas": ["createRecurringInvoiceSchema"]
546
+ },
547
+ "recurring-invoices/recurring-invoice-list-table": {
548
+ "name": "Recurring Invoice List Table",
549
+ "category": "feature",
550
+ "files": [
551
+ "components/recurring-invoices/list/list-table.tsx",
552
+ "components/recurring-invoices/list/list-row-actions.tsx",
553
+ "components/recurring-invoices/recurring-invoices.hooks.ts"
554
+ ],
555
+ "dependencies": ["table/data-table", "ui/dropdown-menu", "ui/button", "ui/badge"],
556
+ "providers": ["sdk-provider"],
557
+ "utils": ["translation", "hooks"]
533
558
  }
534
559
  }
535
560
  }
@@ -1,4 +1,4 @@
1
- import type { AdvanceInvoice, CreateAdvanceInvoiceBody } from "@spaceinvoices/js-sdk";
1
+ import type { AdvanceInvoice, CreateAdvanceInvoice } from "@spaceinvoices/js-sdk";
2
2
  import { useMutation, useQueryClient } from "@tanstack/react-query";
3
3
  import { NEXT_DOCUMENT_NUMBER_CACHE_KEY } from "@/ui/hooks/use-next-document-number";
4
4
  import { useSDK } from "@/ui/providers/sdk-provider";
@@ -21,7 +21,7 @@ export function useCreateAdvanceInvoice({ entityId, onSuccess, onError }: UseCre
21
21
  const queryClient = useQueryClient();
22
22
 
23
23
  return useMutation({
24
- mutationFn: async (data: CreateAdvanceInvoiceBody) => {
24
+ mutationFn: async (data: CreateAdvanceInvoice) => {
25
25
  return sdk.advanceInvoices.create(data, { entity_id: entityId });
26
26
  },
27
27
  onSuccess: (data) => {
@@ -73,3 +73,33 @@ export function setLastUsedFursCombo(entityId: string, combo: FursCombo): void {
73
73
  // Ignore localStorage errors (quota exceeded, etc.)
74
74
  }
75
75
  }
76
+
77
+ // ============================================================================
78
+ // FINA Last-Used Combo (localStorage) for advance invoices
79
+ // ============================================================================
80
+
81
+ const FINA_ADV_LAST_USED_KEY = "hr:fina:adv:last-used";
82
+
83
+ export type FinaCombo = {
84
+ premise_id: string;
85
+ device_id: string;
86
+ };
87
+
88
+ export function getLastUsedFinaCombo(entityId: string): FinaCombo | null {
89
+ if (typeof window === "undefined") return null;
90
+ try {
91
+ const stored = localStorage.getItem(`${FINA_ADV_LAST_USED_KEY}:${entityId}`);
92
+ return stored ? JSON.parse(stored) : null;
93
+ } catch {
94
+ return null;
95
+ }
96
+ }
97
+
98
+ export function setLastUsedFinaCombo(entityId: string, combo: FinaCombo): void {
99
+ if (typeof window === "undefined") return;
100
+ try {
101
+ localStorage.setItem(`${FINA_ADV_LAST_USED_KEY}:${entityId}`, JSON.stringify(combo));
102
+ } catch {
103
+ // Ignore localStorage errors
104
+ }
105
+ }
@@ -25,9 +25,16 @@ import { DocumentRecipientSection } from "../../documents/create/document-recipi
25
25
  import { MarkAsPaidSection } from "../../documents/create/mark-as-paid-section";
26
26
  import { useDocumentCustomerForm } from "../../documents/create/use-document-customer-form";
27
27
  import type { DocumentTypes } from "../../documents/types";
28
+ import { useFinaPremises, useFinaSettings } from "../../entities/fina-settings-form/fina-settings.hooks";
28
29
  import { useFursPremises, useFursSettings } from "../../entities/furs-settings-form/furs-settings.hooks";
29
30
  import { getEntityErrors, getFormFieldErrors, validateEslogForm } from "../../invoices/create/eslog-validation";
30
- import { getLastUsedFursCombo, setLastUsedFursCombo, useCreateAdvanceInvoice } from "../advance-invoices.hooks";
31
+ import {
32
+ getLastUsedFinaCombo,
33
+ getLastUsedFursCombo,
34
+ setLastUsedFinaCombo,
35
+ setLastUsedFursCombo,
36
+ useCreateAdvanceInvoice,
37
+ } from "../advance-invoices.hooks";
31
38
  import de from "./locales/de";
32
39
  import es from "./locales/es";
33
40
  import fr from "./locales/fr";
@@ -118,6 +125,23 @@ export default function CreateAdvanceInvoiceForm({
118
125
  const [selectedDeviceName, setSelectedDeviceName] = useState<string | undefined>();
119
126
  const [skipFiscalization, setSkipFiscalization] = useState(false);
120
127
 
128
+ // ============================================================================
129
+ // FINA Settings & Premises
130
+ // ============================================================================
131
+ const { data: finaSettings, isLoading: isFinaSettingsLoading } = useFinaSettings(entityId);
132
+ const { data: finaPremises, isLoading: isFinaPremisesLoading } = useFinaPremises(entityId, {
133
+ enabled: finaSettings?.enabled === true,
134
+ });
135
+
136
+ const isFinaLoading = isFinaSettingsLoading || (finaSettings?.enabled && isFinaPremisesLoading);
137
+ const isFinaEnabled = finaSettings?.enabled === true;
138
+ const activeFinaPremises = useMemo(() => finaPremises?.filter((p: any) => p.is_active) || [], [finaPremises]);
139
+ const hasFinaPremises = activeFinaPremises.length > 0;
140
+
141
+ // FINA premise/device selection state (no skip - all FINA invoices must be fiscalized)
142
+ const [selectedFinaPremiseId, setSelectedFinaPremiseId] = useState<string | undefined>();
143
+ const [selectedFinaDeviceId, setSelectedFinaDeviceId] = useState<string | undefined>();
144
+
121
145
  // UI-only state (not part of API schema)
122
146
  const [markAsPaid, setMarkAsPaid] = useState(false);
123
147
  const [paymentTypes, setPaymentTypes] = useState<string[]>(["bank_transfer"]);
@@ -209,6 +233,51 @@ export default function CreateAdvanceInvoiceForm({
209
233
  }
210
234
  }, [selectedPremiseName, activePremises, selectedDeviceName]);
211
235
 
236
+ // Get active FINA devices for selected premise
237
+ const activeFinaDevices = useMemo(() => {
238
+ if (!selectedFinaPremiseId) return [];
239
+ const premise = activeFinaPremises.find((p: any) => p.premise_id === selectedFinaPremiseId);
240
+ return premise?.Devices?.filter((d: any) => d.is_active) || [];
241
+ }, [activeFinaPremises, selectedFinaPremiseId]);
242
+
243
+ // Initialize FINA selection from localStorage or first active combo
244
+ useEffect(() => {
245
+ if (!isFinaEnabled || !hasFinaPremises || selectedFinaPremiseId) return;
246
+
247
+ const lastUsed = getLastUsedFinaCombo(entityId);
248
+ if (lastUsed) {
249
+ const premise = activeFinaPremises.find((p: any) => p.premise_id === lastUsed.premise_id);
250
+ const device = premise?.Devices?.find((d: any) => d.device_id === lastUsed.device_id && d.is_active);
251
+ if (premise && device) {
252
+ setSelectedFinaPremiseId(lastUsed.premise_id);
253
+ setSelectedFinaDeviceId(lastUsed.device_id);
254
+ return;
255
+ }
256
+ }
257
+
258
+ const firstPremise = activeFinaPremises[0];
259
+ const firstDevice = firstPremise?.Devices?.find((d: any) => d.is_active);
260
+ if (firstPremise && firstDevice) {
261
+ setSelectedFinaPremiseId(firstPremise.premise_id);
262
+ setSelectedFinaDeviceId(firstDevice.device_id);
263
+ }
264
+ }, [isFinaEnabled, hasFinaPremises, activeFinaPremises, entityId, selectedFinaPremiseId]);
265
+
266
+ // When FINA premise changes, select first active device
267
+ useEffect(() => {
268
+ if (!selectedFinaPremiseId) return;
269
+ const premise = activeFinaPremises.find((p: any) => p.premise_id === selectedFinaPremiseId);
270
+ const firstDevice = premise?.Devices?.find((d: any) => d.is_active);
271
+ if (firstDevice && selectedFinaDeviceId !== firstDevice.device_id) {
272
+ const currentDeviceInPremise = premise?.Devices?.find(
273
+ (d: any) => d.device_id === selectedFinaDeviceId && d.is_active,
274
+ );
275
+ if (!currentDeviceInPremise) {
276
+ setSelectedFinaDeviceId(firstDevice.device_id);
277
+ }
278
+ }
279
+ }, [selectedFinaPremiseId, activeFinaPremises, selectedFinaDeviceId]);
280
+
212
281
  const form = useForm<CreateAdvanceInvoiceFormValues>({
213
282
  // Cast resolver to accept extended form type (includes UI-only fields)
214
283
  resolver: zodResolver(createAdvanceInvoiceSchema) as Resolver<CreateAdvanceInvoiceFormValues>,
@@ -258,23 +327,29 @@ export default function CreateAdvanceInvoiceForm({
258
327
  const isFursActive =
259
328
  isFursEnabled && hasFursPremises && selectedPremiseName && selectedDeviceName && !skipFiscalization;
260
329
 
330
+ // FINA selection ready and active checks
331
+ const isFinaSelectionReady =
332
+ !isFinaEnabled || !hasFinaPremises || (!!selectedFinaPremiseId && !!selectedFinaDeviceId);
333
+ const isFinaActive = isFinaEnabled && hasFinaPremises && selectedFinaPremiseId && selectedFinaDeviceId;
334
+
261
335
  // ============================================================================
262
336
  // Next Advance Invoice Number Preview
263
337
  // ============================================================================
264
338
  const { data: nextNumberData, isLoading: isNextNumberLoading } = useNextDocumentNumber(entityId, "advance_invoice", {
265
339
  businessPremiseName: isFursActive ? selectedPremiseName : undefined,
266
340
  electronicDeviceName: isFursActive ? selectedDeviceName : undefined,
267
- enabled: !!entityId && !isFursLoading && isFursSelectionReady,
341
+ enabled: !!entityId && !isFursLoading && isFursSelectionReady && !isFinaLoading && isFinaSelectionReady,
268
342
  });
269
343
 
270
344
  // Overall loading state
271
- const isFormDataLoading = isFursLoading || !isFursSelectionReady || isNextNumberLoading;
345
+ const isFormDataLoading =
346
+ isFursLoading || !isFursSelectionReady || isFinaLoading || !isFinaSelectionReady || isNextNumberLoading;
272
347
 
273
348
  // Update header action with FURS and e-SLOG toggle buttons
274
349
  useEffect(() => {
275
350
  if (!onHeaderActionChange) return;
276
351
 
277
- if (isFursLoading) {
352
+ if (isFursLoading || isFinaLoading) {
278
353
  onHeaderActionChange(null);
279
354
  return;
280
355
  }
@@ -368,6 +443,7 @@ export default function CreateAdvanceInvoiceForm({
368
443
  }
369
444
  }, [
370
445
  isFursLoading,
446
+ isFinaLoading,
371
447
  isFursEnabled,
372
448
  hasFursPremises,
373
449
  skipFiscalization,
@@ -422,6 +498,12 @@ export default function CreateAdvanceInvoiceForm({
422
498
  electronic_device_name: selectedDeviceName,
423
499
  });
424
500
  }
501
+ if (isFinaActive && selectedFinaPremiseId && selectedFinaDeviceId) {
502
+ setLastUsedFinaCombo(entityId, {
503
+ premise_id: selectedFinaPremiseId,
504
+ device_id: selectedFinaDeviceId,
505
+ });
506
+ }
425
507
  onSuccess?.(data);
426
508
  },
427
509
  onError,
@@ -463,12 +545,19 @@ export default function CreateAdvanceInvoiceForm({
463
545
  const eslogOptions =
464
546
  !isDraft && isEslogAvailable ? { validation_enabled: eslogValidationEnabled === true } : undefined;
465
547
 
548
+ // Build FINA options (skip for drafts; FINA can't be skipped)
549
+ const finaOptions =
550
+ !isDraft && isFinaEnabled && selectedFinaPremiseId && selectedFinaDeviceId
551
+ ? { premise_id: selectedFinaPremiseId, device_id: selectedFinaDeviceId, payment_type: paymentTypes[0] }
552
+ : undefined;
553
+
466
554
  const payload = prepareAdvanceInvoiceSubmission(values, {
467
555
  originalCustomer,
468
556
  wasCustomerFormShown: showCustomerForm,
469
557
  markAsPaid: isDraft ? false : markAsPaid,
470
558
  paymentTypes,
471
559
  furs: fursOptions,
560
+ fina: finaOptions,
472
561
  eslog: eslogOptions,
473
562
  priceModes: priceModesRef.current,
474
563
  isDraft,
@@ -483,11 +572,14 @@ export default function CreateAdvanceInvoiceForm({
483
572
  form,
484
573
  isEslogAvailable,
485
574
  isFursEnabled,
575
+ isFinaEnabled,
486
576
  markAsPaid,
487
577
  originalCustomer,
488
578
  paymentTypes,
489
579
  selectedDeviceName,
490
580
  selectedPremiseName,
581
+ selectedFinaPremiseId,
582
+ selectedFinaDeviceId,
491
583
  showCustomerForm,
492
584
  skipFiscalization,
493
585
  ],
@@ -668,6 +760,18 @@ export default function CreateAdvanceInvoiceForm({
668
760
  }
669
761
  : undefined
670
762
  }
763
+ finaInline={
764
+ isFinaEnabled && hasFinaPremises
765
+ ? {
766
+ premises: activeFinaPremises.map((p: any) => ({ id: p.id, premise_id: p.premise_id })),
767
+ devices: activeFinaDevices.map((d: any) => ({ id: d.id, device_id: d.device_id })),
768
+ selectedPremise: selectedFinaPremiseId,
769
+ selectedDevice: selectedFinaDeviceId,
770
+ onPremiseChange: setSelectedFinaPremiseId,
771
+ onDeviceChange: setSelectedFinaDeviceId,
772
+ }
773
+ : undefined
774
+ }
671
775
  >
672
776
  {/* Mark as paid section (UI-only state, not in form schema) */}
673
777
  <MarkAsPaidSection
@@ -676,6 +780,7 @@ export default function CreateAdvanceInvoiceForm({
676
780
  paymentTypes={paymentTypes}
677
781
  onPaymentTypesChange={setPaymentTypes}
678
782
  t={t}
783
+ alwaysShowPaymentType={!!isFinaActive}
679
784
  />
680
785
  </DocumentDetailsSection>
681
786
  </div>
@@ -26,4 +26,6 @@ export default {
26
26
  Card: "Karte",
27
27
  Check: "Scheck",
28
28
  Other: "Andere",
29
+ Premise: "Geschäftsräume",
30
+ Device: "Gerät",
29
31
  } as const;
@@ -26,4 +26,6 @@ export default {
26
26
  Card: "Tarjeta",
27
27
  Check: "Cheque",
28
28
  Other: "Otro",
29
+ Premise: "Local",
30
+ Device: "Dispositivo",
29
31
  } as const;
@@ -25,4 +25,6 @@ export default {
25
25
  Card: "Carte",
26
26
  Check: "Cheque",
27
27
  Other: "Autre",
28
+ Premise: "Local",
29
+ Device: "Appareil",
28
30
  } as const;
@@ -24,4 +24,6 @@ export default {
24
24
  Card: "Kartica",
25
25
  Check: "Cek",
26
26
  Other: "Ostalo",
27
+ Premise: "Prostor",
28
+ Device: "Uredaj",
27
29
  } as const;
@@ -26,4 +26,6 @@ export default {
26
26
  Card: "Carta",
27
27
  Check: "Assegno",
28
28
  Other: "Altro",
29
+ Premise: "Locale",
30
+ Device: "Dispositivo",
29
31
  } as const;
@@ -25,4 +25,6 @@ export default {
25
25
  Card: "Kaart",
26
26
  Check: "Cheque",
27
27
  Other: "Overig",
28
+ Premise: "Bedrijfsruimte",
29
+ Device: "Apparaat",
28
30
  } as const;
@@ -25,4 +25,6 @@ export default {
25
25
  Card: "Karta",
26
26
  Check: "Czek",
27
27
  Other: "Inne",
28
+ Premise: "Lokal",
29
+ Device: "Urządzenie",
28
30
  } as const;
@@ -26,4 +26,6 @@ export default {
26
26
  Card: "Cartao",
27
27
  Check: "Cheque",
28
28
  Other: "Outro",
29
+ Premise: "Estabelecimento",
30
+ Device: "Dispositivo",
29
31
  } as const;
@@ -22,4 +22,6 @@ export default {
22
22
  Card: "Kartica",
23
23
  Check: "Ček",
24
24
  Other: "Drugo",
25
+ Premise: "Poslovni prostor",
26
+ Device: "Naprava",
25
27
  } as const;
@@ -8,6 +8,12 @@ type FursData = {
8
8
  skip?: boolean;
9
9
  };
10
10
 
11
+ type FinaData = {
12
+ premise_id?: string;
13
+ device_id?: string;
14
+ payment_type?: string;
15
+ };
16
+
11
17
  type EslogData = {
12
18
  validation_enabled?: boolean;
13
19
  };
@@ -22,6 +28,8 @@ type PrepareOptions = {
22
28
  paymentTypes?: string[];
23
29
  /** FURS fiscalization data (for Slovenia) */
24
30
  furs?: FursData;
31
+ /** FINA fiscalization data (for Croatia) */
32
+ fina?: FinaData;
25
33
  /** e-SLOG validation data (for Slovenia) */
26
34
  eslog?: EslogData;
27
35
  /** Map of item index to gross price mode (collected from component state) */
@@ -63,6 +71,15 @@ export function prepareAdvanceInvoiceSubmission(
63
71
  }
64
72
  }
65
73
 
74
+ // Add FINA data if provided (FINA can't be skipped - all invoices must be fiscalized)
75
+ if (options.fina?.premise_id && options.fina.device_id) {
76
+ (payload as any).fina = {
77
+ premise_id: options.fina.premise_id,
78
+ device_id: options.fina.device_id,
79
+ ...(options.fina.payment_type && { payment_type: options.fina.payment_type }),
80
+ };
81
+ }
82
+
66
83
  // Add e-SLOG data if provided
67
84
  if (options.eslog !== undefined) {
68
85
  (payload as any).eslog = {
@@ -17,6 +17,7 @@ import { useAdvanceInvoiceDownload } from "./use-advance-invoice-download";
17
17
 
18
18
  type AdvanceInvoiceListRowActionsProps = {
19
19
  advanceInvoice: AdvanceInvoice;
20
+ onView?: (advanceInvoice: AdvanceInvoice) => void;
20
21
  onAddPayment?: (advanceInvoice: AdvanceInvoice) => void;
21
22
  onDuplicate?: (advanceInvoice: AdvanceInvoice) => void;
22
23
  onDownloadStart?: () => void;
@@ -28,6 +29,7 @@ type AdvanceInvoiceListRowActionsProps = {
28
29
 
29
30
  export default function AdvanceInvoiceListRowActions({
30
31
  advanceInvoice,
32
+ onView,
31
33
  onAddPayment,
32
34
  onDuplicate,
33
35
  onDownloadStart,
@@ -63,12 +65,7 @@ export default function AdvanceInvoiceListRowActions({
63
65
  </DropdownMenuGroup>
64
66
  <DropdownMenuSeparator />
65
67
  <DropdownMenuGroup>
66
- <DropdownMenuItem
67
- className="cursor-pointer"
68
- onClick={() => {
69
- window.location.href = `/app/documents/view/${advanceInvoice.id}`;
70
- }}
71
- >
68
+ <DropdownMenuItem className="cursor-pointer" onClick={() => onView?.(advanceInvoice)}>
72
69
  <Eye className="h-4 w-4" />
73
70
  {t("View advance invoice")}
74
71
  </DropdownMenuItem>
@@ -1,8 +1,9 @@
1
1
  import type { AdvanceInvoice } from "@spaceinvoices/js-sdk";
2
- import { useMemo } from "react";
2
+ import { useCallback, useMemo, useState } from "react";
3
3
  import { DataTable } from "@/ui/components/table/data-table";
4
4
  import { FormattedDate } from "@/ui/components/table/date-cell";
5
5
  import { useTableFetch } from "@/ui/components/table/hooks/use-table-fetch";
6
+ import { SelectionToolbar } from "@/ui/components/table/selection-toolbar";
6
7
  import type {
7
8
  Column,
8
9
  FilterConfig,
@@ -45,16 +46,19 @@ type AdvanceInvoiceListTableProps = {
45
46
  namespace?: string;
46
47
  locale?: string;
47
48
  entityId?: string;
49
+ onView?: (advanceInvoice: AdvanceInvoice) => void;
48
50
  onAddPayment?: (advanceInvoice: AdvanceInvoice) => void;
49
51
  onDuplicate?: (advanceInvoice: AdvanceInvoice) => void;
50
52
  onDownloadStart?: () => void;
51
53
  onDownloadSuccess?: (fileName: string) => void;
52
54
  onDownloadError?: (error: string) => void;
55
+ onExportSelected?: (documentIds: string[]) => void;
53
56
  } & ListTableProps<AdvanceInvoice>;
54
57
 
55
58
  export default function AdvanceInvoiceListTable({
56
59
  queryParams,
57
60
  onRowClick,
61
+ onView,
58
62
  onAddPayment,
59
63
  onDuplicate,
60
64
  onChangeParams,
@@ -62,6 +66,7 @@ export default function AdvanceInvoiceListTable({
62
66
  onDownloadStart,
63
67
  onDownloadSuccess,
64
68
  onDownloadError,
69
+ onExportSelected,
65
70
  ...i18nProps
66
71
  }: AdvanceInvoiceListTableProps) {
67
72
  const t = createTranslation({
@@ -70,6 +75,7 @@ export default function AdvanceInvoiceListTable({
70
75
  });
71
76
 
72
77
  const { sdk } = useSDK();
78
+ const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());
73
79
 
74
80
  const handleFetch = useTableFetch(async (params: TableQueryParams) => {
75
81
  if (!sdk) throw new Error("SDK not initialized");
@@ -99,6 +105,28 @@ export default function AdvanceInvoiceListTable({
99
105
  [t],
100
106
  );
101
107
 
108
+ const handleExportPdfs = useCallback(() => {
109
+ if (selectedIds.size > 0 && onExportSelected) {
110
+ onExportSelected(Array.from(selectedIds));
111
+ }
112
+ }, [selectedIds, onExportSelected]);
113
+
114
+ const handleDeselectAll = useCallback(() => {
115
+ setSelectedIds(new Set());
116
+ }, []);
117
+
118
+ const selectionToolbar = useCallback(
119
+ (count: number) => (
120
+ <SelectionToolbar
121
+ selectedCount={count}
122
+ onExportPdfs={onExportSelected ? handleExportPdfs : undefined}
123
+ onDeselectAll={handleDeselectAll}
124
+ t={t}
125
+ />
126
+ ),
127
+ [handleExportPdfs, handleDeselectAll, onExportSelected, t],
128
+ );
129
+
102
130
  const columns: Column<AdvanceInvoice>[] = useMemo(
103
131
  () => [
104
132
  {
@@ -163,6 +191,7 @@ export default function AdvanceInvoiceListTable({
163
191
  cell: (advanceInvoice) => (
164
192
  <AdvanceInvoiceListRowActions
165
193
  advanceInvoice={advanceInvoice}
194
+ onView={onView}
166
195
  onAddPayment={onAddPayment}
167
196
  onDuplicate={onDuplicate}
168
197
  onDownloadStart={onDownloadStart}
@@ -174,7 +203,17 @@ export default function AdvanceInvoiceListTable({
174
203
  ),
175
204
  },
176
205
  ],
177
- [t, onRowClick, onAddPayment, onDuplicate, onDownloadStart, onDownloadSuccess, onDownloadError, i18nProps.locale],
206
+ [
207
+ t,
208
+ onRowClick,
209
+ onView,
210
+ onAddPayment,
211
+ onDuplicate,
212
+ onDownloadStart,
213
+ onDownloadSuccess,
214
+ onDownloadError,
215
+ i18nProps.locale,
216
+ ],
178
217
  );
179
218
 
180
219
  return (
@@ -190,6 +229,10 @@ export default function AdvanceInvoiceListTable({
190
229
  filterConfig={filterConfig}
191
230
  t={t}
192
231
  locale={i18nProps.locale}
232
+ selectable={!!onExportSelected}
233
+ selectedIds={selectedIds}
234
+ onSelectionChange={setSelectedIds}
235
+ selectionToolbar={selectionToolbar}
193
236
  />
194
237
  );
195
238
  }
@@ -38,4 +38,7 @@ export default {
38
38
  "No results found": "Keine Vorauszahlungsrechnungen gefunden",
39
39
  "Try adjusting your search criteria": "Versuchen Sie, Ihre Suchkriterien anzupassen",
40
40
  "Clear search": "Suche zurücksetzen",
41
+ selected: "ausgewählt",
42
+ "Export PDFs": "PDFs exportieren",
43
+ "Deselect all": "Auswahl aufheben",
41
44
  } as const;
@@ -5,4 +5,7 @@ export default {
5
5
  "Create new": "Create advance invoice",
6
6
  // No results translations
7
7
  "No results found": "No advance invoices found",
8
+ selected: "selected",
9
+ "Export PDFs": "Export PDFs",
10
+ "Deselect all": "Deselect all",
8
11
  } as const;
@@ -38,4 +38,7 @@ export default {
38
38
  "No results found": "No se encontraron facturas anticipadas",
39
39
  "Try adjusting your search criteria": "Intente ajustar sus criterios de busqueda",
40
40
  "Clear search": "Limpiar busqueda",
41
+ selected: "seleccionados",
42
+ "Export PDFs": "Exportar PDFs",
43
+ "Deselect all": "Deseleccionar todo",
41
44
  } as const;
@@ -38,4 +38,7 @@ export default {
38
38
  "No results found": "Aucune facture d'acompte trouvee",
39
39
  "Try adjusting your search criteria": "Essayez de modifier vos criteres de recherche",
40
40
  "Clear search": "Effacer la recherche",
41
+ selected: "sélectionnés",
42
+ "Export PDFs": "Exporter les PDF",
43
+ "Deselect all": "Tout désélectionner",
41
44
  } as const;
@@ -38,4 +38,7 @@ export default {
38
38
  "No results found": "Nije pronadjen nijedan avansni racun",
39
39
  "Try adjusting your search criteria": "Pokusajte prilagoditi kriterije pretrazivanja",
40
40
  "Clear search": "Ocisti pretragu",
41
+ selected: "odabranih",
42
+ "Export PDFs": "Izvezi PDF-ove",
43
+ "Deselect all": "Poništi odabir",
41
44
  } as const;
@@ -38,4 +38,7 @@ export default {
38
38
  "No results found": "Nessuna fattura anticipata trovata",
39
39
  "Try adjusting your search criteria": "Prova a modificare i criteri di ricerca",
40
40
  "Clear search": "Cancella ricerca",
41
+ selected: "selezionati",
42
+ "Export PDFs": "Esporta PDF",
43
+ "Deselect all": "Deseleziona tutto",
41
44
  } as const;
@@ -38,4 +38,7 @@ export default {
38
38
  "No results found": "Geen voorschotfacturen gevonden",
39
39
  "Try adjusting your search criteria": "Probeer uw zoekcriteria aan te passen",
40
40
  "Clear search": "Zoekopdracht wissen",
41
+ selected: "geselecteerd",
42
+ "Export PDFs": "PDFs exporteren",
43
+ "Deselect all": "Alles deselecteren",
41
44
  } as const;
@@ -38,4 +38,7 @@ export default {
38
38
  "No results found": "Nie znaleziono faktur zaliczkowych",
39
39
  "Try adjusting your search criteria": "Sprobuj dostosowac kryteria wyszukiwania",
40
40
  "Clear search": "Wyczysc wyszukiwanie",
41
+ selected: "wybranych",
42
+ "Export PDFs": "Eksportuj PDF-y",
43
+ "Deselect all": "Odznacz wszystko",
41
44
  } as const;
@@ -38,4 +38,7 @@ export default {
38
38
  "No results found": "Nenhuma fatura antecipada encontrada",
39
39
  "Try adjusting your search criteria": "Tente ajustar os seus criterios de pesquisa",
40
40
  "Clear search": "Limpar pesquisa",
41
+ selected: "selecionados",
42
+ "Export PDFs": "Exportar PDFs",
43
+ "Deselect all": "Desselecionar tudo",
41
44
  } as const;
@@ -38,4 +38,7 @@ export default {
38
38
  "No results found": "Ni najdenih avansnih računov",
39
39
  "Try adjusting your search criteria": "Poskusite prilagoditi iskalne kriterije",
40
40
  "Clear search": "Počisti iskanje",
41
+ selected: "izbranih",
42
+ "Export PDFs": "Izvozi PDF-je",
43
+ "Deselect all": "Počisti izbiro",
41
44
  } as const;