@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,209 @@
1
+ import { Check, Crown, Sparkles, Zap } from "lucide-react";
2
+
3
+ import { type GatedFeature, useWLSubscription, type WhiteLabelPlan } from "../../providers/wl-subscription-provider";
4
+ import { Button } from "../ui/button";
5
+ import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "../ui/dialog";
6
+
7
+ type UpgradeModalProps = {
8
+ isOpen: boolean;
9
+ onClose: () => void;
10
+ /** Optional feature that triggered the modal */
11
+ feature?: GatedFeature;
12
+ /** Optional callback when upgrade is clicked */
13
+ onUpgrade?: (planSlug: string) => void;
14
+ };
15
+
16
+ /**
17
+ * UpgradeModal component
18
+ *
19
+ * Shows available plans and allows users to upgrade their subscription.
20
+ * Highlights the feature that triggered the modal and which plans include it.
21
+ */
22
+ export function UpgradeModal({ isOpen, onClose, feature, onUpgrade }: UpgradeModalProps) {
23
+ const { plan: currentPlan, availablePlans } = useWLSubscription();
24
+
25
+ // Sort plans by display order
26
+ const sortedPlans = [...availablePlans].sort((a, b) => a.display_order - b.display_order);
27
+
28
+ // Find the minimum plan that includes the requested feature
29
+ const minimumPlanForFeature = feature
30
+ ? sortedPlans.find((p) => p.features.length === 0 || p.features.includes(feature))
31
+ : null;
32
+
33
+ const handleUpgrade = (planSlug: string) => {
34
+ if (onUpgrade) {
35
+ onUpgrade(planSlug);
36
+ }
37
+ // In the future, this would redirect to Stripe Checkout
38
+ // For now, just close the modal
39
+ onClose();
40
+ };
41
+
42
+ return (
43
+ <Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>
44
+ <DialogContent className="max-w-3xl">
45
+ <DialogHeader>
46
+ <DialogTitle className="flex items-center gap-2">
47
+ <Sparkles className="h-5 w-5 text-primary" />
48
+ Upgrade Your Plan
49
+ </DialogTitle>
50
+ <DialogDescription>
51
+ {feature
52
+ ? `Unlock ${getFeatureDisplayName(feature)} and more with an upgraded plan.`
53
+ : "Get access to more features and higher limits."}
54
+ </DialogDescription>
55
+ </DialogHeader>
56
+
57
+ <div className="grid gap-4 py-4 md:grid-cols-3">
58
+ {sortedPlans.map((plan) => (
59
+ <PlanCard
60
+ key={plan.id}
61
+ plan={plan}
62
+ isCurrentPlan={plan.slug === currentPlan?.slug}
63
+ isRecommended={minimumPlanForFeature?.slug === plan.slug}
64
+ highlightFeature={feature}
65
+ onSelect={() => handleUpgrade(plan.slug)}
66
+ />
67
+ ))}
68
+ </div>
69
+
70
+ {sortedPlans.length === 0 && (
71
+ <p className="py-8 text-center text-muted-foreground">
72
+ No upgrade plans available. Contact support for more information.
73
+ </p>
74
+ )}
75
+ </DialogContent>
76
+ </Dialog>
77
+ );
78
+ }
79
+
80
+ // ============================================
81
+ // PLAN CARD
82
+ // ============================================
83
+
84
+ type PlanCardProps = {
85
+ plan: WhiteLabelPlan;
86
+ isCurrentPlan: boolean;
87
+ isRecommended: boolean;
88
+ highlightFeature?: GatedFeature;
89
+ onSelect: () => void;
90
+ };
91
+
92
+ function PlanCard({ plan, isCurrentPlan, isRecommended, highlightFeature, onSelect }: PlanCardProps) {
93
+ const priceDisplay = plan.is_free
94
+ ? "Free"
95
+ : plan.base_price_cents
96
+ ? `${(plan.base_price_cents / 100).toFixed(0)}/${plan.billing_interval === "yearly" ? "yr" : "mo"}`
97
+ : "Contact us";
98
+
99
+ const documentsLimit = plan.limits?.documents_per_month ?? "Unlimited";
100
+
101
+ return (
102
+ <div
103
+ className={`relative flex flex-col rounded-lg border p-4 ${
104
+ isRecommended ? "border-primary ring-2 ring-primary" : "border-border"
105
+ } ${isCurrentPlan ? "bg-muted/50" : ""}`}
106
+ >
107
+ {isRecommended && (
108
+ <div className="absolute -top-3 left-1/2 -translate-x-1/2 rounded-full bg-primary px-3 py-1 font-medium text-primary-foreground text-xs">
109
+ Recommended
110
+ </div>
111
+ )}
112
+
113
+ <div className="mb-2 flex items-center gap-2">
114
+ <PlanIcon slug={plan.slug} />
115
+ <h3 className="font-semibold">{plan.name}</h3>
116
+ </div>
117
+
118
+ <div className="mb-1 font-bold text-2xl">
119
+ {plan.is_free ? "" : "€"}
120
+ {priceDisplay}
121
+ </div>
122
+
123
+ <p className="mb-4 text-muted-foreground text-sm">{documentsLimit} documents/month</p>
124
+
125
+ <ul className="mb-4 flex-1 space-y-2">
126
+ {getPlanFeatures(plan.slug).map((featureText) => (
127
+ <li
128
+ key={featureText}
129
+ className={`flex items-center gap-2 text-sm ${
130
+ highlightFeature && featureText.toLowerCase().includes(highlightFeature.replace("_", " "))
131
+ ? "font-medium text-primary"
132
+ : ""
133
+ }`}
134
+ >
135
+ <Check className="h-4 w-4 flex-shrink-0 text-green-500" />
136
+ {featureText}
137
+ </li>
138
+ ))}
139
+ </ul>
140
+
141
+ <Button
142
+ variant={isCurrentPlan ? "outline" : isRecommended ? "default" : "secondary"}
143
+ className="w-full"
144
+ disabled={isCurrentPlan}
145
+ onClick={onSelect}
146
+ >
147
+ {isCurrentPlan ? "Current Plan" : `Upgrade to ${plan.name}`}
148
+ </Button>
149
+ </div>
150
+ );
151
+ }
152
+
153
+ // ============================================
154
+ // HELPERS
155
+ // ============================================
156
+
157
+ function PlanIcon({ slug }: { slug: string }) {
158
+ switch (slug) {
159
+ case "free":
160
+ return <Zap className="h-5 w-5 text-muted-foreground" />;
161
+ case "starter":
162
+ return <Sparkles className="h-5 w-5 text-blue-500" />;
163
+ case "advanced":
164
+ return <Crown className="h-5 w-5 text-amber-500" />;
165
+ default:
166
+ return <Zap className="h-5 w-5 text-muted-foreground" />;
167
+ }
168
+ }
169
+
170
+ function getFeatureDisplayName(feature: GatedFeature): string {
171
+ const names: Record<GatedFeature, string> = {
172
+ furs: "FURS Fiscalization",
173
+ eslog: "eSlog Export",
174
+ recurring: "Recurring Invoices",
175
+ email_sending: "Email Sending",
176
+ custom_templates: "Custom Templates",
177
+ api_access: "API Access",
178
+ webhooks: "Webhooks",
179
+ priority_support: "Priority Support",
180
+ };
181
+ return names[feature] || feature;
182
+ }
183
+
184
+ function getPlanFeatures(slug: string): string[] {
185
+ switch (slug) {
186
+ case "free":
187
+ return ["Basic invoicing", "Estimates & quotes", "Customer management", "PDF export"];
188
+ case "starter":
189
+ return [
190
+ "Everything in Free",
191
+ "FURS fiscalization",
192
+ "eSlog export",
193
+ "Recurring invoices",
194
+ "Email sending",
195
+ "100 docs/month",
196
+ ];
197
+ case "advanced":
198
+ return [
199
+ "Everything in Starter",
200
+ "Custom templates",
201
+ "API access",
202
+ "Webhooks",
203
+ "Priority support",
204
+ "2,500 docs/month",
205
+ ];
206
+ default:
207
+ return [];
208
+ }
209
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * This file is the entry point for the React app, it sets up the root
3
+ * element and renders the App component to the DOM.
4
+ *
5
+ * It is included in `src/index.html`.
6
+ */
7
+
8
+ import { StrictMode } from "react";
9
+ import { createRoot } from "react-dom/client";
10
+
11
+ import { App } from "./app";
12
+
13
+ const elem = document.getElementById("root")!;
14
+ const app = (
15
+ <StrictMode>
16
+ <App />
17
+ </StrictMode>
18
+ );
19
+
20
+ if (import.meta.hot) {
21
+ // With hot module reloading, `import.meta.hot.data` is persisted.
22
+ import.meta.hot.data.root ??= createRoot(elem);
23
+ const root = import.meta.hot.data.root;
24
+ root.render(app);
25
+ } else {
26
+ // The hot module reloading API is not available in production.
27
+ createRoot(elem).render(app);
28
+ }
@@ -0,0 +1,265 @@
1
+ import { execSync } from "node:child_process";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+
5
+ const SCHEMAS_DIR = "./src/generated/schemas";
6
+ const GENERATED_DIR = "./generated";
7
+
8
+ type SchemaGroups = {
9
+ [key: string]: string[];
10
+ };
11
+
12
+ // Helper to get group name from schema name
13
+ const getGroupName = (schemaName: string): string => {
14
+ // Remove _Body and extract the resource name (e.g., Customer from createCustomer)
15
+ return schemaName.replace(/(create|patch|update|delete)([A-Z][a-zA-Z]+)_Body/, "$2").toLowerCase();
16
+ };
17
+
18
+ // Helper to format operation name
19
+ const formatOperationName = (operationType: string, resourceName: string): string => {
20
+ // Convert to proper case format (e.g., createCustomer)
21
+ return `${operationType}${resourceName}`;
22
+ };
23
+
24
+ async function main() {
25
+ // Ensure directories exist
26
+ await fs.mkdir(SCHEMAS_DIR, { recursive: true });
27
+ await fs.mkdir(GENERATED_DIR, { recursive: true });
28
+
29
+ // Generate initial schemas with openapi-zod-client
30
+ try {
31
+ const openApiPath = path.resolve(__dirname, "../../../apps/api/openapi.json");
32
+ execSync(
33
+ `bunx openapi-zod-client ${openApiPath} ` +
34
+ "--output " +
35
+ GENERATED_DIR +
36
+ "/schemas.ts " +
37
+ "--export-schemas " +
38
+ "--group-strategy none " +
39
+ "--with-docs",
40
+ { stdio: "inherit" },
41
+ );
42
+ } catch (_error) {
43
+ console.error("Failed to generate schemas.");
44
+ process.exit(1);
45
+ }
46
+
47
+ // Read and parse the generated file
48
+ let content = await fs.readFile("./generated/schemas.ts", "utf-8");
49
+
50
+ // Fix common generation issues
51
+ content = content.replace(/\.prefault\(/g, ".default(");
52
+
53
+ // Fix Zod v3 record syntax - z.record(z.string()) -> z.record(z.string(), z.any())
54
+ content = content.replace(/z\.record\(z\.string\(\)\)/g, "z.record(z.string(), z.any())");
55
+
56
+ // Remove .default({}) from metadata fields to keep them truly optional
57
+ // When using .optional().default({}), Zod infers the type as required since it always has a value after parsing
58
+ // We want metadata to be optional in the form type to match SDK types
59
+ // Handle both single-line and multi-line patterns (with optional whitespace/newlines between)
60
+ content = content.replace(/\.optional\(\)\s*\.default\(\{\}\)/gs, ".optional()");
61
+
62
+ // Keep nullable types as-is (z.union([z.string(), z.null()]) stays nullable)
63
+ // This matches SDK types which also use | null
64
+
65
+ // Replace undefined named schema references with z.any().optional()
66
+ // These are schemas referenced by name (like TaxRules, EntityBankAccount) that aren't defined in this file
67
+ content = content.replace(/: TaxRules,/g, ": z.any().optional(),");
68
+ content = content.replace(/: EuTaxRules,/g, ": z.any().optional(),");
69
+ content = content.replace(/z\.array\(EntityBankAccount\)/g, "z.array(z.any())");
70
+
71
+ // Extract just the schema definitions
72
+ const schemaMatch = content.match(/export const schemas = {([^}]+)}/s);
73
+ if (!schemaMatch) {
74
+ throw new Error("Could not find schema definitions in generated file");
75
+ }
76
+ const schemaSection = schemaMatch[1];
77
+
78
+ // Helper function to find schema dependencies (schemas referenced by other schemas)
79
+ function findSchemaDependencies(schemaName: string, fullContent: string): string[] {
80
+ const dependencies: string[] = [];
81
+ const schemaDefMatch = fullContent.match(new RegExp(`const ${schemaName} = ([^;]+);`, "s"));
82
+ if (schemaDefMatch) {
83
+ // Find references to other const schemas (e.g., CreateFursInvoiceData.optional())
84
+ const constRefs = schemaDefMatch[1].match(/\b([A-Z][a-zA-Z0-9]+)(?:\.optional\(\)|\.nullable\(\))?/g);
85
+ if (constRefs) {
86
+ for (const ref of constRefs) {
87
+ const cleanRef = ref.replace(/\.(optional|nullable)\(\)/, "");
88
+ // Check if it's actually a schema definition in the file
89
+ if (fullContent.includes(`const ${cleanRef} = z.`)) {
90
+ dependencies.push(cleanRef);
91
+ }
92
+ }
93
+ }
94
+ }
95
+ return dependencies;
96
+ }
97
+
98
+ // Parse schema names and group them
99
+ const schemasByGroup = schemaSection
100
+ .split(",\n")
101
+ .map((line) => line.trim())
102
+ .filter((line) => line.includes("_Body"))
103
+ .map((line) => line.split(":")[0].trim())
104
+ .reduce<SchemaGroups>((groups, schemaName) => {
105
+ const groupName = getGroupName(schemaName);
106
+ if (!groups[groupName]) {
107
+ groups[groupName] = [];
108
+ }
109
+
110
+ // Add the main schema
111
+ groups[groupName].push(schemaName);
112
+
113
+ // Find and add dependencies
114
+ const deps = findSchemaDependencies(schemaName, content);
115
+ const queue = [...deps];
116
+ const processed = new Set(deps);
117
+
118
+ while (queue.length > 0) {
119
+ const currentDep = queue.shift()!;
120
+ if (!groups[groupName].includes(currentDep)) {
121
+ groups[groupName].push(currentDep);
122
+ }
123
+
124
+ const nestedDeps = findSchemaDependencies(currentDep, content);
125
+ for (const nested of nestedDeps) {
126
+ if (!processed.has(nested)) {
127
+ processed.add(nested);
128
+ queue.push(nested);
129
+ }
130
+ }
131
+ }
132
+
133
+ return groups;
134
+ }, {});
135
+
136
+ // Create files for each group
137
+ for (const [groupName, schemaNames] of Object.entries(schemasByGroup)) {
138
+ // Separate dependencies from operation schemas
139
+ const dependencies = schemaNames.filter((name) => !name.includes("_Body")).reverse();
140
+ const operations = schemaNames.filter((name) => name.includes("_Body"));
141
+
142
+ // Process dependencies first, then operations
143
+ const orderedNames = [...dependencies, ...operations];
144
+
145
+ const schemas = orderedNames
146
+ .map((schemaName) => {
147
+ // Check if this is an operation schema or a dependency
148
+ const operationMatch = schemaName.match(/(create|patch|update|delete|register|upload|send|preview|render)/i);
149
+ const isOperationSchema = operationMatch && schemaName.includes("_Body");
150
+
151
+ if (!isOperationSchema) {
152
+ // This is a dependency schema, just extract its definition
153
+ const schemaDefinitionMatch = content.match(new RegExp(`const ${schemaName} = ([^;]+);`, "s"));
154
+ if (!schemaDefinitionMatch) {
155
+ console.warn(`Warning: Could not find dependency schema definition for ${schemaName}`);
156
+ return null;
157
+ }
158
+
159
+ return `
160
+ // Dependency schema for ${groupName}
161
+ const ${schemaName} = ${schemaDefinitionMatch[1]};
162
+ `;
163
+ }
164
+
165
+ // Handle operation schemas
166
+ const resourceMatch = schemaName.match(/[A-Z][a-zA-Z]+_Body/);
167
+ if (!resourceMatch) {
168
+ console.warn(`Warning: Invalid schema name format: ${schemaName}`);
169
+ return null;
170
+ }
171
+
172
+ const operationType = operationMatch[1].toLowerCase();
173
+ const resourceName = resourceMatch[0].replace("_Body", "");
174
+ const operationName = formatOperationName(operationType, resourceName);
175
+
176
+ const schemaDefinitionMatch = content.match(new RegExp(`const ${schemaName} = ([^;]+);`, "s"));
177
+ if (!schemaDefinitionMatch) {
178
+ console.warn(`Warning: Could not find schema definition for ${schemaName}`);
179
+ return null;
180
+ }
181
+
182
+ let schemaDefinition = schemaDefinitionMatch[1];
183
+
184
+ // Post-process: Add character limits to name and description fields
185
+ // Add max length validation from API schema (only if not already present)
186
+ schemaDefinition = schemaDefinition.replace(
187
+ /name: z\.string\(\)\.min\(1\)\.max\(100\)(?!\.max)/g,
188
+ 'name: z.string().min(1).max(100, "Name must not exceed 100 characters")',
189
+ );
190
+ // Add description character limit - handles both union and nullable variants
191
+ schemaDefinition = schemaDefinition.replace(
192
+ /description: z\.union\(\[z\.string\(\)(?!\.max)/g,
193
+ 'description: z.union([z.string().max(4000, "Description must not exceed 4000 characters")',
194
+ );
195
+
196
+ // Add min length to country
197
+ schemaDefinition = schemaDefinition.replace(/country: z\.string\(\)(?!\.min)/g, "country: z.string().min(1)");
198
+
199
+ return `
200
+ // Schema for ${operationType} ${resourceName.toLowerCase()} operation
201
+ const ${operationName}SchemaDefinition = ${schemaDefinition};
202
+
203
+ // Type for ${operationType} ${resourceName.toLowerCase()} operation
204
+ export type ${operationName.slice(0, 1).toUpperCase() + operationName.slice(1)}Schema = z.infer<typeof ${operationName}SchemaDefinition>;
205
+ `;
206
+ })
207
+ .filter((schema) => schema !== null) // Remove null entries
208
+ .join("\n");
209
+
210
+ const exports = schemaNames
211
+ .filter((schemaName) => {
212
+ // Only export operation schemas, not dependencies
213
+ const operationMatch = schemaName.match(/(create|patch|update|delete|register|upload|send|preview|render)/i);
214
+ return operationMatch !== null && schemaName.includes("_Body");
215
+ })
216
+ .map((schemaName) => {
217
+ const operationMatch = schemaName.match(/(create|patch|update|delete|register|upload|send|preview|render)/i);
218
+ const resourceMatch = schemaName.match(/[A-Z][a-zA-Z]+_Body/);
219
+
220
+ if (!operationMatch || !resourceMatch) {
221
+ throw new Error(`Invalid schema name format: ${schemaName}`);
222
+ }
223
+
224
+ const operationType = operationMatch[1].toLowerCase();
225
+ const resourceName = resourceMatch[0].replace("_Body", "");
226
+ const operationName = formatOperationName(operationType, resourceName);
227
+ return `export const ${operationName}Schema = ${operationName}SchemaDefinition;`;
228
+ })
229
+ .join("\n");
230
+
231
+ const schemaContent = `/**
232
+ * This file was automatically generated using 'bun generate-schemas'.
233
+ * Do not edit this file manually. To update, run the generator again.
234
+ * @generated
235
+ */
236
+
237
+ import { z } from 'zod';
238
+
239
+ // Schemas for ${groupName} endpoints
240
+ ${schemas}
241
+ ${exports}
242
+ `;
243
+
244
+ await fs.writeFile(path.join(SCHEMAS_DIR, `${groupName}.ts`), schemaContent);
245
+ }
246
+
247
+ // Create index file
248
+ const indexContent = `/**
249
+ * This file was automatically generated using 'bun generate-schemas'.
250
+ * Do not edit this file manually. To update, run the generator again.
251
+ * @generated
252
+ */
253
+
254
+ ${Object.keys(schemasByGroup)
255
+ .map((groupName) => `export * from './${groupName}';`)
256
+ .join("\n")}
257
+ `;
258
+
259
+ await fs.writeFile(path.join(SCHEMAS_DIR, "index.ts"), indexContent);
260
+
261
+ // Clean up temporary files
262
+ await fs.unlink(`${GENERATED_DIR}/schemas.ts`);
263
+ }
264
+
265
+ main().catch(console.error);
@@ -0,0 +1,177 @@
1
+ /**
2
+ * This file was automatically generated using 'bun generate-schemas'.
3
+ * Do not edit this file manually. To update, run the generator again.
4
+ * @generated
5
+ */
6
+
7
+ import { z } from 'zod';
8
+
9
+ // Schemas for advanceinvoice endpoints
10
+
11
+ // Dependency schema for advanceinvoice
12
+ const LineDiscount = z.object({
13
+ value: z.number().gte(0),
14
+ type: z.enum(["percent", "amount"]).optional().default("percent"),
15
+ });
16
+
17
+
18
+ // Schema for create advanceinvoice operation
19
+ const createAdvanceInvoiceSchemaDefinition = z.object({
20
+ is_draft: z.boolean().optional(),
21
+ date: z
22
+ .string()
23
+ .regex(/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d{3})?Z?)?$/)
24
+ .optional(),
25
+ issuer: z
26
+ .object({
27
+ name: z.union([z.string(), z.null()]),
28
+ email: z.union([z.string(), z.null()]),
29
+ address: z.union([z.string(), z.null()]),
30
+ address_2: z.union([z.string(), z.null()]),
31
+ post_code: z.union([z.string(), z.null()]),
32
+ city: z.union([z.string(), z.null()]),
33
+ state: z.union([z.string(), z.null()]),
34
+ country: z.union([z.string(), z.null()]),
35
+ country_code: z.union([z.string(), z.null()]),
36
+ tax_number: z.union([z.string(), z.null()]),
37
+ bank_account: z.union([
38
+ z
39
+ .object({
40
+ type: z
41
+ .enum(["iban", "us_domestic", "uk_domestic", "other"])
42
+ .default("iban"),
43
+ name: z.string(),
44
+ bank_name: z.string(),
45
+ iban: z.string(),
46
+ account_number: z.string(),
47
+ bic: z.string(),
48
+ routing_number: z.string(),
49
+ sort_code: z.string(),
50
+ })
51
+ .partial()
52
+ .passthrough(),
53
+ z.null(),
54
+ ]),
55
+ })
56
+ .partial()
57
+ .passthrough()
58
+ .optional(),
59
+ customer_id: z.union([z.string(), z.null()]).optional(),
60
+ customer: z
61
+ .union([
62
+ z
63
+ .object({
64
+ name: z.union([z.string(), z.null()]),
65
+ email: z.union([z.string(), z.null()]),
66
+ address: z.union([z.string(), z.null()]),
67
+ address_2: z.union([z.string(), z.null()]),
68
+ post_code: z.union([z.string(), z.null()]),
69
+ city: z.union([z.string(), z.null()]),
70
+ state: z.union([z.string(), z.null()]),
71
+ country: z.union([z.string(), z.null()]),
72
+ country_code: z.union([z.string(), z.null()]),
73
+ tax_number: z.union([z.string(), z.null()]),
74
+ bank_account: z.union([
75
+ z
76
+ .object({
77
+ type: z
78
+ .enum(["iban", "us_domestic", "uk_domestic", "other"])
79
+ .default("iban"),
80
+ name: z.string(),
81
+ bank_name: z.string(),
82
+ iban: z.string(),
83
+ account_number: z.string(),
84
+ bic: z.string(),
85
+ routing_number: z.string(),
86
+ sort_code: z.string(),
87
+ })
88
+ .partial()
89
+ .passthrough(),
90
+ z.null(),
91
+ ]),
92
+ save_customer: z.boolean().default(true),
93
+ })
94
+ .partial()
95
+ .passthrough(),
96
+ z.null(),
97
+ ])
98
+ .optional(),
99
+ note: z.union([z.string(), z.null()]).optional(),
100
+ payment_terms: z.union([z.string(), z.null()]).optional(),
101
+ currency_code: z.string().max(3).optional(),
102
+ metadata: z.union([z.record(z.string(), z.any()), z.null()]).optional(),
103
+ date_due: z.union([z.string(), z.null()]).optional(),
104
+ date_service: z.union([z.string(), z.null()]).optional(),
105
+ date_service_to: z.union([z.string(), z.null()]).optional(),
106
+ items: z
107
+ .array(
108
+ z.object({
109
+ name: z.string().min(1),
110
+ description: z.union([z.string().max(4000, "Description must not exceed 4000 characters"), z.null()]).optional(),
111
+ price: z.number().optional(),
112
+ gross_price: z.number().optional(),
113
+ quantity: z.number().gte(-140737488355328).lte(140737488355327),
114
+ unit: z.union([z.string(), z.null()]).optional(),
115
+ taxes: z
116
+ .array(
117
+ z
118
+ .object({
119
+ rate: z.number(),
120
+ tax_id: z.string(),
121
+ classification: z.string(),
122
+ reverse_charge: z.boolean(),
123
+ amount: z.number(),
124
+ })
125
+ .partial()
126
+ )
127
+ .optional(),
128
+ discounts: z.array(LineDiscount).max(5).optional(),
129
+ metadata: z
130
+ .union([
131
+ z.string(),
132
+ z.number(),
133
+ z.boolean(),
134
+ z.null(),
135
+ z.object({}).partial().passthrough(),
136
+ z.array(z.unknown()),
137
+ z.null(),
138
+ ])
139
+ .optional(),
140
+ })
141
+ )
142
+ .min(1),
143
+ linked_documents: z.array(z.string().min(1)).optional(),
144
+ payment: z
145
+ .union([
146
+ z.object({
147
+ advance_invoice_id: z.union([z.string(), z.null()]).optional(),
148
+ amount: z.number().gt(0).optional(),
149
+ type: z.string().max(20),
150
+ date: z.string().optional(),
151
+ reference: z.union([z.string(), z.null()]).optional(),
152
+ note: z.union([z.string(), z.null()]).optional(),
153
+ metadata: z.union([z.record(z.string(), z.any()), z.null()]).optional(),
154
+ }),
155
+ z.null(),
156
+ ])
157
+ .optional(),
158
+ furs: z
159
+ .union([
160
+ z
161
+ .object({
162
+ business_premise_name: z.string().min(1),
163
+ electronic_device_name: z.string().min(1),
164
+ operator_tax_number: z.string(),
165
+ operator_label: z.string(),
166
+ skip: z.boolean(),
167
+ })
168
+ .partial(),
169
+ z.null(),
170
+ ])
171
+ .optional(),
172
+ });
173
+
174
+ // Type for create advanceinvoice operation
175
+ export type CreateAdvanceInvoiceSchema = z.infer<typeof createAdvanceInvoiceSchemaDefinition>;
176
+
177
+ export const createAdvanceInvoiceSchema = createAdvanceInvoiceSchemaDefinition;