@spaceinvoices/react-ui 0.4.2 → 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 (267) 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 +130 -40
  16. package/src/components/advance-invoices/list/locales/de.ts +6 -0
  17. package/src/components/advance-invoices/list/locales/en.ts +5 -0
  18. package/src/components/advance-invoices/list/locales/es.ts +6 -0
  19. package/src/components/advance-invoices/list/locales/fr.ts +6 -0
  20. package/src/components/advance-invoices/list/locales/hr.ts +6 -0
  21. package/src/components/advance-invoices/list/locales/it.ts +6 -0
  22. package/src/components/advance-invoices/list/locales/nl.ts +6 -0
  23. package/src/components/advance-invoices/list/locales/pl.ts +6 -0
  24. package/src/components/advance-invoices/list/locales/pt.ts +6 -0
  25. package/src/components/advance-invoices/list/locales/sl.ts +6 -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 +111 -36
  38. package/src/components/credit-notes/list/locales/de.ts +6 -1
  39. package/src/components/credit-notes/list/locales/en.ts +6 -0
  40. package/src/components/credit-notes/list/locales/es.ts +6 -1
  41. package/src/components/credit-notes/list/locales/fr.ts +6 -1
  42. package/src/components/credit-notes/list/locales/hr.ts +6 -1
  43. package/src/components/credit-notes/list/locales/it.ts +6 -1
  44. package/src/components/credit-notes/list/locales/nl.ts +6 -1
  45. package/src/components/credit-notes/list/locales/pl.ts +6 -1
  46. package/src/components/credit-notes/list/locales/pt.ts +6 -1
  47. package/src/components/credit-notes/list/locales/sl.ts +6 -1
  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/dashboard/collection-rate-card/use-collection-rate.ts +2 -2
  59. package/src/components/dashboard/invoice-status-chart/use-invoice-status.ts +3 -3
  60. package/src/components/dashboard/payment-methods-chart/use-payment-methods.ts +1 -1
  61. package/src/components/dashboard/payment-trend-chart/use-payment-trend.ts +1 -1
  62. package/src/components/dashboard/revenue-trend-chart/use-revenue-trend.ts +1 -1
  63. package/src/components/dashboard/shared/use-revenue-data.ts +4 -4
  64. package/src/components/dashboard/shared/use-stats-counts.ts +4 -4
  65. package/src/components/dashboard/shared/use-stats-query.ts +1 -1
  66. package/src/components/dashboard/tax-collected-card/use-tax-collected.ts +2 -2
  67. package/src/components/dashboard/top-customers-chart/use-top-customers.ts +1 -1
  68. package/src/components/delivery-notes/create/create-delivery-note-form.tsx +332 -0
  69. package/src/components/delivery-notes/create/locales/de.ts +50 -0
  70. package/src/components/delivery-notes/create/locales/es.ts +49 -0
  71. package/src/components/delivery-notes/create/locales/fr.ts +50 -0
  72. package/src/components/delivery-notes/create/locales/hr.ts +49 -0
  73. package/src/components/delivery-notes/create/locales/it.ts +49 -0
  74. package/src/components/delivery-notes/create/locales/nl.ts +50 -0
  75. package/src/components/delivery-notes/create/locales/pl.ts +49 -0
  76. package/src/components/delivery-notes/create/locales/pt.ts +50 -0
  77. package/src/components/delivery-notes/create/locales/sl.ts +49 -0
  78. package/src/components/delivery-notes/create/prepare-delivery-note-submission.ts +38 -0
  79. package/src/components/delivery-notes/create/use-delivery-note-customer-form.ts +1 -0
  80. package/src/components/delivery-notes/delivery-notes.hooks.ts +15 -0
  81. package/src/components/delivery-notes/list/index.ts +3 -0
  82. package/src/components/delivery-notes/list/list-row-actions.tsx +122 -0
  83. package/src/components/delivery-notes/list/list-table.tsx +247 -0
  84. package/src/components/delivery-notes/list/locales/de.ts +13 -0
  85. package/src/components/delivery-notes/list/locales/en.ts +13 -0
  86. package/src/components/delivery-notes/list/locales/es.ts +13 -0
  87. package/src/components/delivery-notes/list/locales/fr.ts +13 -0
  88. package/src/components/delivery-notes/list/locales/hr.ts +13 -0
  89. package/src/components/delivery-notes/list/locales/it.ts +13 -0
  90. package/src/components/delivery-notes/list/locales/nl.ts +13 -0
  91. package/src/components/delivery-notes/list/locales/pl.ts +13 -0
  92. package/src/components/delivery-notes/list/locales/pt.ts +13 -0
  93. package/src/components/delivery-notes/list/locales/sl.ts +13 -0
  94. package/src/components/delivery-notes/list/use-delivery-note-download.ts +63 -0
  95. package/src/components/documents/create/document-details-section.tsx +76 -58
  96. package/src/components/documents/create/linked-documents-info.tsx +82 -0
  97. package/src/components/documents/create/live-preview.tsx +38 -11
  98. package/src/components/documents/create/prepare-document-submission.ts +1 -1
  99. package/src/components/documents/documents.hooks.ts +2 -1
  100. package/src/components/documents/shared/document-preview-display.tsx +12 -5
  101. package/src/components/documents/types.ts +12 -3
  102. package/src/components/documents/view/document-activities-list.tsx +65 -47
  103. package/src/components/documents/view/document-details-card.tsx +102 -77
  104. package/src/components/documents/view/document-payments-list.tsx +102 -68
  105. package/src/components/documents/view/document-relations-list.tsx +120 -0
  106. package/src/components/documents/view/document-sidebar.tsx +151 -0
  107. package/src/components/documents/view/index.ts +2 -0
  108. package/src/components/documents/view/locales/de.ts +23 -0
  109. package/src/components/documents/view/locales/es.ts +23 -0
  110. package/src/components/documents/view/locales/fr.ts +23 -0
  111. package/src/components/documents/view/locales/hr.ts +23 -0
  112. package/src/components/documents/view/locales/it.ts +23 -0
  113. package/src/components/documents/view/locales/nl.ts +23 -0
  114. package/src/components/documents/view/locales/pl.ts +23 -0
  115. package/src/components/documents/view/locales/pt.ts +23 -0
  116. package/src/components/documents/view/locales/sl.ts +23 -0
  117. package/src/components/documents/view/use-document-download.ts +8 -5
  118. package/src/components/entities/create-entity-form.tsx +165 -13
  119. package/src/components/entities/entity-settings-form/entity-settings-form.tsx +101 -1
  120. package/src/components/entities/entity-settings-form/locales/de.ts +9 -0
  121. package/src/components/entities/entity-settings-form/locales/es.ts +9 -0
  122. package/src/components/entities/entity-settings-form/locales/fr.ts +9 -0
  123. package/src/components/entities/entity-settings-form/locales/hr.ts +9 -0
  124. package/src/components/entities/entity-settings-form/locales/it.ts +9 -0
  125. package/src/components/entities/entity-settings-form/locales/nl.ts +9 -0
  126. package/src/components/entities/entity-settings-form/locales/pl.ts +9 -0
  127. package/src/components/entities/entity-settings-form/locales/pt.ts +9 -0
  128. package/src/components/entities/entity-settings-form/locales/sl.ts +9 -0
  129. package/src/components/entities/fina-settings-form/fina-settings-form.tsx +83 -71
  130. package/src/components/entities/fina-settings-form/fina-settings.hooks.ts +7 -2
  131. package/src/components/entities/fina-settings-form/locales/de.ts +2 -2
  132. package/src/components/entities/fina-settings-form/locales/en.ts +2 -2
  133. package/src/components/entities/fina-settings-form/locales/es.ts +2 -2
  134. package/src/components/entities/fina-settings-form/locales/fr.ts +2 -2
  135. package/src/components/entities/fina-settings-form/locales/hr.ts +2 -2
  136. package/src/components/entities/fina-settings-form/locales/it.ts +2 -2
  137. package/src/components/entities/fina-settings-form/locales/nl.ts +2 -2
  138. package/src/components/entities/fina-settings-form/locales/pl.ts +2 -2
  139. package/src/components/entities/fina-settings-form/locales/pt.ts +2 -2
  140. package/src/components/entities/fina-settings-form/locales/sl.ts +2 -2
  141. package/src/components/entities/furs-settings-form/furs-settings-form.tsx +10 -1
  142. package/src/components/entities/furs-settings-form/furs-settings.hooks.ts +7 -2
  143. package/src/components/entities/furs-settings-form/locales/en.ts +0 -1
  144. package/src/components/entities/furs-settings-form/sections/general-settings-section.tsx +12 -4
  145. package/src/components/entities/settings/pdf-template-selector/locales/de.ts +3 -1
  146. package/src/components/entities/settings/pdf-template-selector/locales/es.ts +3 -1
  147. package/src/components/entities/settings/pdf-template-selector/locales/fr.ts +4 -1
  148. package/src/components/entities/settings/pdf-template-selector/locales/hr.ts +4 -1
  149. package/src/components/entities/settings/pdf-template-selector/locales/it.ts +3 -1
  150. package/src/components/entities/settings/pdf-template-selector/locales/nl.ts +3 -1
  151. package/src/components/entities/settings/pdf-template-selector/locales/pl.ts +3 -1
  152. package/src/components/entities/settings/pdf-template-selector/locales/pt.ts +3 -1
  153. package/src/components/entities/settings/pdf-template-selector/locales/sl.ts +3 -1
  154. package/src/components/entities/settings/pdf-template-selector/pdf-template-cards.tsx +1 -0
  155. package/src/components/estimates/create/create-estimate-form.tsx +29 -2
  156. package/src/components/estimates/list/list-table.tsx +3 -6
  157. package/src/components/estimates/list/locales/de.ts +1 -0
  158. package/src/components/estimates/list/locales/es.ts +1 -0
  159. package/src/components/estimates/list/locales/fr.ts +1 -0
  160. package/src/components/estimates/list/locales/hr.ts +1 -0
  161. package/src/components/estimates/list/locales/it.ts +1 -0
  162. package/src/components/estimates/list/locales/nl.ts +1 -0
  163. package/src/components/estimates/list/locales/pl.ts +1 -0
  164. package/src/components/estimates/list/locales/pt.ts +1 -0
  165. package/src/components/estimates/list/locales/sl.ts +1 -0
  166. package/src/components/export/document-export-form.tsx +9 -2
  167. package/src/components/export/index.ts +2 -0
  168. package/src/components/export/sales-per-item-export-form.tsx +223 -0
  169. package/src/components/invoices/create/create-invoice-form.tsx +48 -1
  170. package/src/components/invoices/create/locales/de.ts +11 -0
  171. package/src/components/invoices/create/locales/es.ts +11 -0
  172. package/src/components/invoices/create/locales/fr.ts +11 -0
  173. package/src/components/invoices/create/locales/hr.ts +10 -0
  174. package/src/components/invoices/create/locales/it.ts +11 -0
  175. package/src/components/invoices/create/locales/nl.ts +11 -0
  176. package/src/components/invoices/create/locales/pl.ts +10 -0
  177. package/src/components/invoices/create/locales/pt.ts +10 -0
  178. package/src/components/invoices/create/locales/sl.ts +10 -0
  179. package/src/components/invoices/invoices-furs.hooks.ts +27 -9
  180. package/src/components/invoices/list/list-row-actions.tsx +3 -3
  181. package/src/components/invoices/list/list-table.tsx +132 -21
  182. package/src/components/invoices/list/locales/de.ts +6 -0
  183. package/src/components/invoices/list/locales/en.ts +5 -0
  184. package/src/components/invoices/list/locales/es.ts +6 -0
  185. package/src/components/invoices/list/locales/fr.ts +6 -0
  186. package/src/components/invoices/list/locales/hr.ts +6 -0
  187. package/src/components/invoices/list/locales/it.ts +6 -0
  188. package/src/components/invoices/list/locales/nl.ts +6 -0
  189. package/src/components/invoices/list/locales/pl.ts +6 -0
  190. package/src/components/invoices/list/locales/pt.ts +6 -0
  191. package/src/components/invoices/list/locales/sl.ts +6 -0
  192. package/src/components/invoices/view/fiscalization-status-card.tsx +42 -24
  193. package/src/components/items/item-combobox.tsx +5 -3
  194. package/src/components/items/item-list-table/item-list-header.tsx +4 -17
  195. package/src/components/items/item-list-table/item-list-row-actions.tsx +3 -2
  196. package/src/components/items/item-list-table/item-list-row.tsx +3 -2
  197. package/src/components/items/item-list-table/item-list-table.tsx +3 -3
  198. package/src/components/items/item-list-table/locales/de.ts +1 -0
  199. package/src/components/items/item-list-table/locales/es.ts +1 -0
  200. package/src/components/items/item-list-table/locales/fr.ts +1 -0
  201. package/src/components/items/item-list-table/locales/hr.ts +1 -0
  202. package/src/components/items/item-list-table/locales/it.ts +1 -0
  203. package/src/components/items/item-list-table/locales/nl.ts +1 -0
  204. package/src/components/items/item-list-table/locales/pl.ts +1 -0
  205. package/src/components/items/item-list-table/locales/pt.ts +1 -0
  206. package/src/components/items/item-list-table/locales/sl.ts +1 -0
  207. package/src/components/payments/list/list-table.tsx +0 -4
  208. package/src/components/payments/list/locales/de.ts +1 -0
  209. package/src/components/payments/list/locales/es.ts +1 -0
  210. package/src/components/payments/list/locales/fr.ts +1 -0
  211. package/src/components/payments/list/locales/hr.ts +1 -0
  212. package/src/components/payments/list/locales/it.ts +1 -0
  213. package/src/components/payments/list/locales/nl.ts +1 -0
  214. package/src/components/payments/list/locales/pl.ts +1 -0
  215. package/src/components/payments/list/locales/pt.ts +1 -0
  216. package/src/components/payments/list/locales/sl.ts +1 -0
  217. package/src/components/recurring-invoices/list/list-table.tsx +0 -7
  218. package/src/components/recurring-invoices/list/locales/de.ts +1 -0
  219. package/src/components/recurring-invoices/list/locales/es.ts +1 -0
  220. package/src/components/recurring-invoices/list/locales/fr.ts +1 -0
  221. package/src/components/recurring-invoices/list/locales/hr.ts +1 -0
  222. package/src/components/recurring-invoices/list/locales/it.ts +1 -0
  223. package/src/components/recurring-invoices/list/locales/nl.ts +1 -0
  224. package/src/components/recurring-invoices/list/locales/pl.ts +1 -0
  225. package/src/components/recurring-invoices/list/locales/pt.ts +1 -0
  226. package/src/components/recurring-invoices/list/locales/sl.ts +1 -0
  227. package/src/components/request-logs/request-log-list-table.tsx +0 -3
  228. package/src/components/table/README.md +14 -121
  229. package/src/components/table/data-table.tsx +22 -37
  230. package/src/components/table/hooks/use-table-state.ts +3 -27
  231. package/src/components/table/index.ts +0 -2
  232. package/src/components/table/selection-toolbar.tsx +35 -1
  233. package/src/components/table/table-empty-state.tsx +6 -3
  234. package/src/components/table/table-no-results.tsx +10 -5
  235. package/src/components/table/types.ts +0 -5
  236. package/src/components/taxes/tax-list-table/locales/de.ts +1 -0
  237. package/src/components/taxes/tax-list-table/locales/es.ts +1 -0
  238. package/src/components/taxes/tax-list-table/locales/fr.ts +1 -0
  239. package/src/components/taxes/tax-list-table/locales/hr.ts +1 -0
  240. package/src/components/taxes/tax-list-table/locales/it.ts +1 -0
  241. package/src/components/taxes/tax-list-table/locales/nl.ts +1 -0
  242. package/src/components/taxes/tax-list-table/locales/pl.ts +1 -0
  243. package/src/components/taxes/tax-list-table/locales/pt.ts +1 -0
  244. package/src/components/taxes/tax-list-table/locales/sl.ts +1 -0
  245. package/src/components/taxes/tax-list-table/tax-list-header.tsx +3 -14
  246. package/src/components/taxes/tax-list-table/tax-list-table.tsx +3 -3
  247. package/src/components/ui/popover.tsx +3 -1
  248. package/src/components/ui/tooltip.tsx +3 -1
  249. package/src/generated/schemas/deliverynote.ts +134 -0
  250. package/src/generated/schemas/entity.ts +4 -0
  251. package/src/generated/schemas/index.ts +3 -0
  252. package/src/generated/schemas/order.ts +5 -3
  253. package/src/generated/schemas/payment.ts +22 -2
  254. package/src/generated/schemas/renderadvanceinvoicepreview_body.ts +1 -0
  255. package/src/generated/schemas/rendercreditnotepreview_body.ts +1 -0
  256. package/src/generated/schemas/renderdeliverynotepreview_body.ts +185 -0
  257. package/src/generated/schemas/renderestimatepreview_body.ts +1 -0
  258. package/src/generated/schemas/renderinvoicepreview_body.ts +1 -0
  259. package/src/generated/schemas/startpdfexport_body.ts +18 -2
  260. package/src/generated/schemas/userfinasettings.ts +19 -0
  261. package/src/generated/schemas/webhook.ts +12 -0
  262. package/src/hooks/use-duplicate-document.ts +49 -6
  263. package/src/hooks/use-next-document-number.ts +2 -2
  264. package/src/lib/fiscalization.ts +12 -0
  265. package/src/lib/schemas/advance-invoice.ts +0 -1
  266. package/src/providers/sdk-provider.tsx +5 -7
  267. package/src/components/table/sortable-header.tsx +0 -56
