@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,222 @@
1
+ import { useRef, useState } from "react";
2
+ import ReactCrop, { type Crop, type PixelCrop } from "react-image-crop";
3
+ import "react-image-crop/dist/ReactCrop.css";
4
+ import { Upload } from "lucide-react";
5
+ import { Button } from "@/ui/components/ui/button";
6
+ import {
7
+ Dialog,
8
+ DialogContent,
9
+ DialogDescription,
10
+ DialogFooter,
11
+ DialogHeader,
12
+ DialogTitle,
13
+ } from "@/ui/components/ui/dialog";
14
+
15
+ interface ImageUploadWithCropProps {
16
+ value?: string;
17
+ onChange: (url: string) => void;
18
+ onUpload: (file: File) => Promise<{ secureUrl: string }>;
19
+ translate: (key: string) => string;
20
+ isUploading?: boolean;
21
+ imageType?: "logo" | "signature"; // Type of image for labels
22
+ }
23
+
24
+ export function ImageUploadWithCrop({
25
+ value,
26
+ onChange,
27
+ onUpload,
28
+ translate,
29
+ isUploading = false,
30
+ imageType = "logo",
31
+ }: ImageUploadWithCropProps) {
32
+ const [selectedImage, setSelectedImage] = useState<string | null>(null);
33
+ const [crop, setCrop] = useState<Crop>({
34
+ unit: "%",
35
+ width: 80,
36
+ height: 60,
37
+ x: 10,
38
+ y: 20,
39
+ });
40
+ const [completedCrop, setCompletedCrop] = useState<PixelCrop | null>(null);
41
+ const [isDialogOpen, setIsDialogOpen] = useState(false);
42
+ const [uploading, setUploading] = useState(false);
43
+ const imgRef = useRef<HTMLImageElement>(null);
44
+ const fileInputRef = useRef<HTMLInputElement>(null);
45
+
46
+ const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {
47
+ const file = e.target.files?.[0];
48
+ if (!file) return;
49
+
50
+ const reader = new FileReader();
51
+ reader.onload = () => {
52
+ setSelectedImage(reader.result as string);
53
+ setIsDialogOpen(true);
54
+ };
55
+ reader.readAsDataURL(file);
56
+ };
57
+
58
+ const getCroppedImg = async (): Promise<Blob | null> => {
59
+ if (!imgRef.current) return null;
60
+
61
+ // If no crop was completed, use the full image
62
+ if (!completedCrop || completedCrop.width === 0 || completedCrop.height === 0) {
63
+ // Convert the full image to blob
64
+ const canvas = document.createElement("canvas");
65
+ const ctx = canvas.getContext("2d");
66
+ if (!ctx) return null;
67
+
68
+ canvas.width = imgRef.current.naturalWidth;
69
+ canvas.height = imgRef.current.naturalHeight;
70
+
71
+ ctx.drawImage(imgRef.current, 0, 0);
72
+
73
+ return new Promise((resolve) => {
74
+ canvas.toBlob((blob) => {
75
+ resolve(blob);
76
+ }, "image/png");
77
+ });
78
+ }
79
+
80
+ // Crop the image
81
+ const canvas = document.createElement("canvas");
82
+ const ctx = canvas.getContext("2d");
83
+ if (!ctx) return null;
84
+
85
+ const scaleX = imgRef.current.naturalWidth / imgRef.current.width;
86
+ const scaleY = imgRef.current.naturalHeight / imgRef.current.height;
87
+
88
+ canvas.width = completedCrop.width;
89
+ canvas.height = completedCrop.height;
90
+
91
+ ctx.drawImage(
92
+ imgRef.current,
93
+ completedCrop.x * scaleX,
94
+ completedCrop.y * scaleY,
95
+ completedCrop.width * scaleX,
96
+ completedCrop.height * scaleY,
97
+ 0,
98
+ 0,
99
+ completedCrop.width,
100
+ completedCrop.height,
101
+ );
102
+
103
+ return new Promise((resolve) => {
104
+ canvas.toBlob((blob) => {
105
+ resolve(blob);
106
+ }, "image/png");
107
+ });
108
+ };
109
+
110
+ const handleUploadCropped = async () => {
111
+ try {
112
+ setUploading(true);
113
+ const croppedBlob = await getCroppedImg();
114
+
115
+ if (!croppedBlob) {
116
+ throw new Error("Failed to crop image");
117
+ }
118
+
119
+ const file = new File([croppedBlob], `${imageType}.png`, { type: "image/png" });
120
+ const result = await onUpload(file);
121
+
122
+ onChange(result.secureUrl);
123
+ setIsDialogOpen(false);
124
+ setSelectedImage(null);
125
+ } catch (error) {
126
+ console.error("Upload failed:", error);
127
+ alert(translate("Upload failed. Please try again."));
128
+ } finally {
129
+ setUploading(false);
130
+ }
131
+ };
132
+
133
+ const isDisabled = isUploading || uploading;
134
+
135
+ // Dynamic labels based on image type
136
+ const uploadLabel = imageType === "logo" ? "Upload Logo" : "Upload Signature";
137
+ const changeLabel = imageType === "logo" ? "Change Logo" : "Change Signature";
138
+ const currentLabel =
139
+ imageType === "logo" ? "Current logo (displayed on invoices)" : "Current signature (for PDF documents)";
140
+ const altText = imageType === "logo" ? "Logo preview" : "Signature preview";
141
+
142
+ return (
143
+ <div className="space-y-4">
144
+ {value ? (
145
+ <div className="space-y-3">
146
+ <div className="flex flex-col items-center gap-4 rounded-lg border bg-muted/20 p-6">
147
+ <div className="rounded-md bg-background p-4 shadow-sm">
148
+ <img key={value} src={value} alt={translate(altText)} className="max-h-32 max-w-full object-contain" />
149
+ </div>
150
+ <p className="text-center font-medium text-muted-foreground text-xs">{translate(currentLabel)}</p>
151
+ </div>
152
+ <Button
153
+ type="button"
154
+ variant="outline"
155
+ onClick={() => fileInputRef.current?.click()}
156
+ disabled={isDisabled}
157
+ className="w-full cursor-pointer"
158
+ >
159
+ <Upload className="mr-2 h-4 w-4" />
160
+ {translate(changeLabel)}
161
+ </Button>
162
+ </div>
163
+ ) : (
164
+ <Button
165
+ type="button"
166
+ variant="outline"
167
+ onClick={() => fileInputRef.current?.click()}
168
+ disabled={isDisabled}
169
+ className="h-32 w-full cursor-pointer border-dashed"
170
+ >
171
+ <div className="flex flex-col items-center gap-2">
172
+ <Upload className="h-8 w-8 text-muted-foreground" />
173
+ <span className="font-medium text-sm">{translate(uploadLabel)}</span>
174
+ <span className="text-muted-foreground text-xs">PNG, JPG, WebP, or GIF</span>
175
+ </div>
176
+ </Button>
177
+ )}
178
+ <input
179
+ ref={fileInputRef}
180
+ type="file"
181
+ accept="image/png,image/jpeg,image/jpg,image/webp,image/gif"
182
+ onChange={handleFileSelect}
183
+ className="hidden"
184
+ disabled={isDisabled}
185
+ />
186
+
187
+ <Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
188
+ <DialogContent className="max-w-3xl">
189
+ <DialogHeader>
190
+ <DialogTitle>{translate(imageType === "logo" ? "Crop Your Logo" : "Crop Your Signature")}</DialogTitle>
191
+ <DialogDescription>{translate("Adjust the crop area or upload the full image")}</DialogDescription>
192
+ </DialogHeader>
193
+ <div className="max-h-[60vh] overflow-auto">
194
+ {selectedImage && (
195
+ <ReactCrop
196
+ crop={crop}
197
+ onChange={(c) => setCrop(c)}
198
+ onComplete={(c) => setCompletedCrop(c)}
199
+ aspect={undefined}
200
+ >
201
+ <img ref={imgRef} src={selectedImage} alt="Crop preview" className="max-w-full" />
202
+ </ReactCrop>
203
+ )}
204
+ </div>
205
+ <DialogFooter>
206
+ <Button
207
+ variant="outline"
208
+ className="cursor-pointer"
209
+ onClick={() => setIsDialogOpen(false)}
210
+ disabled={uploading}
211
+ >
212
+ {translate("Cancel")}
213
+ </Button>
214
+ <Button onClick={handleUploadCropped} disabled={uploading} className="cursor-pointer">
215
+ {uploading ? translate("Uploading...") : translate("Upload & Save")}
216
+ </Button>
217
+ </DialogFooter>
218
+ </DialogContent>
219
+ </Dialog>
220
+ </div>
221
+ );
222
+ }
@@ -0,0 +1,2 @@
1
+ export type { EntitySettingsFormProps, EntitySettingsFormSchema } from "./entity-settings-form";
2
+ export { EntitySettingsForm } from "./entity-settings-form";
@@ -0,0 +1,190 @@
1
+ import type { Entity, Estimate, Invoice } from "@spaceinvoices/js-sdk";
2
+ import { forwardRef, useState } from "react";
3
+ import { Input } from "@/ui/components/ui/input";
4
+ import { Textarea } from "@/ui/components/ui/textarea";
5
+ import { cn } from "@/ui/lib/utils";
6
+
7
+ interface InputWithPreviewProps {
8
+ value: string;
9
+ onChange: (value: string) => void;
10
+ placeholder?: string;
11
+ entity: Entity;
12
+ document?: Invoice | Estimate | null;
13
+ multiline?: boolean;
14
+ className?: string;
15
+ rows?: number;
16
+ disabled?: boolean;
17
+ }
18
+
19
+ function formatVariableName(varName: string): string {
20
+ // Convert snake_case to Title Case with spaces
21
+ // e.g., "document_number" -> "Document Number"
22
+ return varName
23
+ .split("_")
24
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
25
+ .join(" ");
26
+ }
27
+
28
+ function getVariableValue(varName: string, entity: Entity, document?: Invoice | Estimate | null): string | null {
29
+ // Entity-related variables
30
+ if (varName === "entity_name") return entity.name || null;
31
+ if (varName === "entity_email") return (entity.settings as any)?.email || null;
32
+
33
+ // Date variables
34
+ if (varName === "current_date") {
35
+ return new Date().toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" });
36
+ }
37
+ if (varName === "current_year") return new Date().getFullYear().toString();
38
+
39
+ // Document-specific variables (only available when document is provided)
40
+ if (document) {
41
+ if (varName === "document_number") return document.number || null;
42
+ if (varName === "document_date") {
43
+ return document.date
44
+ ? new Date(document.date).toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" })
45
+ : null;
46
+ }
47
+ if (varName === "document_total") {
48
+ return document.total_with_tax
49
+ ? new Intl.NumberFormat("en-US", { style: "currency", currency: document.currency_code || "USD" }).format(
50
+ Number(document.total_with_tax),
51
+ )
52
+ : null;
53
+ }
54
+ if (varName === "document_currency") return document.currency_code || null;
55
+
56
+ // Invoice-specific
57
+ if ("date_due" in document && varName === "document_due_date") {
58
+ return document.date_due
59
+ ? new Date(document.date_due).toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" })
60
+ : null;
61
+ }
62
+
63
+ // Estimate-specific
64
+ if ("date_valid_till" in document && varName === "document_valid_until") {
65
+ return document.date_valid_till
66
+ ? new Date(document.date_valid_till).toLocaleDateString("en-US", {
67
+ month: "long",
68
+ day: "numeric",
69
+ year: "numeric",
70
+ })
71
+ : null;
72
+ }
73
+
74
+ // Customer variables
75
+ if (document.customer) {
76
+ if (varName === "customer_name") return document.customer.name || null;
77
+ if (varName === "customer_email") return (document.customer as any).email || null;
78
+ }
79
+ }
80
+
81
+ // Return null for unavailable variables - they will show as placeholders
82
+ return null;
83
+ }
84
+
85
+ function replaceTemplateVariables(
86
+ template: string,
87
+ entity: Entity,
88
+ document?: Invoice | Estimate | null,
89
+ ): React.ReactNode[] {
90
+ if (!template) return [];
91
+
92
+ // Split by variable pattern and process
93
+ const parts: React.ReactNode[] = [];
94
+ const regex = /\{([^}]+)\}/g;
95
+ let lastIndex = 0;
96
+ let match: RegExpExecArray | null = null;
97
+
98
+ match = regex.exec(template);
99
+ while (match !== null) {
100
+ // Add text before the match
101
+ if (match.index > lastIndex) {
102
+ parts.push(template.slice(lastIndex, match.index));
103
+ }
104
+
105
+ // Add the replaced variable with styling
106
+ // Green for resolved values, primary color for placeholders
107
+ const varName = match[1];
108
+ const actualValue = getVariableValue(varName, entity, document);
109
+ const displayValue = actualValue || formatVariableName(varName);
110
+
111
+ parts.push(
112
+ <span
113
+ key={match.index}
114
+ className={cn(
115
+ "rounded px-1.5 py-0.5 font-medium text-xs",
116
+ actualValue ? "bg-secondary text-secondary-foreground" : "bg-primary/10 text-primary",
117
+ )}
118
+ >
119
+ {displayValue}
120
+ </span>,
121
+ );
122
+
123
+ lastIndex = regex.lastIndex;
124
+ match = regex.exec(template);
125
+ }
126
+
127
+ // Add remaining text
128
+ if (lastIndex < template.length) {
129
+ parts.push(template.slice(lastIndex));
130
+ }
131
+
132
+ return parts;
133
+ }
134
+
135
+ export const InputWithPreview = forwardRef<HTMLInputElement | HTMLTextAreaElement, InputWithPreviewProps>(
136
+ function InputWithPreview(
137
+ { value, onChange, placeholder, entity, document, multiline = false, className, rows, disabled = false },
138
+ ref,
139
+ ) {
140
+ const [isFocused, setIsFocused] = useState(false);
141
+
142
+ const preview = replaceTemplateVariables(value, entity, document);
143
+ const hasValue = Boolean(value);
144
+
145
+ const showPreview = !isFocused && hasValue && !disabled;
146
+
147
+ if (multiline) {
148
+ return (
149
+ <div className="relative">
150
+ <Textarea
151
+ ref={ref as React.Ref<HTMLTextAreaElement>}
152
+ value={value}
153
+ onChange={(e) => onChange(e.target.value)}
154
+ onFocus={() => setIsFocused(true)}
155
+ onBlur={() => setIsFocused(false)}
156
+ placeholder={showPreview ? "" : placeholder}
157
+ className={cn(className, showPreview && "text-transparent caret-transparent")}
158
+ rows={rows}
159
+ disabled={disabled}
160
+ />
161
+ {showPreview && (
162
+ <div className="pointer-events-none absolute inset-0 z-10 flex items-start overflow-hidden rounded-md border border-input bg-background px-3 py-2 shadow-xs">
163
+ <div className="w-full whitespace-pre-wrap text-base md:text-sm">{preview}</div>
164
+ </div>
165
+ )}
166
+ </div>
167
+ );
168
+ }
169
+
170
+ return (
171
+ <div className="relative">
172
+ <Input
173
+ ref={ref as React.Ref<HTMLInputElement>}
174
+ value={value}
175
+ onChange={(e) => onChange(e.target.value)}
176
+ onFocus={() => setIsFocused(true)}
177
+ onBlur={() => setIsFocused(false)}
178
+ placeholder={showPreview ? "" : placeholder}
179
+ className={cn(className, showPreview && "text-transparent caret-transparent")}
180
+ disabled={disabled}
181
+ />
182
+ {showPreview && (
183
+ <div className="pointer-events-none absolute inset-0 z-10 flex items-start overflow-hidden rounded-md border border-input bg-background px-3 py-1 shadow-xs">
184
+ <div className="flex h-full w-full items-center truncate text-base md:text-sm">{preview}</div>
185
+ </div>
186
+ )}
187
+ </div>
188
+ );
189
+ },
190
+ );
@@ -0,0 +1,192 @@
1
+ export default {
2
+ // Company settings
3
+ "Company Information": "Unternehmensinformationen",
4
+ "Basic information about your company": "Grundlegende Informationen über Ihr Unternehmen",
5
+ // Branding settings
6
+ Branding: "Markenauftritt",
7
+ "Primary Color": "Primärfarbe",
8
+ Logo: "Logo",
9
+ "Logo URL": "Logo-URL",
10
+ "Enter the URL of your company logo": "Geben Sie die URL Ihres Firmenlogos ein",
11
+ "Upload your company logo for invoices": "Laden Sie Ihr Firmenlogo für Rechnungen hoch",
12
+ "Upload Logo": "Logo hochladen",
13
+ "Change Logo": "Logo ändern",
14
+ "Current logo (displayed on invoices)": "Aktuelles Logo (auf Rechnungen angezeigt)",
15
+ "Logo preview": "Logo-Vorschau",
16
+ "Crop Your Logo": "Logo zuschneiden",
17
+ Signature: "Unterschrift",
18
+ "Upload a signature image for PDFs (optional)": "Laden Sie ein Unterschriftsbild für PDFs hoch (optional)",
19
+ "Upload Signature": "Unterschrift hochladen",
20
+ "Change Signature": "Unterschrift ändern",
21
+ "Current signature (for PDF documents)": "Aktuelle Unterschrift (für PDF-Dokumente)",
22
+ "Signature preview": "Unterschrift-Vorschau",
23
+ "Crop Your Signature": "Unterschrift zuschneiden",
24
+ "Adjust the crop area or upload the full image":
25
+ "Passen Sie den Zuschneidebereich an oder laden Sie das vollständige Bild hoch",
26
+ "Upload failed. Please try again.": "Upload fehlgeschlagen. Bitte versuchen Sie es erneut.",
27
+ Uploading: "Hochladen...",
28
+ "Upload & Save": "Hochladen & Speichern",
29
+ Cancel: "Abbrechen",
30
+ Localization: "Lokalisierung",
31
+ "Currency Code": "Währungscode",
32
+ "ISO 4217 currency code (e.g., USD, EUR, GBP)": "ISO 4217 Währungscode (z.B. USD, EUR, GBP)",
33
+ Locale: "Gebietsschema",
34
+ "BCP 47 language tag (e.g., en-US, de-DE, sl-SI)": "BCP 47 Sprach-Tag (z.B. en-US, de-DE, sl-SI)",
35
+ "Select currency": "Währung auswählen",
36
+ "Select locale": "Gebietsschema auswählen",
37
+ "Configure entity localization": "Lokalisierung konfigurieren",
38
+ "Email Settings": "E-Mail-Einstellungen",
39
+ "Configure email settings for invoices": "Konfigurieren Sie E-Mail-Einstellungen für Rechnungen",
40
+ "Email Address": "E-Mail-Adresse",
41
+ "Email address to send invoices to": "E-Mail-Adresse zum Versenden von Rechnungen",
42
+ "Email Subject": "E-Mail-Betreff",
43
+ "Subject line for email invoices": "Betreffzeile für E-Mail-Rechnungen",
44
+ "Email Body": "E-Mail-Text",
45
+ "Body content for email invoices": "Textinhalt für E-Mail-Rechnungen",
46
+ "Save Settings": "Einstellungen speichern",
47
+ // Document Defaults section
48
+ "Document Defaults": "Dokumentvorlagen",
49
+ "Default values for new documents": "Standardwerte für neue Dokumente",
50
+ "Default Note": "Standardnotiz",
51
+ "Default Invoice Note": "Standard-Rechnungsnotiz",
52
+ "This note will be pre-filled when creating new invoices":
53
+ "Diese Notiz wird beim Erstellen neuer Rechnungen vorausgefüllt",
54
+ "This note will be pre-filled when creating new estimates":
55
+ "Diese Notiz wird beim Erstellen neuer Angebote vorausgefüllt",
56
+ "This note will be pre-filled when creating new credit notes":
57
+ "Diese Notiz wird beim Erstellen neuer Gutschriften vorausgefüllt",
58
+ "Payment terms pre-filled when creating new invoices":
59
+ "Zahlungsbedingungen werden beim Erstellen neuer Rechnungen vorausgefüllt",
60
+ "Payment terms pre-filled when creating new estimates":
61
+ "Zahlungsbedingungen werden beim Erstellen neuer Angebote vorausgefüllt",
62
+ "Payment terms pre-filled when creating new credit notes":
63
+ "Zahlungsbedingungen werden beim Erstellen neuer Gutschriften vorausgefüllt",
64
+ "Payment due by {document_due_date}. Please reference invoice {document_number}.":
65
+ "Zahlung fällig bis {document_due_date}. Bitte Rechnungsnummer {document_number} angeben.",
66
+ "Net 30 days. Payment due by {document_due_date}.": "Netto 30 Tage. Zahlung fällig bis {document_due_date}.",
67
+ "This estimate is valid until {document_valid_until}.": "Dieses Angebot ist gültig bis {document_valid_until}.",
68
+ "Payment due upon acceptance.": "Zahlung bei Annahme fällig.",
69
+ "Credit note for invoice {document_number}.": "Gutschrift für Rechnung {document_number}.",
70
+ "Credit will be applied to your account.": "Die Gutschrift wird Ihrem Konto gutgeschrieben.",
71
+ "Invoice Notes": "Rechnungsnotizen",
72
+ "Smart Template Variables": "Intelligente Vorlagenvariablen",
73
+ "Use variables to personalize your notes automatically":
74
+ "Verwenden Sie Variablen zur automatischen Personalisierung Ihrer Notizen",
75
+ "Set a default note that will appear on all new invoices. Use template variables to personalize the note automatically.":
76
+ "Legen Sie eine Standardnotiz fest, die auf allen neuen Rechnungen erscheint. Verwenden Sie Vorlagenvariablen zur automatischen Personalisierung.",
77
+ // Smart code insert button
78
+ "Insert variable": "Variable einfügen",
79
+ Entity: "Unternehmen",
80
+ Document: "Dokument",
81
+ Customer: "Kunde",
82
+ Other: "Andere",
83
+ "Company name": "Firmenname",
84
+ "Email address": "E-Mail-Adresse",
85
+ "Invoice number": "Rechnungsnummer",
86
+ "Invoice date": "Rechnungsdatum",
87
+ "Due date": "Fälligkeitsdatum",
88
+ "Total amount": "Gesamtbetrag",
89
+ Currency: "Währung",
90
+ "Customer name": "Kundenname",
91
+ "Customer email": "Kunden-E-Mail",
92
+ "Today's date": "Heutiges Datum",
93
+ "Current year": "Aktuelles Jahr",
94
+ // Payment terms defaults
95
+ "Default Payment Terms": "Standard-Zahlungsbedingungen",
96
+ "This payment terms will be pre-filled when creating new documents":
97
+ "Diese Zahlungsbedingungen werden beim Erstellen neuer Dokumente vorausgefüllt",
98
+ "Payment Terms": "Zahlungsbedingungen",
99
+ "Add payment terms...": "Zahlungsbedingungen hinzufügen...",
100
+ // Document footer
101
+ "Document Footer": "Dokumentfußzeile",
102
+ "Footer text displayed at the bottom of PDF documents": "Fußzeilentext am unteren Rand von PDF-Dokumenten",
103
+ "Footer text displayed at the bottom of all PDF documents": "Fußzeilentext am unteren Rand aller PDF-Dokumente",
104
+ "{entity_name} | Due Date: {document_due_date} | Invoice #{document_number}":
105
+ "{entity_name} | Fällig am: {document_due_date} | Rechnung #{document_number}",
106
+ // Overdue Notifications section
107
+ "Overdue Notifications": "Überfälligkeits-Benachrichtigungen",
108
+ "Automatically remind customers about overdue invoices": "Erinnern Sie Kunden automatisch an überfällige Rechnungen",
109
+ "Enable Notifications": "Benachrichtigungen aktivieren",
110
+ "Send automatic payment reminder emails to customers with overdue invoices":
111
+ "Senden Sie automatische Zahlungserinnerungen per E-Mail an Kunden mit überfälligen Rechnungen",
112
+ "Reminder Days": "Erinnerungstage",
113
+ "Days after due date to send reminders (comma-separated). E.g., '7, 14, 30' sends reminders at 7, 14, and 30 days overdue.":
114
+ "Tage nach Fälligkeit für Erinnerungen (durch Komma getrennt). Z.B. '7, 14, 30' sendet Erinnerungen bei 7, 14 und 30 Tagen Überfälligkeit.",
115
+ "Custom Reminder Templates": "Benutzerdefinierte Erinnerungsvorlagen",
116
+ "Subject line for overdue notification emails": "Betreffzeile für Überfälligkeits-E-Mails",
117
+ "Body content for overdue emails. Use {invoice_list} to include the invoice table, or it will be auto-appended.":
118
+ "Textinhalt für Überfälligkeits-E-Mails. Verwenden Sie {invoice_list} für die Rechnungstabelle, sonst wird sie automatisch angehängt.",
119
+ "Dear {customer_name},\n\nThis is a reminder about your overdue invoices...":
120
+ "Sehr geehrte(r) {customer_name},\n\nDies ist eine Erinnerung an Ihre überfälligen Rechnungen...",
121
+ "Payment Reminders": "Zahlungserinnerungen",
122
+ "When enabled, customers will automatically receive email reminders when their invoices become overdue. Emails are sent on the exact day each threshold is reached.":
123
+ "Wenn aktiviert, erhalten Kunden automatisch E-Mail-Erinnerungen, wenn ihre Rechnungen überfällig werden. E-Mails werden genau am Tag gesendet, an dem jeder Schwellenwert erreicht wird.",
124
+ "Available Variables": "Verfügbare Variablen",
125
+ "{customer_name}, {entity_name}, {entity_email}, {invoice_list}, {total_amount}, {overdue_count}":
126
+ "{customer_name}, {entity_name}, {entity_email}, {invoice_list}, {total_amount}, {overdue_count}",
127
+ // UPN QR Payment section
128
+ "UPN QR Payment": "UPN QR Zahlung",
129
+ "Configure UPN QR payment slip for invoices": "UPN QR-Zahlungsbeleg für Rechnungen konfigurieren",
130
+ IBAN: "IBAN",
131
+ "Bank account IBAN for receiving payments": "IBAN des Bankkontos für den Zahlungsempfang",
132
+ "Enable UPN QR on invoices": "UPN QR auf Rechnungen aktivieren",
133
+ "Show payment QR code on PDF invoices for easy mobile banking payments":
134
+ "QR-Code für Zahlung auf PDF-Rechnungen anzeigen für einfache Mobile-Banking-Zahlungen",
135
+ "Display Mode": "Anzeigemodus",
136
+ "QR code only": "Nur QR-Code",
137
+ "Shows compact QR code inline with invoice content": "Zeigt kompakten QR-Code inline mit Rechnungsinhalt",
138
+ "Full UPN payment slip": "Vollständiger UPN-Zahlungsbeleg",
139
+ "Shows complete payment slip at bottom of page": "Zeigt vollständigen Zahlungsbeleg am Seitenende",
140
+ "Purpose Code": "Verwendungszweck-Code",
141
+ "OTHR - Other": "OTHR - Sonstiges",
142
+ "GDSV - Goods and Services": "GDSV - Waren und Dienstleistungen",
143
+ "SUPP - Supplier Payment": "SUPP - Lieferantenzahlung",
144
+ "Payment purpose code (ISO 20022)": "Zahlungszweck-Code (ISO 20022)",
145
+ "UPN QR Payments": "UPN QR-Zahlungen",
146
+ "UPN QR is a Slovenian standard for payment slips. When enabled, your invoices will include a QR code that customers can scan with their mobile banking app to pay instantly.":
147
+ "UPN QR ist ein slowenischer Standard für Zahlungsbelege. Wenn aktiviert, enthalten Ihre Rechnungen einen QR-Code, den Kunden mit ihrer Mobile-Banking-App scannen können, um sofort zu bezahlen.",
148
+ // Number format settings
149
+ Invoice: "Rechnung",
150
+ Estimate: "Angebot",
151
+ "Credit Note": "Gutschrift",
152
+ "Advance Invoice": "Vorausrechnung",
153
+ "Number Format": "Nummernformat",
154
+ Preview: "Vorschau",
155
+ // Tax rules settings
156
+ "EU Tax Rules": "EU-Steuerregeln",
157
+ "Automatic tax handling for cross-border transactions":
158
+ "Automatische Steuerbehandlung für grenzüberschreitende Transaktionen",
159
+ "tax-rules.vies_validate_vat.label": "VIES USt-IdNr. Prüfung",
160
+ "tax-rules.vies_validate_vat.description":
161
+ "EU USt-IdNr. über die VIES-API validieren. USt-IdNr. von Kunden werden vor Rechnungserstellung geprüft.",
162
+ "tax-rules.auto_reverse_charge.label": "Automatisches Reverse-Charge",
163
+ "tax-rules.auto_reverse_charge.description":
164
+ "Automatisch 0% Steuer (Reverse-Charge) für innergemeinschaftliche B2B-Transaktionen mit gültiger USt-IdNr. anwenden.",
165
+ "tax-rules.auto_remove_tax_export.label": "Automatisch Exportsteuer entfernen",
166
+ "tax-rules.auto_remove_tax_export.description": "Automatisch alle Steuern für Exporte in Nicht-EU-Länder entfernen.",
167
+ "tax-rules.require_gross_prices.label": "Bruttopreise erforderlich",
168
+ "tax-rules.require_gross_prices.description":
169
+ "Bruttopreise bei Reverse-Charge erforderlich. Verhindert unerwartete Änderungen der Rechnungssummen.",
170
+ // Tax clauses settings
171
+ "Default Tax Clauses": "Standard-Steuerklauseln",
172
+ "Set default tax clauses that are automatically added to documents based on transaction type":
173
+ "Legen Sie Standard-Steuerklauseln fest, die automatisch zu Dokumenten basierend auf dem Transaktionstyp hinzugefügt werden.",
174
+ "tax-clauses.other-title": "Grenzüberschreitende Steuerklauseln",
175
+ "tax-clauses.other-description": "Steuerklauseln für EU- und internationale Transaktionen (Reverse-Charge, Export).",
176
+ "tax-clauses.intra_eu_b2b.label": "Innergemeinschaftlich B2B (Reverse-Charge)",
177
+ "tax-clauses.intra_eu_b2b.description":
178
+ "Für Verkäufe an EU-Unternehmen mit gültiger USt-IdNr. Enthält typischerweise eine Reverse-Charge-Erklärung.",
179
+ "Enter reverse charge clause...": "Reverse-Charge-Klausel eingeben...",
180
+ "tax-clauses.export.label": "Export (Nicht-EU)",
181
+ "tax-clauses.export.description":
182
+ "Für Verkäufe an Kunden außerhalb der EU. Enthält typischerweise die Steuerbefreiung für Exporte.",
183
+ "Enter export exemption clause...": "Exportbefreiungsklausel eingeben...",
184
+ "tax-clauses.domestic.label": "Standard / Inländisch",
185
+ "tax-clauses.domestic.description":
186
+ "Standardklausel für inländische Transaktionen. Für Kleinunternehmer erscheint diese auf allen Dokumenten.",
187
+ "Enter default tax clause...": "Standard-Steuerklausel eingeben...",
188
+ "tax-clauses.intra_eu_b2c.label": "Innergemeinschaftlich B2C",
189
+ "Enter EU consumer sales clause...": "EU-Verbraucherklausel eingeben...",
190
+ "tax-clauses.other.description":
191
+ "Diese Transaktionstypen erfordern normalerweise keine speziellen Steuerklauseln, können aber bei Bedarf konfiguriert werden.",
192
+ } as const;