@spaceinvoices/react-ui 0.4.7 → 0.4.10

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 (312) hide show
  1. package/cli/dist/index.js +1 -1
  2. package/package.json +1 -1
  3. package/src/common/autocomplete.tsx +69 -6
  4. package/src/components/advance-invoices/create/create-advance-invoice-form.tsx +124 -285
  5. package/src/components/advance-invoices/create/locales/de.ts +2 -1
  6. package/src/components/advance-invoices/create/locales/es.ts +2 -1
  7. package/src/components/advance-invoices/create/locales/fr.ts +2 -1
  8. package/src/components/advance-invoices/create/locales/hr.ts +2 -1
  9. package/src/components/advance-invoices/create/locales/it.ts +2 -1
  10. package/src/components/advance-invoices/create/locales/nl.ts +2 -1
  11. package/src/components/advance-invoices/create/locales/pl.ts +2 -1
  12. package/src/components/advance-invoices/create/locales/pt.ts +2 -1
  13. package/src/components/advance-invoices/create/locales/sl.ts +2 -1
  14. package/src/components/advance-invoices/list/list-table.tsx +10 -3
  15. package/src/components/advance-invoices/list/locales/de.ts +2 -0
  16. package/src/components/advance-invoices/list/locales/en.ts +1 -0
  17. package/src/components/advance-invoices/list/locales/es.ts +1 -0
  18. package/src/components/advance-invoices/list/locales/fr.ts +1 -0
  19. package/src/components/advance-invoices/list/locales/hr.ts +1 -0
  20. package/src/components/advance-invoices/list/locales/it.ts +1 -0
  21. package/src/components/advance-invoices/list/locales/nl.ts +1 -0
  22. package/src/components/advance-invoices/list/locales/pl.ts +1 -0
  23. package/src/components/advance-invoices/list/locales/pt.ts +1 -0
  24. package/src/components/advance-invoices/list/locales/sl.ts +1 -0
  25. package/src/components/advance-invoices/list/use-advance-invoice-download.ts +1 -12
  26. package/src/components/credit-notes/create/create-credit-note-form.tsx +116 -238
  27. package/src/components/credit-notes/create/locales/de.ts +2 -1
  28. package/src/components/credit-notes/create/locales/es.ts +2 -1
  29. package/src/components/credit-notes/create/locales/fr.ts +2 -1
  30. package/src/components/credit-notes/create/locales/hr.ts +2 -1
  31. package/src/components/credit-notes/create/locales/it.ts +2 -1
  32. package/src/components/credit-notes/create/locales/nl.ts +2 -1
  33. package/src/components/credit-notes/create/locales/pl.ts +2 -1
  34. package/src/components/credit-notes/create/locales/pt.ts +2 -1
  35. package/src/components/credit-notes/create/locales/sl.ts +2 -1
  36. package/src/components/credit-notes/list/list-table.tsx +6 -3
  37. package/src/components/credit-notes/list/use-credit-note-download.ts +1 -12
  38. package/src/components/customers/customer-autocomplete.tsx +64 -11
  39. package/src/components/customers/customer-list-table/customer-list-table.tsx +3 -2
  40. package/src/components/dashboard/collection-rate-card/collection-rate-card.tsx +9 -1
  41. package/src/components/dashboard/collection-rate-card/locales/bg.ts +3 -0
  42. package/src/components/dashboard/collection-rate-card/locales/cs.ts +3 -0
  43. package/src/components/dashboard/collection-rate-card/locales/et.ts +3 -0
  44. package/src/components/dashboard/collection-rate-card/locales/fi.ts +3 -0
  45. package/src/components/dashboard/collection-rate-card/locales/is.ts +3 -0
  46. package/src/components/dashboard/collection-rate-card/locales/nb.ts +3 -0
  47. package/src/components/dashboard/collection-rate-card/locales/sk.ts +3 -0
  48. package/src/components/dashboard/collection-rate-card/locales/sv.ts +3 -0
  49. package/src/components/dashboard/invoice-status-chart/invoice-status-chart.tsx +10 -2
  50. package/src/components/dashboard/invoice-status-chart/locales/bg.ts +10 -0
  51. package/src/components/dashboard/invoice-status-chart/locales/cs.ts +10 -0
  52. package/src/components/dashboard/invoice-status-chart/locales/de.ts +1 -0
  53. package/src/components/dashboard/invoice-status-chart/locales/es.ts +1 -0
  54. package/src/components/dashboard/invoice-status-chart/locales/et.ts +10 -0
  55. package/src/components/dashboard/invoice-status-chart/locales/fi.ts +10 -0
  56. package/src/components/dashboard/invoice-status-chart/locales/fr.ts +1 -0
  57. package/src/components/dashboard/invoice-status-chart/locales/hr.ts +1 -0
  58. package/src/components/dashboard/invoice-status-chart/locales/is.ts +10 -0
  59. package/src/components/dashboard/invoice-status-chart/locales/it.ts +1 -0
  60. package/src/components/dashboard/invoice-status-chart/locales/nb.ts +10 -0
  61. package/src/components/dashboard/invoice-status-chart/locales/nl.ts +1 -0
  62. package/src/components/dashboard/invoice-status-chart/locales/pl.ts +1 -0
  63. package/src/components/dashboard/invoice-status-chart/locales/pt.ts +1 -0
  64. package/src/components/dashboard/invoice-status-chart/locales/sk.ts +10 -0
  65. package/src/components/dashboard/invoice-status-chart/locales/sl.ts +1 -0
  66. package/src/components/dashboard/invoice-status-chart/locales/sv.ts +10 -0
  67. package/src/components/dashboard/payment-methods-chart/locales/bg.ts +12 -0
  68. package/src/components/dashboard/payment-methods-chart/locales/cs.ts +12 -0
  69. package/src/components/dashboard/payment-methods-chart/locales/et.ts +12 -0
  70. package/src/components/dashboard/payment-methods-chart/locales/fi.ts +12 -0
  71. package/src/components/dashboard/payment-methods-chart/locales/is.ts +12 -0
  72. package/src/components/dashboard/payment-methods-chart/locales/nb.ts +12 -0
  73. package/src/components/dashboard/payment-methods-chart/locales/sk.ts +12 -0
  74. package/src/components/dashboard/payment-methods-chart/locales/sv.ts +12 -0
  75. package/src/components/dashboard/payment-methods-chart/payment-methods-chart.tsx +9 -1
  76. package/src/components/dashboard/payment-trend-chart/locales/bg.ts +6 -0
  77. package/src/components/dashboard/payment-trend-chart/locales/cs.ts +6 -0
  78. package/src/components/dashboard/payment-trend-chart/locales/de.ts +1 -0
  79. package/src/components/dashboard/payment-trend-chart/locales/es.ts +1 -0
  80. package/src/components/dashboard/payment-trend-chart/locales/et.ts +6 -0
  81. package/src/components/dashboard/payment-trend-chart/locales/fi.ts +6 -0
  82. package/src/components/dashboard/payment-trend-chart/locales/fr.ts +1 -0
  83. package/src/components/dashboard/payment-trend-chart/locales/hr.ts +1 -0
  84. package/src/components/dashboard/payment-trend-chart/locales/is.ts +6 -0
  85. package/src/components/dashboard/payment-trend-chart/locales/it.ts +1 -0
  86. package/src/components/dashboard/payment-trend-chart/locales/nb.ts +6 -0
  87. package/src/components/dashboard/payment-trend-chart/locales/nl.ts +1 -0
  88. package/src/components/dashboard/payment-trend-chart/locales/pl.ts +1 -0
  89. package/src/components/dashboard/payment-trend-chart/locales/pt.ts +1 -0
  90. package/src/components/dashboard/payment-trend-chart/locales/sk.ts +6 -0
  91. package/src/components/dashboard/payment-trend-chart/locales/sl.ts +1 -0
  92. package/src/components/dashboard/payment-trend-chart/locales/sv.ts +6 -0
  93. package/src/components/dashboard/payment-trend-chart/payment-trend-chart.tsx +15 -8
  94. package/src/components/dashboard/revenue-trend-chart/locales/bg.ts +6 -0
  95. package/src/components/dashboard/revenue-trend-chart/locales/cs.ts +6 -0
  96. package/src/components/dashboard/revenue-trend-chart/locales/de.ts +1 -0
  97. package/src/components/dashboard/revenue-trend-chart/locales/es.ts +1 -0
  98. package/src/components/dashboard/revenue-trend-chart/locales/et.ts +6 -0
  99. package/src/components/dashboard/revenue-trend-chart/locales/fi.ts +6 -0
  100. package/src/components/dashboard/revenue-trend-chart/locales/fr.ts +1 -0
  101. package/src/components/dashboard/revenue-trend-chart/locales/hr.ts +1 -0
  102. package/src/components/dashboard/revenue-trend-chart/locales/is.ts +6 -0
  103. package/src/components/dashboard/revenue-trend-chart/locales/it.ts +1 -0
  104. package/src/components/dashboard/revenue-trend-chart/locales/nb.ts +6 -0
  105. package/src/components/dashboard/revenue-trend-chart/locales/nl.ts +1 -0
  106. package/src/components/dashboard/revenue-trend-chart/locales/pl.ts +1 -0
  107. package/src/components/dashboard/revenue-trend-chart/locales/pt.ts +1 -0
  108. package/src/components/dashboard/revenue-trend-chart/locales/sk.ts +6 -0
  109. package/src/components/dashboard/revenue-trend-chart/locales/sl.ts +1 -0
  110. package/src/components/dashboard/revenue-trend-chart/locales/sv.ts +6 -0
  111. package/src/components/dashboard/revenue-trend-chart/revenue-trend-chart.tsx +15 -8
  112. package/src/components/dashboard/tax-collected-card/locales.ts +110 -0
  113. package/src/components/dashboard/tax-collected-card/tax-collected-card.tsx +8 -2
  114. package/src/components/dashboard/tax-collected-card/use-tax-collected.ts +4 -4
  115. package/src/components/dashboard/top-customers-chart/locales/bg.ts +7 -0
  116. package/src/components/dashboard/top-customers-chart/locales/cs.ts +7 -0
  117. package/src/components/dashboard/top-customers-chart/locales/de.ts +2 -0
  118. package/src/components/dashboard/top-customers-chart/locales/es.ts +2 -0
  119. package/src/components/dashboard/top-customers-chart/locales/et.ts +7 -0
  120. package/src/components/dashboard/top-customers-chart/locales/fi.ts +7 -0
  121. package/src/components/dashboard/top-customers-chart/locales/fr.ts +2 -0
  122. package/src/components/dashboard/top-customers-chart/locales/hr.ts +2 -0
  123. package/src/components/dashboard/top-customers-chart/locales/is.ts +7 -0
  124. package/src/components/dashboard/top-customers-chart/locales/it.ts +2 -0
  125. package/src/components/dashboard/top-customers-chart/locales/nb.ts +7 -0
  126. package/src/components/dashboard/top-customers-chart/locales/nl.ts +2 -0
  127. package/src/components/dashboard/top-customers-chart/locales/pl.ts +2 -0
  128. package/src/components/dashboard/top-customers-chart/locales/pt.ts +2 -0
  129. package/src/components/dashboard/top-customers-chart/locales/sk.ts +7 -0
  130. package/src/components/dashboard/top-customers-chart/locales/sl.ts +2 -0
  131. package/src/components/dashboard/top-customers-chart/locales/sv.ts +7 -0
  132. package/src/components/dashboard/top-customers-chart/top-customers-chart.tsx +23 -12
  133. package/src/components/delivery-notes/create/create-delivery-note-form.tsx +33 -20
  134. package/src/components/delivery-notes/create/locales/de.ts +2 -1
  135. package/src/components/delivery-notes/create/locales/es.ts +2 -1
  136. package/src/components/delivery-notes/create/locales/fr.ts +2 -1
  137. package/src/components/delivery-notes/create/locales/hr.ts +2 -1
  138. package/src/components/delivery-notes/create/locales/it.ts +2 -1
  139. package/src/components/delivery-notes/create/locales/nl.ts +2 -1
  140. package/src/components/delivery-notes/create/locales/pl.ts +2 -1
  141. package/src/components/delivery-notes/create/locales/pt.ts +2 -1
  142. package/src/components/delivery-notes/create/locales/sl.ts +2 -1
  143. package/src/components/delivery-notes/list/list-table.tsx +22 -13
  144. package/src/components/delivery-notes/list/locales/de.ts +2 -0
  145. package/src/components/delivery-notes/list/locales/en.ts +1 -0
  146. package/src/components/delivery-notes/list/locales/es.ts +1 -0
  147. package/src/components/delivery-notes/list/locales/fr.ts +1 -0
  148. package/src/components/delivery-notes/list/locales/hr.ts +1 -0
  149. package/src/components/delivery-notes/list/locales/it.ts +1 -0
  150. package/src/components/delivery-notes/list/locales/nl.ts +1 -0
  151. package/src/components/delivery-notes/list/locales/pl.ts +1 -0
  152. package/src/components/delivery-notes/list/locales/pt.ts +1 -0
  153. package/src/components/delivery-notes/list/locales/sl.ts +1 -0
  154. package/src/components/delivery-notes/list/use-delivery-note-download.ts +1 -12
  155. package/src/components/documents/create/document-add-item-form.tsx +28 -16
  156. package/src/components/documents/create/document-add-item-tax-rate-field.tsx +12 -2
  157. package/src/components/documents/create/document-items-section.tsx +70 -39
  158. package/src/components/documents/create/document-recipient-section.tsx +10 -1
  159. package/src/components/documents/create/live-preview.tsx +113 -15
  160. package/src/components/documents/create/prepare-document-submission.ts +35 -16
  161. package/src/components/documents/create/use-document-customer-form.ts +14 -3
  162. package/src/components/documents/documents.hooks.ts +7 -2
  163. package/src/components/documents/shared/document-preview-display.tsx +136 -67
  164. package/src/components/documents/shared/scaled-document-preview.tsx +45 -5
  165. package/src/components/documents/view/document-actions-bar.tsx +284 -182
  166. package/src/components/documents/view/document-activities-list.tsx +3 -0
  167. package/src/components/documents/view/document-payments-list.tsx +3 -0
  168. package/src/components/documents/view/locales/de.ts +8 -0
  169. package/src/components/documents/view/locales/es.ts +8 -0
  170. package/src/components/documents/view/locales/fr.ts +8 -0
  171. package/src/components/documents/view/locales/hr.ts +8 -0
  172. package/src/components/documents/view/locales/it.ts +8 -0
  173. package/src/components/documents/view/locales/nl.ts +8 -0
  174. package/src/components/documents/view/locales/pl.ts +8 -0
  175. package/src/components/documents/view/locales/pt.ts +8 -0
  176. package/src/components/documents/view/locales/sl.ts +8 -0
  177. package/src/components/documents/view/use-document-download.ts +14 -25
  178. package/src/components/entities/create-entity-form.tsx +101 -16
  179. package/src/components/entities/entity-settings-form/locales/de.ts +6 -3
  180. package/src/components/entities/entity-settings-form/locales/es.ts +6 -3
  181. package/src/components/entities/entity-settings-form/locales/fr.ts +6 -3
  182. package/src/components/entities/entity-settings-form/locales/hr.ts +4 -2
  183. package/src/components/entities/entity-settings-form/locales/it.ts +6 -3
  184. package/src/components/entities/entity-settings-form/locales/nl.ts +6 -3
  185. package/src/components/entities/entity-settings-form/locales/pl.ts +6 -2
  186. package/src/components/entities/entity-settings-form/locales/pt.ts +6 -3
  187. package/src/components/entities/entity-settings-form/locales/sl.ts +4 -2
  188. package/src/components/entities/fina-settings-form/fina-operator-required-dialog.tsx +3 -3
  189. package/src/components/entities/fina-settings-form/fina-settings-form.tsx +78 -124
  190. package/src/components/entities/fina-settings-form/sections/certificate-settings-section.tsx +8 -1
  191. package/src/components/entities/fina-settings-form/sections/premises-management-section.tsx +14 -2
  192. package/src/components/entities/fina-settings-form/sections/register-premise-dialog.tsx +7 -2
  193. package/src/components/entities/furs-settings-form/furs-settings-form.tsx +56 -130
  194. package/src/components/entities/furs-settings-form/sections/certificate-settings-section.tsx +8 -1
  195. package/src/components/entities/furs-settings-form/sections/enable-fiscalization-section.tsx +1 -0
  196. package/src/components/entities/furs-settings-form/sections/general-settings-section.tsx +15 -2
  197. package/src/components/entities/furs-settings-form/sections/premises-management-section.tsx +20 -3
  198. package/src/components/entities/furs-settings-form/sections/register-premise-dialog.tsx +38 -12
  199. package/src/components/entities/settings/eslog-settings-form.tsx +13 -1
  200. package/src/components/entities/settings/pdf-template-selector/demo-invoice-data.ts +3 -22
  201. package/src/components/entities/shared/fiscalization-step-flow.ts +77 -0
  202. package/src/components/entities/shared/fiscalization-step-tabs.tsx +71 -0
  203. package/src/components/estimates/create/create-estimate-form.tsx +34 -21
  204. package/src/components/estimates/create/locales/de.ts +2 -1
  205. package/src/components/estimates/create/locales/es.ts +2 -1
  206. package/src/components/estimates/create/locales/fr.ts +2 -1
  207. package/src/components/estimates/create/locales/hr.ts +2 -1
  208. package/src/components/estimates/create/locales/it.ts +2 -1
  209. package/src/components/estimates/create/locales/nl.ts +2 -1
  210. package/src/components/estimates/create/locales/pl.ts +2 -1
  211. package/src/components/estimates/create/locales/pt.ts +2 -1
  212. package/src/components/estimates/create/locales/sl.ts +2 -1
  213. package/src/components/estimates/list/list-table.tsx +23 -14
  214. package/src/components/estimates/list/locales/de.ts +2 -0
  215. package/src/components/estimates/list/locales/en.ts +1 -0
  216. package/src/components/estimates/list/locales/es.ts +1 -0
  217. package/src/components/estimates/list/locales/fr.ts +1 -0
  218. package/src/components/estimates/list/locales/hr.ts +1 -0
  219. package/src/components/estimates/list/locales/it.ts +1 -0
  220. package/src/components/estimates/list/locales/nl.ts +1 -0
  221. package/src/components/estimates/list/locales/pl.ts +1 -0
  222. package/src/components/estimates/list/locales/pt.ts +1 -0
  223. package/src/components/estimates/list/locales/sl.ts +1 -0
  224. package/src/components/estimates/list/use-estimate-download.ts +1 -12
  225. package/src/components/export/document-export-form.tsx +33 -7
  226. package/src/components/export/sales-per-item-export-form.tsx +23 -7
  227. package/src/components/invoices/create/create-invoice-form.tsx +295 -329
  228. package/src/components/invoices/create/locales/de.ts +2 -1
  229. package/src/components/invoices/create/locales/es.ts +2 -1
  230. package/src/components/invoices/create/locales/fr.ts +2 -1
  231. package/src/components/invoices/create/locales/hr.ts +2 -1
  232. package/src/components/invoices/create/locales/it.ts +2 -1
  233. package/src/components/invoices/create/locales/nl.ts +2 -1
  234. package/src/components/invoices/create/locales/pl.ts +2 -1
  235. package/src/components/invoices/create/locales/pt.ts +2 -1
  236. package/src/components/invoices/create/locales/sl.ts +2 -1
  237. package/src/components/invoices/create/prepare-invoice-submission.ts +0 -8
  238. package/src/components/invoices/list/list-table.tsx +7 -4
  239. package/src/components/invoices/list/use-invoice-download.ts +1 -11
  240. package/src/components/invoices/send-email-dialog/locales/de.ts +2 -0
  241. package/src/components/invoices/send-email-dialog/locales/es.ts +2 -0
  242. package/src/components/invoices/send-email-dialog/locales/fr.ts +2 -0
  243. package/src/components/invoices/send-email-dialog/locales/hr.ts +2 -0
  244. package/src/components/invoices/send-email-dialog/locales/it.ts +2 -0
  245. package/src/components/invoices/send-email-dialog/locales/nl.ts +2 -0
  246. package/src/components/invoices/send-email-dialog/locales/pl.ts +2 -0
  247. package/src/components/invoices/send-email-dialog/locales/pt.ts +2 -0
  248. package/src/components/invoices/send-email-dialog/locales/sl.ts +2 -0
  249. package/src/components/invoices/send-email-dialog/send-email-dialog.tsx +77 -8
  250. package/src/components/invoices/view/eslog-info-display.tsx +17 -1
  251. package/src/components/invoices/view/fiscalization-status-card.tsx +7 -3
  252. package/src/components/items/item-combobox.tsx +26 -6
  253. package/src/components/items/item-list-table/item-list-table.tsx +5 -2
  254. package/src/components/payments/list/list-table.tsx +14 -4
  255. package/src/components/recurring-invoices/list/list-table.tsx +7 -4
  256. package/src/components/request-logs/locales.ts +412 -0
  257. package/src/components/request-logs/request-log-detail.tsx +37 -21
  258. package/src/components/request-logs/request-log-list-table.tsx +57 -11
  259. package/src/components/table/data-table.tsx +5 -2
  260. package/src/components/table/date-cell.tsx +3 -1
  261. package/src/components/table/filter-bar.tsx +14 -2
  262. package/src/components/table/hooks/use-table-query.ts +1 -1
  263. package/src/components/table/locales.ts +1116 -0
  264. package/src/components/table/search-input.tsx +12 -3
  265. package/src/components/table/selection-toolbar.tsx +23 -6
  266. package/src/components/table/table-empty-state.tsx +43 -3
  267. package/src/components/table/table-no-results.tsx +3 -3
  268. package/src/components/table/table-pagination.tsx +4 -3
  269. package/src/components/table/types.ts +1 -0
  270. package/src/components/tax-reports/index.ts +1 -0
  271. package/src/components/tax-reports/kir-export-form.tsx +46 -8
  272. package/src/components/tax-reports/slovenia-tax-profile-step.tsx +191 -0
  273. package/src/components/tax-reports/slovenia-yearly-export-form.tsx +509 -0
  274. package/src/components/tax-reports/slovenia-yearly-review-step.tsx +253 -0
  275. package/src/components/tax-reports/slovenia-yearly-summary.tsx +19 -0
  276. package/src/components/taxes/tax-list-table/tax-list-table.tsx +3 -2
  277. package/src/components/ui/sticky-form-footer.tsx +7 -1
  278. package/src/components/webhook-logs/index.ts +6 -0
  279. package/src/components/webhook-logs/locales.ts +392 -0
  280. package/src/components/webhook-logs/webhook-delivery-detail.tsx +255 -0
  281. package/src/components/webhook-logs/webhook-delivery-list-table.tsx +278 -0
  282. package/src/components/wl-subscription/index.ts +1 -0
  283. package/src/components/wl-subscription/locked-feature.tsx +1 -0
  284. package/src/components/wl-subscription/paywall.tsx +193 -0
  285. package/src/components/wl-subscription/upgrade-modal.tsx +93 -29
  286. package/src/generate-schemas.ts +10 -5
  287. package/src/generated/schemas/customer.ts +2 -0
  288. package/src/generated/schemas/entity.ts +34 -0
  289. package/src/generated/schemas/me.ts +20 -1
  290. package/src/generated/schemas/renderadvanceinvoicepreview_body.ts +40 -34
  291. package/src/generated/schemas/rendercreditnotepreview_body.ts +42 -36
  292. package/src/generated/schemas/renderdeliverynotepreview_body.ts +23 -13
  293. package/src/generated/schemas/renderestimatepreview_body.ts +23 -13
  294. package/src/generated/schemas/renderinvoicepreview_body.ts +40 -34
  295. package/src/generated/schemas/sendemail_body.ts +44 -0
  296. package/src/generated/schemas/startpdfexport_body.ts +91 -1
  297. package/src/generated/schemas/webhook.ts +10 -0
  298. package/src/hooks/use-duplicate-document.ts +51 -13
  299. package/src/hooks/use-eslog-validation.ts +59 -0
  300. package/src/hooks/use-premise-selection.ts +186 -0
  301. package/src/lib/browser-cookies.ts +4 -4
  302. package/src/lib/date-fns-locale.ts +48 -0
  303. package/src/lib/fiscalization-options.ts +81 -0
  304. package/src/lib/locale.ts +38 -0
  305. package/src/lib/template-variables.tsx +1 -1
  306. package/src/lib/translation.ts +14 -3
  307. package/src/providers/entities-context.tsx +1 -0
  308. package/src/providers/entities-provider.tsx +102 -3
  309. package/src/providers/form-footer-context.tsx +37 -4
  310. package/src/providers/sdk-provider.tsx +7 -2
  311. package/src/providers/white-label-provider.tsx +4 -1
  312. package/src/providers/wl-subscription-provider.tsx +90 -3