@@ -1,10 +1,14 @@
1
1
  import { zodResolver } from "@hookform/resolvers/zod";
2
- import type { CreateEntityRequest, Entity } from "@spaceinvoices/js-sdk";
2
+ import type { CompanyRegistryResult, CreateEntityRequest, Entity } from "@spaceinvoices/js-sdk";
3
+ import { useEffect, useRef, useState } from "react";
3
4
  import type { Resolver } from "react-hook-form";
4
5
  import { useForm } from "react-hook-form";
6
+ import { Autocomplete } from "@/ui/common/autocomplete";
7
+ import { useCompanyRegistrySearch, useIsCountrySupported } from "@/ui/components/company-registry";
5
8
  import { FormInput } from "@/ui/components/form";
6
9
  import { Button } from "@/ui/components/ui/button";
7
- import { Form } from "@/ui/components/ui/form";
10
+ import { Checkbox } from "@/ui/components/ui/checkbox";
11
+ import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/ui/components/ui/form";
8
12
  import { type CreateEntitySchema, createEntitySchema } from "@/ui/generated/schemas";
9
13
 
10
14
  import ButtonLoader from "../button-loader";
@@ -16,6 +20,8 @@ export type CreateEntityFormProps = {
16
20
  accountId?: string;
17
21
  environment?: string;
18
22
  defaultName?: string;
23
+ countryCode?: string;
24
+ locale?: string;
19
25
  defaultValues?: Partial<CreateEntitySchema>;
20
26
  onSuccess?: (data: Entity) => void;
21
27
  onError?: (error: unknown) => void;
@@ -29,12 +35,44 @@ export function CreateEntityForm({
29
35
  accountId,
30
36
  environment,
31
37
  defaultName,
38
+ countryCode,
39
+ locale = "en",
32
40
  defaultValues: extraDefaults,
33
41
  onSuccess,
34
42
  onError,
35
43
  }: CreateEntityFormProps) {
36
44
  const translate = (key: string) => t(namespace ? `${namespace}.${key}` : key);
37
45
 
46
+ const countryName = countryCode ? new Intl.DisplayNames([locale], { type: "region" }).of(countryCode) : undefined;
47
+
48
+ // Track whether the country code is still valid (cleared when user edits country name)
49
+ const [activeCountryCode, setActiveCountryCode] = useState<string | undefined>(countryCode);
50
+ const autoFilledCountryRef = useRef(countryName);
51
+
52
+ // Company registry autocomplete state
53
+ const [nameSearch, setNameSearch] = useState("");
54
+ const { isSupported: isRegistrySupported } = useIsCountrySupported(activeCountryCode || "");
55
+ const { data: searchData, isLoading: isSearching } = useCompanyRegistrySearch(activeCountryCode || "", nameSearch);
56
+ const companies = searchData?.data || [];
57
+
58
+ const showAutocomplete = !!activeCountryCode && isRegistrySupported;
59
+
60
+ const nameOptions = companies.map((company) => {
61
+ const addressParts = [company.address, company.city].filter(Boolean);
62
+ const address = addressParts.join(", ");
63
+ return {
64
+ value: company.id,
65
+ label: (
66
+ <div className="flex flex-col overflow-hidden py-1">
67
+ <span className="truncate font-medium">{company.name}</span>
68
+ {address && <span className="truncate text-muted-foreground text-xs">{address}</span>}
69
+ {company.tax_number && <span className="truncate text-muted-foreground text-xs">{company.tax_number}</span>}
70
+ </div>
71
+ ),
72
+ company,
73
+ };
74
+ });
75
+
38
76
  const form = useForm<CreateEntitySchema>({
39
77
  resolver: zodResolver(createEntitySchema) as Resolver<CreateEntitySchema>,
40
78
  defaultValues: {
@@ -44,9 +82,11 @@ export function CreateEntityForm({
44
82
  post_code: "",
45
83
  city: "",
46
84
  state: "",
47
- country: "",
85
+ country: countryName || "",
86
+ country_code: countryCode || "",
48
87
  tax_number: "",
49
88
  company_number: "",
89
+ is_tax_subject: true,
50
90
  environment: environment as "live" | "sandbox" | undefined,
51
91
  ...extraDefaults,
52
92
  // defaultName takes priority over extraDefaults.name if provided
@@ -54,6 +94,26 @@ export function CreateEntityForm({
54
94
  },
55
95
  });
56
96
 
97
+ // Watch country field — clear activeCountryCode when user edits away from auto-filled value
98
+ const countryValue = form.watch("country");
99
+ useEffect(() => {
100
+ if (countryValue !== autoFilledCountryRef.current) {
101
+ setActiveCountryCode(undefined);
102
+ } else {
103
+ setActiveCountryCode(countryCode);
104
+ }
105
+ }, [countryValue, countryCode]);
106
+
107
+ const handleCompanySelect = (company: CompanyRegistryResult) => {
108
+ form.setValue("name", company.name);
109
+ if (company.address) form.setValue("address", company.address);
110
+ if (company.post_code) form.setValue("post_code", company.post_code);
111
+ if (company.city) form.setValue("city", company.city);
112
+ if (company.tax_number) form.setValue("tax_number", company.tax_number);
113
+ if (company.registration_number) form.setValue("company_number", company.registration_number);
114
+ setNameSearch("");
115
+ };
116
+
57
117
  // Wrap onSuccess to reset form only after successful mutation
58
118
  const handleSuccess = (data: Entity) => {
59
119
  form.reset();
@@ -84,30 +144,122 @@ export function CreateEntityForm({
84
144
  }
85
145
  };
86
146
 
147
+ const nameValue = form.watch("name");
148
+
87
149
  return (
88
150
  <Form {...form}>
89
151
  <form onSubmit={form.handleSubmit(onSubmit as any)} className="space-y-4">
90
- <FormInput control={form.control} name="name" label={translate("Name")} placeholder="Name" required />
152
+ {showAutocomplete ? (
153
+ <FormField
154
+ control={form.control}
155
+ name="name"
156
+ render={({ field }) => (
157
+ <FormItem>
158
+ <FormLabel>
159
+ {translate("name")}
160
+ <span className="ml-1 text-red-500">*</span>
161
+ </FormLabel>
162
+ <FormControl>
163
+ <Autocomplete
164
+ searchValue={nameSearch}
165
+ onSearch={(v) => {
166
+ setNameSearch(v);
167
+ field.onChange(v || undefined);
168
+ }}
169
+ displayValue={nameValue || ""}
170
+ options={nameOptions}
171
+ onValueChange={(selectedId) => {
172
+ const option = nameOptions.find((o) => o.value === selectedId);
173
+ if (option?.company) {
174
+ handleCompanySelect(option.company);
175
+ }
176
+ }}
177
+ onBlur={() => {
178
+ setNameSearch("");
179
+ }}
180
+ placeholder={translate("name")}
181
+ loading={isSearching}
182
+ emptyText={nameSearch.length < 2 ? translate("search-hint") : translate("no-results")}
183
+ />
184
+ </FormControl>
185
+ <FormMessage />
186
+ </FormItem>
187
+ )}
188
+ />
189
+ ) : (
190
+ <FormInput
191
+ control={form.control}
192
+ name="name"
193
+ label={translate("name")}
194
+ placeholder={translate("name")}
195
+ required
196
+ />
197
+ )}
91
198
 
92
- <FormInput control={form.control} name="country" label="Country" placeholder="Country" required />
199
+ <FormInput
200
+ control={form.control}
201
+ name="country"
202
+ label={translate("country")}
203
+ placeholder={translate("country")}
204
+ required
205
+ />
93
206
 
94
- <FormInput control={form.control} name="address" label="Address" placeholder="Address" />
207
+ <FormInput
208
+ control={form.control}
209
+ name="address"
210
+ label={translate("address")}
211
+ placeholder={translate("address")}
212
+ />
95
213
 
96
- <FormInput control={form.control} name="address_2" label="Address 2" placeholder="Address 2" />
214
+ <FormInput
215
+ control={form.control}
216
+ name="address_2"
217
+ label={translate("address-2")}
218
+ placeholder={translate("address-2")}
219
+ />
97
220
 
98
221
  <div className="grid grid-cols-2 gap-4">
99
- <FormInput control={form.control} name="post_code" label="Post code" placeholder="Post code" />
100
- <FormInput control={form.control} name="city" label="City" placeholder="City" />
222
+ <FormInput
223
+ control={form.control}
224
+ name="post_code"
225
+ label={translate("post-code")}
226
+ placeholder={translate("post-code")}
227
+ />
228
+ <FormInput control={form.control} name="city" label={translate("city")} placeholder={translate("city")} />
101
229
  </div>
102
230
 
103
- <FormInput control={form.control} name="state" label="State" placeholder="State" />
231
+ <FormInput control={form.control} name="state" label={translate("state")} placeholder={translate("state")} />
104
232
 
105
- <FormInput control={form.control} name="tax_number" label="Tax number" placeholder="Tax number" />
233
+ <div className="grid grid-cols-[1fr_auto] items-end gap-4">
234
+ <FormInput
235
+ control={form.control}
236
+ name="tax_number"
237
+ label={translate("tax-number")}
238
+ placeholder={translate("tax-number")}
239
+ />
240
+ <FormField
241
+ control={form.control}
242
+ name="is_tax_subject"
243
+ render={({ field }) => (
244
+ <FormItem className="flex flex-row items-center space-x-2 space-y-0 pb-2">
245
+ <FormControl>
246
+ <Checkbox checked={field.value} onCheckedChange={field.onChange} />
247
+ </FormControl>
248
+ <FormLabel className="font-normal">{translate("is-tax-subject")}</FormLabel>
249
+ </FormItem>
250
+ )}
251
+ />
252
+ </div>
106
253
 
107
- <FormInput control={form.control} name="company_number" label="Company number" placeholder="Company number" />
254
+ <FormInput
255
+ control={form.control}
256
+ name="company_number"
257
+ label={translate("company-number")}
258
+ placeholder={translate("company-number")}
259
+ />
108
260
 
109
261
  <Button type="submit" className="w-full cursor-pointer" disabled={isPending} aria-busy={isPending}>
110
- {isPending ? <ButtonLoader /> : "Create"}
262
+ {isPending ? <ButtonLoader /> : translate("submit")}
111
263
  </Button>
112
264
  </form>
113
265
  </Form>
@@ -1,6 +1,6 @@
1
1
  import { zodResolver } from "@hookform/resolvers/zod";
2
2
  import type { Entity } from "@spaceinvoices/js-sdk";
3
- import { CreditCard, FileText, Globe, Mail, Palette, Sparkles } from "lucide-react";
3
+ import { CreditCard, FileText, Globe, Mail, Palette, QrCode, Sparkles } from "lucide-react";
4
4
  import { useEffect, useRef, useState } from "react";
5
5
  import { useForm } from "react-hook-form";
6
6
  import { z } from "zod";
@@ -67,6 +67,38 @@ const SUPPORTED_LOCALES = [
67
67
  { value: "sl-SI", label: "Slovenščina (SI)" },
68
68
  ] as const;
69
69
 
70
+ // Countries with EPC QR feature (EU 27 + Switzerland)
71
+ const EPC_QR_COUNTRIES = new Set([
72
+ "AT",
73
+ "BE",
74
+ "BG",
75
+ "HR",
76
+ "CY",
77
+ "CZ",
78
+ "DK",
79
+ "EE",
80
+ "FI",
81
+ "FR",
82
+ "DE",
83
+ "GR",
84
+ "HU",
85
+ "IE",
86
+ "IT",
87
+ "LV",
88
+ "LT",
89
+ "LU",
90
+ "MT",
91
+ "NL",
92
+ "PL",
93
+ "PT",
94
+ "RO",
95
+ "SK",
96
+ "SI",
97
+ "ES",
98
+ "SE",
99
+ "CH",
100
+ ]);
101
+
70
102
  // Form schema extends the generated patchEntitySchema but flattens nested settings for better UX
71
103
  // Uses .omit() to remove nested fields, then .extend() to add flattened versions
72
104
  // This approach keeps the base validation from the API schema while allowing a better form structure
@@ -116,6 +148,8 @@ const entitySettingsFormSchema = patchEntitySchema
116
148
  message: "Must be a 4-letter uppercase code (e.g., OTHR)",
117
149
  })
118
150
  .optional(),
151
+ // EPC QR settings (EU + CH)
152
+ epc_qr_enabled: z.union([z.boolean(), z.null()]).optional(),
119
153
  });
120
154
 
121
155
  export type EntitySettingsFormSchema = z.infer<typeof entitySettingsFormSchema>;
@@ -186,6 +220,7 @@ export function EntitySettingsForm({
186
220
  upn_qr_enabled: currentSettings.upn_qr?.enabled || false,
187
221
  upn_qr_display_mode: currentSettings.upn_qr?.display_mode || "qr_only",
188
222
  upn_qr_purpose_code: currentSettings.upn_qr?.purpose_code || "OTHR",
223
+ epc_qr_enabled: currentSettings.epc_qr?.enabled || false,
189
224
  },
190
225
  });
191
226
 
@@ -346,6 +381,9 @@ export function EntitySettingsForm({
346
381
  purpose_code: values.upn_qr_purpose_code || "OTHR",
347
382
  }
348
383
  : undefined,
384
+ // EPC QR settings - only include if enabled or was previously enabled
385
+ epc_qr:
386
+ values.epc_qr_enabled || currentSettings.epc_qr ? { enabled: values.epc_qr_enabled || false } : undefined,
349
387
  // Bank accounts - store in array format (preserving other accounts if any)
350
388
  bank_accounts: values.bank_account_iban
351
389
  ? [
@@ -1015,6 +1053,68 @@ export function EntitySettingsForm({
1015
1053
  </div>
1016
1054
  )}
1017
1055
 
1056
+ {/* EPC QR Section - For EU + CH entities */}
1057
+ {EPC_QR_COUNTRIES.has((entity as any).country_code) && (
1058
+ <div className="grid gap-8 border-t pt-8 lg:grid-cols-2">
1059
+ <div className="space-y-4">
1060
+ <div className="flex items-center gap-3">
1061
+ <div className="flex h-10 w-10 items-center justify-center rounded-lg bg-sky-500/10">
1062
+ <QrCode className="h-5 w-5 text-sky-600 dark:text-sky-400" />
1063
+ </div>
1064
+ <div>
1065
+ <h3 className="font-semibold text-lg">{translate("EPC QR Payment")}</h3>
1066
+ <p className="text-muted-foreground text-sm">
1067
+ {translate("SEPA credit transfer QR code for invoices")}
1068
+ </p>
1069
+ </div>
1070
+ </div>
1071
+
1072
+ <div className="space-y-6 pl-[52px]">
1073
+ <FormField
1074
+ control={form.control}
1075
+ name="epc_qr_enabled"
1076
+ render={({ field }) => (
1077
+ <FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
1078
+ <div className="space-y-0.5">
1079
+ <FormLabel className="font-medium text-base">
1080
+ {translate("Enable EPC QR on invoices")}
1081
+ </FormLabel>
1082
+ <FormDescription className="text-xs">
1083
+ {translate("Show SEPA QR code on EUR invoices for easy bank payments")}
1084
+ </FormDescription>
1085
+ </div>
1086
+ <FormControl>
1087
+ <Switch
1088
+ checked={field.value || false}
1089
+ onCheckedChange={field.onChange}
1090
+ disabled={!form.watch("bank_account_iban")}
1091
+ />
1092
+ </FormControl>
1093
+ </FormItem>
1094
+ )}
1095
+ />
1096
+ </div>
1097
+ </div>
1098
+
1099
+ {/* Help Content */}
1100
+ <div className="hidden lg:block">
1101
+ <div className="sticky top-6 space-y-3 border-muted border-l-2 pl-4">
1102
+ <div className="flex items-start gap-2">
1103
+ <QrCode className="mt-0.5 h-4 w-4 shrink-0 text-muted-foreground/70" />
1104
+ <div className="space-y-2">
1105
+ <p className="font-medium text-muted-foreground text-sm">{translate("EPC QR Payments")}</p>
1106
+ <p className="text-muted-foreground/80 text-xs leading-relaxed">
1107
+ {translate(
1108
+ "EPC QR is a European standard for SEPA credit transfers. When enabled, EUR invoices include a QR code that customers can scan with their banking app to pay instantly.",
1109
+ )}
1110
+ </p>
1111
+ </div>
1112
+ </div>
1113
+ </div>
1114
+ </div>
1115
+ </div>
1116
+ )}
1117
+
1018
1118
  {/* Document Defaults Section */}
1019
1119
  <div className="grid gap-8 border-t pt-8 lg:grid-cols-2">
1020
1120
  <div className="space-y-4">
@@ -191,4 +191,13 @@ export default {
191
191
  "Enter EU consumer sales clause...": "EU-Verbraucherklausel eingeben...",
192
192
  "tax-clauses.other.description":
193
193
  "Diese Transaktionstypen erfordern normalerweise keine speziellen Steuerklauseln, können aber bei Bedarf konfiguriert werden.",
194
+ // EPC QR Payment section
195
+ "EPC QR Payment": "EPC QR Zahlung",
196
+ "SEPA credit transfer QR code for invoices": "SEPA-Überweisungs-QR-Code für Rechnungen",
197
+ "Enable EPC QR on invoices": "EPC QR auf Rechnungen aktivieren",
198
+ "Show SEPA QR code on EUR invoices for easy bank payments":
199
+ "SEPA-QR-Code auf EUR-Rechnungen für einfache Bankzahlungen anzeigen",
200
+ "EPC QR Payments": "EPC QR Zahlungen",
201
+ "EPC QR is a European standard for SEPA credit transfers. When enabled, EUR invoices include a QR code that customers can scan with their banking app to pay instantly.":
202
+ "EPC QR ist ein europäischer Standard für SEPA-Überweisungen. Wenn aktiviert, enthalten EUR-Rechnungen einen QR-Code, den Kunden mit ihrer Banking-App scannen können, um sofort zu bezahlen.",
194
203
  } as const;
@@ -196,4 +196,13 @@ export default {
196
196
  "Enter EU consumer sales clause...": "Introduzca la cláusula de venta a consumidores de la UE...",
197
197
  "tax-clauses.other.description":
198
198
  "Estos tipos de transacciones normalmente no requieren cláusulas fiscales específicas, pero puede configurarlas según sea necesario.",
199
+ // EPC QR Payment section
200
+ "EPC QR Payment": "Pago EPC QR",
201
+ "SEPA credit transfer QR code for invoices": "Código QR de transferencia SEPA para facturas",
202
+ "Enable EPC QR on invoices": "Activar EPC QR en facturas",
203
+ "Show SEPA QR code on EUR invoices for easy bank payments":
204
+ "Mostrar código QR SEPA en facturas en EUR para pagos bancarios fáciles",
205
+ "EPC QR Payments": "Pagos EPC QR",
206
+ "EPC QR is a European standard for SEPA credit transfers. When enabled, EUR invoices include a QR code that customers can scan with their banking app to pay instantly.":
207
+ "EPC QR es un estándar europeo para transferencias SEPA. Cuando está activado, las facturas en EUR incluyen un código QR que los clientes pueden escanear con su app bancaria para pagar al instante.",
199
208
  } as const;
@@ -195,4 +195,13 @@ export default {
195
195
  "Enter EU consumer sales clause...": "Entrez la clause de vente aux consommateurs UE...",
196
196
  "tax-clauses.other.description":
197
197
  "Ces types de transactions ne nécessitent généralement pas de clauses fiscales spécifiques, mais vous pouvez les configurer selon vos besoins.",
198
+ // EPC QR Payment section
199
+ "EPC QR Payment": "Paiement EPC QR",
200
+ "SEPA credit transfer QR code for invoices": "Code QR de virement SEPA pour les factures",
201
+ "Enable EPC QR on invoices": "Activer EPC QR sur les factures",
202
+ "Show SEPA QR code on EUR invoices for easy bank payments":
203
+ "Afficher le code QR SEPA sur les factures en EUR pour des paiements bancaires faciles",
204
+ "EPC QR Payments": "Paiements EPC QR",
205
+ "EPC QR is a European standard for SEPA credit transfers. When enabled, EUR invoices include a QR code that customers can scan with their banking app to pay instantly.":
206
+ "EPC QR est un standard européen pour les virements SEPA. Lorsqu'il est activé, les factures en EUR incluent un code QR que les clients peuvent scanner avec leur application bancaire pour payer instantanément.",
198
207
  } as const;
@@ -188,4 +188,13 @@ export default {
188
188
  "Enter EU consumer sales clause...": "Unesite klauzulu za prodaju EU potrošačima...",
189
189
  "tax-clauses.other.description":
190
190
  "Ove vrste transakcija obično ne zahtijevaju posebne porezne klauzule, ali ih možete konfigurirati prema potrebi.",
191
+ // EPC QR Payment section
192
+ "EPC QR Payment": "EPC QR plaćanje",
193
+ "SEPA credit transfer QR code for invoices": "SEPA QR kod za kreditne transfere na fakturama",
194
+ "Enable EPC QR on invoices": "Omogući EPC QR na fakturama",
195
+ "Show SEPA QR code on EUR invoices for easy bank payments":
196
+ "Prikaži SEPA QR kod na EUR fakturama za jednostavno bankovne uplate",
197
+ "EPC QR Payments": "EPC QR plaćanja",
198
+ "EPC QR is a European standard for SEPA credit transfers. When enabled, EUR invoices include a QR code that customers can scan with their banking app to pay instantly.":
199
+ "EPC QR je europski standard za SEPA kreditne transfere. Kada je omogućen, EUR fakture uključuju QR kod koji kupci mogu skenirati bankovnom aplikacijom za trenutačno plaćanje.",
191
200
  } as const;
@@ -194,4 +194,13 @@ export default {
194
194
  "Enter EU consumer sales clause...": "Inserisci la clausola per vendite ai consumatori UE...",
195
195
  "tax-clauses.other.description":
196
196
  "Questi tipi di transazioni di solito non richiedono clausole fiscali specifiche, ma puoi configurarle secondo necessità.",
197
+ // EPC QR Payment section
198
+ "EPC QR Payment": "Pagamento EPC QR",
199
+ "SEPA credit transfer QR code for invoices": "Codice QR per bonifico SEPA sulle fatture",
200
+ "Enable EPC QR on invoices": "Attiva EPC QR sulle fatture",
201
+ "Show SEPA QR code on EUR invoices for easy bank payments":
202
+ "Mostra il codice QR SEPA sulle fatture in EUR per pagamenti bancari facili",
203
+ "EPC QR Payments": "Pagamenti EPC QR",
204
+ "EPC QR is a European standard for SEPA credit transfers. When enabled, EUR invoices include a QR code that customers can scan with their banking app to pay instantly.":
205
+ "EPC QR è uno standard europeo per i bonifici SEPA. Quando attivato, le fatture in EUR includono un codice QR che i clienti possono scansionare con la loro app bancaria per pagare istantaneamente.",
197
206
  } as const;
@@ -191,4 +191,13 @@ export default {
191
191
  "Enter EU consumer sales clause...": "Voer de EU-consumentenverkoopclausule in...",
192
192
  "tax-clauses.other.description":
193
193
  "Deze soorten transacties vereisen doorgaans geen specifieke belastingclausules, maar u kunt ze naar behoefte configureren.",
194
+ // EPC QR Payment section
195
+ "EPC QR Payment": "EPC QR Betaling",
196
+ "SEPA credit transfer QR code for invoices": "SEPA-overboeking QR-code voor facturen",
197
+ "Enable EPC QR on invoices": "EPC QR op facturen inschakelen",
198
+ "Show SEPA QR code on EUR invoices for easy bank payments":
199
+ "Toon SEPA QR-code op EUR-facturen voor eenvoudige bankbetalingen",
200
+ "EPC QR Payments": "EPC QR Betalingen",
201
+ "EPC QR is a European standard for SEPA credit transfers. When enabled, EUR invoices include a QR code that customers can scan with their banking app to pay instantly.":
202
+ "EPC QR is een Europese standaard voor SEPA-overboekingen. Wanneer ingeschakeld, bevatten EUR-facturen een QR-code die klanten kunnen scannen met hun bankapp om direct te betalen.",
194
203
  } as const;
@@ -192,4 +192,13 @@ export default {
192
192
  "Enter EU consumer sales clause...": "Wprowadź klauzulę sprzedaży konsumenckiej UE...",
193
193
  "tax-clauses.other.description":
194
194
  "Te rodzaje transakcji zwykle nie wymagają specyficznych klauzul podatkowych, ale możesz je skonfigurować w razie potrzeby.",
195
+ // EPC QR Payment section
196
+ "EPC QR Payment": "Płatność EPC QR",
197
+ "SEPA credit transfer QR code for invoices": "Kod QR przelewu SEPA na fakturach",
198
+ "Enable EPC QR on invoices": "Włącz EPC QR na fakturach",
199
+ "Show SEPA QR code on EUR invoices for easy bank payments":
200
+ "Pokaż kod QR SEPA na fakturach EUR dla łatwych płatności bankowych",
201
+ "EPC QR Payments": "Płatności EPC QR",
202
+ "EPC QR is a European standard for SEPA credit transfers. When enabled, EUR invoices include a QR code that customers can scan with their banking app to pay instantly.":
203
+ "EPC QR to europejski standard dla przelewów SEPA. Po włączeniu faktury EUR zawierają kod QR, który klienci mogą zeskanować aplikacją bankową, aby natychmiast zapłacić.",
195
204
  } as const;
@@ -193,4 +193,13 @@ export default {
193
193
  "Enter EU consumer sales clause...": "Introduza a cláusula de venda ao consumidor UE...",
194
194
  "tax-clauses.other.description":
195
195
  "Estes tipos de transações normalmente não requerem cláusulas fiscais específicas, mas pode configurá-las conforme necessário.",
196
+ // EPC QR Payment section
197
+ "EPC QR Payment": "Pagamento EPC QR",
198
+ "SEPA credit transfer QR code for invoices": "Código QR de transferência SEPA para faturas",
199
+ "Enable EPC QR on invoices": "Ativar EPC QR nas faturas",
200
+ "Show SEPA QR code on EUR invoices for easy bank payments":
201
+ "Mostrar código QR SEPA em faturas EUR para pagamentos bancários fáceis",
202
+ "EPC QR Payments": "Pagamentos EPC QR",
203
+ "EPC QR is a European standard for SEPA credit transfers. When enabled, EUR invoices include a QR code that customers can scan with their banking app to pay instantly.":
204
+ "EPC QR é um padrão europeu para transferências SEPA. Quando ativado, as faturas em EUR incluem um código QR que os clientes podem digitalizar com a sua app bancária para pagar instantaneamente.",
196
205
  } as const;
@@ -187,4 +187,13 @@ export default {
187
187
  "Enter EU consumer sales clause...": "Vnesite klavzulo za EU potrošniško prodajo...",
188
188
  "tax-clauses.other.description":
189
189
  "Te vrste transakcij običajno ne zahtevajo posebnih davčnih klavzul, vendar jih lahko konfigurirate po potrebi.",
190
+ // EPC QR Payment section
191
+ "EPC QR Payment": "EPC QR plačilo",
192
+ "SEPA credit transfer QR code for invoices": "SEPA QR koda za kreditne prenose na računih",
193
+ "Enable EPC QR on invoices": "Omogoči EPC QR na računih",
194
+ "Show SEPA QR code on EUR invoices for easy bank payments":
195
+ "Prikaži SEPA QR kodo na EUR računih za enostavna bančna plačila",
196
+ "EPC QR Payments": "EPC QR plačila",
197
+ "EPC QR is a European standard for SEPA credit transfers. When enabled, EUR invoices include a QR code that customers can scan with their banking app to pay instantly.":
198
+ "EPC QR je evropski standard za SEPA kreditne prenose. Ko je omogočen, EUR računi vključujejo QR kodo, ki jo stranke lahko skenirajo z bančno aplikacijo za takojšnje plačilo.",
190
199
  } as const;