@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,256 @@
1
+ import type { Payment } from "@spaceinvoices/js-sdk";
2
+ import { useQuery, useQueryClient } from "@tanstack/react-query";
3
+ import { MoreHorizontal, Pencil, Plus, Trash2 } from "lucide-react";
4
+ import { useState } from "react";
5
+ import { Button } from "@/ui/components/ui/button";
6
+ import { Card, CardContent, CardHeader, CardTitle } from "@/ui/components/ui/card";
7
+ import {
8
+ Dialog,
9
+ DialogContent,
10
+ DialogDescription,
11
+ DialogFooter,
12
+ DialogHeader,
13
+ DialogTitle,
14
+ } from "@/ui/components/ui/dialog";
15
+ import {
16
+ DropdownMenu,
17
+ DropdownMenuContent,
18
+ DropdownMenuItem,
19
+ DropdownMenuTrigger,
20
+ } from "@/ui/components/ui/dropdown-menu";
21
+ import { Skeleton } from "@/ui/components/ui/skeleton";
22
+ import type { ComponentTranslationProps } from "@/ui/lib/translation";
23
+ import { createTranslation } from "@/ui/lib/translation";
24
+ import { useSDK } from "@/ui/providers/sdk-provider";
25
+ import de from "./locales/de";
26
+ import sl from "./locales/sl";
27
+
28
+ const translations = { de, sl } as const;
29
+
30
+ type DocumentType = "invoice" | "credit_note" | "advance_invoice";
31
+
32
+ interface DocumentPaymentsListProps extends ComponentTranslationProps {
33
+ documentId: string;
34
+ documentType: DocumentType;
35
+ entityId: string;
36
+ currencyCode: string;
37
+ /** Locale for formatting */
38
+ locale?: string;
39
+ /** Callback when Add Payment is clicked */
40
+ onAddPayment?: () => void;
41
+ /** Callback when Edit Payment is clicked */
42
+ onEditPayment?: (payment: Payment) => void;
43
+ /** Callback on successful delete */
44
+ onDeleteSuccess?: () => void;
45
+ /** Callback on delete error */
46
+ onDeleteError?: (error: string) => void;
47
+ }
48
+
49
+ /**
50
+ * Format currency value
51
+ */
52
+ function formatCurrency(amount: number, currencyCode: string, locale: string): string {
53
+ return new Intl.NumberFormat(locale, {
54
+ style: "currency",
55
+ currency: currencyCode,
56
+ }).format(amount);
57
+ }
58
+
59
+ /**
60
+ * Format date
61
+ */
62
+ function formatDate(date: Date | string | null, locale: string): string {
63
+ if (!date) return "-";
64
+ const d = typeof date === "string" ? new Date(date) : date;
65
+ return new Intl.DateTimeFormat(locale, {
66
+ month: "short",
67
+ day: "numeric",
68
+ }).format(d);
69
+ }
70
+
71
+ /**
72
+ * Document Payments List Component
73
+ *
74
+ * Displays a list of payments for a document with CRUD actions:
75
+ * - View payments with date, amount, type
76
+ * - Add new payment
77
+ * - Edit existing payment
78
+ * - Delete payment with confirmation
79
+ */
80
+ export function DocumentPaymentsList({
81
+ documentId,
82
+ documentType,
83
+ entityId,
84
+ currencyCode,
85
+ locale = "en",
86
+ onAddPayment,
87
+ onEditPayment,
88
+ onDeleteSuccess,
89
+ onDeleteError,
90
+ ...i18nProps
91
+ }: DocumentPaymentsListProps) {
92
+ const t = createTranslation({ translations, locale, ...i18nProps });
93
+ const { sdk } = useSDK();
94
+ const queryClient = useQueryClient();
95
+
96
+ const [paymentToDelete, setPaymentToDelete] = useState<Payment | null>(null);
97
+ const [isDeleting, setIsDeleting] = useState(false);
98
+
99
+ // Build the filter based on document type
100
+ const getFilter = () => {
101
+ if (documentType === "invoice") {
102
+ return { invoice_id: documentId };
103
+ }
104
+ if (documentType === "advance_invoice") {
105
+ return { advance_invoice_id: documentId };
106
+ }
107
+ if (documentType === "credit_note") {
108
+ return { credit_note_id: documentId };
109
+ }
110
+ return {};
111
+ };
112
+
113
+ // Fetch payments for this document
114
+ // SDK list methods return { data: Payment[], pagination: ... }
115
+ const { data: paymentsData, isLoading } = useQuery({
116
+ queryKey: ["payments", documentType, documentId, entityId],
117
+ queryFn: async () => {
118
+ if (!sdk) throw new Error("SDK not initialized");
119
+
120
+ const response = await sdk.payments.list({
121
+ entity_id: entityId,
122
+ query: JSON.stringify(getFilter()),
123
+ order_by: "-date",
124
+ });
125
+
126
+ return response.data;
127
+ },
128
+ enabled: !!sdk && !!entityId && !!documentId,
129
+ });
130
+
131
+ const payments = paymentsData || [];
132
+
133
+ /**
134
+ * Handle payment deletion
135
+ */
136
+ const handleDelete = async () => {
137
+ if (!paymentToDelete || !sdk) return;
138
+
139
+ setIsDeleting(true);
140
+ try {
141
+ await sdk.payments.delete(paymentToDelete.id, { entity_id: entityId });
142
+
143
+ // Invalidate queries to refresh data
144
+ queryClient.invalidateQueries({ queryKey: ["payments"] });
145
+ queryClient.invalidateQueries({ queryKey: ["documents"] });
146
+
147
+ onDeleteSuccess?.();
148
+ } catch (error) {
149
+ console.error("Failed to delete payment:", error);
150
+ onDeleteError?.(t("Delete failed"));
151
+ } finally {
152
+ setIsDeleting(false);
153
+ setPaymentToDelete(null);
154
+ }
155
+ };
156
+
157
+ /**
158
+ * Get payment type label
159
+ */
160
+ const getTypeLabel = (type: string): string => {
161
+ const labels: Record<string, string> = {
162
+ cash: t("cash"),
163
+ bank_transfer: t("bank_transfer"),
164
+ card: t("card"),
165
+ check: t("check"),
166
+ credit_note: t("credit_note"),
167
+ other: t("other"),
168
+ advance: t("advance_invoice"),
169
+ };
170
+ return labels[type] || type;
171
+ };
172
+
173
+ const fmt = (amount: number) => formatCurrency(amount, currencyCode, locale);
174
+ const fmtDate = (date: Date | string | null) => formatDate(date, locale);
175
+
176
+ return (
177
+ <>
178
+ <Card>
179
+ <CardHeader className="flex flex-row items-center justify-between pb-3">
180
+ <CardTitle className="text-lg">
181
+ {t("Payments")} {payments.length > 0 && `(${payments.length})`}
182
+ </CardTitle>
183
+ <Button variant="outline" size="sm" onClick={onAddPayment} className="cursor-pointer">
184
+ <Plus className="mr-1 h-4 w-4" />
185
+ {t("Add payment")}
186
+ </Button>
187
+ </CardHeader>
188
+ <CardContent>
189
+ {isLoading ? (
190
+ <div className="space-y-2">
191
+ <Skeleton className="h-10 w-full" />
192
+ <Skeleton className="h-10 w-full" />
193
+ </div>
194
+ ) : payments.length === 0 ? (
195
+ <p className="py-4 text-center text-muted-foreground text-sm">{t("No payments")}</p>
196
+ ) : (
197
+ <div className="space-y-2">
198
+ {payments.map((payment) => (
199
+ <div key={payment.id} className="flex items-center justify-between rounded-md border p-3">
200
+ <div className="flex items-center gap-4">
201
+ <span className="text-muted-foreground text-sm">{fmtDate(payment.date)}</span>
202
+ <span className="font-medium">{fmt(payment.amount)}</span>
203
+ <span className="text-muted-foreground text-sm">{getTypeLabel(payment.type)}</span>
204
+ </div>
205
+ <DropdownMenu>
206
+ <DropdownMenuTrigger asChild>
207
+ <Button variant="ghost" size="sm" className="h-8 w-8 cursor-pointer p-0">
208
+ <MoreHorizontal className="h-4 w-4" />
209
+ </Button>
210
+ </DropdownMenuTrigger>
211
+ <DropdownMenuContent align="end">
212
+ <DropdownMenuItem onClick={() => onEditPayment?.(payment)} className="cursor-pointer">
213
+ <Pencil className="mr-2 h-4 w-4" />
214
+ {t("Edit")}
215
+ </DropdownMenuItem>
216
+ <DropdownMenuItem
217
+ onClick={() => setPaymentToDelete(payment)}
218
+ className="cursor-pointer text-destructive focus:text-destructive"
219
+ >
220
+ <Trash2 className="mr-2 h-4 w-4" />
221
+ {t("Delete")}
222
+ </DropdownMenuItem>
223
+ </DropdownMenuContent>
224
+ </DropdownMenu>
225
+ </div>
226
+ ))}
227
+ </div>
228
+ )}
229
+ </CardContent>
230
+ </Card>
231
+
232
+ {/* Delete Confirmation Dialog */}
233
+ <Dialog open={!!paymentToDelete} onOpenChange={() => setPaymentToDelete(null)}>
234
+ <DialogContent>
235
+ <DialogHeader>
236
+ <DialogTitle>{t("Delete payment")}</DialogTitle>
237
+ <DialogDescription>{t("Delete payment confirmation")}</DialogDescription>
238
+ </DialogHeader>
239
+ <DialogFooter>
240
+ <Button
241
+ variant="outline"
242
+ disabled={isDeleting}
243
+ onClick={() => setPaymentToDelete(null)}
244
+ className="cursor-pointer"
245
+ >
246
+ {t("Cancel")}
247
+ </Button>
248
+ <Button variant="destructive" onClick={handleDelete} disabled={isDeleting} className="cursor-pointer">
249
+ {t("Delete")}
250
+ </Button>
251
+ </DialogFooter>
252
+ </DialogContent>
253
+ </Dialog>
254
+ </>
255
+ );
256
+ }
@@ -0,0 +1,4 @@
1
+ export { DocumentActionsBar } from "./document-actions-bar";
2
+ export { DocumentDetailsCard } from "./document-details-card";
3
+ export { DocumentPaymentsList } from "./document-payments-list";
4
+ export { useDocumentDownload } from "./use-document-download";
@@ -0,0 +1,85 @@
1
+ export default {
2
+ // Actions
3
+ PDF: "PDF",
4
+ Send: "Senden",
5
+ Payment: "Zahlung",
6
+ Share: "Teilen",
7
+ Unshare: "Freigabe aufheben",
8
+ Copied: "Kopiert",
9
+ "Copy shareable link": "Freigabelink kopieren",
10
+ "Unshare document": "Dokumentfreigabe aufheben",
11
+ "Unshare document confirmation":
12
+ "Sind Sie sicher, dass Sie den öffentlichen Zugang zu diesem Dokument entfernen möchten?",
13
+ "Document unshared": "Dokument ist nicht mehr freigegeben",
14
+ "Unshare failed": "Freigabe aufheben fehlgeschlagen",
15
+ "Download failed": "Download fehlgeschlagen",
16
+ "e-SLOG download failed": "e-SLOG Download fehlgeschlagen",
17
+ Duplicate: "Duplizieren",
18
+ "Duplicate invoice": "Rechnung duplizieren",
19
+ "Duplicate estimate": "Angebot duplizieren",
20
+ "Duplicate credit_note": "Gutschrift duplizieren",
21
+ "Duplicate advance_invoice": "Anzahlungsrechnung duplizieren",
22
+ "Create invoice": "Rechnung erstellen",
23
+ "Create estimate": "Angebot erstellen",
24
+ "Create credit_note": "Gutschrift erstellen",
25
+ "Create advance_invoice": "Anzahlungsrechnung erstellen",
26
+
27
+ // Details card
28
+ Details: "Details",
29
+ Number: "Nummer",
30
+ Date: "Datum",
31
+ "Due date": "Fälligkeitsdatum",
32
+ "Service date": "Leistungsdatum",
33
+ "Service period": "Leistungszeitraum",
34
+ "Valid until": "Gültig bis",
35
+ Customer: "Kunde",
36
+ Subtotal: "Zwischensumme",
37
+ Tax: "Steuer",
38
+ Total: "Gesamt",
39
+ Paid: "Bezahlt",
40
+ Due: "Offen",
41
+ Status: "Status",
42
+
43
+ // Payment status
44
+ "Paid in full": "Vollständig bezahlt",
45
+ "Partially paid": "Teilweise bezahlt",
46
+ Unpaid: "Unbezahlt",
47
+ Voided: "Storniert",
48
+
49
+ // Payments list
50
+ Payments: "Zahlungen",
51
+ "No payments": "Keine Zahlungen",
52
+ "Add payment": "Zahlung hinzufügen",
53
+ Edit: "Bearbeiten",
54
+ Delete: "Löschen",
55
+ "Delete payment": "Zahlung löschen",
56
+ "Delete payment confirmation": "Sind Sie sicher, dass Sie diese Zahlung löschen möchten?",
57
+ Cancel: "Abbrechen",
58
+
59
+ // Payment types
60
+ cash: "Bargeld",
61
+ bank_transfer: "Banküberweisung",
62
+ card: "Karte",
63
+ check: "Scheck",
64
+ credit_note: "Gutschrift",
65
+ other: "Andere",
66
+ advance_invoice: "Anzahlungsrechnung",
67
+
68
+ // Errors
69
+ "Delete failed": "Löschen fehlgeschlagen",
70
+
71
+ // Draft actions
72
+ Finalize: "Fertigstellen",
73
+ "Delete Draft": "Entwurf löschen",
74
+ "Finalize document": "Dokument fertigstellen",
75
+ "Finalize document confirmation":
76
+ "Dadurch wird dem Dokument eine endgültige Nummer zugewiesen. Nach der Fertigstellung kann das Dokument nicht mehr gelöscht werden. Möchten Sie fortfahren?",
77
+ "Delete draft document": "Entwurfsdokument löschen",
78
+ "Delete draft confirmation":
79
+ "Sind Sie sicher, dass Sie diesen Entwurf löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden.",
80
+ "Document finalized": "Dokument wurde fertiggestellt",
81
+ "Finalize failed": "Fertigstellung fehlgeschlagen",
82
+ "Draft deleted": "Entwurf wurde gelöscht",
83
+ "Delete draft failed": "Entwurf löschen fehlgeschlagen",
84
+ Draft: "Entwurf",
85
+ } as const;
@@ -0,0 +1,84 @@
1
+ export default {
2
+ // Actions
3
+ PDF: "PDF",
4
+ Send: "Pošlji",
5
+ Payment: "Plačilo",
6
+ Share: "Deli",
7
+ Unshare: "Odstrani deljenje",
8
+ Copied: "Kopirano",
9
+ "Copy shareable link": "Kopiraj povezavo za deljenje",
10
+ "Unshare document": "Odstrani deljenje dokumenta",
11
+ "Unshare document confirmation": "Ali ste prepričani, da želite odstraniti javni dostop do tega dokumenta?",
12
+ "Document unshared": "Dokument ni več deljen",
13
+ "Unshare failed": "Odstranitev deljenja ni uspela",
14
+ "Download failed": "Prenos ni uspel",
15
+ "e-SLOG download failed": "Prenos e-SLOG ni uspel",
16
+ Duplicate: "Podvoji",
17
+ "Duplicate invoice": "Podvoji račun",
18
+ "Duplicate estimate": "Podvoji predračun",
19
+ "Duplicate credit_note": "Podvoji dobropis",
20
+ "Duplicate advance_invoice": "Podvoji avansni račun",
21
+ "Create invoice": "Ustvari račun",
22
+ "Create estimate": "Ustvari predračun",
23
+ "Create credit_note": "Ustvari dobropis",
24
+ "Create advance_invoice": "Ustvari avansni račun",
25
+
26
+ // Details card
27
+ Details: "Podrobnosti",
28
+ Number: "Številka",
29
+ Date: "Datum",
30
+ "Due date": "Datum zapadlosti",
31
+ "Service date": "Datum storitve",
32
+ "Service period": "Obdobje storitve",
33
+ "Valid until": "Veljavno do",
34
+ Customer: "Stranka",
35
+ Subtotal: "Vmesni seštevek",
36
+ Tax: "Davek",
37
+ Total: "Skupaj",
38
+ Paid: "Plačano",
39
+ Due: "Za plačilo",
40
+ Status: "Status",
41
+
42
+ // Payment status
43
+ "Paid in full": "Plačano v celoti",
44
+ "Partially paid": "Delno plačano",
45
+ Unpaid: "Neplačano",
46
+ Voided: "Stornirano",
47
+
48
+ // Payments list
49
+ Payments: "Plačila",
50
+ "No payments": "Ni plačil",
51
+ "Add payment": "Dodaj plačilo",
52
+ Edit: "Uredi",
53
+ Delete: "Izbriši",
54
+ "Delete payment": "Izbriši plačilo",
55
+ "Delete payment confirmation": "Ali ste prepričani, da želite izbrisati to plačilo?",
56
+ Cancel: "Prekliči",
57
+
58
+ // Payment types
59
+ cash: "Gotovina",
60
+ bank_transfer: "Bančno nakazilo",
61
+ card: "Kartica",
62
+ check: "Ček",
63
+ credit_note: "Dobropis",
64
+ other: "Drugo",
65
+ advance_invoice: "Avansni račun",
66
+
67
+ // Errors
68
+ "Delete failed": "Brisanje ni uspelo",
69
+
70
+ // Draft actions
71
+ Finalize: "Potrdi",
72
+ "Delete Draft": "Izbriši osnutek",
73
+ "Finalize document": "Potrdi dokument",
74
+ "Finalize document confirmation":
75
+ "S tem boste dokumentu dodelili končno številko. Po potrditvi dokumenta ni več mogoče izbrisati. Ali želite nadaljevati?",
76
+ "Delete draft document": "Izbriši osnutek dokumenta",
77
+ "Delete draft confirmation":
78
+ "Ali ste prepričani, da želite izbrisati ta osnutek? Tega dejanja ni mogoče razveljaviti.",
79
+ "Document finalized": "Dokument je bil potrjen",
80
+ "Finalize failed": "Potrditev ni uspela",
81
+ "Draft deleted": "Osnutek je bil izbrisan",
82
+ "Delete draft failed": "Brisanje osnutka ni uspelo",
83
+ Draft: "Osnutek",
84
+ } as const;
@@ -0,0 +1,125 @@
1
+ import type { AdvanceInvoice, CreditNote, Estimate, Invoice } from "@spaceinvoices/js-sdk";
2
+ import { useState } from "react";
3
+ import { useEntities } from "@/ui/providers/entities-context";
4
+ import { useSDK } from "@/ui/providers/sdk-provider";
5
+
6
+ type Document = Invoice | Estimate | CreditNote | AdvanceInvoice;
7
+ type DocumentType = "invoice" | "estimate" | "credit_note" | "advance_invoice";
8
+
9
+ // Document type labels for PDF filename
10
+ const TYPE_LABELS: Record<string, string> = {
11
+ invoice: "Invoice",
12
+ estimate: "Estimate",
13
+ credit_note: "Credit Note",
14
+ advance_invoice: "Advance Invoice",
15
+ };
16
+
17
+ interface UseDocumentDownloadOptions {
18
+ onDownloadStart?: () => void;
19
+ onDownloadSuccess?: (fileName: string) => void;
20
+ onDownloadError?: (error: string) => void;
21
+ }
22
+
23
+ /**
24
+ * Hook for downloading document PDFs and e-SLOG XML
25
+ */
26
+ export function useDocumentDownload({
27
+ onDownloadStart,
28
+ onDownloadSuccess,
29
+ onDownloadError,
30
+ }: UseDocumentDownloadOptions = {}) {
31
+ const { sdk } = useSDK();
32
+ const { activeEntity } = useEntities();
33
+
34
+ const [isDownloadingPdf, setIsDownloadingPdf] = useState(false);
35
+ const [isDownloadingEslog, setIsDownloadingEslog] = useState(false);
36
+
37
+ /**
38
+ * Download PDF in specified locale
39
+ */
40
+ const downloadPdf = async (document: Document, documentType: DocumentType, _locale: string) => {
41
+ if (!sdk || !activeEntity?.id) {
42
+ onDownloadError?.("Download failed");
43
+ return;
44
+ }
45
+
46
+ setIsDownloadingPdf(true);
47
+ onDownloadStart?.();
48
+
49
+ try {
50
+ // SDK signature: renderPdf(id, params?, SDKMethodOptions?)
51
+ // entity_id goes in SDKMethodOptions (last arg), not params
52
+ // Note: renderPdf is on invoices module but works with any document ID via /documents/{id}/pdf
53
+ const blob = await sdk.invoices.renderPdf(document.id, {}, { entity_id: activeEntity.id });
54
+ const downloadUrl = window.URL.createObjectURL(blob);
55
+ const link = window.document.createElement("a");
56
+ link.href = downloadUrl;
57
+
58
+ const typeLabel = TYPE_LABELS[documentType] || "Document";
59
+ const fileName = `${typeLabel} ${document.number}.pdf`;
60
+ link.download = fileName;
61
+
62
+ window.document.body.appendChild(link);
63
+ link.click();
64
+ window.document.body.removeChild(link);
65
+ window.URL.revokeObjectURL(downloadUrl);
66
+
67
+ onDownloadSuccess?.(fileName);
68
+ } catch (error) {
69
+ console.error("Error downloading PDF:", error);
70
+ onDownloadError?.("Download failed");
71
+ } finally {
72
+ setIsDownloadingPdf(false);
73
+ }
74
+ };
75
+
76
+ /**
77
+ * Download e-SLOG XML
78
+ */
79
+ const downloadEslog = async (document: Document, documentType: DocumentType) => {
80
+ if (!sdk || !activeEntity?.id) {
81
+ onDownloadError?.("Download failed");
82
+ return;
83
+ }
84
+
85
+ setIsDownloadingEslog(true);
86
+
87
+ try {
88
+ const typeMap: Record<DocumentType, string> = {
89
+ invoice: "invoice",
90
+ advance_invoice: "advance_invoice",
91
+ credit_note: "credit_note",
92
+ estimate: "estimate",
93
+ };
94
+
95
+ // e-SLOG download - cast to any since the SDK structure may vary
96
+ const eSlogModule = (sdk as any).eSlog;
97
+ if (!eSlogModule?.download) {
98
+ throw new Error("e-SLOG download not available");
99
+ }
100
+ const xml = await eSlogModule.download(document.id, typeMap[documentType], { entity_id: activeEntity.id });
101
+
102
+ const blob = new Blob([xml], { type: "application/xml" });
103
+ const url = window.URL.createObjectURL(blob);
104
+ const a = window.document.createElement("a");
105
+ a.href = url;
106
+ a.download = `${document.number}.xml`;
107
+ window.document.body.appendChild(a);
108
+ a.click();
109
+ window.URL.revokeObjectURL(url);
110
+ window.document.body.removeChild(a);
111
+ } catch (error) {
112
+ console.error("Error downloading e-SLOG:", error);
113
+ onDownloadError?.("e-SLOG download failed");
114
+ } finally {
115
+ setIsDownloadingEslog(false);
116
+ }
117
+ };
118
+
119
+ return {
120
+ isDownloadingPdf,
121
+ isDownloadingEslog,
122
+ downloadPdf,
123
+ downloadEslog,
124
+ };
125
+ }
@@ -0,0 +1,105 @@
1
+ import { zodResolver } from "@hookform/resolvers/zod";
2
+ import type { CreateEntityRequest, Entity } from "@spaceinvoices/js-sdk";
3
+ import type { Resolver } from "react-hook-form";
4
+ import { useForm } from "react-hook-form";
5
+ import { FormInput } from "@/ui/components/form";
6
+ import { Button } from "@/ui/components/ui/button";
7
+ import { Form } from "@/ui/components/ui/form";
8
+ import { type CreateEntitySchema, createEntitySchema } from "@/ui/generated/schemas";
9
+
10
+ import ButtonLoader from "../button-loader";
11
+ import { useCreateEntity } from "./entities.hooks";
12
+
13
+ export type CreateEntityFormProps = {
14
+ t?: (key: string) => string;
15
+ namespace?: string;
16
+ accountId?: string;
17
+ environment?: string;
18
+ onSuccess?: (data: Entity) => void;
19
+ onError?: (error: unknown) => void;
20
+ };
21
+
22
+ const defaultTranslate = (text: string) => text;
23
+
24
+ export function CreateEntityForm({
25
+ t = defaultTranslate,
26
+ namespace = "",
27
+ accountId,
28
+ environment,
29
+ onSuccess,
30
+ onError,
31
+ }: CreateEntityFormProps) {
32
+ const translate = (key: string) => t(namespace ? `${namespace}.${key}` : key);
33
+
34
+ const form = useForm<CreateEntitySchema>({
35
+ resolver: zodResolver(createEntitySchema) as Resolver<CreateEntitySchema>,
36
+ defaultValues: {
37
+ name: "",
38
+ address: "",
39
+ address_2: "",
40
+ post_code: "",
41
+ city: "",
42
+ state: "",
43
+ country: "",
44
+ tax_number: "",
45
+ environment,
46
+ },
47
+ });
48
+
49
+ // Wrap onSuccess to reset form only after successful mutation
50
+ const handleSuccess = (data: Entity) => {
51
+ form.reset();
52
+ onSuccess?.(data);
53
+ };
54
+
55
+ // Use the createEntity mutation hook
56
+ const { mutate: createEntity, isPending } = useCreateEntity({
57
+ entityId: null,
58
+ accountId,
59
+ onSuccess: handleSuccess,
60
+ onError: (error, _variables, _context) => {
61
+ onError?.(error);
62
+ },
63
+ });
64
+
65
+ const onSubmit = async (values: CreateEntitySchema) => {
66
+ try {
67
+ // Zod validation ensures required fields are present before this is called
68
+ // The type cast is safe because React Hook Form's DeepPartial doesn't reflect runtime validation
69
+ createEntity(values as CreateEntityRequest);
70
+ } catch (e) {
71
+ onError?.(e);
72
+ form.setError("root", {
73
+ type: "submit",
74
+ message: "Failed to create entity",
75
+ });
76
+ }
77
+ };
78
+
79
+ return (
80
+ <Form {...form}>
81
+ <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
82
+ <FormInput control={form.control} name="name" label={translate("Name")} placeholder="Name" required />
83
+
84
+ <FormInput control={form.control} name="country" label="Country" placeholder="Country" required />
85
+
86
+ <FormInput control={form.control} name="address" label="Address" placeholder="Address" />
87
+
88
+ <FormInput control={form.control} name="address_2" label="Address 2" placeholder="Address 2" />
89
+
90
+ <div className="grid grid-cols-2 gap-4">
91
+ <FormInput control={form.control} name="post_code" label="Post code" placeholder="Post code" />
92
+ <FormInput control={form.control} name="city" label="City" placeholder="City" />
93
+ </div>
94
+
95
+ <FormInput control={form.control} name="state" label="State" placeholder="State" />
96
+
97
+ <FormInput control={form.control} name="tax_number" label="Tax number" placeholder="Tax number" />
98
+
99
+ <Button type="submit" className="w-full cursor-pointer" disabled={isPending} aria-busy={isPending}>
100
+ {isPending ? <ButtonLoader /> : "Create"}
101
+ </Button>
102
+ </form>
103
+ </Form>
104
+ );
105
+ }