@@ -1,19 +1,18 @@
1
1
  import { zodResolver } from "@hookform/resolvers/zod";
2
2
  import type { Entity } from "@spaceinvoices/js-sdk";
3
- import { AlertCircle, CheckCircle2, Info } from "lucide-react";
4
- import { type FC, type ReactNode, useCallback, useEffect, useState } from "react";
3
+ import { AlertCircle, Info } from "lucide-react";
4
+ import type { FC, ReactNode } from "react";
5
5
  import { useForm } from "react-hook-form";
6
6
  import type { z } from "zod";
7
7
  import { Alert, AlertDescription, AlertTitle } from "@/ui/components/ui/alert";
8
8
  import { Form } from "@/ui/components/ui/form";
9
9
  import { PageLoadingSpinner } from "@/ui/components/ui/loading-spinner";
10
- import { Tabs, TabsList, TabsTrigger } from "@/ui/components/ui/tabs";
11
- import { Tooltip, TooltipContent, TooltipTrigger } from "@/ui/components/ui/tooltip";
12
10
  import { updateFursSettingsSchema } from "@/ui/generated/schemas";
13
11
  import type { ComponentTranslationProps } from "@/ui/lib/translation";
14
12
  import { createTranslation } from "@/ui/lib/translation";
15
- import { cn } from "@/ui/lib/utils";
16
13
  import { useFormFooterRegistration } from "@/ui/providers/form-footer-context";
