@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,79 @@
1
+ import type { CreateInvoiceRequest } from "@spaceinvoices/js-sdk";
2
+ import type { CreateInvoiceSchema } from "@/ui/generated/schemas";
3
+ import { prepareDocumentSubmission } from "../../documents/create/prepare-document-submission";
4
+
5
+ type FursData = {
6
+ business_premise_name?: string;
7
+ electronic_device_name?: string;
8
+ skip?: boolean;
9
+ };
10
+
11
+ type EslogData = {
12
+ validation_enabled?: boolean;
13
+ };
14
+
15
+ /** Map of item index to gross price mode */
16
+ type PriceModesMap = Record<number, boolean>;
17
+
18
+ type PrepareOptions = {
19
+ originalCustomer: any;
20
+ wasCustomerFormShown?: boolean;
21
+ markAsPaid?: boolean;
22
+ paymentType?: string;
23
+ /** FURS fiscalization data (for Slovenia) */
24
+ furs?: FursData;
25
+ /** e-SLOG validation data (for Slovenia) */
26
+ eslog?: EslogData;
27
+ /** Map of item index to gross price mode (collected from component state) */
28
+ priceModes?: PriceModesMap;
29
+ /** Whether to save as draft (skips numbering and fiscalization) */
30
+ isDraft?: boolean;
31
+ };
32
+
33
+ /**
34
+ * Prepares invoice form data for API submission
35
+ * Handles customer data transformation, payment data, and FURS fiscalization
36
+ */
37
+ export function prepareInvoiceSubmission(values: CreateInvoiceSchema, options: PrepareOptions): CreateInvoiceRequest {
38
+ const payload = prepareDocumentSubmission(values, {
39
+ originalCustomer: options.originalCustomer,
40
+ wasCustomerFormShown: options.wasCustomerFormShown,
41
+ markAsPaid: options.markAsPaid,
42
+ paymentType: options.paymentType,
43
+ documentType: "invoice",
44
+ secondaryDate: values.date_due,
45
+ priceModes: options.priceModes,
46
+ isDraft: options.isDraft,
47
+ }) as CreateInvoiceRequest;
48
+
49
+ // Add service date fields if provided
50
+ if ((values as any).date_service) {
51
+ (payload as any).date_service = new Date((values as any).date_service);
52
+ }
53
+ if ((values as any).date_service_to) {
54
+ (payload as any).date_service_to = new Date((values as any).date_service_to);
55
+ }
56
+
57
+ // Add FURS data if provided
58
+ if (options.furs) {
59
+ if (options.furs.skip) {
60
+ // Skip fiscalization - only send skip flag
61
+ (payload as any).furs = { skip: true };
62
+ } else if (options.furs.business_premise_name && options.furs.electronic_device_name) {
63
+ // Full FURS fiscalization
64
+ (payload as any).furs = {
65
+ business_premise_name: options.furs.business_premise_name,
66
+ electronic_device_name: options.furs.electronic_device_name,
67
+ };
68
+ }
69
+ }
70
+
71
+ // Add e-SLOG data if provided
72
+ if (options.eslog !== undefined) {
73
+ (payload as any).eslog = {
74
+ validation_enabled: options.eslog.validation_enabled,
75
+ };
76
+ }
77
+
78
+ return payload;
79
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @deprecated Use useDocumentCustomerForm from documents/create instead
3
+ * This re-export exists for backward compatibility
4
+ */
5
+ export { useDocumentCustomerForm as useInvoiceCustomerForm } from "../../documents/create/use-document-customer-form";
@@ -0,0 +1,9 @@
1
+ export { default as CreateInvoiceForm } from "./create/create-invoice-form";
2
+ export * from "./invoices.hooks";
3
+ export * from "./invoices-furs.hooks";
4
+ export * from "./list";
5
+ export { SendEmailDialog } from "./send-email-dialog";
6
+ export * from "./shared";
7
+ export { EslogInfoDisplay } from "./view/eslog-info-display";
8
+ export { FursInfoDisplay } from "./view/furs-info-display";
9
+ // Note: InvoicePreviewDisplay is now DocumentPreviewDisplay in documents/shared
@@ -0,0 +1,28 @@
1
+ import { useMutation, useQueryClient } from "@tanstack/react-query";
2
+ import { useSDK } from "@/ui/providers/sdk-provider";
3
+
4
+ interface VoidInvoiceParams {
5
+ invoiceId: string;
6
+ entityId: string;
7
+ reason?: string;
8
+ }
9
+
10
+ /**
11
+ * Hook to void an invoice
12
+ * Automatically handles FURS technical cancellation for fiscalized invoices
13
+ */
14
+ export function useVoidInvoice() {
15
+ const { sdk } = useSDK();
16
+ const queryClient = useQueryClient();
17
+
18
+ return useMutation({
19
+ mutationFn: async ({ invoiceId, entityId, reason }: VoidInvoiceParams) => {
20
+ return sdk.invoices.void(invoiceId, { reason: reason || undefined }, { entity_id: entityId });
21
+ },
22
+ onSuccess: (_, variables) => {
23
+ // Invalidate invoice queries to refresh the data
24
+ queryClient.invalidateQueries({ queryKey: ["invoices"] });
25
+ queryClient.invalidateQueries({ queryKey: ["documents", "invoice", variables.invoiceId] });
26
+ },
27
+ });
28
+ }
@@ -0,0 +1,110 @@
1
+ import type { CreateInvoice201, CreateInvoiceBody } from "@spaceinvoices/js-sdk";
2
+ import { useQuery } from "@tanstack/react-query";
3
+
4
+ import { createResourceHooks } from "@/ui/hooks/create-resource-hooks";
5
+ import { useSDK } from "@/ui/providers/sdk-provider";
6
+
7
+ // Define a constant for the invoices cache key
8
+ export const INVOICES_CACHE_KEY = "invoices";
9
+ export const NEXT_INVOICE_NUMBER_CACHE_KEY = "next-invoice-number";
10
+
11
+ // Create invoice-specific hooks using the factory
12
+ const {
13
+ useCreateResource: useCreateInvoice,
14
+ useUpdateResource: useUpdateInvoice,
15
+ useDeleteResource: useDeleteInvoice,
16
+ } = createResourceHooks<CreateInvoice201, CreateInvoiceBody>("invoices", INVOICES_CACHE_KEY);
17
+
18
+ export { useCreateInvoice, useUpdateInvoice, useDeleteInvoice };
19
+
20
+ // Re-export document types for backward compatibility
21
+ export type { DocumentTypes } from "../documents/types";
22
+
23
+ // ============================================================================
24
+ // Next Invoice Number Preview
25
+ // ============================================================================
26
+
27
+ /** Response type for next invoice number preview */
28
+ export type NextInvoiceNumberResponse = {
29
+ number: string | null;
30
+ furs: {
31
+ business_premise_name: string;
32
+ electronic_device_name: string;
33
+ } | null;
34
+ };
35
+
36
+ /**
37
+ * Hook to fetch the next invoice number preview
38
+ * Does not increment the sequence - purely for preview purposes
39
+ */
40
+ export function useNextInvoiceNumber(
41
+ entityId: string,
42
+ options?: {
43
+ business_premise_name?: string;
44
+ electronic_device_name?: string;
45
+ enabled?: boolean;
46
+ },
47
+ ) {
48
+ const { sdk } = useSDK();
49
+
50
+ return useQuery<NextInvoiceNumberResponse>({
51
+ queryKey: [
52
+ NEXT_INVOICE_NUMBER_CACHE_KEY,
53
+ entityId,
54
+ options?.business_premise_name,
55
+ options?.electronic_device_name,
56
+ ],
57
+ queryFn: async () => {
58
+ const response = await sdk.documents.getNextNumber(
59
+ {
60
+ type: "invoice",
61
+ business_premise_name: options?.business_premise_name,
62
+ electronic_device_name: options?.electronic_device_name,
63
+ },
64
+ { entity_id: entityId },
65
+ );
66
+ return response as NextInvoiceNumberResponse;
67
+ },
68
+ enabled: options?.enabled !== false && !!entityId && !!sdk?.documents,
69
+ staleTime: 5000, // 5 seconds - short to catch concurrent creates
70
+ });
71
+ }
72
+
73
+ // ============================================================================
74
+ // FURS Last-Used Combo (localStorage)
75
+ // ============================================================================
76
+
77
+ const FURS_LAST_USED_KEY = "si:furs:last-used";
78
+
79
+ export type FursCombo = {
80
+ business_premise_name: string;
81
+ electronic_device_name: string;
82
+ };
83
+
84
+ /**
85
+ * Get last-used FURS premise/device combo from localStorage
86
+ * @param entityId - Entity ID (combos are stored per-entity)
87
+ */
88
+ export function getLastUsedFursCombo(entityId: string): FursCombo | null {
89
+ if (typeof window === "undefined") return null;
90
+ try {
91
+ const stored = localStorage.getItem(`${FURS_LAST_USED_KEY}:${entityId}`);
92
+ return stored ? JSON.parse(stored) : null;
93
+ } catch {
94
+ return null;
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Save last-used FURS premise/device combo to localStorage
100
+ * @param entityId - Entity ID
101
+ * @param combo - FURS premise/device combo
102
+ */
103
+ export function setLastUsedFursCombo(entityId: string, combo: FursCombo): void {
104
+ if (typeof window === "undefined") return;
105
+ try {
106
+ localStorage.setItem(`${FURS_LAST_USED_KEY}:${entityId}`, JSON.stringify(combo));
107
+ } catch {
108
+ // Ignore localStorage errors (quota exceeded, etc.)
109
+ }
110
+ }
@@ -0,0 +1,3 @@
1
+ export { default as InvoiceListRowActions } from "./list-row-actions";
2
+ export { default as InvoiceListTable } from "./list-table";
3
+ export { useInvoiceDownload } from "./use-invoice-download";
@@ -0,0 +1,132 @@
1
+ import type { Invoice } from "@spaceinvoices/js-sdk";
2
+
3
+ import { Copy, Download, Eye, Link2Off, Loader2, Mail, MoreHorizontal, Plus } from "lucide-react";
4
+ import { useState } from "react";
5
+ import { Button } from "@/ui/components/ui/button";
6
+ import {
7
+ DropdownMenu,
8
+ DropdownMenuContent,
9
+ DropdownMenuGroup,
10
+ DropdownMenuItem,
11
+ DropdownMenuLabel,
12
+ DropdownMenuSeparator,
13
+ DropdownMenuTrigger,
14
+ } from "@/ui/components/ui/dropdown-menu";
15
+ import type { ComponentTranslationProps } from "@/ui/lib/translation";
16
+ import { createTranslation } from "@/ui/lib/translation";
17
+ import { SendEmailDialog } from "../send-email-dialog";
18
+ import { useInvoiceDownload } from "./use-invoice-download";
19
+
20
+ type InvoiceListRowActionsProps = {
21
+ invoice: Invoice;
22
+ onAddPayment?: (invoice: Invoice) => void;
23
+ onDuplicate?: (invoice: Invoice) => void;
24
+ onDownloadStart?: () => void;
25
+ onDownloadSuccess?: (fileName: string) => void;
26
+ onDownloadError?: (error: string) => void;
27
+ onUnshare?: (invoice: Invoice) => Promise<void>;
28
+ isUnsharing?: boolean;
29
+ } & ComponentTranslationProps;
30
+
31
+ export default function InvoiceListRowActions({
32
+ invoice,
33
+ onAddPayment,
34
+ onDuplicate,
35
+ onDownloadStart,
36
+ onDownloadSuccess,
37
+ onDownloadError,
38
+ onUnshare,
39
+ isUnsharing,
40
+ ...i18nProps
41
+ }: InvoiceListRowActionsProps) {
42
+ const t = createTranslation(i18nProps);
43
+ const [emailDialogOpen, setEmailDialogOpen] = useState(false);
44
+ const { isDownloading, downloadPDF } = useInvoiceDownload({
45
+ onDownloadStart,
46
+ onDownloadSuccess,
47
+ onDownloadError,
48
+ ...i18nProps,
49
+ });
50
+
51
+ return (
52
+ <>
53
+ <DropdownMenu>
54
+ <DropdownMenuTrigger asChild>
55
+ <Button variant="ghost" className="h-8 w-8 cursor-pointer p-0" id="action-menu-trigger">
56
+ <span className="sr-only">{t("Open menu")}</span>
57
+ <MoreHorizontal className="h-4 w-4" />
58
+ </Button>
59
+ </DropdownMenuTrigger>
60
+ <DropdownMenuContent align="end">
61
+ <DropdownMenuLabel>{t("Actions")}</DropdownMenuLabel>
62
+ <DropdownMenuGroup>
63
+ <DropdownMenuItem className="cursor-pointer" onClick={() => navigator.clipboard.writeText(invoice.id)}>
64
+ <Copy className="h-4 w-4" />
65
+ {t("Copy invoice ID")}
66
+ </DropdownMenuItem>
67
+ </DropdownMenuGroup>
68
+ <DropdownMenuSeparator />
69
+ <DropdownMenuGroup>
70
+ <DropdownMenuItem
71
+ className="cursor-pointer"
72
+ onClick={() => {
73
+ // TODO: Use router
74
+ window.location.href = `/app/documents/view/${invoice.id}`;
75
+ }}
76
+ >
77
+ <Eye className="h-4 w-4" />
78
+ {t("View invoice")}
79
+ </DropdownMenuItem>
80
+ <DropdownMenuItem className="cursor-pointer" onClick={() => downloadPDF(invoice)} disabled={isDownloading}>
81
+ <Download className="h-4 w-4" />
82
+ {isDownloading ? t("Downloading...") : t("Download PDF")}
83
+ </DropdownMenuItem>
84
+ <DropdownMenuItem className="cursor-pointer" onClick={() => setEmailDialogOpen(true)}>
85
+ <Mail className="h-4 w-4" />
86
+ {t("Send Email")}
87
+ </DropdownMenuItem>
88
+ {onDuplicate && (
89
+ <DropdownMenuItem className="cursor-pointer" onClick={() => onDuplicate(invoice)}>
90
+ <Copy className="h-4 w-4" />
91
+ {t("Duplicate")}
92
+ </DropdownMenuItem>
93
+ )}
94
+ </DropdownMenuGroup>
95
+ {!invoice.paid_in_full && (
96
+ <>
97
+ <DropdownMenuSeparator />
98
+ <DropdownMenuGroup>
99
+ <DropdownMenuItem className="cursor-pointer" onClick={() => onAddPayment?.(invoice)}>
100
+ <Plus className="h-4 w-4" />
101
+ {t("Add Payment")}
102
+ </DropdownMenuItem>
103
+ </DropdownMenuGroup>
104
+ </>
105
+ )}
106
+ {invoice.shareable_id && onUnshare && (
107
+ <>
108
+ <DropdownMenuSeparator />
109
+ <DropdownMenuGroup>
110
+ <DropdownMenuItem
111
+ className="cursor-pointer text-destructive focus:text-destructive"
112
+ onClick={() => onUnshare(invoice)}
113
+ disabled={isUnsharing}
114
+ >
115
+ {isUnsharing ? <Loader2 className="h-4 w-4 animate-spin" /> : <Link2Off className="h-4 w-4" />}
116
+ {t("Unshare")}
117
+ </DropdownMenuItem>
118
+ </DropdownMenuGroup>
119
+ </>
120
+ )}
121
+ </DropdownMenuContent>
122
+ </DropdownMenu>
123
+ <SendEmailDialog
124
+ invoice={invoice}
125
+ defaultEmail={invoice.customer?.email || ""}
126
+ open={emailDialogOpen}
127
+ onOpenChange={setEmailDialogOpen}
128
+ translationFn={t}
129
+ />
130
+ </>
131
+ );
132
+ }
@@ -0,0 +1,165 @@
1
+ import type { Invoice } 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 { Button } from "@/ui/components/ui/button";
14
+ import { createTranslation } from "@/ui/lib/translation";
15
+ import { useSDK } from "@/ui/providers/sdk-provider";
16
+
17
+ import InvoiceListRowActions from "./list-row-actions";
18
+ import de from "./locales/de";
19
+ import sl from "./locales/sl";
20
+
21
+ const translations = {
22
+ sl,
23
+ de,
24
+ } as const;
25
+
26
+ type InvoiceListTableProps = {
27
+ t?: (key: string) => string;
28
+ namespace?: string;
29
+ locale?: string;
30
+ entityId?: string;
31
+ onAddPayment?: (invoice: Invoice) => void;
32
+ onDuplicate?: (invoice: Invoice) => void;
33
+ onDownloadStart?: () => void;
34
+ onDownloadSuccess?: (fileName: string) => void;
35
+ onDownloadError?: (error: string) => void;
36
+ } & ListTableProps<Invoice>;
37
+
38
+ export default function InvoiceListTable({
39
+ queryParams,
40
+ onRowClick,
41
+ onAddPayment,
42
+ onDuplicate,
43
+ onChangeParams,
44
+ disableUrlSync,
45
+ entityId,
46
+ onDownloadStart,
47
+ onDownloadSuccess,
48
+ onDownloadError,
49
+ ...i18nProps
50
+ }: InvoiceListTableProps) {
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.invoices.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<Invoice>;
72
+ }, entityId);
73
+
74
+ const filterConfig: FilterConfig = useMemo(
75
+ () => ({
76
+ dateFields: [
77
+ { id: "date", label: t("Date") },
78
+ { id: "date_due", label: t("Date Due") },
79
+ { id: "created_at", label: t("Created At") },
80
+ ],
81
+ statusFilter: true,
82
+ }),
83
+ [t],
84
+ );
85
+
86
+ const columns: Column<Invoice>[] = useMemo(
87
+ () => [
88
+ {
89
+ id: "number",
90
+ header: t("Number"),
91
+ sortable: true,
92
+ cell: (invoice) => (
93
+ <Button variant="link" className="cursor-pointer py-0 underline" onClick={() => onRowClick?.(invoice)}>
94
+ {(invoice as any).is_draft ? t("Draft") : invoice.number}
95
+ </Button>
96
+ ),
97
+ },
98
+ {
99
+ id: "customer",
100
+ header: t("Customer"),
101
+ cell: (invoice) => invoice.customer?.name ?? "-",
102
+ },
103
+ {
104
+ id: "date",
105
+ header: t("Date"),
106
+ sortable: true,
107
+ cell: (invoice) => <FormattedDate date={invoice.date} />,
108
+ },
109
+ {
110
+ id: "date_due",
111
+ header: t("Date Due"),
112
+ sortable: true,
113
+ cell: (invoice) => <FormattedDate date={invoice.date_due} />,
114
+ },
115
+ {
116
+ id: "total",
117
+ header: t("Total"),
118
+ sortable: true,
119
+ align: "right",
120
+ cell: (invoice) => invoice.total,
121
+ },
122
+ {
123
+ id: "total_with_tax",
124
+ header: t("Total with Tax"),
125
+ sortable: true,
126
+ align: "right",
127
+ cell: (invoice) => invoice.total_with_tax,
128
+ },
129
+ {
130
+ id: "actions",
131
+ header: "",
132
+ align: "right",
133
+ cell: (invoice) => (
134
+ <InvoiceListRowActions
135
+ invoice={invoice}
136
+ onAddPayment={onAddPayment}
137
+ onDuplicate={onDuplicate}
138
+ onDownloadStart={onDownloadStart}
139
+ onDownloadSuccess={onDownloadSuccess}
140
+ onDownloadError={onDownloadError}
141
+ {...i18nProps}
142
+ />
143
+ ),
144
+ },
145
+ ],
146
+ [t, onRowClick, onAddPayment, onDuplicate, onDownloadStart, onDownloadSuccess, onDownloadError, i18nProps],
147
+ );
148
+
149
+ return (
150
+ <DataTable
151
+ columns={columns}
152
+ queryParams={queryParams}
153
+ resourceName="invoice"
154
+ cacheKey="invoices"
155
+ createNewLink="/app/documents/add/invoice"
156
+ onFetch={handleFetch}
157
+ onChangeParams={onChangeParams}
158
+ disableUrlSync={disableUrlSync}
159
+ entityId={entityId}
160
+ filterConfig={filterConfig}
161
+ t={t}
162
+ locale={i18nProps.locale}
163
+ />
164
+ );
165
+ }
@@ -0,0 +1,33 @@
1
+ export default {
2
+ Draft: "Entwurf",
3
+ Number: "Nummer",
4
+ Customer: "Kunde",
5
+ Date: "Datum",
6
+ "Date Due": "Fälligkeitsdatum",
7
+ Total: "Gesamt",
8
+ "Total with Tax": "Gesamt mit MwSt",
9
+ Actions: "Aktionen",
10
+ "Open menu": "Menü öffnen",
11
+ "Copy invoice ID": "Rechnungs-ID kopieren",
12
+ "View invoice": "Rechnung anzeigen",
13
+ "Add Payment": "Zahlung hinzufügen",
14
+ "Download PDF": "PDF herunterladen",
15
+ "Downloading...": "Wird heruntergeladen...",
16
+ Duplicate: "Duplizieren",
17
+ "Send Email": "E-Mail senden",
18
+ Invoice: "Rechnung",
19
+ "Failed to download PDF": "PDF-Download fehlgeschlagen",
20
+ // Filter translations
21
+ "Search...": "Suchen...",
22
+ Filters: "Filter",
23
+ "Date Range": "Datumsbereich",
24
+ From: "Von",
25
+ To: "Bis",
26
+ "Clear filters": "Filter löschen",
27
+ Status: "Status",
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
+ "Date Due": "Datum zapadlosti",
7
+ Total: "Skupaj",
8
+ "Total with Tax": "Skupaj z DDV",
9
+ Actions: "Akcije",
10
+ "Open menu": "Odpri meni",
11
+ "Copy invoice ID": "Kopiraj ID računa",
12
+ "View invoice": "Prikaži račun",
13
+ "Add Payment": "Dodaj plačilo",
14
+ "Download PDF": "Prenesi PDF",
15
+ "Downloading...": "Prenašam...",
16
+ Duplicate: "Podvoji",
17
+ "Send Email": "Pošlji e-pošto",
18
+ Invoice: "Račun",
19
+ "Failed to download PDF": "Prenos PDF-ja je spodletel",
20
+ // Filter translations
21
+ "Search...": "Iskanje...",
22
+ Filters: "Filtri",
23
+ "Date Range": "Datumski razpon",
24
+ From: "Od",
25
+ To: "Do",
26
+ "Clear filters": "Počisti filtre",
27
+ Status: "Status",
28
+ Paid: "Plačano",
29
+ Unpaid: "Neplačano",
30
+ Overdue: "Zapadlo",
31
+ Voided: "Stornirano",
32
+ "Created At": "Ustvarjeno",
33
+ } as const;
@@ -0,0 +1,62 @@
1
+ import type { Invoice } from "@spaceinvoices/js-sdk";
2
+ import { useState } from "react";
3
+ import type { ComponentTranslationProps } from "@/ui/lib/translation";
4
+ import { createTranslation } from "@/ui/lib/translation";
5
+ import { useEntities } from "@/ui/providers/entities-context";
6
+ import { useSDK } from "@/ui/providers/sdk-provider";
7
+
8
+ type UseInvoiceDownloadProps = {
9
+ onDownloadStart?: () => void;
10
+ onDownloadSuccess?: (fileName: string) => void;
11
+ onDownloadError?: (error: string) => void;
12
+ } & ComponentTranslationProps;
13
+
14
+ export function useInvoiceDownload({
15
+ onDownloadStart,
16
+ onDownloadSuccess,
17
+ onDownloadError,
18
+ ...i18nProps
19
+ }: UseInvoiceDownloadProps) {
20
+ const [isDownloading, setIsDownloading] = useState(false);
21
+ const { activeEntity } = useEntities();
22
+ const { sdk } = useSDK();
23
+ const t = createTranslation(i18nProps);
24
+
25
+ const downloadPDF = async (invoice: Invoice) => {
26
+ if (!activeEntity?.id || !sdk) {
27
+ console.error("Missing SDK or active entity for PDF download");
28
+ onDownloadError?.(t("Failed to download PDF"));
29
+ return;
30
+ }
31
+
32
+ setIsDownloading(true);
33
+ onDownloadStart?.();
34
+
35
+ try {
36
+ // SDK signature: renderPdf(id, params?, SDKMethodOptions?)
37
+ // entity_id goes in SDKMethodOptions (last arg), not params
38
+ const blob = await sdk.invoices.renderPdf(invoice.id, {}, { entity_id: activeEntity.id });
39
+ const downloadUrl = window.URL.createObjectURL(blob);
40
+ const link = document.createElement("a");
41
+ link.href = downloadUrl;
42
+ const fileName = `${t("Invoice")} ${invoice.number}.pdf`;
43
+ link.download = fileName;
44
+ document.body.appendChild(link);
45
+ link.click();
46
+ document.body.removeChild(link);
47
+ window.URL.revokeObjectURL(downloadUrl);
48
+
49
+ onDownloadSuccess?.(fileName);
50
+ } catch (error) {
51
+ console.error("Error downloading PDF:", error);
52
+ onDownloadError?.(t("Failed to download PDF"));
53
+ } finally {
54
+ setIsDownloading(false);
55
+ }
56
+ };
57
+
58
+ return {
59
+ isDownloading,
60
+ downloadPDF,
61
+ };
62
+ }
@@ -0,0 +1 @@
1
+ export { SendEmailDialog } from "./send-email-dialog";