@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,20 @@
1
+ export default {
2
+ Name: "Name",
3
+ "Enter name": "Namen eingeben",
4
+ Address: "Adresse",
5
+ "Enter address": "Adresse eingeben",
6
+ "Post Code": "Postleitzahl",
7
+ "Enter post code": "Postleitzahl eingeben",
8
+ City: "Stadt",
9
+ "Enter city": "Stadt eingeben",
10
+ State: "Bundesland",
11
+ "Enter state": "Bundesland eingeben",
12
+ Country: "Land",
13
+ "Enter country": "Land eingeben",
14
+ "Tax Number": "Steuernummer",
15
+ "Enter tax number": "Steuernummer eingeben",
16
+ "Create Customer": "Kunde erstellen",
17
+ Cancel: "Abbrechen",
18
+ "Search by company name or tax number": "Suche nach Firmenname oder Steuernummer",
19
+ "There was an error creating the customer": "Beim Erstellen des Kunden ist ein Fehler aufgetreten",
20
+ } as const;
@@ -0,0 +1,20 @@
1
+ export default {
2
+ Name: "Ime",
3
+ "Enter name": "Vnesite ime stranke",
4
+ Address: "Naslov",
5
+ "Enter address": "Vnesite naslov",
6
+ "Post Code": "Poštna številka",
7
+ "Enter post code": "Vnesite poštno številko",
8
+ City: "Mesto",
9
+ "Enter city": "Vnesite mesto",
10
+ State: "Regija",
11
+ "Enter state": "Vnesite regijo",
12
+ Country: "Država",
13
+ "Enter country": "Vnesite državo",
14
+ "Tax Number": "Davčna številka",
15
+ "Enter tax number": "Vnesite davčno številko",
16
+ "Create Customer": "Ustvari stranko",
17
+ Cancel: "Prekliči",
18
+ "Search by company name or tax number": "Iskanje po imenu podjetja ali davčni številki",
19
+ "There was an error creating the customer": "Prišlo je do napake pri ustvarjanju stranke",
20
+ } as const;
@@ -0,0 +1,173 @@
1
+ import type { Customer } from "@spaceinvoices/js-sdk";
2
+
3
+ import { Plus } from "lucide-react";
4
+ import { useEffect, useMemo, useState } from "react";
5
+
6
+ import { Autocomplete } from "@/ui/common/autocomplete";
7
+ import { useDebounce } from "@/ui/hooks/use-debounce";
8
+
9
+ import { useCustomerSearch, useRecentCustomers } from "./customers.hooks";
10
+
11
+ const MAX_TEXT_LENGTH = 100;
12
+
13
+ const truncateText = (text: string, maxLength: number = MAX_TEXT_LENGTH): string => {
14
+ return text.length > maxLength ? `${text.substring(0, maxLength)}...` : text;
15
+ };
16
+
17
+ type CustomerAutocompleteProps = {
18
+ entityId: string;
19
+ value?: string | null;
20
+ onValueChange?: (value: string, customer: Customer) => void;
21
+ onClear?: () => void;
22
+ placeholder?: string;
23
+ className?: string;
24
+ disabled?: boolean;
25
+ onBlur?: () => void; // Added onBlur prop
26
+ /** Initial display name when pre-populating with a customer (e.g., for duplication) */
27
+ initialDisplayName?: string;
28
+ };
29
+
30
+ export function CustomerAutocomplete({
31
+ entityId,
32
+ value,
33
+ onValueChange,
34
+ placeholder = "Name",
35
+ className,
36
+ disabled,
37
+ onBlur: onBlurPropFromParent, // Destructure the onBlur prop from parent
38
+ initialDisplayName,
39
+ }: CustomerAutocompleteProps) {
40
+ const [search, setSearch] = useState(initialDisplayName || "");
41
+ const [displayValue, setDisplayValue] = useState(initialDisplayName || "");
42
+ const debouncedSearch = useDebounce(search, 300);
43
+
44
+ const handleSearch = (value: string) => {
45
+ setSearch(value);
46
+ // Clear displayValue when user starts typing to allow free editing
47
+ if (displayValue && value !== displayValue) {
48
+ setDisplayValue("");
49
+ }
50
+ };
51
+
52
+ // Fetch recent customers (non-blocking, cached)
53
+ const { data: recentData } = useRecentCustomers(entityId);
54
+ const recentCustomers = recentData?.data || [];
55
+
56
+ // Fetch search results
57
+ const { data: searchData, isLoading } = useCustomerSearch(entityId, debouncedSearch);
58
+ const searchResults = searchData?.data || [];
59
+
60
+ // Use search results if searching, otherwise show recent customers
61
+ const customers = useMemo(() => {
62
+ if (debouncedSearch) {
63
+ return searchResults;
64
+ }
65
+ return recentCustomers;
66
+ }, [debouncedSearch, searchResults, recentCustomers]);
67
+
68
+ const options = customers.map((customer) => {
69
+ const truncatedName = truncateText(customer.name);
70
+ const address = [customer.address, customer.city, customer.country].filter(Boolean).join(", ");
71
+ const truncatedAddress = truncateText(address);
72
+
73
+ return {
74
+ value: customer.id,
75
+ label: (
76
+ <div className="flex flex-col overflow-hidden">
77
+ <span className="truncate">{truncatedName}</span>
78
+ {truncatedAddress && <span className="truncate text-muted-foreground text-xs">{truncatedAddress}</span>}
79
+ </div>
80
+ ),
81
+ };
82
+ });
83
+
84
+ // Always add "Create new" option at the top
85
+ const createNewLabel = debouncedSearch?.trim() ? `Create "${debouncedSearch}"` : "Create new";
86
+
87
+ options.unshift({
88
+ value: `__create__:${debouncedSearch || ""}`,
89
+ label: (
90
+ <span className="flex items-center gap-2">
91
+ <Plus className="size-4" />
92
+ {createNewLabel}
93
+ </span>
94
+ ) as any,
95
+ });
96
+
97
+ const handleValueChange = (selectedValue: string) => {
98
+ // Handle "create new" selection
99
+ if (selectedValue.startsWith("__create__:")) {
100
+ const customerName = selectedValue.replace("__create__:", "");
101
+ const truncatedName = truncateText(customerName);
102
+
103
+ if (onValueChange) {
104
+ // Pass pseudo-customer with just name, empty id to indicate new customer
105
+ onValueChange("", {
106
+ name: customerName || "",
107
+ address: null,
108
+ address_2: null,
109
+ post_code: null,
110
+ city: null,
111
+ state: null,
112
+ country: null,
113
+ tax_number: null,
114
+ } as Customer);
115
+ }
116
+
117
+ // Set search to the customer name so it shows in the input
118
+ setSearch(truncatedName);
119
+ setDisplayValue(truncatedName);
120
+ return;
121
+ }
122
+
123
+ // Find customer in both recent and search results
124
+ const selectedCustomer =
125
+ customers.find((c) => c.id === selectedValue) ||
126
+ recentCustomers.find((c) => c.id === selectedValue) ||
127
+ searchResults.find((c) => c.id === selectedValue);
128
+
129
+ if (selectedCustomer) {
130
+ if (onValueChange) {
131
+ onValueChange(selectedValue, selectedCustomer);
132
+ }
133
+ // Set search to the customer name (truncated) so it shows in the input
134
+ const truncatedName = truncateText(selectedCustomer.name);
135
+ setSearch(truncatedName);
136
+ setDisplayValue(truncatedName);
137
+ }
138
+ };
139
+
140
+ const handleBlur = () => {
141
+ // If displayValue is empty (nothing selected) and there's text in search (something was typed),
142
+ // then behave as if "Create new" was clicked.
143
+ if (!displayValue && search) {
144
+ handleValueChange(`__create__:${search}`);
145
+ }
146
+ onBlurPropFromParent?.(); // Call the passed onBlur prop after internal logic
147
+ };
148
+
149
+ // Reset search when value changes externally
150
+ useEffect(() => {
151
+ if (!value) {
152
+ setSearch("");
153
+ setDisplayValue("");
154
+ }
155
+ }, [value]);
156
+
157
+ return (
158
+ <Autocomplete
159
+ searchValue={search}
160
+ onSearch={handleSearch}
161
+ value={value ?? undefined}
162
+ onValueChange={handleValueChange}
163
+ onBlur={handleBlur} // Pass the new handleBlur to Autocomplete
164
+ options={options}
165
+ placeholder={placeholder}
166
+ className={className}
167
+ disabled={disabled}
168
+ loading={isLoading}
169
+ emptyText={debouncedSearch ? "No customers found" : "Recent customers"}
170
+ displayValue={displayValue}
171
+ />
172
+ );
173
+ }
@@ -0,0 +1,130 @@
1
+ import type { Customer } from "@spaceinvoices/js-sdk";
2
+
3
+ import { Plus } from "lucide-react";
4
+ import { useEffect, useMemo, useState } from "react";
5
+
6
+ import { Combobox } from "@/ui/components/combobox";
7
+ import { useDebounce } from "@/ui/hooks/use-debounce";
8
+
9
+ import { useCustomerSearch, useRecentCustomers } from "./customers.hooks";
10
+
11
+ type CustomerComboboxProps = {
12
+ entityId: string;
13
+ value?: string | null;
14
+ onValueChange?: (value: string, customer: Customer) => void;
15
+ placeholder?: string;
16
+ className?: string;
17
+ disabled?: boolean;
18
+ };
19
+
20
+ export function CustomerCombobox({
21
+ entityId,
22
+ value,
23
+ onValueChange,
24
+ placeholder = "Search customer...",
25
+ className,
26
+ disabled,
27
+ }: CustomerComboboxProps) {
28
+ const [search, setSearch] = useState("");
29
+ const [selectedLabel, setSelectedLabel] = useState<string | undefined>(undefined);
30
+ const debouncedSearch = useDebounce(search, 300);
31
+
32
+ // Fetch recent customers (non-blocking, cached)
33
+ const { data: recentData } = useRecentCustomers(entityId);
34
+ const recentCustomers = recentData?.data || [];
35
+
36
+ // Fetch search results
37
+ const { data: searchData, isLoading } = useCustomerSearch(entityId, debouncedSearch);
38
+ const searchResults = searchData?.data || [];
39
+
40
+ // Use search results if searching, otherwise show recent customers
41
+ const customers = useMemo(() => {
42
+ if (debouncedSearch) {
43
+ return searchResults;
44
+ }
45
+ return recentCustomers;
46
+ }, [debouncedSearch, searchResults, recentCustomers]);
47
+
48
+ const options = customers.map((customer) => ({
49
+ value: customer.id,
50
+ label: customer.name,
51
+ }));
52
+
53
+ // Always add "Create new" option at the top
54
+ const createNewLabel = debouncedSearch?.trim() ? `Create "${debouncedSearch}"` : "Create new";
55
+
56
+ options.unshift({
57
+ value: `__create__:${debouncedSearch || ""}`,
58
+ label: (
59
+ <span className="flex items-center gap-2">
60
+ <Plus className="size-4" />
61
+ {createNewLabel}
62
+ </span>
63
+ ) as any,
64
+ });
65
+
66
+ const handleValueChange = (selectedValue: string) => {
67
+ // Handle "create new" selection
68
+ if (selectedValue.startsWith("__create__:")) {
69
+ const customerName = selectedValue.replace("__create__:", "");
70
+
71
+ if (onValueChange) {
72
+ // Pass pseudo-customer with just name, empty id to indicate new customer
73
+ onValueChange("", {
74
+ name: customerName || "",
75
+ address: null,
76
+ address_2: null,
77
+ post_code: null,
78
+ city: null,
79
+ state: null,
80
+ country: null,
81
+ tax_number: null,
82
+ } as Customer);
83
+ }
84
+
85
+ // Clear display
86
+ setSelectedLabel(undefined);
87
+ setSearch("");
88
+ return;
89
+ }
90
+
91
+ // Find customer in both recent and search results
92
+ const selectedCustomer =
93
+ customers.find((c) => c.id === selectedValue) ||
94
+ recentCustomers.find((c) => c.id === selectedValue) ||
95
+ searchResults.find((c) => c.id === selectedValue);
96
+
97
+ if (selectedCustomer) {
98
+ if (onValueChange) {
99
+ onValueChange(selectedValue, selectedCustomer);
100
+ }
101
+ }
102
+
103
+ // Clear display after selection
104
+ setSelectedLabel(undefined);
105
+ setSearch("");
106
+ };
107
+
108
+ // Reset search and label when value changes externally
109
+ useEffect(() => {
110
+ setSearch("");
111
+ if (!value) {
112
+ setSelectedLabel(undefined);
113
+ }
114
+ }, [value]);
115
+
116
+ return (
117
+ <Combobox
118
+ value={value ?? undefined}
119
+ onValueChange={handleValueChange}
120
+ onSearch={setSearch}
121
+ options={options}
122
+ placeholder={placeholder}
123
+ className={className}
124
+ disabled={disabled}
125
+ loading={isLoading}
126
+ emptyText={debouncedSearch ? "No customers found" : "Recent customers"}
127
+ selectedLabel={selectedLabel}
128
+ />
129
+ );
130
+ }
@@ -0,0 +1,48 @@
1
+ import type { Customer } from "@spaceinvoices/js-sdk";
2
+
3
+ import { MoreHorizontal } from "lucide-react";
4
+ import { Button } from "@/ui/components/ui/button";
5
+ import {
6
+ DropdownMenu,
7
+ DropdownMenuContent,
8
+ DropdownMenuItem,
9
+ DropdownMenuLabel,
10
+ DropdownMenuSeparator,
11
+ DropdownMenuTrigger,
12
+ } from "@/ui/components/ui/dropdown-menu";
13
+ import type { ComponentTranslationProps } from "@/ui/lib/translation";
14
+ import { createTranslation } from "@/ui/lib/translation";
15
+
16
+ type CustomerListRowActionsProps = {
17
+ customer: Customer;
18
+ } & ComponentTranslationProps;
19
+
20
+ export default function CustomerListRowActions({ customer, ...i18nProps }: CustomerListRowActionsProps) {
21
+ const t = createTranslation(i18nProps);
22
+
23
+ return (
24
+ <DropdownMenu>
25
+ <DropdownMenuTrigger asChild>
26
+ <Button variant="ghost" className="h-8 w-8 p-0" id="action-menu-trigger">
27
+ <span className="sr-only">{t("Open menu")}</span>
28
+ <MoreHorizontal className="h-4 w-4" />
29
+ </Button>
30
+ </DropdownMenuTrigger>
31
+ <DropdownMenuContent align="end">
32
+ <DropdownMenuLabel>{t("Actions")}</DropdownMenuLabel>
33
+ <DropdownMenuItem className="cursor-pointer" onClick={() => navigator.clipboard.writeText(customer.id)}>
34
+ {t("Copy customer ID")}
35
+ </DropdownMenuItem>
36
+ <DropdownMenuSeparator />
37
+ <DropdownMenuItem
38
+ className="cursor-pointer"
39
+ onClick={() => {
40
+ window.location.href = `/app/customers/${customer.id}`;
41
+ }}
42
+ >
43
+ {t("View customer")}
44
+ </DropdownMenuItem>
45
+ </DropdownMenuContent>
46
+ </DropdownMenu>
47
+ );
48
+ }
@@ -0,0 +1,124 @@
1
+ import type { Customer } from "@spaceinvoices/js-sdk";
2
+ import { User } from "lucide-react";
3
+ import { useMemo } from "react";
4
+ import { Button } from "@/ui/components/ui/button";
5
+ import { createTranslation } from "@/ui/lib/translation";
6
+ import { useSDK } from "@/ui/providers/sdk-provider";
7
+ import { DataTable } from "../../table/data-table";
8
+ import { useTableFetch } from "../../table/hooks/use-table-fetch";
9
+ import type { Column, ListTableProps, TableQueryParams, TableQueryResponse } from "../../table/types";
10
+ import { CUSTOMERS_CACHE_KEY } from "../customers.hooks";
11
+ import CustomerListRowActions from "./customer-list-row-actions";
12
+ import de from "./locales/de";
13
+ import sl from "./locales/sl";
14
+
15
+ const translations = {
16
+ sl,
17
+ de,
18
+ } as const;
19
+
20
+ type CustomerListTableProps = {
21
+ t?: (key: string) => string;
22
+ namespace?: string;
23
+ locale?: string;
24
+ entityId?: string;
25
+ } & ListTableProps<Customer>;
26
+
27
+ export default function CustomerListTable({
28
+ queryParams,
29
+ createNewTrigger,
30
+ onRowClick,
31
+ onChangeParams,
32
+ entityId,
33
+ ...i18nProps
34
+ }: CustomerListTableProps) {
35
+ const t = createTranslation({
36
+ translations,
37
+ ...i18nProps,
38
+ });
39
+ const { sdk } = useSDK();
40
+
41
+ const handleFetch = useTableFetch(async (params: TableQueryParams) => {
42
+ if (!sdk) throw new Error("SDK not initialized");
43
+ if (!params.entity_id) throw new Error("Entity ID required");
44
+
45
+ const response = await sdk.customers.list({
46
+ entity_id: params.entity_id,
47
+ limit: params.limit,
48
+ next_cursor: params.next_cursor,
49
+ prev_cursor: params.prev_cursor,
50
+ order_by: params.order_by,
51
+ search: params.search,
52
+ query: params.query,
53
+ });
54
+ return response as unknown as TableQueryResponse<Customer>;
55
+ }, entityId);
56
+
57
+ const columns: Column<Customer>[] = useMemo(
58
+ () => [
59
+ {
60
+ id: "name",
61
+ header: t("Name"),
62
+ sortable: true,
63
+ cell: (customer) => (
64
+ <Button variant="link" className="cursor-pointer py-0 underline" onClick={() => onRowClick?.(customer)}>
65
+ <User className="h-4 w-4 flex-shrink-0" />
66
+ {customer.name}
67
+ </Button>
68
+ ),
69
+ },
70
+ {
71
+ id: "address",
72
+ header: t("Address"),
73
+ sortable: true,
74
+ cell: (customer) => customer.address,
75
+ },
76
+ {
77
+ id: "post_code",
78
+ header: t("Post Code"),
79
+ cell: (customer) => customer.post_code,
80
+ },
81
+ {
82
+ id: "city",
83
+ header: t("City"),
84
+ cell: (customer) => customer.city,
85
+ },
86
+ {
87
+ id: "state",
88
+ header: t("State"),
89
+ cell: (customer) => customer.state,
90
+ },
91
+ {
92
+ id: "country",
93
+ header: t("Country"),
94
+ cell: (customer) => customer.country,
95
+ },
96
+ {
97
+ id: "tax_number",
98
+ header: t("Tax number"),
99
+ align: "right",
100
+ cell: (customer) => customer.tax_number,
101
+ },
102
+ {
103
+ id: "actions",
104
+ header: "",
105
+ align: "right",
106
+ cell: (customer) => <CustomerListRowActions customer={customer} t={t} />,
107
+ },
108
+ ],
109
+ [t, onRowClick],
110
+ );
111
+
112
+ return (
113
+ <DataTable
114
+ columns={columns}
115
+ queryParams={queryParams}
116
+ resourceName="customer"
117
+ cacheKey={CUSTOMERS_CACHE_KEY}
118
+ createNewTrigger={createNewTrigger}
119
+ onFetch={handleFetch}
120
+ onChangeParams={onChangeParams}
121
+ entityId={entityId}
122
+ />
123
+ );
124
+ }
@@ -0,0 +1,2 @@
1
+ export { default as CustomerListRowActions } from "./customer-list-row-actions";
2
+ export { default as CustomerListTable } from "./customer-list-table";
@@ -0,0 +1,16 @@
1
+ export default {
2
+ Name: "Name",
3
+ Address: "Adresse",
4
+ "Post Code": "Postleitzahl",
5
+ City: "Stadt",
6
+ State: "Bundesland",
7
+ Country: "Land",
8
+ "Tax number": "Steuernummer",
9
+ Email: "E-Mail",
10
+ "Created At": "Erstellt am",
11
+ Actions: "Aktionen",
12
+ "Create new customer": "Neuen Kunden erstellen",
13
+ "Copy customer ID": "Kunden-ID kopieren",
14
+ "View customer": "Kunde anzeigen",
15
+ "Open menu": "Menü öffnen",
16
+ } as const;
@@ -0,0 +1,16 @@
1
+ export default {
2
+ Name: "Ime",
3
+ Address: "Naslov",
4
+ "Post Code": "Poštna številka",
5
+ City: "Mesto",
6
+ State: "Kraj",
7
+ Country: "Država",
8
+ "Tax number": "Davčna številka",
9
+ Email: "E-pošta",
10
+ "Created At": "Ustvarjeno",
11
+ Actions: "Akcije",
12
+ "Create new customer": "Ustvari novo stranko",
13
+ "Copy customer ID": "Kopiraj ID stranke",
14
+ "View customer": "Prikaži stranko",
15
+ "Open menu": "Odpri meni",
16
+ } as const;