14
+ import { type FiscalizationStepConfig, useFiscalizationStepFlow } from "../shared/fiscalization-step-flow";
15
+ import { FiscalizationStepTabs } from "../shared/fiscalization-step-tabs";
17
16
  import { useFursPremises, useFursSettings, useUpdateFursSettings, useUserFursSettings } from "./furs-settings.hooks";
18
17
  // Import locale files
19
18
  import de from "./locales/de";
@@ -99,10 +98,6 @@ export const FursSettingsForm: FC<FursSettingsFormProps> = ({
99
98
  renderSection,
100
99
  hideUserOperatorSection,
101
100
  }) => {
102
- // Step navigation state (can be controlled via props for URL sync)
103
- const [activeStep, setActiveStep] = useState<StepType>(initialStep);
104
- const [hasInitializedStep, setHasInitializedStep] = useState(false);
105
-
106
101
  // Create a guaranteed translation function using the createTranslation utility
107
102
  const translate = createTranslation({
108
103
  t: translateFn,
@@ -111,15 +106,6 @@ export const FursSettingsForm: FC<FursSettingsFormProps> = ({
111
106
  translations,
112
107
  });
113
108
 
114
- // Handle step changes
115
- const handleStepChange = useCallback(
116
- (newStep: StepType) => {
117
- setActiveStep(newStep);
118
- onStepChange?.(newStep); // Notify parent (e.g., for URL updates)
119
- },
120
- [onStepChange],
121
- );
122
-
123
109
  // Fetch FURS settings and premises
124
110
  const { data: fursSettings, isLoading: settingsLoading } = useFursSettings(entity.id);
125
111
  const { data: premises, isLoading: premisesLoading } = useFursPremises(entity.id);
@@ -178,7 +164,7 @@ export const FursSettingsForm: FC<FursSettingsFormProps> = ({
178
164
  const canAccessEnable =
179
165
  hasEntityTaxNumber && hasOperatorSettings && certificateValid && hasPremises && hasPremiseWithDevice;
180
166
 
181
- const steps = [
167
+ const steps: FiscalizationStepConfig<StepType>[] = [
182
168
  {
183
169
  id: "settings" as const,
184
170
  title: translate("General Settings"),
@@ -194,14 +180,14 @@ export const FursSettingsForm: FC<FursSettingsFormProps> = ({
194
180
  {
195
181
  id: "premises" as const,
196
182
  title: translate("Business Premises"),
197
- complete: hasPremiseWithDevice,
198
- unlocked: canAccessPremises,
183
+ complete: Boolean(hasPremiseWithDevice),
184
+ unlocked: Boolean(canAccessPremises),
199
185
  },
200
186
  {
201
187
  id: "enable" as const,
202
188
  title: translate("Enable Fiscalization"),
203
- complete: fursEnabled,
204
- unlocked: canAccessEnable,
189
+ complete: Boolean(fursEnabled),
190
+ unlocked: Boolean(canAccessEnable),
205
191
  },
206
192
  ];
207
193
 
@@ -222,30 +208,13 @@ export const FursSettingsForm: FC<FursSettingsFormProps> = ({
222
208
  return "settings";
223
209
  };
224
210
 
225
- // Smart initial step selection on first load (when data is ready)
226
- // biome-ignore lint/correctness/useExhaustiveDependencies: Intentionally run only when data loads, not on every dep change
227
- useEffect(() => {
228
- if (!hasInitializedStep && !settingsLoading && !premisesLoading) {
229
- const smartStep = getDefaultStep();
230
- if (smartStep !== activeStep) {
231
- handleStepChange(smartStep);
232
- }
233
- setHasInitializedStep(true);
234
- }
235
- }, [settingsLoading, premisesLoading, hasInitializedStep]);
236
-
237
- // Validate step and redirect if current step becomes locked
238
- // biome-ignore lint/correctness/useExhaustiveDependencies: steps is recreated on each render but values are stable
239
- useEffect(() => {
240
- const currentStepInfo = steps.find((s) => s.id === activeStep);
241
- if (currentStepInfo && !currentStepInfo.unlocked) {
242
- // If current step is locked, redirect to first unlocked step
243
- const firstUnlockedStep = steps.find((s) => s.unlocked);
244
- if (firstUnlockedStep) {
245
- handleStepChange(firstUnlockedStep.id);
246
- }
247
- }
248
- }, [activeStep, handleStepChange]);
211
+ const { activeStep, handleStepChange } = useFiscalizationStepFlow({
212
+ initialStep,
213
+ isReady: !settingsLoading && !premisesLoading,
214
+ steps,
215
+ getDefaultStep,
216
+ onStepChange,
217
+ });
249
218
 
250
219
  // Check if entity is Slovenian
251
220
  if (entity.country_code !== "SI") {
@@ -274,88 +243,39 @@ export const FursSettingsForm: FC<FursSettingsFormProps> = ({
274
243
  // Check if entity is in sandbox (test) mode
275
244
  const isSandboxMode = entity.environment === "sandbox";
276
245
 
277
- // Shared tabs navigation component - in left column only
278
- const tabsNavigation = (
279
- <div className="grid items-start gap-6 lg:grid-cols-[1fr_280px]">
280
- <Tabs
281
- value={activeStep}
282
- onValueChange={(value) => handleStepChange(value as typeof activeStep)}
283
- className="w-full"
284
- >
285
- <TabsList className="grid w-full grid-cols-4 rounded-none p-0">
286
- {steps.map((step, index) => {
287
- const isLocked = !step.unlocked;
288
- let tooltipText = "";
289
-
290
- if (isLocked) {
291
- if (step.id === "certificate") {
292
- if (!hasEntityTaxNumber) {
293
- tooltipText = translate("Set entity tax number in General Settings first");
294
- } else {
295
- tooltipText = translate("Set operator tax number and label in General Settings first");
296
- }
297
- } else if (step.id === "premises") {
298
- if (!hasEntityTaxNumber) {
299
- tooltipText = translate("Set entity tax number in General Settings first");
300
- } else if (!hasOperatorSettings) {
301
- tooltipText = translate("Set operator tax number and label in General Settings first");
302
- } else {
303
- tooltipText = translate("Upload and validate digital certificate first");
304
- }
305
- } else if (step.id === "enable") {
306
- if (!hasEntityTaxNumber || !hasOperatorSettings) {
307
- tooltipText = translate("Complete General Settings first");
308
- } else if (!certificateValid) {
309
- tooltipText = translate("Upload and validate digital certificate first");
310
- } else if (!hasPremises) {
311
- tooltipText = translate("Register at least one business premise first");
312
- } else {
313
- tooltipText = translate("Register at least one electronic device first");
314
- }
315
- }
316
- }
317
-
318
- const trigger = (
319
- <TabsTrigger
320
- value={step.id}
321
- disabled={isLocked}
322
- className={cn("cursor-pointer justify-center", !step.unlocked && "opacity-50")}
323
- >
324
- <span className="flex items-center gap-2">
325
- {step.complete ? (
326
- <CheckCircle2 className="h-4 w-4 text-green-500" />
327
- ) : (
328
- <span className="text-xs">{index + 1}</span>
329
- )}
330
- {step.title}
331
- </span>
332
- </TabsTrigger>
333
- );
334
-
335
- if (isLocked) {
336
- return (
337
- <Tooltip key={step.id} delayDuration={0}>
338
- <TooltipTrigger asChild>
339
- <span className="flex cursor-not-allowed justify-center">{trigger}</span>
340
- </TooltipTrigger>
341
- <TooltipContent>
342
- <p>{tooltipText}</p>
343
- </TooltipContent>
344
- </Tooltip>
345
- );
346
- }
347
-
348
- return (
349
- <span key={step.id} className="flex justify-center">
350
- {trigger}
351
- </span>
352
- );
353
- })}
354
- </TabsList>
355
- </Tabs>
356
- <div className="hidden lg:block" />
357
- </div>
358
- );
246
+ const getStepTooltipText = (step: (typeof steps)[number]) => {
247
+ if (step.id === "certificate") {
248
+ if (!hasEntityTaxNumber) {
249
+ return translate("Set entity tax number in General Settings first");
250
+ }
251
+ return translate("Set operator tax number and label in General Settings first");
252
+ }
253
+
254
+ if (step.id === "premises") {
255
+ if (!hasEntityTaxNumber) {
256
+ return translate("Set entity tax number in General Settings first");
257
+ }
258
+ if (!hasOperatorSettings) {
259
+ return translate("Set operator tax number and label in General Settings first");
260
+ }
261
+ return translate("Upload and validate digital certificate first");
262
+ }
263
+
264
+ if (step.id === "enable") {
265
+ if (!hasEntityTaxNumber || !hasOperatorSettings) {
266
+ return translate("Complete General Settings first");
267
+ }
268
+ if (!certificateValid) {
269
+ return translate("Upload and validate digital certificate first");
270
+ }
271
+ if (!hasPremises) {
272
+ return translate("Register at least one business premise first");
273
+ }
274
+ return translate("Register at least one electronic device first");
275
+ }
276
+
277
+ return "";
278
+ };
359
279
 
360
280
  // Helper to wrap section content with render prop if provided
361
281
  const wrapSection = (section: SectionType, content: ReactNode) => {
@@ -385,7 +305,13 @@ export const FursSettingsForm: FC<FursSettingsFormProps> = ({
385
305
  )}
386
306
 
387
307
  {/* Tabs navigation */}
388
- {tabsNavigation}
308
+ <FiscalizationStepTabs
309
+ activeStep={activeStep}
310
+ steps={steps}
311
+ onStepChange={handleStepChange}
312
+ getTooltipText={getStepTooltipText}
313
+ testIdPrefix="furs-tab"
314
+ />
389
315
 
390
316
  {/* Step content - each section wrapped with its own help */}
391
317
  {activeStep === "settings" && (
@@ -171,7 +171,11 @@ export const CertificateSettingsSection: FC<CertificateSettingsSectionProps> = (
171
171
  {/* Certificate Status - Show when certificate exists */}
172
172
  {hasCertificate && (
173
173
  <div className="space-y-4">
174
- <Alert variant={currentStatus.variant}>
174
+ <Alert
175
+ variant={currentStatus.variant}
176
+ data-testid="furs-certificate-status"
177
+ data-status={fursSettings?.certificate_status || "unknown"}
178
+ >
175
179
  <StatusIcon className={cn("h-4 w-4", currentStatus.iconColor)} />
176
180
  <AlertTitle>Certificate Status: {currentStatus.label}</AlertTitle>
177
181
  <AlertDescription className="space-y-2">
@@ -221,6 +225,7 @@ export const CertificateSettingsSection: FC<CertificateSettingsSectionProps> = (
221
225
  onChange={handleFileChange}
222
226
  disabled={isPending}
223
227
  className="flex-1"
228
+ data-testid="furs-certificate-file-input"
224
229
  />
225
230
  {certificateFile && <CheckCircle2 className="h-5 w-5 text-green-500" />}
226
231
  </div>
@@ -240,6 +245,7 @@ export const CertificateSettingsSection: FC<CertificateSettingsSectionProps> = (
240
245
  onChange={(e) => setPassphrase(e.target.value)}
241
246
  disabled={isPending}
242
247
  placeholder={t("Enter certificate passphrase")}
248
+ data-testid="furs-certificate-passphrase-input"
243
249
  />
244
250
  </div>
245
251
 
@@ -264,6 +270,7 @@ export const CertificateSettingsSection: FC<CertificateSettingsSectionProps> = (
264
270
  onClick={handleUpload}
265
271
  disabled={!certificateFile || !passphrase || isPending}
266
272
  className={cn(hasCertificate && showUploadForm ? "flex-1" : "w-full", "cursor-pointer")}
273
+ data-testid="furs-certificate-upload-submit"
267
274
  >
268
275
  <Upload className="mr-2 h-4 w-4" />
269
276
  {isPending ? t("Loading...") : hasCertificate ? t("Upload New Certificate") : t("Upload Certificate")}
@@ -116,6 +116,7 @@ export const EnableFiscalizationSection: FC<EnableFiscalizationSectionProps> = (
116
116
  onCheckedChange={field.onChange}
117
117
  disabled={!allPrerequisitesMet && !field.value}
118
118
  className="cursor-pointer"
119
+ data-testid="furs-enable-switch"
119
120
  />
120
121
  </FormControl>
121
122
  </FormItem>
@@ -175,6 +175,7 @@ export const GeneralSettingsSection: FC<GeneralSettingsSectionProps> = ({
175
175
  onClick={handleSaveEntityInfo}
176
176
  disabled={isEntityUpdatePending}
177
177
  className="cursor-pointer"
178
+ data-testid="furs-entity-info-save"
178
179
  >
179
180
  {isEntityUpdatePending ? t("Saving...") : t("Save Entity Info")}
180
181
  </Button>
@@ -240,6 +241,7 @@ export const GeneralSettingsSection: FC<GeneralSettingsSectionProps> = ({
240
241
  onClick={handleSaveUserSettings}
241
242
  disabled={isUserSettingsPending || userSettingsLoading}
242
243
  className="cursor-pointer"
244
+ data-testid="furs-operator-settings-save"
243
245
  >
244
246
  {isUserSettingsPending ? t("Saving...") : t("Save Operator Settings")}
245
247
  </Button>
@@ -320,6 +322,7 @@ export const GeneralSettingsSection: FC<GeneralSettingsSectionProps> = ({
320
322
  type="button"
321
323
  onClick={() => setIsAdvancedOpen(!isAdvancedOpen)}
322
324
  className="flex w-full items-center gap-2 py-2 text-muted-foreground hover:text-foreground"
325
+ data-testid="furs-advanced-toggle"
323
326
  >
324
327
  <ChevronRight className={cn("h-4 w-4 transition-transform", isAdvancedOpen && "rotate-90")} />
325
328
  <span className="font-medium text-sm">{t("Advanced Settings")}</span>
@@ -342,7 +345,12 @@ export const GeneralSettingsSection: FC<GeneralSettingsSectionProps> = ({
342
345
  <FormItem>
343
346
  <FormLabel className="text-sm">{t("Operator Tax Number")}</FormLabel>
344
347
  <FormControl>
345
- <Input placeholder="12345678" {...field} className="h-10" />
348
+ <Input
349
+ placeholder="12345678"
350
+ {...field}
351
+ className="h-10"
352
+ data-testid="furs-api-operator-tax-number-input"
353
+ />
346
354
  </FormControl>
347
355
  <FormDescription className="text-xs">
348
356
  {t("Tax number for API key usage (optional)")}
@@ -359,7 +367,12 @@ export const GeneralSettingsSection: FC<GeneralSettingsSectionProps> = ({
359
367
  <FormItem>
360
368
  <FormLabel className="text-sm">{t("Operator Label")}</FormLabel>
361
369
  <FormControl>
362
- <Input placeholder="API Default" {...field} className="h-10" />
370
+ <Input
371
+ placeholder="API Default"
372
+ {...field}
373
+ className="h-10"
374
+ data-testid="furs-api-operator-label-input"
375
+ />
363
376
  </FormControl>
364
377
  <FormDescription className="text-xs">
365
378
  {t("Operator label for API key usage (optional)")}
@@ -150,11 +150,21 @@ export const PremisesManagementSection: FC<PremisesManagementSectionProps> = ({
150
150
  <div className="space-y-6">
151
151
  {/* Add Premise Buttons */}
152
152
  <div className="flex gap-3">
153
- <Button onClick={() => handleAddPremise("real-estate")} variant="default" className="flex-1 cursor-pointer">
153
+ <Button
154
+ onClick={() => handleAddPremise("real-estate")}
155
+ variant="default"
156
+ className="flex-1 cursor-pointer"
157
+ data-testid="furs-add-real-estate-premise"
158
+ >
154
159
  <Building2 className="mr-2 h-4 w-4" />
155
160
  {t("Add Real Estate")}
156
161
  </Button>
157
- <Button onClick={() => handleAddPremise("movable")} variant="outline" className="flex-1 cursor-pointer">
162
+ <Button
163
+ onClick={() => handleAddPremise("movable")}
164
+ variant="outline"
165
+ className="flex-1 cursor-pointer"
166
+ data-testid="furs-add-movable-premise"
167
+ >
158
168
  <Truck className="mr-2 h-4 w-4" />
159
169
  {t("Add Movable")}
160
170
  </Button>
@@ -196,7 +206,11 @@ export const PremisesManagementSection: FC<PremisesManagementSectionProps> = ({
196
206
  </Button>
197
207
  </DropdownMenuTrigger>
198
208
  <DropdownMenuContent align="end">
199
- <DropdownMenuItem onClick={() => handleAddDevice(premise.id)} className="cursor-pointer">
209
+ <DropdownMenuItem
210
+ onClick={() => handleAddDevice(premise.id)}
211
+ className="cursor-pointer"
212
+ data-testid={`furs-add-device-${premise.business_premise_name}`}
213
+ >
200
214
  <Cpu className="mr-2 h-4 w-4" />
201
215
  {t("Add Electronic Device")}
202
216
  </DropdownMenuItem>
@@ -274,6 +288,7 @@ export const PremisesManagementSection: FC<PremisesManagementSectionProps> = ({
274
288
  variant="outline"
275
289
  onClick={() => handleAddDevice(premise.id)}
276
290
  className="cursor-pointer"
291
+ data-testid={`furs-add-device-${premise.business_premise_name}`}
277
292
  >
278
293
  <Cpu className="mr-2 h-4 w-4" />
279
294
  {t("Add Electronic Device")}
@@ -337,6 +352,7 @@ export const PremisesManagementSection: FC<PremisesManagementSectionProps> = ({
337
352
  handleRegisterDevice();
338
353
  }
339
354
  }}
355
+ data-testid="furs-device-name-input"
340
356
  />
341
357
  <p className="text-muted-foreground text-sm">
342
358
  {t("Enter a unique name for this device (e.g., E1, E2, POS1, DEVICE1)")}
@@ -357,6 +373,7 @@ export const PremisesManagementSection: FC<PremisesManagementSectionProps> = ({
357
373
  onClick={handleRegisterDevice}
358
374
  disabled={!deviceName.trim() || isRegisteringDevice}
359
375
  className="cursor-pointer"
376
+ data-testid="furs-register-device-submit"
360
377
  >
361
378
  {isRegisteringDevice ? t("Registering...") : t("Register Device")}
362
379
  </Button>
@@ -188,7 +188,14 @@ export const RegisterPremiseDialog: FC<RegisterPremiseDialogProps> = ({
188
188
  <FormItem>
189
189
  <FormLabel>{t("Cadastral Number")} *</FormLabel>
190
190
  <FormControl>
191
- <Input type="text" inputMode="numeric" pattern="[0-9]*" placeholder="123" {...field} />
191
+ <Input
192
+ type="text"
193
+ inputMode="numeric"
194
+ pattern="[0-9]*"
195
+ placeholder="123"
196
+ {...field}
197
+ data-testid="furs-real-estate-cadastral-number"
198
+ />
192
199
  </FormControl>
193
200
  <FormDescription>{t("Required by FURS (must be numeric)")}</FormDescription>
194
201
  <FormMessage />
@@ -205,7 +212,14 @@ export const RegisterPremiseDialog: FC<RegisterPremiseDialogProps> = ({
205
212
  <FormItem>
206
213
  <FormLabel>{t("Building Number")} *</FormLabel>
207
214
  <FormControl>
208
- <Input type="text" inputMode="numeric" pattern="[0-9]*" placeholder="456" {...field} />
215
+ <Input
216
+ type="text"
217
+ inputMode="numeric"
218
+ pattern="[0-9]*"
219
+ placeholder="456"
220
+ {...field}
221
+ data-testid="furs-real-estate-building-number"
222
+ />
209
223
  </FormControl>
210
224
  <FormDescription className="text-xs">{t("Numeric, use 0 if not applicable")}</FormDescription>
211
225
  <FormMessage />
@@ -219,7 +233,14 @@ export const RegisterPremiseDialog: FC<RegisterPremiseDialogProps> = ({
219
233
  <FormItem>
220
234
  <FormLabel>{t("Building Section")} *</FormLabel>
221
235
  <FormControl>
222
- <Input type="text" inputMode="numeric" pattern="[0-9]*" placeholder="1" {...field} />
236
+ <Input
237
+ type="text"
238
+ inputMode="numeric"
239
+ pattern="[0-9]*"
240
+ placeholder="1"
241
+ {...field}
242
+ data-testid="furs-real-estate-building-section"
243
+ />
223
244
  </FormControl>
224
245
  <FormDescription className="text-xs">{t("Numeric, use 0 if not applicable")}</FormDescription>
225
246
  <FormMessage />
@@ -236,7 +257,7 @@ export const RegisterPremiseDialog: FC<RegisterPremiseDialogProps> = ({
236
257
  <FormItem>
237
258
  <FormLabel>{t("Community")} *</FormLabel>
238
259
  <FormControl>
239
- <Input placeholder="Ljubljana" {...field} />
260
+ <Input placeholder="Ljubljana" {...field} data-testid="furs-real-estate-community" />
240
261
  </FormControl>
241
262
  <FormDescription>{t("Slovenian administrative community (občina) name")}</FormDescription>
242
263
  <FormMessage />
@@ -252,7 +273,7 @@ export const RegisterPremiseDialog: FC<RegisterPremiseDialogProps> = ({
252
273
  <FormItem>
253
274
  <FormLabel>{t("Street")} *</FormLabel>
254
275
  <FormControl>
255
- <Input placeholder="Dunajska cesta" {...field} />
276
+ <Input placeholder="Dunajska cesta" {...field} data-testid="furs-real-estate-street" />
256
277
  </FormControl>
257
278
  <FormMessage />
258
279
  </FormItem>
@@ -267,7 +288,7 @@ export const RegisterPremiseDialog: FC<RegisterPremiseDialogProps> = ({
267
288
  <FormItem>
268
289
  <FormLabel>{t("House Number")} *</FormLabel>
269
290
  <FormControl>
270
- <Input placeholder="22" {...field} />
291
+ <Input placeholder="22" {...field} data-testid="furs-real-estate-house-number" />
271
292
  </FormControl>
272
293
  <FormMessage />
273
294
  </FormItem>
@@ -280,7 +301,12 @@ export const RegisterPremiseDialog: FC<RegisterPremiseDialogProps> = ({
280
301
  <FormItem>
281
302
  <FormLabel>{t("Additional")}</FormLabel>
282
303
  <FormControl>
283
- <Input placeholder="A" {...field} value={field.value || ""} />
304
+ <Input
305
+ placeholder="A"
306
+ {...field}
307
+ value={field.value || ""}
308
+ data-testid="furs-real-estate-house-number-additional"
309
+ />
284
310
  </FormControl>
285
311
  <FormMessage />
286
312
  </FormItem>
@@ -296,7 +322,7 @@ export const RegisterPremiseDialog: FC<RegisterPremiseDialogProps> = ({
296
322
  <FormItem>
297
323
  <FormLabel>{t("City")} *</FormLabel>
298
324
  <FormControl>
299
- <Input placeholder="Ljubljana" {...field} />
325
+ <Input placeholder="Ljubljana" {...field} data-testid="furs-real-estate-city" />
300
326
  </FormControl>
301
327
  <FormMessage />
302
328
  </FormItem>
@@ -309,7 +335,7 @@ export const RegisterPremiseDialog: FC<RegisterPremiseDialogProps> = ({
309
335
  <FormItem>
310
336
  <FormLabel>{t("Postal Code")} *</FormLabel>
311
337
  <FormControl>
312
- <Input placeholder="1000" {...field} />
338
+ <Input placeholder="1000" {...field} data-testid="furs-real-estate-postal-code" />
313
339
  </FormControl>
314
340
  <FormDescription className="text-xs">{t("Exactly 4 digits")}</FormDescription>
315
341
  <FormMessage />
@@ -322,7 +348,7 @@ export const RegisterPremiseDialog: FC<RegisterPremiseDialogProps> = ({
322
348
  <Button type="button" variant="outline" onClick={() => onOpenChange(false)} disabled={isPending}>
323
349
  {t("Cancel")}
324
350
  </Button>
325
- <Button type="submit" disabled={isPending}>
351
+ <Button type="submit" disabled={isPending} data-testid="furs-register-premise-submit">
326
352
  {isPending ? t("Registering...") : t("Register Premise")}
327
353
  </Button>
328
354
  </DialogFooter>
@@ -345,7 +371,7 @@ export const RegisterPremiseDialog: FC<RegisterPremiseDialogProps> = ({
345
371
  <FormItem>
346
372
  <FormLabel>{t("Premise Name")}</FormLabel>
347
373
  <FormControl>
348
- <Input placeholder="P1" {...field} />
374
+ <Input placeholder="P1" {...field} data-testid="furs-movable-premise-name" />
349
375
  </FormControl>
350
376
  <FormDescription>{t("Unique identifier for this premise (e.g., P1, P2)")}</FormDescription>
351
377
  <FormMessage />
@@ -382,7 +408,7 @@ export const RegisterPremiseDialog: FC<RegisterPremiseDialogProps> = ({
382
408
  <Button type="button" variant="outline" onClick={() => onOpenChange(false)} disabled={isPending}>
383
409
  {t("Cancel")}
384
410
  </Button>
385
- <Button type="submit" disabled={isPending}>
411
+ <Button type="submit" disabled={isPending} data-testid="furs-register-premise-submit">
386
412
  {isPending ? t("Registering...") : t("Register Premise")}
387
413
  </Button>
388
414
  </DialogFooter>
@@ -16,6 +16,18 @@ const eslogSettingsSchema = z.object({
16
16
 
17
17
  type EslogSettingsSchema = z.infer<typeof eslogSettingsSchema>;
18
18
 
19
+ const translations = {
20
+ en: {
21
+ "Save Settings": "Save Settings",
22
+ "Enable e-SLOG validation": "Enable e-SLOG validation",
23
+ "When enabled, documents will be automatically validated against e-SLOG 2.0 requirements when created.":
24
+ "When enabled, documents will be automatically validated against e-SLOG 2.0 requirements when created.",
25
+ "About e-SLOG 2.0": "About e-SLOG 2.0",
26
+ "e-SLOG 2.0 is the Slovenian electronic invoice standard based on the European EN 16931 specification. Valid documents can be downloaded in XML format and attached to emails.":
27
+ "e-SLOG 2.0 is the Slovenian electronic invoice standard based on the European EN 16931 specification. Valid documents can be downloaded in XML format and attached to emails.",
28
+ },
29
+ } as const;
30
+
19
31
  export type EslogSettingsFormProps = {
20
32
  entity: Entity;
21
33
  onSuccess?: (data: Entity) => void;
@@ -30,7 +42,7 @@ export function EslogSettingsForm({
30
42
  onSuccess,
31
43
  onError,
32
44
  }: EslogSettingsFormProps) {
33
- const t = createTranslation({ t: translateProp, namespace, locale, translations: {} });
45
+ const t = createTranslation({ t: translateProp, namespace, locale, translations });
34
46
 
35
47
  const currentSettings = (entity.settings as Record<string, unknown>) || {};
36
48
 
@@ -116,12 +116,13 @@ const demoDataByLocale: Record<string, LocaleDemoData> = {
116
116
  },
117
117
  };
118
118
 
119
+ import { getFullLocale } from "@/ui/lib/locale";
120
+
119
121
  /**
120
122
  * Get demo invoice data for template preview based on locale
121
123
  */
122
124
  export function getDemoInvoiceData(locale: string): DemoInvoiceData {
123
- // Normalize locale (e.g., "en" -> "en-US", "sl" -> "sl-SI")
124
- const normalizedLocale = normalizeLocale(locale);
125
+ const normalizedLocale = getFullLocale(locale);
125
126
  const data = demoDataByLocale[normalizedLocale] || demoDataByLocale["en-US"];
126
127
 
127
128
  const today = new Date();
@@ -142,23 +143,3 @@ export function getDemoInvoiceData(locale: string): DemoInvoiceData {
142
143
  note: data.note,
143
144
  };
144
145
  }
145
-
146
- function normalizeLocale(locale: string): string {
147
- const mapping: Record<string, string> = {
148
- en: "en-US",
149
- sl: "sl-SI",
150
- de: "de-DE",
151
- fr: "fr-FR",
152
- es: "es-ES",
153
- it: "it-IT",
154
- };
155
-
156
- // If already full locale, return as-is if supported
157
- if (demoDataByLocale[locale]) {
158
- return locale;
159
- }
160
-
161
- // Try to match short code
162
- const shortCode = locale.split("-")[0].toLowerCase();
163
- return mapping[shortCode] || "en-US";
164
- }