@spaceinvoices/react-ui 0.4.0 → 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 (200) hide show
  1. package/cli/dist/index.js +1 -1
  2. package/package.json +1 -1
  3. package/registry.json +23 -27
  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/premises-management-section.tsx +1 -0
  107. package/src/components/entities/furs-settings-form/sections/register-premise-dialog.tsx +58 -34
  108. package/src/components/entities/settings/tax-rules-settings-form.tsx +4 -4
  109. package/src/components/estimates/list/list-row-actions.tsx +3 -7
  110. package/src/components/estimates/list/list-table.tsx +35 -2
  111. package/src/components/estimates/list/locales/de.ts +3 -0
  112. package/src/components/estimates/list/locales/en.ts +3 -0
  113. package/src/components/estimates/list/locales/es.ts +3 -0
  114. package/src/components/estimates/list/locales/fr.ts +3 -0
  115. package/src/components/estimates/list/locales/hr.ts +3 -0
  116. package/src/components/estimates/list/locales/it.ts +3 -0
  117. package/src/components/estimates/list/locales/nl.ts +3 -0
  118. package/src/components/estimates/list/locales/pl.ts +3 -0
  119. package/src/components/estimates/list/locales/pt.ts +3 -0
  120. package/src/components/estimates/list/locales/sl.ts +3 -0
  121. package/src/components/export/document-export-form.tsx +34 -34
  122. package/src/components/invoices/create/create-invoice-form.tsx +107 -5
  123. package/src/components/invoices/create/prepare-invoice-submission.ts +17 -0
  124. package/src/components/invoices/invoices.hooks.ts +32 -2
  125. package/src/components/invoices/list/list-row-actions.tsx +23 -8
  126. package/src/components/invoices/list/list-table.tsx +53 -2
  127. package/src/components/invoices/list/locales/de.ts +4 -0
  128. package/src/components/invoices/list/locales/en.ts +4 -0
  129. package/src/components/invoices/list/locales/es.ts +4 -0
  130. package/src/components/invoices/list/locales/fr.ts +4 -0
  131. package/src/components/invoices/list/locales/hr.ts +4 -0
  132. package/src/components/invoices/list/locales/it.ts +4 -0
  133. package/src/components/invoices/list/locales/nl.ts +4 -0
  134. package/src/components/invoices/list/locales/pl.ts +4 -0
  135. package/src/components/invoices/list/locales/pt.ts +4 -0
  136. package/src/components/invoices/list/locales/sl.ts +4 -0
  137. package/src/components/invoices/view/fiscalization-status-card.tsx +4 -1
  138. package/src/components/items/item-list-table/item-list-row-actions.tsx +3 -7
  139. package/src/components/items/item-list-table/item-list-row.tsx +3 -2
  140. package/src/components/items/item-list-table/item-list-table.tsx +5 -1
  141. package/src/components/recurring-invoices/create-recurring-invoice-form/create-recurring-invoice-form.tsx +418 -0
  142. package/src/components/recurring-invoices/create-recurring-invoice-form/locales/de.ts +45 -0
  143. package/src/components/recurring-invoices/create-recurring-invoice-form/locales/es.ts +44 -0
  144. package/src/components/recurring-invoices/create-recurring-invoice-form/locales/fr.ts +44 -0
  145. package/src/components/recurring-invoices/create-recurring-invoice-form/locales/hr.ts +44 -0
  146. package/src/components/recurring-invoices/create-recurring-invoice-form/locales/it.ts +44 -0
  147. package/src/components/recurring-invoices/create-recurring-invoice-form/locales/nl.ts +44 -0
  148. package/src/components/recurring-invoices/create-recurring-invoice-form/locales/pl.ts +44 -0
  149. package/src/components/recurring-invoices/create-recurring-invoice-form/locales/pt.ts +44 -0
  150. package/src/components/recurring-invoices/create-recurring-invoice-form/locales/sl.ts +44 -0
  151. package/src/components/recurring-invoices/index.ts +3 -0
  152. package/src/components/recurring-invoices/list/index.ts +2 -0
  153. package/src/components/recurring-invoices/list/list-row-actions.tsx +139 -0
  154. package/src/components/recurring-invoices/list/list-table.tsx +179 -0
  155. package/src/components/recurring-invoices/list/locales/de.ts +27 -0
  156. package/src/components/recurring-invoices/list/locales/en.ts +5 -0
  157. package/src/components/recurring-invoices/list/locales/es.ts +27 -0
  158. package/src/components/recurring-invoices/list/locales/fr.ts +27 -0
  159. package/src/components/recurring-invoices/list/locales/hr.ts +27 -0
  160. package/src/components/recurring-invoices/list/locales/it.ts +27 -0
  161. package/src/components/recurring-invoices/list/locales/nl.ts +27 -0
  162. package/src/components/recurring-invoices/list/locales/pl.ts +27 -0
  163. package/src/components/recurring-invoices/list/locales/pt.ts +27 -0
  164. package/src/components/recurring-invoices/list/locales/sl.ts +27 -0
  165. package/src/components/recurring-invoices/recurring-invoices.hooks.ts +28 -0
  166. package/src/components/table/data-table.tsx +122 -5
  167. package/src/components/table/selection-toolbar.tsx +36 -0
  168. package/src/components/tax-reports/kir-export-form.tsx +75 -55
  169. package/src/components/taxes/tax-list-table/tax-list-row-actions.tsx +3 -6
  170. package/src/components/taxes/tax-list-table/tax-list-row.tsx +3 -2
  171. package/src/components/taxes/tax-list-table/tax-list-table.tsx +5 -1
  172. package/src/components/ui/checkbox.tsx +5 -5
  173. package/src/generate-schemas.ts +46 -7
  174. package/src/generated/schemas/advanceinvoice.ts +79 -187
  175. package/src/generated/schemas/authorizeshopify_body.ts +22 -0
  176. package/src/generated/schemas/creditnote.ts +60 -88
  177. package/src/generated/schemas/customadvanceinvoice.ts +70 -97
  178. package/src/generated/schemas/customcreditnote.ts +70 -97
  179. package/src/generated/schemas/customestimate.ts +68 -97
  180. package/src/generated/schemas/custominvoice.ts +70 -97
  181. package/src/generated/schemas/entity.ts +1 -1
  182. package/src/generated/schemas/estimate.ts +67 -172
  183. package/src/generated/schemas/index.ts +39 -28
  184. package/src/generated/schemas/invoice.ts +79 -187
  185. package/src/generated/schemas/order.ts +127 -0
  186. package/src/generated/schemas/orderintegration.ts +51 -0
  187. package/src/generated/schemas/payment.ts +2 -0
  188. package/src/generated/schemas/recurringinvoice.ts +61 -0
  189. package/src/generated/schemas/registerfursrealestatepremise_body.ts +11 -7
  190. package/src/generated/schemas/renderadvanceinvoicepreview_body.ts +140 -269
  191. package/src/generated/schemas/rendercreditnotepreview_body.ts +141 -270
  192. package/src/generated/schemas/renderestimatepreview_body.ts +112 -212
  193. package/src/generated/schemas/renderinvoicepreview_body.ts +141 -270
  194. package/src/generated/schemas/webhook.ts +42 -0
  195. package/src/lib/furs-error-utils.ts +36 -0
  196. package/src/lib/schemas/advance-invoice.ts +3 -3
  197. package/src/lib/schemas/credit-note.ts +3 -3
  198. package/src/lib/schemas/estimate.ts +3 -3
  199. package/src/lib/schemas/invoice.ts +3 -3
  200. package/src/providers/white-label-provider.tsx +3 -0
