@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,164 @@
1
+ import type { CreateInvoiceRequest } from "@spaceinvoices/js-sdk";
2
+
3
+ type DemoInvoiceData = Partial<CreateInvoiceRequest>;
4
+
5
+ interface LocaleDemoData {
6
+ customer: {
7
+ name: string;
8
+ address: string;
9
+ city: string;
10
+ post_code: string;
11
+ country: string;
12
+ };
13
+ items: Array<{
14
+ name: string;
15
+ description?: string;
16
+ quantity: number;
17
+ price: number;
18
+ }>;
19
+ note: string;
20
+ }
21
+
22
+ const demoDataByLocale: Record<string, LocaleDemoData> = {
23
+ "en-US": {
24
+ customer: {
25
+ name: "Acme Corporation",
26
+ address: "123 Business Avenue",
27
+ city: "New York",
28
+ post_code: "10001",
29
+ country: "United States",
30
+ },
31
+ items: [
32
+ {
33
+ name: "Professional Consulting",
34
+ description: "Strategic business consulting services",
35
+ quantity: 8,
36
+ price: 150.0,
37
+ },
38
+ { name: "Project Management", description: "End-to-end project coordination", quantity: 1, price: 500.0 },
39
+ ],
40
+ note: "Thank you for your business. Payment is due within 30 days.",
41
+ },
42
+ "sl-SI": {
43
+ customer: {
44
+ name: "Podjetje d.o.o.",
45
+ address: "Slovenska cesta 123",
46
+ city: "Ljubljana",
47
+ post_code: "1000",
48
+ country: "Slovenija",
49
+ },
50
+ items: [
51
+ { name: "Poslovno svetovanje", description: "Strateško poslovno svetovanje", quantity: 8, price: 120.0 },
52
+ { name: "Vodenje projekta", description: "Celostna koordinacija projekta", quantity: 1, price: 400.0 },
53
+ ],
54
+ note: "Hvala za zaupanje. Rok plačila je 30 dni.",
55
+ },
56
+ "de-DE": {
57
+ customer: {
58
+ name: "Musterfirma GmbH",
59
+ address: "Musterstraße 123",
60
+ city: "Berlin",
61
+ post_code: "10115",
62
+ country: "Deutschland",
63
+ },
64
+ items: [
65
+ { name: "Unternehmensberatung", description: "Strategische Geschäftsberatung", quantity: 8, price: 140.0 },
66
+ { name: "Projektmanagement", description: "Umfassende Projektkoordination", quantity: 1, price: 450.0 },
67
+ ],
68
+ note: "Vielen Dank für Ihr Vertrauen. Zahlungsziel: 30 Tage.",
69
+ },
70
+ "fr-FR": {
71
+ customer: {
72
+ name: "Société Exemple SARL",
73
+ address: "123 Rue du Commerce",
74
+ city: "Paris",
75
+ post_code: "75001",
76
+ country: "France",
77
+ },
78
+ items: [
79
+ { name: "Conseil professionnel", description: "Services de conseil stratégique", quantity: 8, price: 130.0 },
80
+ { name: "Gestion de projet", description: "Coordination de projet complète", quantity: 1, price: 480.0 },
81
+ ],
82
+ note: "Merci pour votre confiance. Paiement à 30 jours.",
83
+ },
84
+ "es-ES": {
85
+ customer: {
86
+ name: "Empresa Ejemplo S.L.",
87
+ address: "Calle Comercio 123",
88
+ city: "Madrid",
89
+ post_code: "28001",
90
+ country: "España",
91
+ },
92
+ items: [
93
+ {
94
+ name: "Consultoría profesional",
95
+ description: "Servicios de consultoría estratégica",
96
+ quantity: 8,
97
+ price: 125.0,
98
+ },
99
+ { name: "Gestión de proyectos", description: "Coordinación integral de proyectos", quantity: 1, price: 460.0 },
100
+ ],
101
+ note: "Gracias por su confianza. Pago a 30 días.",
102
+ },
103
+ "it-IT": {
104
+ customer: {
105
+ name: "Azienda Esempio S.r.l.",
106
+ address: "Via del Commercio 123",
107
+ city: "Roma",
108
+ post_code: "00100",
109
+ country: "Italia",
110
+ },
111
+ items: [
112
+ { name: "Consulenza professionale", description: "Servizi di consulenza strategica", quantity: 8, price: 135.0 },
113
+ { name: "Gestione progetti", description: "Coordinamento completo del progetto", quantity: 1, price: 470.0 },
114
+ ],
115
+ note: "Grazie per la fiducia. Pagamento entro 30 giorni.",
116
+ },
117
+ };
118
+
119
+ /**
120
+ * Get demo invoice data for template preview based on locale
121
+ */
122
+ export function getDemoInvoiceData(locale: string): DemoInvoiceData {
123
+ // Normalize locale (e.g., "en" -> "en-US", "sl" -> "sl-SI")
124
+ const normalizedLocale = normalizeLocale(locale);
125
+ const data = demoDataByLocale[normalizedLocale] || demoDataByLocale["en-US"];
126
+
127
+ const today = new Date();
128
+ const dueDate = new Date(today);
129
+ dueDate.setDate(dueDate.getDate() + 30);
130
+
131
+ return {
132
+ date: today.toISOString(),
133
+ date_due: dueDate.toISOString(),
134
+ customer: data.customer,
135
+ items: data.items.map((item) => ({
136
+ name: item.name,
137
+ description: item.description,
138
+ quantity: item.quantity,
139
+ price: item.price,
140
+ taxes: [{ rate: 22 }],
141
+ })),
142
+ note: data.note,
143
+ };
144
+ }
145
+
146
+ function normalizeLocale(locale: string): string {
147
+ const mapping: Record<string, string> = {
148
+ en: "en-US",
149
+ sl: "sl-SI",
150
+ de: "de-DE",
151
+ fr: "fr-FR",
152
+ es: "es-ES",
153
+ it: "it-IT",
154
+ };
155
+
156
+ // If already full locale, return as-is if supported
157
+ if (demoDataByLocale[locale]) {
158
+ return locale;
159
+ }
160
+
161
+ // Try to match short code
162
+ const shortCode = locale.split("-")[0].toLowerCase();
163
+ return mapping[shortCode] || "en-US";
164
+ }
@@ -0,0 +1,2 @@
1
+ export { getDemoInvoiceData } from "./demo-invoice-data";
2
+ export { PdfTemplateCards, type PdfTemplateCardsProps } from "./pdf-template-cards";
@@ -0,0 +1,18 @@
1
+ export default {
2
+ "PDF Template": "PDF-Vorlage",
3
+ "Choose the design template for your invoices and documents":
4
+ "Wählen Sie die Design-Vorlage für Ihre Rechnungen und Dokumente",
5
+ Preview: "Vorschau",
6
+ Template: "Vorlage",
7
+ Modern: "Modern",
8
+ "Modern template description": "Klares, professionelles Design für die meisten Unternehmen geeignet",
9
+ Classic: "Klassisch",
10
+ "Classic template description": "Traditioneller Rechnungsstil mit Serifenschriften und Rahmen",
11
+ Minimal: "Minimal",
12
+ "Minimal template description": "Typografie-fokussiertes Design mit klarer Ästhetik",
13
+ Fashion: "Mode",
14
+ "Fashion template description": "Redaktioneller Stil mit eleganten Überschriften für kreative Unternehmen",
15
+ "Save Template": "Vorlage speichern",
16
+ "Template saved successfully": "Vorlage erfolgreich gespeichert",
17
+ "Failed to save template": "Vorlage konnte nicht gespeichert werden",
18
+ } as const;
@@ -0,0 +1,18 @@
1
+ export default {
2
+ "PDF Template": "PDF predloga",
3
+ "Choose the design template for your invoices and documents":
4
+ "Izberite oblikovno predlogo za vaše račune in dokumente",
5
+ Preview: "Predogled",
6
+ Template: "Predloga",
7
+ Modern: "Moderna",
8
+ "Modern template description": "Čista, profesionalna oblika primerna za večino podjetij",
9
+ Classic: "Klasična",
10
+ "Classic template description": "Tradicionalna oblika računa s serifnimi pisavami in okvirji",
11
+ Minimal: "Minimalistična",
12
+ "Minimal template description": "Tipografsko osredotočena oblika s čisto estetiko",
13
+ Fashion: "Modna",
14
+ "Fashion template description": "Uredniški slog z elegantnimi naslovi za kreativna podjetja",
15
+ "Save Template": "Shrani predlogo",
16
+ "Template saved successfully": "Predloga uspešno shranjena",
17
+ "Failed to save template": "Shranjevanje predloge ni uspelo",
18
+ } as const;
@@ -0,0 +1,49 @@
1
+ import { Check } from "lucide-react";
2
+ import type { PdfTemplateId } from "@/ui/components/documents/create/live-preview";
3
+ import { cn } from "@/ui/lib/utils";
4
+
5
+ const TEMPLATES: Array<{
6
+ id: PdfTemplateId;
7
+ nameKey: string;
8
+ descriptionKey: string;
9
+ }> = [
10
+ { id: "modern", nameKey: "Modern", descriptionKey: "Modern template description" },
11
+ { id: "classic", nameKey: "Classic", descriptionKey: "Classic template description" },
12
+ { id: "minimal", nameKey: "Minimal", descriptionKey: "Minimal template description" },
13
+ { id: "fashion", nameKey: "Fashion", descriptionKey: "Fashion template description" },
14
+ ];
15
+
16
+ export type PdfTemplateCardsProps = {
17
+ selectedTemplate: PdfTemplateId;
18
+ onTemplateChange: (template: PdfTemplateId) => void;
19
+ t: (key: string) => string;
20
+ };
21
+
22
+ export function PdfTemplateCards({ selectedTemplate, onTemplateChange, t }: PdfTemplateCardsProps) {
23
+ return (
24
+ <div className="space-y-3">
25
+ <h3 className="font-medium text-muted-foreground text-sm">{t("Template")}</h3>
26
+ <div className="grid gap-3">
27
+ {TEMPLATES.map((template) => (
28
+ <button
29
+ key={template.id}
30
+ type="button"
31
+ onClick={() => onTemplateChange(template.id)}
32
+ className={cn(
33
+ "relative flex cursor-pointer flex-col items-start rounded-lg border-2 p-4 text-left transition-all hover:border-primary/50",
34
+ selectedTemplate === template.id ? "border-primary bg-primary/5" : "border-border bg-background",
35
+ )}
36
+ >
37
+ {selectedTemplate === template.id && (
38
+ <div className="absolute top-3 right-3">
39
+ <Check className="h-5 w-5 text-primary" />
40
+ </div>
41
+ )}
42
+ <span className="font-semibold">{t(template.nameKey)}</span>
43
+ <span className="mt-1 text-muted-foreground text-sm">{t(template.descriptionKey)}</span>
44
+ </button>
45
+ ))}
46
+ </div>
47
+ </div>
48
+ );
49
+ }
@@ -0,0 +1,16 @@
1
+ import { Button } from "@/ui/components/ui/button";
2
+ import ButtonLoader from "../../button-loader";
3
+
4
+ type SettingsFooterProps = {
5
+ isPending: boolean;
6
+ isDirty: boolean;
7
+ label: string;
8
+ };
9
+
10
+ export function SettingsFooter({ isPending, isDirty, label }: SettingsFooterProps) {
11
+ return (
12
+ <Button type="submit" className="cursor-pointer px-8" disabled={isPending || !isDirty}>
13
+ {isPending ? <ButtonLoader /> : label}
14
+ </Button>
15
+ );
16
+ }
@@ -0,0 +1,346 @@
1
+ import { zodResolver } from "@hookform/resolvers/zod";
2
+ import type {
3
+ Entity,
4
+ EntitySettings,
5
+ EntitySettingsTaxClauseDefaultsAnyOf,
6
+ GetEntities200DataItem,
7
+ TaxRulesAnyOf,
8
+ } from "@spaceinvoices/js-sdk";
9
+ import { ChevronDown, Globe, MessageSquareText } from "lucide-react";
10
+ import type { ReactNode } from "react";
11
+ import { useState } from "react";
12
+ import { useForm } from "react-hook-form";
13
+ import { z } from "zod";
14
+ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/ui/components/ui/collapsible";
15
+ import {
16
+ Form,
17
+ FormControl,
18
+ FormDescription,
19
+ FormField,
20
+ FormItem,
21
+ FormLabel,
22
+ FormMessage,
23
+ } from "@/ui/components/ui/form";
24
+ import { Switch } from "@/ui/components/ui/switch";
25
+ import { Textarea } from "@/ui/components/ui/textarea";
26
+ import type { ComponentTranslationProps } from "@/ui/lib/translation";
27
+ import { createTranslation } from "@/ui/lib/translation";
28
+ import { cn } from "@/ui/lib/utils";
29
+ import { useFormFooterRegistration } from "@/ui/providers/form-footer-context";
30
+ import { useUpdateEntity } from "../entities.hooks";
31
+ import de from "../entity-settings-form/locales/de";
32
+ import sl from "../entity-settings-form/locales/sl";
33
+
34
+ const translations = { sl, de } as const;
35
+
36
+ const taxRulesSettingsSchema = z.object({
37
+ vies_validate_vat: z.boolean(),
38
+ auto_reverse_charge: z.boolean(),
39
+ auto_remove_tax_export: z.boolean(),
40
+ require_gross_prices: z.boolean(),
41
+ // Tax clause defaults per transaction type
42
+ tax_clause_intra_eu_b2b: z.string().optional(),
43
+ tax_clause_export: z.string().optional(),
44
+ tax_clause_domestic: z.string().optional(),
45
+ tax_clause_intra_eu_b2c: z.string().optional(),
46
+ });
47
+
48
+ type TaxRulesSettingsSchema = z.infer<typeof taxRulesSettingsSchema>;
49
+
50
+ type SectionType = "tax-rules" | "tax-clauses";
51
+
52
+ /** Entity type with country_rules included (from getEntities response) */
53
+ type EntityWithRules = GetEntities200DataItem;
54
+
55
+ export type TaxRulesSettingsFormProps = {
56
+ entity: EntityWithRules;
57
+ onSuccess?: (data: Entity) => void;
58
+ onError?: (error: unknown) => void;
59
+ /** Optional render prop to wrap each section with help content */
60
+ renderSection?: (section: SectionType, content: ReactNode) => ReactNode;
61
+ } & ComponentTranslationProps;
62
+
63
+ export function TaxRulesSettingsForm({
64
+ entity,
65
+ t: translateProp,
66
+ namespace,
67
+ locale,
68
+ onSuccess,
69
+ onError,
70
+ renderSection,
71
+ }: TaxRulesSettingsFormProps) {
72
+ const t = createTranslation({ t: translateProp, namespace, locale, translations });
73
+ const [taxClausesOpen, setTaxClausesOpen] = useState(false);
74
+
75
+ // Helper to wrap section content with render prop if provided
76
+ const wrapSection = (section: SectionType, content: ReactNode) => {
77
+ return renderSection ? renderSection(section, content) : content;
78
+ };
79
+
80
+ // Check if tax clause defaults feature is available for this entity's country
81
+ const showTaxClauseDefaults = entity.country_rules?.features?.includes("tax_clause_defaults") ?? false;
82
+
83
+ const currentSettings = (entity.settings as EntitySettings) || {};
84
+ const currentTaxRules = (currentSettings.tax_rules as TaxRulesAnyOf | null)?.eu || {};
85
+ const currentTaxClauseDefaults =
86
+ (currentSettings.tax_clause_defaults as EntitySettingsTaxClauseDefaultsAnyOf | null) || {};
87
+
88
+ const form = useForm<TaxRulesSettingsSchema>({
89
+ resolver: zodResolver(taxRulesSettingsSchema),
90
+ defaultValues: {
91
+ vies_validate_vat: currentTaxRules.vies_validate_vat ?? true,
92
+ auto_reverse_charge: currentTaxRules.auto_reverse_charge ?? false,
93
+ auto_remove_tax_export: currentTaxRules.auto_remove_tax_export ?? false,
94
+ require_gross_prices: currentTaxRules.require_gross_prices ?? false,
95
+ tax_clause_intra_eu_b2b: currentTaxClauseDefaults.intra_eu_b2b ?? "",
96
+ tax_clause_export: currentTaxClauseDefaults.export ?? "",
97
+ tax_clause_domestic: currentTaxClauseDefaults.domestic ?? "",
98
+ tax_clause_intra_eu_b2c: currentTaxClauseDefaults.intra_eu_b2c ?? "",
99
+ },
100
+ });
101
+
102
+ const { mutate: updateEntity, isPending } = useUpdateEntity({
103
+ entityId: entity.id,
104
+ onSuccess: (data) => {
105
+ form.reset(form.getValues());
106
+ onSuccess?.(data);
107
+ },
108
+ onError,
109
+ });
110
+
111
+ useFormFooterRegistration({
112
+ formId: "tax-rules-settings-form",
113
+ isPending,
114
+ isDirty: form.formState.isDirty,
115
+ label: t("Save Settings"),
116
+ });
117
+
118
+ const onSubmit = (values: TaxRulesSettingsSchema) => {
119
+ const updatedSettings: EntitySettings = {
120
+ ...currentSettings,
121
+ tax_rules: {
122
+ eu: {
123
+ vies_validate_vat: values.vies_validate_vat,
124
+ auto_reverse_charge: values.auto_reverse_charge,
125
+ auto_remove_tax_export: values.auto_remove_tax_export,
126
+ require_gross_prices: values.require_gross_prices,
127
+ },
128
+ },
129
+ tax_clause_defaults: {
130
+ intra_eu_b2b: values.tax_clause_intra_eu_b2b || null,
131
+ export: values.tax_clause_export || null,
132
+ domestic: values.tax_clause_domestic || null,
133
+ intra_eu_b2c: values.tax_clause_intra_eu_b2c || null,
134
+ },
135
+ };
136
+
137
+ updateEntity({ id: entity.id, data: { settings: updatedSettings } });
138
+ };
139
+
140
+ // Tax rules header
141
+ const taxRulesHeader = (
142
+ <div className={cn("mb-4 flex items-center gap-3", showTaxClauseDefaults && "border-t pt-6")}>
143
+ <div className="flex h-10 w-10 items-center justify-center rounded-lg bg-green-500/10">
144
+ <Globe className="h-5 w-5 text-green-600 dark:text-green-400" />
145
+ </div>
146
+ <div>
147
+ <h3 className="font-semibold text-lg">{t("EU Tax Rules")}</h3>
148
+ <p className="text-muted-foreground text-sm">{t("Automatic tax handling for cross-border transactions")}</p>
149
+ </div>
150
+ </div>
151
+ );
152
+
153
+ // Tax rules section content (switches)
154
+ const taxRulesContent = (
155
+ <div className="space-y-4">
156
+ <FormField
157
+ control={form.control}
158
+ name="vies_validate_vat"
159
+ render={({ field }) => (
160
+ <FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
161
+ <div className="space-y-0.5">
162
+ <FormLabel className="text-base">{t("tax-rules.vies_validate_vat.label")}</FormLabel>
163
+ <FormDescription>{t("tax-rules.vies_validate_vat.description")}</FormDescription>
164
+ </div>
165
+ <FormControl>
166
+ <Switch checked={field.value} onCheckedChange={field.onChange} />
167
+ </FormControl>
168
+ <FormMessage />
169
+ </FormItem>
170
+ )}
171
+ />
172
+
173
+ <FormField
174
+ control={form.control}
175
+ name="auto_reverse_charge"
176
+ render={({ field }) => (
177
+ <FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
178
+ <div className="space-y-0.5">
179
+ <FormLabel className="text-base">{t("tax-rules.auto_reverse_charge.label")}</FormLabel>
180
+ <FormDescription>{t("tax-rules.auto_reverse_charge.description")}</FormDescription>
181
+ </div>
182
+ <FormControl>
183
+ <Switch checked={field.value} onCheckedChange={field.onChange} />
184
+ </FormControl>
185
+ <FormMessage />
186
+ </FormItem>
187
+ )}
188
+ />
189
+
190
+ <FormField
191
+ control={form.control}
192
+ name="auto_remove_tax_export"
193
+ render={({ field }) => (
194
+ <FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
195
+ <div className="space-y-0.5">
196
+ <FormLabel className="text-base">{t("tax-rules.auto_remove_tax_export.label")}</FormLabel>
197
+ <FormDescription>{t("tax-rules.auto_remove_tax_export.description")}</FormDescription>
198
+ </div>
199
+ <FormControl>
200
+ <Switch checked={field.value} onCheckedChange={field.onChange} />
201
+ </FormControl>
202
+ <FormMessage />
203
+ </FormItem>
204
+ )}
205
+ />
206
+
207
+ <FormField
208
+ control={form.control}
209
+ name="require_gross_prices"
210
+ render={({ field }) => (
211
+ <FormItem className="flex flex-row items-center justify-between rounded-lg border p-4">
212
+ <div className="space-y-0.5">
213
+ <FormLabel className="text-base">{t("tax-rules.require_gross_prices.label")}</FormLabel>
214
+ <FormDescription>{t("tax-rules.require_gross_prices.description")}</FormDescription>
215
+ </div>
216
+ <FormControl>
217
+ <Switch checked={field.value} onCheckedChange={field.onChange} />
218
+ </FormControl>
219
+ <FormMessage />
220
+ </FormItem>
221
+ )}
222
+ />
223
+ </div>
224
+ );
225
+
226
+ // Tax clauses header
227
+ const taxClausesHeader = showTaxClauseDefaults ? (
228
+ <div className="mb-4 flex items-center gap-3">
229
+ <div className="flex h-10 w-10 items-center justify-center rounded-lg bg-blue-500/10">
230
+ <MessageSquareText className="h-5 w-5 text-blue-600 dark:text-blue-400" />
231
+ </div>
232
+ <div>
233
+ <h3 className="font-semibold text-lg">{t("Default Tax Clauses")}</h3>
234
+ <p className="text-muted-foreground text-sm">
235
+ {t("Set default tax clauses that are automatically added to documents based on transaction type")}
236
+ </p>
237
+ </div>
238
+ </div>
239
+ ) : null;
240
+
241
+ // Tax clauses section content
242
+ const taxClausesContent = showTaxClauseDefaults ? (
243
+ <div className="space-y-4">
244
+ {/* Default / Domestic - always visible */}
245
+ <FormField
246
+ control={form.control}
247
+ name="tax_clause_domestic"
248
+ render={({ field }) => (
249
+ <FormItem className="rounded-lg border p-4">
250
+ <FormLabel>{t("tax-clauses.domestic.label")}</FormLabel>
251
+ <FormDescription>{t("tax-clauses.domestic.description")}</FormDescription>
252
+ <FormControl>
253
+ <Textarea placeholder={t("Enter default tax clause...")} className="min-h-[80px] resize-y" {...field} />
254
+ </FormControl>
255
+ <FormMessage />
256
+ </FormItem>
257
+ )}
258
+ />
259
+
260
+ {/* Other tax clauses - collapsible */}
261
+ <Collapsible open={taxClausesOpen} onOpenChange={setTaxClausesOpen} className="space-y-2">
262
+ <CollapsibleTrigger className="flex w-full items-center justify-between rounded-lg border p-4 transition-colors hover:bg-muted/50">
263
+ <div className="text-left">
264
+ <div className="font-medium">{t("tax-clauses.other-title")}</div>
265
+ <div className="text-muted-foreground text-sm">{t("tax-clauses.other-description")}</div>
266
+ </div>
267
+ <ChevronDown
268
+ className={cn("h-5 w-5 text-muted-foreground transition-transform", taxClausesOpen && "rotate-180")}
269
+ />
270
+ </CollapsibleTrigger>
271
+ <CollapsibleContent className="space-y-4 pt-2">
272
+ {/* Intra-EU B2B */}
273
+ <FormField
274
+ control={form.control}
275
+ name="tax_clause_intra_eu_b2b"
276
+ render={({ field }) => (
277
+ <FormItem className="rounded-lg border p-4">
278
+ <FormLabel>{t("tax-clauses.intra_eu_b2b.label")}</FormLabel>
279
+ <FormDescription>{t("tax-clauses.intra_eu_b2b.description")}</FormDescription>
280
+ <FormControl>
281
+ <Textarea
282
+ placeholder={t("Enter reverse charge clause...")}
283
+ className="min-h-[80px] resize-y"
284
+ {...field}
285
+ />
286
+ </FormControl>
287
+ <FormMessage />
288
+ </FormItem>
289
+ )}
290
+ />
291
+
292
+ {/* Export */}
293
+ <FormField
294
+ control={form.control}
295
+ name="tax_clause_export"
296
+ render={({ field }) => (
297
+ <FormItem className="rounded-lg border p-4">
298
+ <FormLabel>{t("tax-clauses.export.label")}</FormLabel>
299
+ <FormDescription>{t("tax-clauses.export.description")}</FormDescription>
300
+ <FormControl>
301
+ <Textarea
302
+ placeholder={t("Enter export exemption clause...")}
303
+ className="min-h-[80px] resize-y"
304
+ {...field}
305
+ />
306
+ </FormControl>
307
+ <FormMessage />
308
+ </FormItem>
309
+ )}
310
+ />
311
+
312
+ {/* Intra-EU B2C */}
313
+ <FormField
314
+ control={form.control}
315
+ name="tax_clause_intra_eu_b2c"
316
+ render={({ field }) => (
317
+ <FormItem className="rounded-lg border p-4">
318
+ <FormLabel>{t("tax-clauses.intra_eu_b2c.label")}</FormLabel>
319
+ <FormDescription>{t("tax-clauses.other.description")}</FormDescription>
320
+ <FormControl>
321
+ <Textarea
322
+ placeholder={t("Enter EU consumer sales clause...")}
323
+ className="min-h-[80px] resize-y"
324
+ {...field}
325
+ />
326
+ </FormControl>
327
+ <FormMessage />
328
+ </FormItem>
329
+ )}
330
+ />
331
+ </CollapsibleContent>
332
+ </Collapsible>
333
+ </div>
334
+ ) : null;
335
+
336
+ return (
337
+ <Form {...form}>
338
+ <form id="tax-rules-settings-form" onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
339
+ {taxClausesHeader}
340
+ {taxClausesContent && wrapSection("tax-clauses", taxClausesContent)}
341
+ {taxRulesHeader}
342
+ {wrapSection("tax-rules", taxRulesContent)}
343
+ </form>
344
+ </Form>
345
+ );
346
+ }