@spaceinvoices/react-ui 0.1.1

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 (352) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +340 -0
  3. package/cli/dist/index.js +922 -0
  4. package/package.json +87 -0
  5. package/registry.json +600 -0
  6. package/spaceinvoices.schema.json +47 -0
  7. package/src/app.tsx +25 -0
  8. package/src/common/autocomplete.tsx +135 -0
  9. package/src/components/activities/activity-timeline.tsx +160 -0
  10. package/src/components/activities/index.ts +1 -0
  11. package/src/components/activities/locales/de.ts +30 -0
  12. package/src/components/activities/locales/sl.ts +30 -0
  13. package/src/components/advance-invoices/advance-invoices.hooks.ts +75 -0
  14. package/src/components/advance-invoices/create/create-advance-invoice-form.tsx +702 -0
  15. package/src/components/advance-invoices/create/locales/de.ts +29 -0
  16. package/src/components/advance-invoices/create/locales/sl.ts +25 -0
  17. package/src/components/advance-invoices/create/prepare-advance-invoice-submission.ts +74 -0
  18. package/src/components/advance-invoices/index.ts +5 -0
  19. package/src/components/advance-invoices/list/index.ts +3 -0
  20. package/src/components/advance-invoices/list/list-row-actions.tsx +119 -0
  21. package/src/components/advance-invoices/list/list-table.tsx +178 -0
  22. package/src/components/advance-invoices/list/locales/de.ts +32 -0
  23. package/src/components/advance-invoices/list/locales/sl.ts +32 -0
  24. package/src/components/advance-invoices/list/use-advance-invoice-download.ts +63 -0
  25. package/src/components/button-loader.tsx +11 -0
  26. package/src/components/combobox.tsx +96 -0
  27. package/src/components/company-registry/company-registry-autocomplete.tsx +151 -0
  28. package/src/components/company-registry/company-registry.hooks.ts +67 -0
  29. package/src/components/company-registry/index.ts +7 -0
  30. package/src/components/credit-notes/create/create-credit-note-form.tsx +332 -0
  31. package/src/components/credit-notes/create/index.ts +1 -0
  32. package/src/components/credit-notes/create/locales/de.ts +69 -0
  33. package/src/components/credit-notes/create/locales/sl.ts +67 -0
  34. package/src/components/credit-notes/credit-notes.hooks.ts +22 -0
  35. package/src/components/credit-notes/index.ts +10 -0
  36. package/src/components/credit-notes/list/index.ts +3 -0
  37. package/src/components/credit-notes/list/list-row-actions.tsx +116 -0
  38. package/src/components/credit-notes/list/list-table.tsx +183 -0
  39. package/src/components/credit-notes/list/locales/de.ts +33 -0
  40. package/src/components/credit-notes/list/locales/sl.ts +33 -0
  41. package/src/components/credit-notes/list/use-credit-note-download.ts +65 -0
  42. package/src/components/customers/create-customer-form/create-customer-form.tsx +134 -0
  43. package/src/components/customers/create-customer-form/locales/de.ts +20 -0
  44. package/src/components/customers/create-customer-form/locales/sl.ts +20 -0
  45. package/src/components/customers/customer-autocomplete.tsx +173 -0
  46. package/src/components/customers/customer-combobox.tsx +130 -0
  47. package/src/components/customers/customer-list-table/customer-list-row-actions.tsx +48 -0
  48. package/src/components/customers/customer-list-table/customer-list-table.tsx +124 -0
  49. package/src/components/customers/customer-list-table/index.ts +2 -0
  50. package/src/components/customers/customer-list-table/locales/de.ts +16 -0
  51. package/src/components/customers/customer-list-table/locales/sl.ts +16 -0
  52. package/src/components/customers/customers.hooks.test.ts +348 -0
  53. package/src/components/customers/customers.hooks.ts +57 -0
  54. package/src/components/customers/index.ts +5 -0
  55. package/src/components/dashboard/chart-empty-state.tsx +29 -0
  56. package/src/components/dashboard/collection-rate-card/collection-rate-card.tsx +80 -0
  57. package/src/components/dashboard/collection-rate-card/index.ts +4 -0
  58. package/src/components/dashboard/collection-rate-card/locales/sl.ts +3 -0
  59. package/src/components/dashboard/collection-rate-card/use-collection-rate.ts +74 -0
  60. package/src/components/dashboard/index.ts +54 -0
  61. package/src/components/dashboard/invoice-status-chart/index.ts +4 -0
  62. package/src/components/dashboard/invoice-status-chart/invoice-status-chart.tsx +130 -0
  63. package/src/components/dashboard/invoice-status-chart/locales/sl.ts +9 -0
  64. package/src/components/dashboard/invoice-status-chart/use-invoice-status.ts +105 -0
  65. package/src/components/dashboard/loading-card.tsx +19 -0
  66. package/src/components/dashboard/payment-methods-chart/index.ts +4 -0
  67. package/src/components/dashboard/payment-methods-chart/locales/sl.ts +12 -0
  68. package/src/components/dashboard/payment-methods-chart/payment-methods-chart.tsx +152 -0
  69. package/src/components/dashboard/payment-methods-chart/use-payment-methods.ts +50 -0
  70. package/src/components/dashboard/payment-trend-chart/index.ts +4 -0
  71. package/src/components/dashboard/payment-trend-chart/locales/sl.ts +5 -0
  72. package/src/components/dashboard/payment-trend-chart/payment-trend-chart.tsx +137 -0
  73. package/src/components/dashboard/payment-trend-chart/use-payment-trend.ts +92 -0
  74. package/src/components/dashboard/revenue-card.tsx +49 -0
  75. package/src/components/dashboard/revenue-trend-chart/index.ts +4 -0
  76. package/src/components/dashboard/revenue-trend-chart/locales/sl.ts +5 -0
  77. package/src/components/dashboard/revenue-trend-chart/revenue-trend-chart.tsx +137 -0
  78. package/src/components/dashboard/revenue-trend-chart/use-revenue-trend.ts +93 -0
  79. package/src/components/dashboard/shared/index.ts +5 -0
  80. package/src/components/dashboard/shared/use-revenue-data.ts +160 -0
  81. package/src/components/dashboard/shared/use-stats-counts.ts +89 -0
  82. package/src/components/dashboard/shared/use-stats-query.ts +38 -0
  83. package/src/components/dashboard/stat-card.tsx +41 -0
  84. package/src/components/dashboard/tax-collected-card/index.ts +2 -0
  85. package/src/components/dashboard/tax-collected-card/tax-collected-card.tsx +77 -0
  86. package/src/components/dashboard/tax-collected-card/use-tax-collected.ts +145 -0
  87. package/src/components/dashboard/top-customers-chart/index.ts +4 -0
  88. package/src/components/dashboard/top-customers-chart/locales/sl.ts +5 -0
  89. package/src/components/dashboard/top-customers-chart/top-customers-chart.tsx +130 -0
  90. package/src/components/dashboard/top-customers-chart/use-top-customers.ts +72 -0
  91. package/src/components/documents/create/document-add-item-form.tsx +379 -0
  92. package/src/components/documents/create/document-add-item-tax-rate-field.tsx +120 -0
  93. package/src/components/documents/create/document-details-section.tsx +597 -0
  94. package/src/components/documents/create/document-items-section.tsx +133 -0
  95. package/src/components/documents/create/document-recipient-section.tsx +101 -0
  96. package/src/components/documents/create/form-types.ts +36 -0
  97. package/src/components/documents/create/index.ts +9 -0
  98. package/src/components/documents/create/live-preview.tsx +235 -0
  99. package/src/components/documents/create/mark-as-paid-section.tsx +82 -0
  100. package/src/components/documents/create/prepare-document-submission.test.ts +132 -0
  101. package/src/components/documents/create/prepare-document-submission.ts +187 -0
  102. package/src/components/documents/create/prepare-preview-data.test.ts +155 -0
  103. package/src/components/documents/create/prepare-preview-data.ts +16 -0
  104. package/src/components/documents/create/smart-code-insert-button.tsx +139 -0
  105. package/src/components/documents/create/use-document-customer-form.ts +161 -0
  106. package/src/components/documents/document-preview.tsx +13 -0
  107. package/src/components/documents/documents.hooks.ts +146 -0
  108. package/src/components/documents/index.ts +23 -0
  109. package/src/components/documents/shared/document-preview-display.tsx +172 -0
  110. package/src/components/documents/shared/index.ts +3 -0
  111. package/src/components/documents/shared/scaled-document-preview.tsx +70 -0
  112. package/src/components/documents/shared/use-a4-scaling.ts +62 -0
  113. package/src/components/documents/types.ts +61 -0
  114. package/src/components/documents/view/document-actions-bar.tsx +328 -0
  115. package/src/components/documents/view/document-details-card.tsx +179 -0
  116. package/src/components/documents/view/document-payments-list.tsx +256 -0
  117. package/src/components/documents/view/index.ts +4 -0
  118. package/src/components/documents/view/locales/de.ts +85 -0
  119. package/src/components/documents/view/locales/sl.ts +84 -0
  120. package/src/components/documents/view/use-document-download.ts +125 -0
  121. package/src/components/entities/create-entity-form.tsx +105 -0
  122. package/src/components/entities/entities.hooks.ts +50 -0
  123. package/src/components/entities/entity-settings-form/email-template-variables-info.tsx +103 -0
  124. package/src/components/entities/entity-settings-form/entity-settings-form.tsx +1326 -0
  125. package/src/components/entities/entity-settings-form/image-upload-with-crop.tsx +222 -0
  126. package/src/components/entities/entity-settings-form/index.ts +2 -0
  127. package/src/components/entities/entity-settings-form/input-with-preview.tsx +190 -0
  128. package/src/components/entities/entity-settings-form/locales/de.ts +192 -0
  129. package/src/components/entities/entity-settings-form/locales/sl.ts +188 -0
  130. package/src/components/entities/furs-settings-form/furs-settings-form.tsx +410 -0
  131. package/src/components/entities/furs-settings-form/furs-settings.hooks.ts +320 -0
  132. package/src/components/entities/furs-settings-form/index.ts +3 -0
  133. package/src/components/entities/furs-settings-form/locales/de.ts +233 -0
  134. package/src/components/entities/furs-settings-form/locales/en.ts +194 -0
  135. package/src/components/entities/furs-settings-form/locales/sl.ts +196 -0
  136. package/src/components/entities/furs-settings-form/sections/certificate-settings-section.tsx +242 -0
  137. package/src/components/entities/furs-settings-form/sections/enable-fiscalization-section.tsx +139 -0
  138. package/src/components/entities/furs-settings-form/sections/general-settings-section.tsx +252 -0
  139. package/src/components/entities/furs-settings-form/sections/premises-management-section.tsx +370 -0
  140. package/src/components/entities/furs-settings-form/sections/register-premise-dialog.tsx +420 -0
  141. package/src/components/entities/keys.ts +2 -0
  142. package/src/components/entities/settings/branding-settings-form.tsx +274 -0
  143. package/src/components/entities/settings/company-settings-form.tsx +256 -0
  144. package/src/components/entities/settings/defaults-settings-form.tsx +501 -0
  145. package/src/components/entities/settings/email-settings-form.tsx +288 -0
  146. package/src/components/entities/settings/eslog-settings-form.tsx +113 -0
  147. package/src/components/entities/settings/index.ts +8 -0
  148. package/src/components/entities/settings/number-format-settings-form.tsx +244 -0
  149. package/src/components/entities/settings/pdf-template-selector/demo-invoice-data.ts +164 -0
  150. package/src/components/entities/settings/pdf-template-selector/index.ts +2 -0
  151. package/src/components/entities/settings/pdf-template-selector/locales/de.ts +18 -0
  152. package/src/components/entities/settings/pdf-template-selector/locales/sl.ts +18 -0
  153. package/src/components/entities/settings/pdf-template-selector/pdf-template-cards.tsx +49 -0
  154. package/src/components/entities/settings/settings-footer.tsx +16 -0
  155. package/src/components/entities/settings/tax-rules-settings-form.tsx +346 -0
  156. package/src/components/estimates/create/create-estimate-form.tsx +384 -0
  157. package/src/components/estimates/create/locales/de.ts +64 -0
  158. package/src/components/estimates/create/locales/sl.ts +63 -0
  159. package/src/components/estimates/create/prepare-estimate-submission.ts +39 -0
  160. package/src/components/estimates/create/use-estimate-customer-form.ts +5 -0
  161. package/src/components/estimates/estimates.hooks.ts +15 -0
  162. package/src/components/estimates/index.ts +6 -0
  163. package/src/components/estimates/list/index.ts +3 -0
  164. package/src/components/estimates/list/list-row-actions.tsx +103 -0
  165. package/src/components/estimates/list/list-table.tsx +171 -0
  166. package/src/components/estimates/list/locales/de.ts +26 -0
  167. package/src/components/estimates/list/locales/sl.ts +26 -0
  168. package/src/components/estimates/list/use-estimate-download.ts +63 -0
  169. package/src/components/export/document-export-form.tsx +288 -0
  170. package/src/components/export/index.ts +2 -0
  171. package/src/components/form/form-input.tsx +89 -0
  172. package/src/components/form/index.ts +1 -0
  173. package/src/components/invoices/create/create-invoice-form.tsx +852 -0
  174. package/src/components/invoices/create/eslog-validation.test.ts +242 -0
  175. package/src/components/invoices/create/eslog-validation.ts +208 -0
  176. package/src/components/invoices/create/locales/de.ts +118 -0
  177. package/src/components/invoices/create/locales/sl.ts +114 -0
  178. package/src/components/invoices/create/prepare-invoice-submission.test.ts +777 -0
  179. package/src/components/invoices/create/prepare-invoice-submission.ts +79 -0
  180. package/src/components/invoices/create/use-invoice-customer-form.ts +5 -0
  181. package/src/components/invoices/index.ts +9 -0
  182. package/src/components/invoices/invoices-furs.hooks.ts +28 -0
  183. package/src/components/invoices/invoices.hooks.ts +110 -0
  184. package/src/components/invoices/list/index.ts +3 -0
  185. package/src/components/invoices/list/list-row-actions.tsx +132 -0
  186. package/src/components/invoices/list/list-table.tsx +165 -0
  187. package/src/components/invoices/list/locales/de.ts +33 -0
  188. package/src/components/invoices/list/locales/sl.ts +33 -0
  189. package/src/components/invoices/list/use-invoice-download.ts +62 -0
  190. package/src/components/invoices/send-email-dialog/index.ts +1 -0
  191. package/src/components/invoices/send-email-dialog/locales/de.ts +18 -0
  192. package/src/components/invoices/send-email-dialog/locales/sl.ts +17 -0
  193. package/src/components/invoices/send-email-dialog/send-email-dialog.tsx +289 -0
  194. package/src/components/invoices/send-email-dialog.tsx +2 -0
  195. package/src/components/invoices/shared/index.ts +2 -0
  196. package/src/components/invoices/shared/scaled-document-preview.tsx +32 -0
  197. package/src/components/invoices/shared/use-a4-scaling.tsx +39 -0
  198. package/src/components/invoices/view/eslog-info-display.tsx +160 -0
  199. package/src/components/invoices/view/furs-info-display.tsx +213 -0
  200. package/src/components/items/create-item-form/create-item-form.tsx +155 -0
  201. package/src/components/items/create-item-form/locales/de.ts +14 -0
  202. package/src/components/items/create-item-form/locales/en.ts +9 -0
  203. package/src/components/items/create-item-form/locales/sl.ts +14 -0
  204. package/src/components/items/item-combobox.tsx +147 -0
  205. package/src/components/items/item-list-table/item-list-header.tsx +33 -0
  206. package/src/components/items/item-list-table/item-list-row-actions.tsx +48 -0
  207. package/src/components/items/item-list-table/item-list-row.tsx +32 -0
  208. package/src/components/items/item-list-table/item-list-table.tsx +76 -0
  209. package/src/components/items/item-list-table/locales/de.ts +10 -0
  210. package/src/components/items/item-list-table/locales/en.ts +10 -0
  211. package/src/components/items/item-list-table/locales/sl.ts +10 -0
  212. package/src/components/items/items.hooks.ts +63 -0
  213. package/src/components/loading-spinner.tsx +24 -0
  214. package/src/components/payments/create-payment-form/create-payment-form.tsx +222 -0
  215. package/src/components/payments/create-payment-form/locales/de.ts +20 -0
  216. package/src/components/payments/create-payment-form/locales/sl.ts +20 -0
  217. package/src/components/payments/edit-payment-form/edit-payment-form.tsx +230 -0
  218. package/src/components/payments/edit-payment-form/index.ts +1 -0
  219. package/src/components/payments/edit-payment-form/locales/de.ts +20 -0
  220. package/src/components/payments/edit-payment-form/locales/sl.ts +20 -0
  221. package/src/components/payments/index.ts +4 -0
  222. package/src/components/payments/list/index.ts +2 -0
  223. package/src/components/payments/list/list-row-actions.tsx +98 -0
  224. package/src/components/payments/list/list-table.tsx +186 -0
  225. package/src/components/payments/list/locales/de.ts +19 -0
  226. package/src/components/payments/list/locales/sl.ts +19 -0
  227. package/src/components/payments/payments.hooks.ts +15 -0
  228. package/src/components/request-logs/index.ts +3 -0
  229. package/src/components/request-logs/request-log-detail.tsx +242 -0
  230. package/src/components/request-logs/request-log-list-table.tsx +266 -0
  231. package/src/components/request-logs/request-logs-page.tsx +10 -0
  232. package/src/components/table/README.md +410 -0
  233. package/src/components/table/data-table.tsx +251 -0
  234. package/src/components/table/date-cell.tsx +35 -0
  235. package/src/components/table/filter-bar.tsx +114 -0
  236. package/src/components/table/filter-panel.tsx +407 -0
  237. package/src/components/table/hooks/use-table-fetch.ts +17 -0
  238. package/src/components/table/hooks/use-table-query.ts +36 -0
  239. package/src/components/table/hooks/use-table-state.ts +293 -0
  240. package/src/components/table/index.ts +35 -0
  241. package/src/components/table/search-input.tsx +85 -0
  242. package/src/components/table/sortable-header.tsx +56 -0
  243. package/src/components/table/table-empty-state.tsx +40 -0
  244. package/src/components/table/table-no-results.tsx +41 -0
  245. package/src/components/table/table-pagination.tsx +42 -0
  246. package/src/components/table/table-skeleton.tsx +54 -0
  247. package/src/components/table/types.ts +136 -0
  248. package/src/components/tax-reports/index.ts +1 -0
  249. package/src/components/tax-reports/kir-export-form.tsx +172 -0
  250. package/src/components/taxes/create-tax-form/create-tax-form.tsx +112 -0
  251. package/src/components/taxes/create-tax-form/locales/de.ts +8 -0
  252. package/src/components/taxes/create-tax-form/locales/en.ts +7 -0
  253. package/src/components/taxes/create-tax-form/locales/sl.ts +8 -0
  254. package/src/components/taxes/tax-list-table/locales/de.ts +11 -0
  255. package/src/components/taxes/tax-list-table/locales/en.ts +10 -0
  256. package/src/components/taxes/tax-list-table/locales/sl.ts +11 -0
  257. package/src/components/taxes/tax-list-table/tax-list-header.tsx +29 -0
  258. package/src/components/taxes/tax-list-table/tax-list-row-actions.tsx +43 -0
  259. package/src/components/taxes/tax-list-table/tax-list-row.tsx +46 -0
  260. package/src/components/taxes/tax-list-table/tax-list-table.tsx +59 -0
  261. package/src/components/taxes/taxes.hooks.ts +35 -0
  262. package/src/components/ui/alert-dialog.tsx +61 -0
  263. package/src/components/ui/alert.tsx +72 -0
  264. package/src/components/ui/badge.tsx +48 -0
  265. package/src/components/ui/breadcrumb.tsx +132 -0
  266. package/src/components/ui/button.tsx +61 -0
  267. package/src/components/ui/calendar.tsx +213 -0
  268. package/src/components/ui/card.tsx +94 -0
  269. package/src/components/ui/chart.tsx +380 -0
  270. package/src/components/ui/checkbox.tsx +27 -0
  271. package/src/components/ui/collapsible.tsx +56 -0
  272. package/src/components/ui/command.tsx +187 -0
  273. package/src/components/ui/dialog.tsx +187 -0
  274. package/src/components/ui/drawer.tsx +123 -0
  275. package/src/components/ui/dropdown-menu.tsx +291 -0
  276. package/src/components/ui/form.tsx +166 -0
  277. package/src/components/ui/input-group.tsx +149 -0
  278. package/src/components/ui/input.tsx +20 -0
  279. package/src/components/ui/label.tsx +18 -0
  280. package/src/components/ui/loading-spinner.tsx +16 -0
  281. package/src/components/ui/popover.tsx +108 -0
  282. package/src/components/ui/radio-group.tsx +37 -0
  283. package/src/components/ui/select.tsx +200 -0
  284. package/src/components/ui/separator.tsx +23 -0
  285. package/src/components/ui/sheet.tsx +145 -0
  286. package/src/components/ui/sidebar.tsx +771 -0
  287. package/src/components/ui/skeleton.tsx +13 -0
  288. package/src/components/ui/sonner.tsx +60 -0
  289. package/src/components/ui/spinner.tsx +10 -0
  290. package/src/components/ui/sticky-form-footer.tsx +55 -0
  291. package/src/components/ui/switch.tsx +30 -0
  292. package/src/components/ui/table.tsx +101 -0
  293. package/src/components/ui/tabs.tsx +80 -0
  294. package/src/components/ui/textarea.tsx +18 -0
  295. package/src/components/ui/tooltip.tsx +89 -0
  296. package/src/components/wl-subscription/index.ts +2 -0
  297. package/src/components/wl-subscription/locked-feature.tsx +173 -0
  298. package/src/components/wl-subscription/upgrade-modal.tsx +209 -0
  299. package/src/frontend.tsx +28 -0
  300. package/src/generate-schemas.ts +265 -0
  301. package/src/generated/schemas/advanceinvoice.ts +177 -0
  302. package/src/generated/schemas/creditnote.ts +187 -0
  303. package/src/generated/schemas/customer.ts +29 -0
  304. package/src/generated/schemas/entity.ts +252 -0
  305. package/src/generated/schemas/estimate.ts +159 -0
  306. package/src/generated/schemas/furssettings.ts +25 -0
  307. package/src/generated/schemas/index.ts +24 -0
  308. package/src/generated/schemas/invoice.ts +167 -0
  309. package/src/generated/schemas/item.ts +38 -0
  310. package/src/generated/schemas/payment.ts +44 -0
  311. package/src/generated/schemas/previewadvanceinvoice_body.ts +354 -0
  312. package/src/generated/schemas/previewestimate_body.ts +309 -0
  313. package/src/generated/schemas/registerfursmovablepremise_body.ts +22 -0
  314. package/src/generated/schemas/registerfursrealestatepremise_body.ts +32 -0
  315. package/src/generated/schemas/renderdocument_body.ts +594 -0
  316. package/src/generated/schemas/sendemail_body.ts +26 -0
  317. package/src/generated/schemas/startpdfexport_body.ts +20 -0
  318. package/src/generated/schemas/tax.ts +48 -0
  319. package/src/generated/schemas/uploadfile_body.ts +23 -0
  320. package/src/generated/schemas/uploadfurscertificate_body.ts +20 -0
  321. package/src/generated/schemas/userfurssettings.ts +19 -0
  322. package/src/hooks/create-resource-hooks.test.ts +483 -0
  323. package/src/hooks/create-resource-hooks.ts +300 -0
  324. package/src/hooks/use-debounce.ts +12 -0
  325. package/src/hooks/use-duplicate-document.ts +185 -0
  326. package/src/hooks/use-media-query.tsx +19 -0
  327. package/src/hooks/use-mobile.ts +39 -0
  328. package/src/hooks/use-next-document-number.ts +57 -0
  329. package/src/hooks/use-resource-mutation.ts +118 -0
  330. package/src/hooks/use-vies-check.ts +130 -0
  331. package/src/index.css +11 -0
  332. package/src/index.html +13 -0
  333. package/src/index.tsx +12 -0
  334. package/src/lib/auth.ts +4 -0
  335. package/src/lib/browser-cookies.ts +70 -0
  336. package/src/lib/constants.ts +287 -0
  337. package/src/lib/cookies.ts +36 -0
  338. package/src/lib/schemas/advance-invoice.ts +43 -0
  339. package/src/lib/schemas/credit-note.ts +32 -0
  340. package/src/lib/schemas/estimate.ts +31 -0
  341. package/src/lib/schemas/index.ts +18 -0
  342. package/src/lib/schemas/invoice.ts +43 -0
  343. package/src/lib/schemas/shared.ts +79 -0
  344. package/src/lib/translation.ts +38 -0
  345. package/src/lib/utils.ts +6 -0
  346. package/src/providers/entities-context.tsx +41 -0
  347. package/src/providers/entities-provider.tsx +201 -0
  348. package/src/providers/form-footer-context.tsx +72 -0
  349. package/src/providers/sdk-provider.tsx +164 -0
  350. package/src/providers/white-label-provider.tsx +91 -0
  351. package/src/providers/wl-subscription-provider.tsx +277 -0
  352. package/src/utils/string-helpers.ts +111 -0