@@ -38,4 +38,7 @@ export default {
38
38
  "No results found": "Nenhuma nota de credito 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 dobropisov",
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;
@@ -1,7 +1,6 @@
1
1
  import { zodResolver } from "@hookform/resolvers/zod";
2
2
  import type { CompanyRegistryResult, CreateCustomerRequest, Customer } from "@spaceinvoices/js-sdk";
3
3
  import { useForm } from "react-hook-form";
4
- import type z from "zod";
5
4
  import { CompanyRegistryAutocomplete } from "@/ui/components/company-registry";
6
5
  import { FormInput } from "@/ui/components/form";
7
6
  import { Form } from "@/ui/components/ui/form";
@@ -39,6 +39,25 @@ type FursInlineProps = {
39
39
  isSkipped?: boolean;
40
40
  };
41
41
 
42
+ type FinaPremise = {
43
+ id: string;
44
+ premise_id: string;
45
+ };
46
+
47
+ type FinaDevice = {
48
+ id: string;
49
+ device_id: string;
50
+ };
51
+
52
+ type FinaInlineProps = {
53
+ premises: FinaPremise[];
54
+ devices: FinaDevice[];
55
+ selectedPremise?: string;
56
+ selectedDevice?: string;
57
+ onPremiseChange: (value: string | undefined) => void;
58
+ onDeviceChange: (value: string | undefined) => void;
59
+ };
60
+
42
61
  type ServiceDateProps = {
43
62
  dateType: "single" | "range";
44
63
  onDateTypeChange: (type: "single" | "range") => void;
@@ -50,6 +69,7 @@ type DocumentDetailsSectionProps = {
50
69
  t: (key: string) => string;
51
70
  children?: React.ReactNode; // For document-specific additions (e.g., mark as paid for invoices)
52
71
  fursInline?: FursInlineProps; // FURS premise/device inline with number
72
+ finaInline?: FinaInlineProps; // FINA premise/device inline with number
53
73
  serviceDate?: ServiceDateProps; // Service date section (invoice only)
54
74
  };
55
75
 
@@ -59,6 +79,7 @@ export function DocumentDetailsSection({
59
79
  t,
60
80
  children,
61
81
  fursInline,
82
+ finaInline,
62
83
  serviceDate,
63
84
  }: DocumentDetailsSectionProps) {
64
85
  // Determine the date field name based on document type
@@ -67,8 +88,9 @@ export function DocumentDetailsSection({
67
88
  const dateFieldLabel =
68
89
  documentType === "invoice" || documentType === "advance_invoice" ? t("Due Date") : t("Valid Until");
69
90
 
70
- // Check if FURS inline should show premise/device selects
91
+ // Check if FURS/FINA inline should show premise/device selects
71
92
  const showFursSelects = fursInline && !fursInline.isSkipped;
93
+ const showFinaSelects = !!finaInline;
72
94
 
73
95
  return (
74
96
  <div className="flex-1 space-y-4">
@@ -125,6 +147,50 @@ export function DocumentDetailsSection({
125
147
  </TooltipContent>
126
148
  </Tooltip>
127
149
  </div>
150
+ ) : showFinaSelects ? (
151
+ <div className="flex gap-2">
152
+ <Select
153
+ value={finaInline.selectedPremise || ""}
154
+ onValueChange={(v) => finaInline.onPremiseChange(v ?? undefined)}
155
+ >
156
+ <SelectTrigger className="w-24">
157
+ <SelectValue placeholder={t("Premise")} />
158
+ </SelectTrigger>
159
+ <SelectContent>
160
+ {finaInline.premises.map((premise) => (
161
+ <SelectItem key={premise.id} value={premise.premise_id}>
162
+ {premise.premise_id}
163
+ </SelectItem>
164
+ ))}
165
+ </SelectContent>
166
+ </Select>
167
+ <Select
168
+ value={finaInline.selectedDevice || ""}
169
+ onValueChange={(v) => finaInline.onDeviceChange(v ?? undefined)}
170
+ disabled={!finaInline.selectedPremise || finaInline.devices.length === 0}
171
+ >
172
+ <SelectTrigger className="w-24">
173
+ <SelectValue placeholder={t("Device")} />
174
+ </SelectTrigger>
175
+ <SelectContent>
176
+ {finaInline.devices.map((device) => (
177
+ <SelectItem key={device.id} value={device.device_id}>
178
+ {device.device_id}
179
+ </SelectItem>
180
+ ))}
181
+ </SelectContent>
182
+ </Select>
183
+ <Tooltip>
184
+ <TooltipTrigger asChild>
185
+ <FormControl>
186
+ <Input {...field} disabled className="flex-1" />
187
+ </FormControl>
188
+ </TooltipTrigger>
189
+ <TooltipContent>
190
+ <p>{t("Number format can be changed in settings")}</p>
191
+ </TooltipContent>
192
+ </Tooltip>
193
+ </div>
128
194
  ) : (
129
195
  <Tooltip>
130
196
  <TooltipTrigger asChild>
@@ -29,6 +29,8 @@ type MarkAsPaidSectionProps = {
29
29
  onPaymentTypesChange: (values: string[]) => void;
30
30
  /** Translation function */
31
31
  t: (key: string) => string;
32
+ /** Always show payment type selector (e.g. for FINA fiscalization) */
33
+ alwaysShowPaymentType?: boolean;
32
34
  };
33
35
 
34
36
  export function MarkAsPaidSection({
@@ -37,9 +39,12 @@ export function MarkAsPaidSection({
37
39
  paymentTypes,
38
40
  onPaymentTypesChange,
39
41
  t,
42
+ alwaysShowPaymentType,
40
43
  }: MarkAsPaidSectionProps) {
44
+ const showPaymentTypes = checked || alwaysShowPaymentType;
45
+
41
46
  return (
42
- <div className={cn("flex flex-col gap-4 rounded-md border p-4", checked && "gap-3")}>
47
+ <div className={cn("flex flex-col gap-4 rounded-md border p-4", showPaymentTypes && "gap-3")}>
43
48
  <div className="flex flex-row items-center space-x-3 space-y-0">
44
49
  <Checkbox checked={checked} onCheckedChange={(v) => onCheckedChange(v === true)} />
45
50
  <div className="flex items-center gap-1 leading-none">
@@ -61,9 +66,13 @@ export function MarkAsPaidSection({
61
66
  </div>
62
67
  </div>
63
68
 
64
- {checked && (
69
+ {showPaymentTypes && (
65
70
  <div className="flex flex-col gap-2">
71
+ {alwaysShowPaymentType && !checked && (
72
+ <Label className="text-muted-foreground text-xs">{t("Payment Type")}</Label>
73
+ )}
66
74
  {paymentTypes.map((type, index) => (
75
+ // biome-ignore lint/suspicious/noArrayIndexKey: payment types list uses index key
67
76
  <div key={index} className="flex items-center gap-2">
68
77
  <Select
69
78
  value={type}
@@ -1,5 +1,6 @@
1
1
  import type { AdvanceInvoice, CreditNote, Estimate, Invoice } from "@spaceinvoices/js-sdk";
2
2
  import {
3
+ Ban,
3
4
  Check,
4
5
  CheckCircle,
5
6
  ChevronDown,
@@ -11,6 +12,7 @@ import {
11
12
  Mail,
12
13
  Pencil,
13
14
  Plus,
15
+ RefreshCw,
14
16
  Share2,
15
17
  Trash2,
16
18
  } from "lucide-react";
@@ -88,6 +90,14 @@ interface DocumentActionsBarProps extends ComponentTranslationProps {
88
90
  onDeleteDraft?: () => void;
89
91
  /** Whether draft deletion is in progress */
90
92
  isDeletingDraft?: boolean;
93
+ /** Called when user wants to create a recurring schedule from this document */
94
+ onCreateRecurring?: () => void;
95
+ /** Custom label for recurring button (e.g. "Edit Recurring" when one already exists) */
96
+ recurringLabel?: string;
97
+ /** Called when user wants to void the document */
98
+ onVoid?: () => void;
99
+ /** Whether voiding is in progress */
100
+ isVoiding?: boolean;
91
101
  }
92
102
 
93
103
  function getApiLocale(uiLanguage: string): string {
@@ -128,6 +138,10 @@ export function DocumentActionsBar({
128
138
  isFinalizing,
129
139
  onDeleteDraft,
130
140
  isDeletingDraft,
141
+ onCreateRecurring,
142
+ recurringLabel,
143
+ onVoid,
144
+ isVoiding,
131
145
  ...i18nProps
132
146
  }: DocumentActionsBarProps) {
133
147
  const t = createTranslation({ translations, locale: currentLocale, ...i18nProps });
@@ -298,6 +312,14 @@ export function DocumentActionsBar({
298
312
  </Button>
299
313
  ) : null}
300
314
 
315
+ {/* Recurring */}
316
+ {onCreateRecurring && (
317
+ <Button variant="outline" size="sm" onClick={onCreateRecurring} className="cursor-pointer">
318
+ <RefreshCw className="mr-2 h-4 w-4" />
319
+ {recurringLabel || t("Recurring")}
320
+ </Button>
321
+ )}
322
+
301
323
  {/* Duplicate/Convert */}
302
324
  {onDuplicate && (
303
325
  <DropdownMenu>
@@ -318,6 +340,14 @@ export function DocumentActionsBar({
318
340
  </DropdownMenu>
319
341
  )}
320
342
 
343
+ {/* Void */}
344
+ {!isDraft && onVoid && (
345
+ <Button variant="destructive" size="sm" onClick={onVoid} disabled={isVoiding} className="cursor-pointer">
346
+ {isVoiding ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : <Ban className="mr-2 h-4 w-4" />}
347
+ {isVoiding ? t("Voiding...") : t("Void")}
348
+ </Button>
349
+ )}
350
+
321
351
  {/* Draft Actions */}
322
352
  {isDraft && onFinalize && (
323
353
  <Button variant="default" size="sm" onClick={onFinalize} disabled={isFinalizing} className="cursor-pointer">
@@ -14,6 +14,7 @@ export default {
14
14
  "Unshare failed": "Freigabe aufheben fehlgeschlagen",
15
15
  "Download failed": "Download fehlgeschlagen",
16
16
  "e-SLOG download failed": "e-SLOG Download fehlgeschlagen",
17
+ Recurring: "Wiederkehrend",
17
18
  Duplicate: "Duplizieren",
18
19
  "Duplicate invoice": "Rechnung duplizieren",
19
20
  "Duplicate estimate": "Angebot duplizieren",
@@ -83,6 +84,10 @@ export default {
83
84
  "Delete draft failed": "Entwurf löschen fehlgeschlagen",
84
85
  Draft: "Entwurf",
85
86
 
87
+ // Void
88
+ Void: "Stornieren",
89
+ "Voiding...": "Stornierung...",
90
+
86
91
  // Activity list
87
92
  Activity: "Aktivität",
88
93
  "No activity": "Keine Aktivität",
@@ -13,6 +13,7 @@ export default {
13
13
  "Unshare failed": "Error al dejar de compartir",
14
14
  "Download failed": "Error en la descarga",
15
15
  "e-SLOG download failed": "Error en la descarga e-SLOG",
16
+ Recurring: "Recurrente",
16
17
  Duplicate: "Duplicar",
17
18
  "Duplicate invoice": "Duplicar factura",
18
19
  "Duplicate estimate": "Duplicar presupuesto",
@@ -81,6 +82,10 @@ export default {
81
82
  "Delete draft failed": "Error al eliminar el borrador",
82
83
  Draft: "Borrador",
83
84
 
85
+ // Void
86
+ Void: "Anular",
87
+ "Voiding...": "Anulando...",
88
+
84
89
  // Activity list
85
90
  Activity: "Actividad",
86
91
  "No activity": "Sin actividad",
@@ -13,6 +13,7 @@ export default {
13
13
  "Unshare failed": "Échec de l'annulation du partage",
14
14
  "Download failed": "Échec du téléchargement",
15
15
  "e-SLOG download failed": "Échec du téléchargement e-SLOG",
16
+ Recurring: "Récurrent",
16
17
  Duplicate: "Dupliquer",
17
18
  "Duplicate invoice": "Dupliquer la facture",
18
19
  "Duplicate estimate": "Dupliquer le devis",
@@ -81,6 +82,10 @@ export default {
81
82
  "Delete draft failed": "Échec de la suppression du brouillon",
82
83
  Draft: "Brouillon",
83
84
 
85
+ // Void
86
+ Void: "Annuler",
87
+ "Voiding...": "Annulation...",
88
+
84
89
  // Activity list
85
90
  Activity: "Activité",
86
91
  "No activity": "Aucune activité",
@@ -13,6 +13,7 @@ export default {
13
13
  "Unshare failed": "Uklanjanje dijeljenja nije uspjelo",
14
14
  "Download failed": "Preuzimanje nije uspjelo",
15
15
  "e-SLOG download failed": "Preuzimanje e-SLOG nije uspjelo",
16
+ Recurring: "Ponavljajuće",
16
17
  Duplicate: "Dupliciraj",
17
18
  "Duplicate invoice": "Dupliciraj račun",
18
19
  "Duplicate estimate": "Dupliciraj ponudu",
@@ -81,6 +82,10 @@ export default {
81
82
  "Delete draft failed": "Brisanje nacrta nije uspjelo",
82
83
  Draft: "Nacrt",
83
84
 
85
+ // Void
86
+ Void: "Storniraj",
87
+ "Voiding...": "Storniranje...",
88
+
84
89
  // Activity list
85
90
  Activity: "Aktivnost",
86
91
  "No activity": "Nema aktivnosti",
@@ -13,6 +13,7 @@ export default {
13
13
  "Unshare failed": "Rimozione condivisione fallita",
14
14
  "Download failed": "Download fallito",
15
15
  "e-SLOG download failed": "Download e-SLOG fallito",
16
+ Recurring: "Ricorrente",
16
17
  Duplicate: "Duplica",
17
18
  "Duplicate invoice": "Duplica fattura",
18
19
  "Duplicate estimate": "Duplica preventivo",
@@ -81,6 +82,10 @@ export default {
81
82
  "Delete draft failed": "Eliminazione bozza fallita",
82
83
  Draft: "Bozza",
83
84
 
85
+ // Void
86
+ Void: "Annulla",
87
+ "Voiding...": "Annullamento...",
88
+
84
89
  // Activity list
85
90
  Activity: "Attività",
86
91
  "No activity": "Nessuna attività",
@@ -13,6 +13,7 @@ export default {
13
13
  "Unshare failed": "Opheffen van delen mislukt",
14
14
  "Download failed": "Download mislukt",
15
15
  "e-SLOG download failed": "e-SLOG download mislukt",
16
+ Recurring: "Terugkerend",
16
17
  Duplicate: "Dupliceren",
17
18
  "Duplicate invoice": "Factuur dupliceren",
18
19
  "Duplicate estimate": "Offerte dupliceren",
@@ -82,6 +83,10 @@ export default {
82
83
  "Delete draft failed": "Verwijderen van concept mislukt",
83
84
  Draft: "Concept",
84
85
 
86
+ // Void
87
+ Void: "Nietig verklaren",
88
+ "Voiding...": "Nietig verklaren...",
89
+
85
90
  // Activity list
86
91
  Activity: "Activiteit",
87
92
  "No activity": "Geen activiteit",
@@ -13,6 +13,7 @@ export default {
13
13
  "Unshare failed": "Cofnięcie udostępnienia nie powiodło się",
14
14
  "Download failed": "Pobieranie nie powiodło się",
15
15
  "e-SLOG download failed": "Pobieranie e-SLOG nie powiodło się",
16
+ Recurring: "Cykliczna",
16
17
  Duplicate: "Duplikuj",
17
18
  "Duplicate invoice": "Duplikuj fakturę",
18
19
  "Duplicate estimate": "Duplikuj kosztorys",
@@ -81,6 +82,10 @@ export default {
81
82
  "Delete draft failed": "Usunięcie szkicu nie powiodło się",
82
83
  Draft: "Szkic",
83
84
 
85
+ // Void
86
+ Void: "Anuluj",
87
+ "Voiding...": "Anulowanie...",
88
+
84
89
  // Activity list
85
90
  Activity: "Aktywność",
86
91
  "No activity": "Brak aktywności",
@@ -13,6 +13,7 @@ export default {
13
13
  "Unshare failed": "Falha ao remover partilha",
14
14
  "Download failed": "Falha no download",
15
15
  "e-SLOG download failed": "Falha no download e-SLOG",
16
+ Recurring: "Recorrente",
16
17
  Duplicate: "Duplicar",
17
18
  "Duplicate invoice": "Duplicar fatura",
18
19
  "Duplicate estimate": "Duplicar orçamento",
@@ -81,6 +82,10 @@ export default {
81
82
  "Delete draft failed": "Falha ao eliminar rascunho",
82
83
  Draft: "Rascunho",
83
84
 
85
+ // Void
86
+ Void: "Anular",
87
+ "Voiding...": "Anulando...",
88
+
84
89
  // Activity list
85
90
  Activity: "Atividade",
86
91
  "No activity": "Sem atividade",
@@ -13,6 +13,7 @@ export default {
13
13
  "Unshare failed": "Odstranitev deljenja ni uspela",
14
14
  "Download failed": "Prenos ni uspel",
15
15
  "e-SLOG download failed": "Prenos e-SLOG ni uspel",
16
+ Recurring: "Ponavljajoče",
16
17
  Duplicate: "Podvoji",
17
18
  "Duplicate invoice": "Podvoji račun",
18
19
  "Duplicate estimate": "Podvoji predračun",
@@ -82,6 +83,10 @@ export default {
82
83
  "Delete draft failed": "Brisanje osnutka ni uspelo",
83
84
  Draft: "Osnutek",
84
85
 
86
+ // Void
87
+ Void: "Storniraj",
88
+ "Voiding...": "Storniranje...",
89
+
85
90
  // Activity list
86
91
  Activity: "Aktivnost",
87
92
  "No activity": "Ni aktivnosti",
@@ -47,7 +47,7 @@ export function CreateEntityForm({
47
47
  country: "",
48
48
  tax_number: "",
49
49
  company_number: "",
50
- environment,
50
+ environment: environment as "live" | "sandbox" | undefined,
51
51
  ...extraDefaults,
52
52
  // defaultName takes priority over extraDefaults.name if provided
53
53
  ...(defaultName ? { name: defaultName } : {}),
@@ -74,7 +74,6 @@ const entitySettingsFormSchema = patchEntitySchema
74
74
  .omit({
75
75
  settings: true, // Remove nested settings - we'll flatten them
76
76
  metadata: true, // Not used in this form
77
- environment: true, // Not editable here
78
77
  })
79
78
  .extend({
80
79
  // Flattened settings fields for easier form handling
@@ -85,8 +84,8 @@ const entitySettingsFormSchema = patchEntitySchema
85
84
  message: "Must be a valid hex color (e.g., #5c6ac4)",
86
85
  })
87
86
  .optional(),
88
- has_logo: z.union([z.boolean(), z.null()]).optional(),
89
- has_signature: z.union([z.boolean(), z.null()]).optional(),
87
+ has_logo: z.boolean().nullable().optional(),
88
+ has_signature: z.boolean().nullable().optional(),
90
89
  email: z
91
90
  .union([z.string(), z.null()])
92
91
  .refine((val) => !val || /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val), {
@@ -1,5 +1,7 @@
1
1
  export default {
2
2
  // Company settings
3
+ "Tax ID 2": "Tax ID 2",
4
+ "Secondary tax identification number (optional)": "Secondary tax identification number (optional)",
3
5
  "Company Information": "Información de la empresa",
4
6
  "Basic information about your company": "Información básica sobre su empresa",
5
7
  // Branding settings
@@ -1,5 +1,7 @@
1
1
  export default {
2
2
  // Company settings
3
+ "Tax ID 2": "Tax ID 2",
4
+ "Secondary tax identification number (optional)": "Secondary tax identification number (optional)",
3
5
  "Company Information": "Informations sur l'entreprise",
4
6
  "Basic information about your company": "Informations de base sur votre entreprise",
5
7
  // Branding settings
@@ -1,5 +1,7 @@
1
1
  export default {
2
2
  // Company settings
3
+ "Tax ID 2": "Tax ID 2",
4
+ "Secondary tax identification number (optional)": "Secondary tax identification number (optional)",
3
5
  "Company Information": "Podaci o tvrtki",
4
6
  "Basic information about your company": "Osnovni podaci o vašoj tvrtki",
5
7
  // Branding settings
@@ -1,5 +1,7 @@
1
1
  export default {
2
2
  // Company settings
3
+ "Tax ID 2": "Tax ID 2",
4
+ "Secondary tax identification number (optional)": "Secondary tax identification number (optional)",
3
5
  "Company Information": "Informazioni aziendali",
4
6
  "Basic information about your company": "Informazioni di base sulla tua azienda",
5
7
  // Branding settings
@@ -1,5 +1,7 @@
1
1
  export default {
2
2
  // Company settings
3
+ "Tax ID 2": "Tax ID 2",
4
+ "Secondary tax identification number (optional)": "Secondary tax identification number (optional)",
3
5
  "Company Information": "Bedrijfsinformatie",
4
6
  "Basic information about your company": "Basisinformatie over uw bedrijf",
5
7
  // Branding settings
@@ -1,5 +1,7 @@
1
1
  export default {
2
2
  // Company settings
3
+ "Tax ID 2": "Tax ID 2",
4
+ "Secondary tax identification number (optional)": "Secondary tax identification number (optional)",
3
5
  "Company Information": "Informacje o firmie",
4
6
  "Basic information about your company": "Podstawowe informacje o Twojej firmie",
5
7
  // Branding settings
@@ -1,5 +1,7 @@
1
1
  export default {
2
2
  // Company settings
3
+ "Tax ID 2": "Tax ID 2",
4
+ "Secondary tax identification number (optional)": "Secondary tax identification number (optional)",
3
5
  "Company Information": "Informações da empresa",
4
6
  "Basic information about your company": "Informações básicas sobre a sua empresa",
5
7
  // Branding settings
@@ -0,0 +1,109 @@
1
+ import { type FC, useState } from "react";
2
+ import { Button } from "@/ui/components/ui/button";
3
+ import {
4
+ Dialog,
5
+ DialogContent,
6
+ DialogDescription,
7
+ DialogFooter,
8
+ DialogHeader,
9
+ DialogTitle,
10
+ } from "@/ui/components/ui/dialog";
11
+ import { Input } from "@/ui/components/ui/input";
12
+ import { useUpdateUserFinaSettings } from "./fina-settings.hooks";
13
+
14
+ interface FinaOperatorRequiredDialogProps {
15
+ open: boolean;
16
+ onOpenChange: (open: boolean) => void;
17
+ entityId: string;
18
+ onSaved: () => void;
19
+ t: (key: string) => string;
20
+ }
21
+
22
+ export const FinaOperatorRequiredDialog: FC<FinaOperatorRequiredDialogProps> = ({
23
+ open,
24
+ onOpenChange,
25
+ entityId,
26
+ onSaved,
27
+ t,
28
+ }) => {
29
+ const [operatorOib, setOperatorOib] = useState("");
30
+ const [operatorLabel, setOperatorLabel] = useState("");
31
+
32
+ const { mutate: updateUserSettings, isPending } = useUpdateUserFinaSettings({
33
+ onSuccess: () => {
34
+ setOperatorOib("");
35
+ setOperatorLabel("");
36
+ onSaved();
37
+ },
38
+ });
39
+
40
+ const handleSubmit = (e: React.FormEvent) => {
41
+ e.preventDefault();
42
+ e.stopPropagation();
43
+ if (!operatorOib || !operatorLabel) return;
44
+ updateUserSettings({
45
+ entityId,
46
+ data: {
47
+ operator_oib: operatorOib,
48
+ operator_label: operatorLabel,
49
+ },
50
+ });
51
+ };
52
+
53
+ const oibError = operatorOib !== "" && !/^\d{11}$/.test(operatorOib);
54
+ const isValid = /^\d{11}$/.test(operatorOib) && operatorLabel.trim() !== "";
55
+
56
+ return (
57
+ <Dialog open={open} onOpenChange={onOpenChange}>
58
+ <DialogContent className="max-w-md">
59
+ <DialogHeader>
60
+ <DialogTitle>{t("FINA Operator Settings Required")}</DialogTitle>
61
+ <DialogDescription>
62
+ {t(
63
+ "Your FINA operator information is needed to fiscalize this document. Please enter your operator details.",
64
+ )}
65
+ </DialogDescription>
66
+ </DialogHeader>
67
+
68
+ <form onSubmit={handleSubmit} className="space-y-4">
69
+ <div>
70
+ <label htmlFor="fina-dialog-operator-oib" className="font-medium text-sm">
71
+ {t("Operator OIB")}
72
+ </label>
73
+ <Input
74
+ id="fina-dialog-operator-oib"
75
+ placeholder="12345678901"
76
+ value={operatorOib}
77
+ onChange={(e) => setOperatorOib(e.target.value.replace(/[^0-9]/g, ""))}
78
+ className={`mt-2 h-10${oibError ? "border-destructive" : ""}`}
79
+ maxLength={11}
80
+ />
81
+ {oibError && <p className="mt-1 text-destructive text-xs">{t("OIB must be exactly 11 digits")}</p>}
82
+ </div>
83
+
84
+ <div>
85
+ <label htmlFor="fina-dialog-operator-label" className="font-medium text-sm">
86
+ {t("Operator Label")}
87
+ </label>
88
+ <Input
89
+ id="fina-dialog-operator-label"
90
+ placeholder={t("e.g. Cashier 1")}
91
+ value={operatorLabel}
92
+ onChange={(e) => setOperatorLabel(e.target.value)}
93
+ className="mt-2 h-10"
94
+ />
95
+ </div>
96
+
97
+ <DialogFooter>
98
+ <Button type="button" variant="outline" onClick={() => onOpenChange(false)} disabled={isPending}>
99
+ {t("Cancel")}
100
+ </Button>
101
+ <Button type="submit" disabled={isPending || !isValid}>
102
+ {isPending ? t("Saving...") : t("Save & Retry")}
103
+ </Button>
104
+ </DialogFooter>
105
+ </form>
106
+ </DialogContent>
107
+ </Dialog>
108
+ );
109
+ };