@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,29 @@
1
+ export default {
2
+ Save: "Speichern",
3
+ "Save as Draft": "Als Entwurf speichern",
4
+ "Create Advance Invoice": "Vorauszahlungsrechnung erstellen",
5
+ "e-SLOG": "e-SLOG",
6
+ "Fiscally verify": "Steuerlich bestätigen",
7
+ "Click to skip e-SLOG validation for this advance invoice":
8
+ "Klicken, um die e-SLOG-Validierung für diese Vorauszahlungsrechnung zu überspringen",
9
+ "Click to enable e-SLOG validation": "Klicken, um die e-SLOG-Validierung zu aktivieren",
10
+ "Click to skip fiscalization for this advance invoice":
11
+ "Klicken, um die Fiskalisierung für diese Vorauszahlungsrechnung zu überspringen",
12
+ "Click to enable fiscalization": "Klicken, um die Fiskalisierung zu aktivieren",
13
+ "Cannot skip fiscalization for cash payments": "Fiskalisierung kann für Barzahlungen nicht übersprungen werden",
14
+ "e-SLOG Validation Failed": "e-SLOG-Validierung fehlgeschlagen",
15
+ "The following entity settings need to be updated:":
16
+ "Die folgenden Entitätseinstellungen müssen aktualisiert werden:",
17
+ "Reverse charge - tax exempt EU B2B sale": "Umkehrung der Steuerschuldnerschaft - steuerbefreiter EU B2B-Verkauf",
18
+ "Mark as Paid": "Als bezahlt markieren",
19
+ Paid: "Bezahlt",
20
+ "Advance invoice will be marked as fully paid upon creation":
21
+ "Vorauszahlungsrechnung wird bei Erstellung als vollständig bezahlt markiert",
22
+ "Payment Type": "Zahlungsart",
23
+ "Select payment type": "Zahlungsart auswählen",
24
+ Cash: "Bargeld",
25
+ "Bank Transfer": "Banküberweisung",
26
+ Card: "Karte",
27
+ Check: "Scheck",
28
+ Other: "Andere",
29
+ } as const;
@@ -0,0 +1,25 @@
1
+ export default {
2
+ Save: "Shrani",
3
+ "Save as Draft": "Shrani kot osnutek",
4
+ "Create Advance Invoice": "Ustvari avansni račun",
5
+ "e-SLOG": "e-SLOG",
6
+ "Fiscally verify": "Davčno potrdi",
7
+ "Click to skip e-SLOG validation for this advance invoice": "Klikni za preskok e-SLOG validacije za ta avansni račun",
8
+ "Click to enable e-SLOG validation": "Klikni za vključitev e-SLOG validacije",
9
+ "Click to skip fiscalization for this advance invoice": "Klikni za preskok davčnega potrjevanja za ta avansni račun",
10
+ "Click to enable fiscalization": "Klikni za vključitev davčnega potrjevanja",
11
+ "Cannot skip fiscalization for cash payments": "Za gotovinska plačila ni mogoče preskočiti davčnega potrjevanja",
12
+ "e-SLOG Validation Failed": "e-SLOG validacija ni uspela",
13
+ "The following entity settings need to be updated:": "Naslednje nastavitve entitete je treba posodobiti:",
14
+ "Reverse charge - tax exempt EU B2B sale": "Obrnjeno davčno breme - davčno oproščena EU B2B prodaja",
15
+ "Mark as Paid": "Označi kot plačano",
16
+ Paid: "Plačano",
17
+ "Advance invoice will be marked as fully paid upon creation": "Avansni račun bo označen kot plačan ob ustvarjanju",
18
+ "Payment Type": "Vrsta plačila",
19
+ "Select payment type": "Izberite vrsto plačila",
20
+ Cash: "Gotovina",
21
+ "Bank Transfer": "Bančno nakazilo",
22
+ Card: "Kartica",
23
+ Check: "Ček",
24
+ Other: "Drugo",
25
+ } as const;
@@ -0,0 +1,74 @@
1
+ import type { CreateAdvanceInvoiceRequest } from "@spaceinvoices/js-sdk";
2
+ import type { CreateAdvanceInvoiceSchema } 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 advance invoice form data for API submission
35
+ * Handles customer data transformation, payment data, and FURS fiscalization
36
+ */
37
+ export function prepareAdvanceInvoiceSubmission(
38
+ values: CreateAdvanceInvoiceSchema,
39
+ options: PrepareOptions,
40
+ ): CreateAdvanceInvoiceRequest {
41
+ const payload = prepareDocumentSubmission(values as any, {
42
+ originalCustomer: options.originalCustomer,
43
+ wasCustomerFormShown: options.wasCustomerFormShown,
44
+ markAsPaid: options.markAsPaid,
45
+ paymentType: options.paymentType,
46
+ documentType: "advance_invoice",
47
+ secondaryDate: values.date_due,
48
+ priceModes: options.priceModes,
49
+ isDraft: options.isDraft,
50
+ }) as CreateAdvanceInvoiceRequest;
51
+
52
+ // Add FURS data if provided
53
+ if (options.furs) {
54
+ if (options.furs.skip) {
55
+ // Skip fiscalization - only send skip flag
56
+ (payload as any).furs = { skip: true };
57
+ } else if (options.furs.business_premise_name && options.furs.electronic_device_name) {
58
+ // Full FURS fiscalization
59
+ (payload as any).furs = {
60
+ business_premise_name: options.furs.business_premise_name,
61
+ electronic_device_name: options.furs.electronic_device_name,
62
+ };
63
+ }
64
+ }
65
+
66
+ // Add e-SLOG data if provided
67
+ if (options.eslog !== undefined) {
68
+ (payload as any).eslog = {
69
+ validation_enabled: options.eslog.validation_enabled,
70
+ };
71
+ }
72
+
73
+ return payload;
74
+ }
@@ -0,0 +1,5 @@
1
+ export * from "./advance-invoices.hooks";
2
+ export { default as CreateAdvanceInvoiceForm } from "./create/create-advance-invoice-form";
3
+ export { default as AdvanceInvoiceListRowActions } from "./list/list-row-actions";
4
+ export { default as AdvanceInvoiceListTable } from "./list/list-table";
5
+ export { useAdvanceInvoiceDownload } from "./list/use-advance-invoice-download";
@@ -0,0 +1,3 @@
1
+ export { default as AdvanceInvoiceListRowActions } from "./list-row-actions";
2
+ export { default as AdvanceInvoiceListTable } from "./list-table";
3
+ export { useAdvanceInvoiceDownload } from "./use-advance-invoice-download";
@@ -0,0 +1,119 @@
1
+ import type { AdvanceInvoice } from "@spaceinvoices/js-sdk";
2
+
3
+ import { Copy, Download, Eye, Link2Off, Loader2, MoreHorizontal, Plus } from "lucide-react";
4
+ import { Button } from "@/ui/components/ui/button";
5
+ import {
6
+ DropdownMenu,
7
+ DropdownMenuContent,
8
+ DropdownMenuGroup,
9
+ DropdownMenuItem,
10
+ DropdownMenuLabel,
11
+ DropdownMenuSeparator,
12
+ DropdownMenuTrigger,
13
+ } from "@/ui/components/ui/dropdown-menu";
14
+ import type { ComponentTranslationProps } from "@/ui/lib/translation";
15
+ import { createTranslation } from "@/ui/lib/translation";
16
+ import { useAdvanceInvoiceDownload } from "./use-advance-invoice-download";
17
+
18
+ type AdvanceInvoiceListRowActionsProps = {
19
+ advanceInvoice: AdvanceInvoice;
20
+ onAddPayment?: (advanceInvoice: AdvanceInvoice) => void;
21
+ onDuplicate?: (advanceInvoice: AdvanceInvoice) => void;
22
+ onDownloadStart?: () => void;
23
+ onDownloadSuccess?: (fileName: string) => void;
24
+ onDownloadError?: (error: string) => void;
25
+ onUnshare?: (advanceInvoice: AdvanceInvoice) => Promise<void>;
26
+ isUnsharing?: boolean;
27
+ } & ComponentTranslationProps;
28
+
29
+ export default function AdvanceInvoiceListRowActions({
30
+ advanceInvoice,
31
+ onAddPayment,
32
+ onDuplicate,
33
+ onDownloadStart,
34
+ onDownloadSuccess,
35
+ onDownloadError,
36
+ onUnshare,
37
+ isUnsharing,
38
+ ...i18nProps
39
+ }: AdvanceInvoiceListRowActionsProps) {
40
+ const t = createTranslation(i18nProps);
41
+ const { isDownloading, downloadPDF } = useAdvanceInvoiceDownload({
42
+ onDownloadStart,
43
+ onDownloadSuccess,
44
+ onDownloadError,
45
+ ...i18nProps,
46
+ });
47
+
48
+ return (
49
+ <DropdownMenu>
50
+ <DropdownMenuTrigger asChild>
51
+ <Button variant="ghost" className="h-8 w-8 cursor-pointer p-0" id="action-menu-trigger">
52
+ <span className="sr-only">{t("Open menu")}</span>
53
+ <MoreHorizontal className="h-4 w-4" />
54
+ </Button>
55
+ </DropdownMenuTrigger>
56
+ <DropdownMenuContent align="end">
57
+ <DropdownMenuLabel>{t("Actions")}</DropdownMenuLabel>
58
+ <DropdownMenuGroup>
59
+ <DropdownMenuItem className="cursor-pointer" onClick={() => navigator.clipboard.writeText(advanceInvoice.id)}>
60
+ <Copy className="h-4 w-4" />
61
+ {t("Copy advance invoice ID")}
62
+ </DropdownMenuItem>
63
+ </DropdownMenuGroup>
64
+ <DropdownMenuSeparator />
65
+ <DropdownMenuGroup>
66
+ <DropdownMenuItem
67
+ className="cursor-pointer"
68
+ onClick={() => {
69
+ window.location.href = `/app/documents/view/${advanceInvoice.id}`;
70
+ }}
71
+ >
72
+ <Eye className="h-4 w-4" />
73
+ {t("View advance invoice")}
74
+ </DropdownMenuItem>
75
+ <DropdownMenuItem
76
+ className="cursor-pointer"
77
+ onClick={() => downloadPDF(advanceInvoice)}
78
+ disabled={isDownloading}
79
+ >
80
+ <Download className="h-4 w-4" />
81
+ {isDownloading ? t("Downloading...") : t("Download PDF")}
82
+ </DropdownMenuItem>
83
+ {onDuplicate && (
84
+ <DropdownMenuItem className="cursor-pointer" onClick={() => onDuplicate(advanceInvoice)}>
85
+ <Copy className="h-4 w-4" />
86
+ {t("Duplicate")}
87
+ </DropdownMenuItem>
88
+ )}
89
+ </DropdownMenuGroup>
90
+ {!advanceInvoice.paid_in_full && (
91
+ <>
92
+ <DropdownMenuSeparator />
93
+ <DropdownMenuGroup>
94
+ <DropdownMenuItem className="cursor-pointer" onClick={() => onAddPayment?.(advanceInvoice)}>
95
+ <Plus className="h-4 w-4" />
96
+ {t("Add Payment")}
97
+ </DropdownMenuItem>
98
+ </DropdownMenuGroup>
99
+ </>
100
+ )}
101
+ {advanceInvoice.shareable_id && onUnshare && (
102
+ <>
103
+ <DropdownMenuSeparator />
104
+ <DropdownMenuGroup>
105
+ <DropdownMenuItem
106
+ className="cursor-pointer text-destructive focus:text-destructive"
107
+ onClick={() => onUnshare(advanceInvoice)}
108
+ disabled={isUnsharing}
109
+ >
110
+ {isUnsharing ? <Loader2 className="h-4 w-4 animate-spin" /> : <Link2Off className="h-4 w-4" />}
111
+ {t("Unshare")}
112
+ </DropdownMenuItem>
113
+ </DropdownMenuGroup>
114
+ </>
115
+ )}
116
+ </DropdownMenuContent>
117
+ </DropdownMenu>
118
+ );
119
+ }
@@ -0,0 +1,178 @@
1
+ import type { AdvanceInvoice } from "@spaceinvoices/js-sdk";
2
+ import { useMemo } from "react";
3
+ import { DataTable } from "@/ui/components/table/data-table";
4
+ import { FormattedDate } from "@/ui/components/table/date-cell";
5
+ import { useTableFetch } from "@/ui/components/table/hooks/use-table-fetch";
6
+ import type {
7
+ Column,
8
+ FilterConfig,
9
+ ListTableProps,
10
+ TableQueryParams,
11
+ TableQueryResponse,
12
+ } from "@/ui/components/table/types";
13
+ import { Badge } from "@/ui/components/ui/badge";
14
+ import { Button } from "@/ui/components/ui/button";
15
+ import { createTranslation } from "@/ui/lib/translation";
16
+ import { useSDK } from "@/ui/providers/sdk-provider";
17
+
18
+ import AdvanceInvoiceListRowActions from "./list-row-actions";
19
+ import de from "./locales/de";
20
+ import sl from "./locales/sl";
21
+
22
+ const translations = {
23
+ sl,
24
+ de,
25
+ } as const;
26
+
27
+ type AdvanceInvoiceListTableProps = {
28
+ t?: (key: string) => string;
29
+ namespace?: string;
30
+ locale?: string;
31
+ entityId?: string;
32
+ onAddPayment?: (advanceInvoice: AdvanceInvoice) => void;
33
+ onDuplicate?: (advanceInvoice: AdvanceInvoice) => void;
34
+ onDownloadStart?: () => void;
35
+ onDownloadSuccess?: (fileName: string) => void;
36
+ onDownloadError?: (error: string) => void;
37
+ } & ListTableProps<AdvanceInvoice>;
38
+
39
+ export default function AdvanceInvoiceListTable({
40
+ queryParams,
41
+ onRowClick,
42
+ onAddPayment,
43
+ onDuplicate,
44
+ onChangeParams,
45
+ entityId,
46
+ onDownloadStart,
47
+ onDownloadSuccess,
48
+ onDownloadError,
49
+ ...i18nProps
50
+ }: AdvanceInvoiceListTableProps) {
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.advanceInvoices.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<AdvanceInvoice>;
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<AdvanceInvoice>[] = useMemo(
87
+ () => [
88
+ {
89
+ id: "number",
90
+ header: t("Number"),
91
+ sortable: true,
92
+ cell: (advanceInvoice) => (
93
+ <div className="flex items-center gap-2">
94
+ <Button
95
+ variant="link"
96
+ className="cursor-pointer py-0 underline"
97
+ onClick={() => onRowClick?.(advanceInvoice)}
98
+ >
99
+ {advanceInvoice.number}
100
+ </Button>
101
+ {(advanceInvoice as any).is_draft && (
102
+ <Badge
103
+ variant="outline"
104
+ className="border-amber-500 bg-amber-50 text-amber-700 dark:bg-amber-950 dark:text-amber-400"
105
+ >
106
+ {t("Draft")}
107
+ </Badge>
108
+ )}
109
+ </div>
110
+ ),
111
+ },
112
+ {
113
+ id: "customer",
114
+ header: t("Customer"),
115
+ cell: (advanceInvoice) => advanceInvoice.customer?.name ?? "-",
116
+ },
117
+ {
118
+ id: "date",
119
+ header: t("Date"),
120
+ sortable: true,
121
+ cell: (advanceInvoice) => <FormattedDate date={advanceInvoice.date} />,
122
+ },
123
+ {
124
+ id: "date_due",
125
+ header: t("Date Due"),
126
+ sortable: true,
127
+ cell: (advanceInvoice) => <FormattedDate date={advanceInvoice.date_due} />,
128
+ },
129
+ {
130
+ id: "total",
131
+ header: t("Total"),
132
+ sortable: true,
133
+ align: "right",
134
+ cell: (advanceInvoice) => advanceInvoice.total,
135
+ },
136
+ {
137
+ id: "total_with_tax",
138
+ header: t("Total with Tax"),
139
+ sortable: true,
140
+ align: "right",
141
+ cell: (advanceInvoice) => advanceInvoice.total_with_tax,
142
+ },
143
+ {
144
+ id: "actions",
145
+ header: "",
146
+ align: "right",
147
+ cell: (advanceInvoice) => (
148
+ <AdvanceInvoiceListRowActions
149
+ advanceInvoice={advanceInvoice}
150
+ onAddPayment={onAddPayment}
151
+ onDuplicate={onDuplicate}
152
+ onDownloadStart={onDownloadStart}
153
+ onDownloadSuccess={onDownloadSuccess}
154
+ onDownloadError={onDownloadError}
155
+ {...i18nProps}
156
+ />
157
+ ),
158
+ },
159
+ ],
160
+ [t, onRowClick, onAddPayment, onDuplicate, onDownloadStart, onDownloadSuccess, onDownloadError, i18nProps],
161
+ );
162
+
163
+ return (
164
+ <DataTable
165
+ columns={columns}
166
+ queryParams={queryParams}
167
+ resourceName="advance_invoice"
168
+ cacheKey="advance-invoices"
169
+ createNewLink="/app/documents/add/advance_invoice"
170
+ onFetch={handleFetch}
171
+ onChangeParams={onChangeParams}
172
+ entityId={entityId}
173
+ filterConfig={filterConfig}
174
+ t={t}
175
+ locale={i18nProps.locale}
176
+ />
177
+ );
178
+ }
@@ -0,0 +1,32 @@
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 advance invoice ID": "Vorauszahlungsrechnung-ID kopieren",
12
+ "View advance invoice": "Vorauszahlungsrechnung anzeigen",
13
+ "Add Payment": "Zahlung hinzufügen",
14
+ "Download PDF": "PDF herunterladen",
15
+ "Downloading...": "Wird heruntergeladen...",
16
+ Duplicate: "Duplizieren",
17
+ "Advance Invoice": "Vorauszahlungsrechnung",
18
+ "Failed to download PDF": "PDF-Download fehlgeschlagen",
19
+ // Filter translations
20
+ "Search...": "Suchen...",
21
+ Filters: "Filter",
22
+ "Date Range": "Datumsbereich",
23
+ From: "Von",
24
+ To: "Bis",
25
+ "Clear filters": "Filter löschen",
26
+ Status: "Status",
27
+ Paid: "Bezahlt",
28
+ Unpaid: "Unbezahlt",
29
+ Overdue: "Überfällig",
30
+ Voided: "Storniert",
31
+ "Created At": "Erstellt am",
32
+ } as const;
@@ -0,0 +1,32 @@
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 advance invoice ID": "Kopiraj ID avansnega računa",
12
+ "View advance invoice": "Prikaži avansni račun",
13
+ "Add Payment": "Dodaj plačilo",
14
+ "Download PDF": "Prenesi PDF",
15
+ "Downloading...": "Prenašam...",
16
+ Duplicate: "Podvoji",
17
+ "Advance Invoice": "Avansni račun",
18
+ "Failed to download PDF": "Prenos PDF-ja je spodletel",
19
+ // Filter translations
20
+ "Search...": "Iskanje...",
21
+ Filters: "Filtri",
22
+ "Date Range": "Datumski razpon",
23
+ From: "Od",
24
+ To: "Do",
25
+ "Clear filters": "Počisti filtre",
26
+ Status: "Status",
27
+ Paid: "Plačano",
28
+ Unpaid: "Neplačano",
29
+ Overdue: "Zapadlo",
30
+ Voided: "Stornirano",
31
+ "Created At": "Ustvarjeno",
32
+ } as const;
@@ -0,0 +1,63 @@
1
+ import type { AdvanceInvoice } 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 UseAdvanceInvoiceDownloadProps = {
9
+ onDownloadStart?: () => void;
10
+ onDownloadSuccess?: (fileName: string) => void;
11
+ onDownloadError?: (error: string) => void;
12
+ } & ComponentTranslationProps;
13
+
14
+ export function useAdvanceInvoiceDownload({
15
+ onDownloadStart,
16
+ onDownloadSuccess,
17
+ onDownloadError,
18
+ ...i18nProps
19
+ }: UseAdvanceInvoiceDownloadProps) {
20
+ const [isDownloading, setIsDownloading] = useState(false);
21
+ const { activeEntity } = useEntities();
22
+ const { sdk } = useSDK();
23
+ const t = createTranslation(i18nProps);
24
+
25
+ const downloadPDF = async (advanceInvoice: AdvanceInvoice) => {
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
+ // Note: renderPdf is on invoices module but works with any document ID
39
+ const blob = await sdk.invoices.renderPdf(advanceInvoice.id, {}, { entity_id: activeEntity.id });
40
+ const downloadUrl = window.URL.createObjectURL(blob);
41
+ const link = document.createElement("a");
42
+ link.href = downloadUrl;
43
+ const fileName = `${t("Advance Invoice")} ${advanceInvoice.number}.pdf`;
44
+ link.download = fileName;
45
+ document.body.appendChild(link);
46
+ link.click();
47
+ document.body.removeChild(link);
48
+ window.URL.revokeObjectURL(downloadUrl);
49
+
50
+ onDownloadSuccess?.(fileName);
51
+ } catch (error) {
52
+ console.error("Error downloading PDF:", error);
53
+ onDownloadError?.(t("Failed to download PDF"));
54
+ } finally {
55
+ setIsDownloading(false);
56
+ }
57
+ };
58
+
59
+ return {
60
+ isDownloading,
61
+ downloadPDF,
62
+ };
63
+ }
@@ -0,0 +1,11 @@
1
+ import { Loader2 } from "lucide-react";
2
+
3
+ import { cn } from "../lib/utils";
4
+
5
+ type ButtonLoaderProps = {
6
+ className?: string;
7
+ };
8
+
9
+ export default function ButtonLoader({ className }: ButtonLoaderProps) {
10
+ return <Loader2 className={cn("h-4 w-4 animate-spin", className)} role="status" aria-label="Loading" />;
11
+ }
@@ -0,0 +1,96 @@
1
+ import { Check, ChevronsUpDown } from "lucide-react";
2
+ import * as React from "react";
3
+ import { Button } from "@/ui/components/ui/button";
4
+ import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem } from "@/ui/components/ui/command";
5
+ import { Popover, PopoverContent, PopoverTrigger } from "@/ui/components/ui/popover";
6
+ import { Tooltip, TooltipContent, TooltipTrigger } from "@/ui/components/ui/tooltip";
7
+ import { cn } from "@/ui/lib/utils";
8
+
9
+ export type ComboboxOption = {
10
+ value: string;
11
+ label: string;
12
+ disabled?: boolean;
13
+ tooltip?: string;
14
+ };
15
+
16
+ type ComboboxProps = {
17
+ options: ComboboxOption[];
18
+ value?: string;
19
+ onValueChange?: (value: string) => void;
20
+ placeholder?: string;
21
+ emptyText?: string;
22
+ className?: string;
23
+ disabled?: boolean;
24
+ loading?: boolean;
25
+ onSearch?: (value: string) => void;
26
+ selectedLabel?: string;
27
+ };
28
+
29
+ export function Combobox({
30
+ options,
31
+ value,
32
+ onValueChange,
33
+ placeholder = "Select an option",
34
+ emptyText = "No results found.",
35
+ className,
36
+ disabled,
37
+ loading,
38
+ onSearch,
39
+ selectedLabel,
40
+ }: ComboboxProps) {
41
+ const [open, setOpen] = React.useState(false);
42
+
43
+ return (
44
+ <Popover open={open} onOpenChange={setOpen}>
45
+ <PopoverTrigger asChild>
46
+ <Button
47
+ variant="outline"
48
+ role="combobox"
49
+ aria-expanded={open}
50
+ className={cn("w-full justify-between", className)}
51
+ disabled={disabled}
52
+ >
53
+ {value ? selectedLabel || options.find((option) => option.value === value)?.label : placeholder}
54
+ <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
55
+ </Button>
56
+ </PopoverTrigger>
57
+ <PopoverContent className="w-full min-w-[var(--radix-popover-trigger-width)] p-0">
58
+ <Command shouldFilter={false}>
59
+ <CommandInput placeholder={placeholder} onValueChange={onSearch} className="h-9" disabled={disabled} />
60
+ <CommandEmpty>{loading ? "Loading..." : emptyText}</CommandEmpty>
61
+ <CommandGroup>
62
+ {options.map((option) => {
63
+ const item = (
64
+ <CommandItem
65
+ key={option.value}
66
+ value={option.value}
67
+ disabled={option.disabled}
68
+ onSelect={() => {
69
+ if (option.disabled) return;
70
+ onValueChange?.(option.value);
71
+ setOpen(false);
72
+ }}
73
+ className={cn(option.disabled && "cursor-not-allowed opacity-50")}
74
+ >
75
+ <Check className={cn("mr-2 h-4 w-4", value === option.value ? "opacity-100" : "opacity-0")} />
76
+ {option.label}
77
+ </CommandItem>
78
+ );
79
+
80
+ if (option.disabled && option.tooltip) {
81
+ return (
82
+ <Tooltip key={option.value}>
83
+ <TooltipTrigger asChild>{item}</TooltipTrigger>
84
+ <TooltipContent>{option.tooltip}</TooltipContent>
85
+ </Tooltip>
86
+ );
87
+ }
88
+
89
+ return item;
90
+ })}
91
+ </CommandGroup>
92
+ </Command>
93
+ </PopoverContent>
94
+ </Popover>
95
+ );
96
+ }