@@ -0,0 +1,67 @@
1
+ export default {
2
+ Recipient: "Prejemnik",
3
+ Name: "Ime",
4
+ Details: "Podrobnosti",
5
+ Number: "Številka",
6
+ Date: "Datum",
7
+ "Pick a date": "Izberi datum",
8
+ "Due Date": "Rok plačila",
9
+ "Valid Until": "Veljavno do",
10
+ Items: "Postavke",
11
+ "Add item": "Dodaj postavko",
12
+ Save: "Shrani",
13
+ "Save as Draft": "Shrani kot osnutek",
14
+ Quantity: "Količina",
15
+ Price: "Cena",
16
+ Unit: "Enota",
17
+ Discount: "Popust",
18
+ Tax: "Davek",
19
+ "Tax rate": "Davčna stopnja",
20
+ "Add tax": "Dodaj davek",
21
+ "Select tax...": "Izberi davek...",
22
+ "Loading...": "Nalaganje...",
23
+ "No taxes found": "Ni najdenih davkov",
24
+ "Add new tax...": "Dodaj nov davek...",
25
+ Description: "Opis",
26
+ "Mark as Paid": "Označi kot plačano",
27
+ Paid: "Plačano",
28
+ "Credit note will be marked as fully paid upon creation": "Dobropis bo označen kot plačan ob ustvarjanju",
29
+ "Payment Type": "Vrsta plačila",
30
+ "Select payment type": "Izberite vrsto plačila",
31
+ Cash: "Gotovina",
32
+ "Bank Transfer": "Bančno nakazilo",
33
+ Card: "Kartica",
34
+ Check: "Ček",
35
+ Other: "Drugo",
36
+ // Note field
37
+ Note: "Opomba",
38
+ "Insert variable": "Vstavi spremenljivko",
39
+ "Add payment instructions, terms, or other notes...": "Dodajte navodila za plačilo, pogoje ali druge opombe...",
40
+ // Payment terms field
41
+ "Payment Terms": "Plačilni pogoji",
42
+ "Add payment terms...": "Dodajte plačilne pogoje...",
43
+ // Recipient fields
44
+ "Search or create customer...": "Išči ali ustvari stranko...",
45
+ Clear: "Počisti",
46
+ Address: "Naslov",
47
+ "Address 2": "Naslov 2",
48
+ "Post Code": "Poštna številka",
49
+ City: "Mesto",
50
+ State: "Regija",
51
+ Country: "Država",
52
+ "Tax Number": "Davčna številka",
53
+ // Currency
54
+ Currency: "Valuta",
55
+ "Select currency": "Izberi valuto",
56
+ // Discount types
57
+ "Percentage discount": "Odstotni popust",
58
+ "Fixed amount discount": "Fiksni popust",
59
+ Percentage: "Odstotek",
60
+ "Fixed amount": "Fiksni znesek",
61
+ "Taxes disabled": "Davki onemogočeni",
62
+ // Gross price support
63
+ "Gross price": "Bruto cena",
64
+ "Net price": "Neto cena",
65
+ "Gross price (tax included)": "Bruto cena (z davkom)",
66
+ "Net price (before tax)": "Neto cena (brez davka)",
67
+ } as const;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Credit note hooks using the shared createResourceHooks factory
3
+ *
4
+ * This provides:
5
+ * - Optimistic updates
6
+ * - Automatic cache invalidation
7
+ * - Consistent error handling
8
+ * - Less code duplication
9
+ */
10
+
11
+ import type { CreateCreditNoteRequest, CreditNote } from "@spaceinvoices/js-sdk";
12
+ import { createResourceHooks } from "@/ui/hooks/create-resource-hooks";
13
+
14
+ export const CREDIT_NOTES_CACHE_KEY = "credit-notes";
15
+
16
+ const {
17
+ useCreateResource: useCreateCreditNote,
18
+ useUpdateResource: useUpdateCreditNote,
19
+ useDeleteResource: useDeleteCreditNote,
20
+ } = createResourceHooks<CreditNote, CreateCreditNoteRequest>("creditNotes", CREDIT_NOTES_CACHE_KEY);
21
+
22
+ export { useCreateCreditNote, useUpdateCreditNote, useDeleteCreditNote };
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Credit Notes components - Main exports
3
+ */
4
+
5
+ // Credit Note Form
6
+ export * from "./create";
7
+ // Credit Note Hooks
8
+ export * from "./credit-notes.hooks";
9
+ // Credit Note List
10
+ export * from "./list";
@@ -0,0 +1,3 @@
1
+ export { default as CreditNoteListRowActions } from "./list-row-actions";
2
+ export { default as CreditNoteListTable } from "./list-table";
3
+ export { useCreditNoteDownload } from "./use-credit-note-download";
@@ -0,0 +1,116 @@
1
+ import { Copy, Download, Eye, Link2Off, Loader2, MoreHorizontal, Plus } from "lucide-react";
2
+ import { Button } from "@/ui/components/ui/button";
3
+ import {
4
+ DropdownMenu,
5
+ DropdownMenuContent,
6
+ DropdownMenuGroup,
7
+ DropdownMenuItem,
8
+ DropdownMenuLabel,
9
+ DropdownMenuSeparator,
10
+ DropdownMenuTrigger,
11
+ } from "@/ui/components/ui/dropdown-menu";
12
+ import type { ComponentTranslationProps } from "@/ui/lib/translation";
13
+ import { createTranslation } from "@/ui/lib/translation";
14
+ import { useCreditNoteDownload } from "./use-credit-note-download";
15
+
16
+ // Type for credit note - using any until SDK is regenerated
17
+ type CreditNote = any;
18
+
19
+ type CreditNoteListRowActionsProps = {
20
+ creditNote: CreditNote;
21
+ onAddPayment?: (creditNote: CreditNote) => void;
22
+ onDuplicate?: (creditNote: CreditNote) => void;
23
+ onDownloadStart?: () => void;
24
+ onDownloadSuccess?: (fileName: string) => void;
25
+ onDownloadError?: (error: string) => void;
26
+ onUnshare?: (creditNote: CreditNote) => Promise<void>;
27
+ isUnsharing?: boolean;
28
+ } & ComponentTranslationProps;
29
+
30
+ export default function CreditNoteListRowActions({
31
+ creditNote,
32
+ onAddPayment,
33
+ onDuplicate,
34
+ onDownloadStart,
35
+ onDownloadSuccess,
36
+ onDownloadError,
37
+ onUnshare,
38
+ isUnsharing,
39
+ ...i18nProps
40
+ }: CreditNoteListRowActionsProps) {
41
+ const t = createTranslation(i18nProps);
42
+ const { isDownloading, downloadPDF } = useCreditNoteDownload({
43
+ onDownloadStart,
44
+ onDownloadSuccess,
45
+ onDownloadError,
46
+ ...i18nProps,
47
+ });
48
+
49
+ return (
50
+ <DropdownMenu>
51
+ <DropdownMenuTrigger asChild>
52
+ <Button variant="ghost" className="h-8 w-8 cursor-pointer p-0" id="action-menu-trigger">
53
+ <span className="sr-only">{t("Open menu")}</span>
54
+ <MoreHorizontal className="h-4 w-4" />
55
+ </Button>
56
+ </DropdownMenuTrigger>
57
+ <DropdownMenuContent align="end">
58
+ <DropdownMenuLabel>{t("Actions")}</DropdownMenuLabel>
59
+ <DropdownMenuGroup>
60
+ <DropdownMenuItem className="cursor-pointer" onClick={() => navigator.clipboard.writeText(creditNote.id)}>
61
+ <Copy className="h-4 w-4" />
62
+ {t("Copy credit note ID")}
63
+ </DropdownMenuItem>
64
+ </DropdownMenuGroup>
65
+ <DropdownMenuSeparator />
66
+ <DropdownMenuGroup>
67
+ <DropdownMenuItem
68
+ className="cursor-pointer"
69
+ onClick={() => {
70
+ window.location.href = `/app/documents/view/${creditNote.id}`;
71
+ }}
72
+ >
73
+ <Eye className="h-4 w-4" />
74
+ {t("View credit note")}
75
+ </DropdownMenuItem>
76
+ <DropdownMenuItem className="cursor-pointer" onClick={() => downloadPDF(creditNote)} disabled={isDownloading}>
77
+ <Download className="h-4 w-4" />
78
+ {isDownloading ? t("Downloading...") : t("Download PDF")}
79
+ </DropdownMenuItem>
80
+ {onDuplicate && (
81
+ <DropdownMenuItem className="cursor-pointer" onClick={() => onDuplicate(creditNote)}>
82
+ <Copy className="h-4 w-4" />
83
+ {t("Duplicate")}
84
+ </DropdownMenuItem>
85
+ )}
86
+ </DropdownMenuGroup>
87
+ {!creditNote.paid_in_full && (
88
+ <>
89
+ <DropdownMenuSeparator />
90
+ <DropdownMenuGroup>
91
+ <DropdownMenuItem className="cursor-pointer" onClick={() => onAddPayment?.(creditNote)}>
92
+ <Plus className="h-4 w-4" />
93
+ {t("Add Payment")}
94
+ </DropdownMenuItem>
95
+ </DropdownMenuGroup>
96
+ </>
97
+ )}
98
+ {creditNote.shareable_id && onUnshare && (
99
+ <>
100
+ <DropdownMenuSeparator />
101
+ <DropdownMenuGroup>
102
+ <DropdownMenuItem
103
+ className="cursor-pointer text-destructive focus:text-destructive"
104
+ onClick={() => onUnshare(creditNote)}
105
+ disabled={isUnsharing}
106
+ >
107
+ {isUnsharing ? <Loader2 className="h-4 w-4 animate-spin" /> : <Link2Off className="h-4 w-4" />}
108
+ {t("Unshare")}
109
+ </DropdownMenuItem>
110
+ </DropdownMenuGroup>
111
+ </>
112
+ )}
113
+ </DropdownMenuContent>
114
+ </DropdownMenu>
115
+ );
116
+ }
@@ -0,0 +1,183 @@
1
+ import type { CreditNote } from "@spaceinvoices/js-sdk";
2
+ import { useMemo } from "react";
3
+ import { DataTable } from "@/ui/components/table/data-table";
4
+ import { FormattedDate } from "@/ui/components/table/date-cell";
5
+ import { useTableFetch } from "@/ui/components/table/hooks/use-table-fetch";
6
+ import type {
7
+ Column,
8
+ FilterConfig,
9
+ ListTableProps,
10
+ TableQueryParams,
11
+ TableQueryResponse,
12
+ } from "@/ui/components/table/types";
13
+ import { Badge } from "@/ui/components/ui/badge";
14
+ import { Button } from "@/ui/components/ui/button";
15
+ import { createTranslation } from "@/ui/lib/translation";
16
+ import { useSDK } from "@/ui/providers/sdk-provider";
17
+
18
+ import CreditNoteListRowActions from "./list-row-actions";
19
+ import de from "./locales/de";
20
+ import sl from "./locales/sl";
21
+
22
+ const translations = {
23
+ sl,
24
+ de,
25
+ } as const;
26
+
27
+ type CreditNoteListTableProps = {
28
+ t?: (key: string) => string;
29
+ namespace?: string;
30
+ locale?: string;
31
+ entityId?: string;
32
+ onAddPayment?: (creditNote: CreditNote) => void;
33
+ onDuplicate?: (creditNote: CreditNote) => void;
34
+ onDownloadStart?: () => void;
35
+ onDownloadSuccess?: (fileName: string) => void;
36
+ onDownloadError?: (error: string) => void;
37
+ } & ListTableProps<CreditNote>;
38
+
39
+ export default function CreditNoteListTable({
40
+ queryParams,
41
+ onRowClick,
42
+ onAddPayment,
43
+ onDuplicate,
44
+ onChangeParams,
45
+ entityId,
46
+ onDownloadStart,
47
+ onDownloadSuccess,
48
+ onDownloadError,
49
+ ...i18nProps
50
+ }: CreditNoteListTableProps) {
51
+ const t = createTranslation({
52
+ translations,
53
+ ...i18nProps,
54
+ });
55
+
56
+ const { sdk } = useSDK();
57
+
58
+ const handleFetch = useTableFetch(async (params: TableQueryParams) => {
59
+ if (!sdk) throw new Error("SDK not initialized");
60
+ if (!params.entity_id) throw new Error("Entity ID required");
61
+
62
+ const response = await sdk.creditNotes.list({
63
+ entity_id: params.entity_id,
64
+ limit: params.limit,
65
+ next_cursor: params.next_cursor,
66
+ prev_cursor: params.prev_cursor,
67
+ order_by: params.order_by,
68
+ search: params.search,
69
+ query: params.query,
70
+ });
71
+ return response as unknown as TableQueryResponse<CreditNote>;
72
+ }, entityId);
73
+
74
+ const filterConfig: FilterConfig = useMemo(
75
+ () => ({
76
+ dateFields: [
77
+ { id: "date", label: t("Date") },
78
+ { id: "created_at", label: t("Created At") },
79
+ ],
80
+ statusFilter: true, // Credit notes have payment status
81
+ }),
82
+ [t],
83
+ );
84
+
85
+ const columns: Column<CreditNote>[] = useMemo(
86
+ () => [
87
+ {
88
+ id: "number",
89
+ header: t("Number"),
90
+ sortable: true,
91
+ cell: (creditNote) => (
92
+ <div className="flex items-center gap-2">
93
+ <Button variant="link" className="cursor-pointer py-0 underline" onClick={() => onRowClick?.(creditNote)}>
94
+ {creditNote.number}
95
+ </Button>
96
+ {(creditNote as any).is_draft && (
97
+ <Badge
98
+ variant="outline"
99
+ className="border-amber-500 bg-amber-50 text-amber-700 dark:bg-amber-950 dark:text-amber-400"
100
+ >
101
+ {t("Draft")}
102
+ </Badge>
103
+ )}
104
+ </div>
105
+ ),
106
+ },
107
+ {
108
+ id: "customer",
109
+ header: t("Customer"),
110
+ cell: (creditNote) => creditNote.customer?.name ?? "-",
111
+ },
112
+ {
113
+ id: "date",
114
+ header: t("Date"),
115
+ sortable: true,
116
+ cell: (creditNote) => <FormattedDate date={creditNote.date} />,
117
+ },
118
+ {
119
+ id: "total",
120
+ header: t("Total"),
121
+ sortable: true,
122
+ align: "right",
123
+ cell: (creditNote) => creditNote.total,
124
+ },
125
+ {
126
+ id: "total_with_tax",
127
+ header: t("Total with Tax"),
128
+ sortable: true,
129
+ align: "right",
130
+ cell: (creditNote) => creditNote.total_with_tax,
131
+ },
132
+ {
133
+ id: "status",
134
+ header: t("Status"),
135
+ cell: (creditNote) => <PaymentStatusBadge creditNote={creditNote} />,
136
+ },
137
+ {
138
+ id: "actions",
139
+ header: "",
140
+ align: "right",
141
+ cell: (creditNote) => (
142
+ <CreditNoteListRowActions
143
+ creditNote={creditNote}
144
+ onAddPayment={onAddPayment}
145
+ onDuplicate={onDuplicate}
146
+ onDownloadStart={onDownloadStart}
147
+ onDownloadSuccess={onDownloadSuccess}
148
+ onDownloadError={onDownloadError}
149
+ {...i18nProps}
150
+ />
151
+ ),
152
+ },
153
+ ],
154
+ [t, onRowClick, onAddPayment, onDuplicate, onDownloadStart, onDownloadSuccess, onDownloadError, i18nProps],
155
+ );
156
+
157
+ return (
158
+ <DataTable
159
+ columns={columns}
160
+ queryParams={queryParams}
161
+ resourceName="credit_note"
162
+ cacheKey="credit-notes"
163
+ createNewLink="/app/documents/add/credit_note"
164
+ onFetch={handleFetch}
165
+ onChangeParams={onChangeParams}
166
+ entityId={entityId}
167
+ filterConfig={filterConfig}
168
+ t={t}
169
+ locale={i18nProps.locale}
170
+ />
171
+ );
172
+ }
173
+
174
+ /** Payment status badge for credit notes */
175
+ function PaymentStatusBadge({ creditNote }: { creditNote: CreditNote }) {
176
+ if (creditNote.paid_in_full) {
177
+ return <span className="rounded-full bg-green-100 px-2 py-1 text-green-800 text-xs">Paid</span>;
178
+ }
179
+ if (creditNote.total_paid > 0) {
180
+ return <span className="rounded-full bg-yellow-100 px-2 py-1 text-xs text-yellow-800">Partial</span>;
181
+ }
182
+ return <span className="rounded-full bg-gray-100 px-2 py-1 text-gray-800 text-xs">Unpaid</span>;
183
+ }
@@ -0,0 +1,33 @@
1
+ export default {
2
+ Draft: "Entwurf",
3
+ Number: "Nummer",
4
+ Customer: "Kunde",
5
+ Date: "Datum",
6
+ Total: "Gesamt",
7
+ "Total with Tax": "Gesamt mit MwSt.",
8
+ Status: "Status",
9
+ Actions: "Aktionen",
10
+ "Open menu": "Menü öffnen",
11
+ "Copy credit note ID": "Gutschrift-ID kopieren",
12
+ "View credit note": "Gutschrift anzeigen",
13
+ "Download PDF": "PDF herunterladen",
14
+ "Downloading...": "Wird heruntergeladen...",
15
+ "Add Payment": "Zahlung hinzufügen",
16
+ Duplicate: "Duplizieren",
17
+ "Failed to download PDF": "PDF-Download fehlgeschlagen",
18
+ "Credit Note": "Gutschrift",
19
+ "No credit notes found": "Keine Gutschriften gefunden",
20
+ "Create Credit Note": "Gutschrift erstellen",
21
+ // Filter translations
22
+ "Search...": "Suchen...",
23
+ Filters: "Filter",
24
+ "Date Range": "Datumsbereich",
25
+ From: "Von",
26
+ To: "Bis",
27
+ "Clear filters": "Filter löschen",
28
+ Paid: "Bezahlt",
29
+ Unpaid: "Unbezahlt",
30
+ Overdue: "Überfällig",
31
+ Voided: "Storniert",
32
+ "Created At": "Erstellt am",
33
+ } as const;
@@ -0,0 +1,33 @@
1
+ export default {
2
+ Draft: "Osnutek",
3
+ Number: "Številka",
4
+ Customer: "Stranka",
5
+ Date: "Datum",
6
+ Total: "Skupaj",
7
+ "Total with Tax": "Skupaj z DDV",
8
+ Status: "Status",
9
+ Actions: "Dejanja",
10
+ "Open menu": "Odpri meni",
11
+ "Copy credit note ID": "Kopiraj ID dobropisa",
12
+ "View credit note": "Prikaži dobropis",
13
+ "Download PDF": "Prenesi PDF",
14
+ "Downloading...": "Prenašanje...",
15
+ "Add Payment": "Dodaj plačilo",
16
+ Duplicate: "Podvoji",
17
+ "Failed to download PDF": "Prenos PDF ni uspel",
18
+ "Credit Note": "Dobropis",
19
+ "No credit notes found": "Ni najdenih dobropisov",
20
+ "Create Credit Note": "Ustvari dobropis",
21
+ // Filter translations
22
+ "Search...": "Iskanje...",
23
+ Filters: "Filtri",
24
+ "Date Range": "Datumski razpon",
25
+ From: "Od",
26
+ To: "Do",
27
+ "Clear filters": "Počisti filtre",
28
+ Paid: "Plačano",
29
+ Unpaid: "Neplačano",
30
+ Overdue: "Zapadlo",
31
+ Voided: "Stornirano",
32
+ "Created At": "Ustvarjeno",
33
+ } as const;
@@ -0,0 +1,65 @@
1
+ import { useState } from "react";
2
+ import type { ComponentTranslationProps } from "@/ui/lib/translation";
3
+ import { createTranslation } from "@/ui/lib/translation";
4
+ import { useEntities } from "@/ui/providers/entities-context";
5
+ import { useSDK } from "@/ui/providers/sdk-provider";
6
+
7
+ // Type for credit note - using any until SDK is regenerated
8
+ type CreditNote = any;
9
+
10
+ type UseCreditNoteDownloadProps = {
11
+ onDownloadStart?: () => void;
12
+ onDownloadSuccess?: (fileName: string) => void;
13
+ onDownloadError?: (error: string) => void;
14
+ } & ComponentTranslationProps;
15
+
16
+ export function useCreditNoteDownload({
17
+ onDownloadStart,
18
+ onDownloadSuccess,
19
+ onDownloadError,
20
+ ...i18nProps
21
+ }: UseCreditNoteDownloadProps) {
22
+ const [isDownloading, setIsDownloading] = useState(false);
23
+ const { activeEntity } = useEntities();
24
+ const { sdk } = useSDK();
25
+ const t = createTranslation(i18nProps);
26
+
27
+ const downloadPDF = async (creditNote: CreditNote) => {
28
+ if (!activeEntity?.id || !sdk) {
29
+ console.error("Missing SDK or active entity for PDF download");
30
+ onDownloadError?.(t("Failed to download PDF"));
31
+ return;
32
+ }
33
+
34
+ setIsDownloading(true);
35
+ onDownloadStart?.();
36
+
37
+ try {
38
+ // SDK signature: renderPdf(id, params?, SDKMethodOptions?)
39
+ // entity_id goes in SDKMethodOptions (last arg), not params
40
+ // Note: renderPdf is on invoices module but works with any document ID
41
+ const blob = await sdk.invoices.renderPdf(creditNote.id, {}, { entity_id: activeEntity.id });
42
+ const downloadUrl = window.URL.createObjectURL(blob);
43
+ const link = document.createElement("a");
44
+ link.href = downloadUrl;
45
+ const fileName = `${t("Credit Note")} ${creditNote.number}.pdf`;
46
+ link.download = fileName;
47
+ document.body.appendChild(link);
48
+ link.click();
49
+ document.body.removeChild(link);
50
+ window.URL.revokeObjectURL(downloadUrl);
51
+
52
+ onDownloadSuccess?.(fileName);
53
+ } catch (error) {
54
+ console.error("Error downloading PDF:", error);
55
+ onDownloadError?.(t("Failed to download PDF"));
56
+ } finally {
57
+ setIsDownloading(false);
58
+ }
59
+ };
60
+
61
+ return {
62
+ isDownloading,
63
+ downloadPDF,
64
+ };
65
+ }
@@ -0,0 +1,134 @@
1
+ import { zodResolver } from "@hookform/resolvers/zod";
2
+ import type { CompanyRegistryResult, CreateCustomerRequest, Customer } from "@spaceinvoices/js-sdk";
3
+ import { useForm } from "react-hook-form";
4
+ import type z from "zod";
5
+ import { CompanyRegistryAutocomplete } from "@/ui/components/company-registry";
6
+ import { FormInput } from "@/ui/components/form";
7
+ import { Form } from "@/ui/components/ui/form";
8
+ import type { CreateCustomerSchema } from "@/ui/generated/schemas";
9
+ import { createCustomerSchema } from "@/ui/generated/schemas";
10
+ import type { ComponentTranslationProps } from "@/ui/lib/translation";
11
+ import { createTranslation } from "@/ui/lib/translation";
12
+ import { useCreateCustomer } from "../customers.hooks";
13
+ import de from "./locales/de";
14
+ import sl from "./locales/sl";
15
+
16
+ const translations = {
17
+ sl,
18
+ de,
19
+ } as const;
20
+
21
+ type CreateCustomerFormProps = {
22
+ entityId: string;
23
+ /**
24
+ * Entity's ISO 3166-1 alpha-2 country code (e.g., "SI", "AT")
25
+ * Used to enable company registry autocomplete for supported countries
26
+ */
27
+ entityCountryCode?: string;
28
+ onSuccess?: (customer: Customer) => void;
29
+ onError?: (error: Error) => void;
30
+ renderSubmitButton?: (props: { isSubmitting: boolean; submit: () => void }) => React.ReactNode;
31
+ } & ComponentTranslationProps;
32
+
33
+ export default function CreateCustomerForm({
34
+ entityId,
35
+ entityCountryCode,
36
+ onSuccess,
37
+ onError,
38
+ renderSubmitButton,
39
+ ...i18nProps
40
+ }: CreateCustomerFormProps) {
41
+ const t = createTranslation({
42
+ ...i18nProps,
43
+ translations,
44
+ });
45
+
46
+ /**
47
+ * Handle company selection from registry autocomplete
48
+ * Auto-fills form fields with company data
49
+ */
50
+ const handleCompanySelect = (company: CompanyRegistryResult) => {
51
+ form.setValue("name", company.name);
52
+ if (company.address) form.setValue("address", company.address);
53
+ if (company.post_code) form.setValue("post_code", company.post_code);
54
+ if (company.city) form.setValue("city", company.city);
55
+ if (company.tax_number) form.setValue("tax_number", company.tax_number);
56
+ // Note: country is intentionally not set - keep entity's country or let user choose
57
+ };
58
+
59
+ const form = useForm<CreateCustomerSchema>({
60
+ resolver: zodResolver(createCustomerSchema),
61
+ defaultValues: {
62
+ name: "",
63
+ address: "",
64
+ post_code: "",
65
+ city: "",
66
+ state: "",
67
+ country: "",
68
+ tax_number: "",
69
+ },
70
+ });
71
+
72
+ const { mutate: createCustomer, isPending } = useCreateCustomer({
73
+ entityId,
74
+ onSuccess: (customer, _variables, _context) => {
75
+ onSuccess?.(customer);
76
+ form.reset(); // Reset form after successful submission
77
+ },
78
+ onError: (error, _variables, _context) => {
79
+ form.setError("root", {
80
+ type: "submit",
81
+ message: t("There was an error creating the customer"),
82
+ });
83
+ onError?.(error);
84
+ },
85
+ });
86
+
87
+ const onSubmit = async (values: z.infer<typeof createCustomerSchema>) => {
88
+ // Zod validation ensures required fields are present before this is called
89
+ // The type cast is safe because React Hook Form's DeepPartial doesn't reflect runtime validation
90
+ createCustomer(values as CreateCustomerRequest);
91
+ };
92
+
93
+ const handleSubmitClick = () => {
94
+ form.handleSubmit(onSubmit)();
95
+ };
96
+
97
+ return (
98
+ <Form {...form}>
99
+ <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
100
+ {/* Company Registry Autocomplete - only shown for supported countries */}
101
+ {entityCountryCode && (
102
+ <div className="mb-4 rounded-lg border bg-muted/30 p-4">
103
+ <CompanyRegistryAutocomplete
104
+ countryCode={entityCountryCode}
105
+ onSelect={handleCompanySelect}
106
+ placeholder={t("Search by company name or tax number")}
107
+ />
108
+ </div>
109
+ )}
110
+
111
+ <FormInput control={form.control} name="name" label={t("Name")} placeholder={t("Enter name")} />
112
+
113
+ <FormInput control={form.control} name="address" label={t("Address")} placeholder={t("Enter address")} />
114
+
115
+ <div className="grid grid-cols-2 gap-4">
116
+ <FormInput control={form.control} name="post_code" label={t("Post Code")} />
117
+ <FormInput control={form.control} name="city" label={t("City")} />
118
+ </div>
119
+
120
+ <div className="grid grid-cols-2 gap-4">
121
+ <FormInput control={form.control} name="state" label={t("State")} />
122
+ <FormInput control={form.control} name="country" label={t("Country")} />
123
+ </div>
124
+
125
+ <FormInput control={form.control} name="tax_number" label={t("Tax Number")} />
126
+
127
+ {renderSubmitButton?.({
128
+ isSubmitting: isPending || form.formState.isSubmitting,
129
+ submit: handleSubmitClick,
130
+ })}
131
+ </form>
132
+ </Form>
133
+ );
134
+ }