@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.
- package/LICENSE +21 -0
- package/README.md +340 -0
- package/cli/dist/index.js +922 -0
- package/package.json +87 -0
- package/registry.json +600 -0
- package/spaceinvoices.schema.json +47 -0
- package/src/app.tsx +25 -0
- package/src/common/autocomplete.tsx +135 -0
- package/src/components/activities/activity-timeline.tsx +160 -0
- package/src/components/activities/index.ts +1 -0
- package/src/components/activities/locales/de.ts +30 -0
- package/src/components/activities/locales/sl.ts +30 -0
- package/src/components/advance-invoices/advance-invoices.hooks.ts +75 -0
- package/src/components/advance-invoices/create/create-advance-invoice-form.tsx +702 -0
- package/src/components/advance-invoices/create/locales/de.ts +29 -0
- package/src/components/advance-invoices/create/locales/sl.ts +25 -0
- package/src/components/advance-invoices/create/prepare-advance-invoice-submission.ts +74 -0
- package/src/components/advance-invoices/index.ts +5 -0
- package/src/components/advance-invoices/list/index.ts +3 -0
- package/src/components/advance-invoices/list/list-row-actions.tsx +119 -0
- package/src/components/advance-invoices/list/list-table.tsx +178 -0
- package/src/components/advance-invoices/list/locales/de.ts +32 -0
- package/src/components/advance-invoices/list/locales/sl.ts +32 -0
- package/src/components/advance-invoices/list/use-advance-invoice-download.ts +63 -0
- package/src/components/button-loader.tsx +11 -0
- package/src/components/combobox.tsx +96 -0
- package/src/components/company-registry/company-registry-autocomplete.tsx +151 -0
- package/src/components/company-registry/company-registry.hooks.ts +67 -0
- package/src/components/company-registry/index.ts +7 -0
- package/src/components/credit-notes/create/create-credit-note-form.tsx +332 -0
- package/src/components/credit-notes/create/index.ts +1 -0
- package/src/components/credit-notes/create/locales/de.ts +69 -0
- package/src/components/credit-notes/create/locales/sl.ts +67 -0
- package/src/components/credit-notes/credit-notes.hooks.ts +22 -0
- package/src/components/credit-notes/index.ts +10 -0
- package/src/components/credit-notes/list/index.ts +3 -0
- package/src/components/credit-notes/list/list-row-actions.tsx +116 -0
- package/src/components/credit-notes/list/list-table.tsx +183 -0
- package/src/components/credit-notes/list/locales/de.ts +33 -0
- package/src/components/credit-notes/list/locales/sl.ts +33 -0
- package/src/components/credit-notes/list/use-credit-note-download.ts +65 -0
- package/src/components/customers/create-customer-form/create-customer-form.tsx +134 -0
- package/src/components/customers/create-customer-form/locales/de.ts +20 -0
- package/src/components/customers/create-customer-form/locales/sl.ts +20 -0
- package/src/components/customers/customer-autocomplete.tsx +173 -0
- package/src/components/customers/customer-combobox.tsx +130 -0
- package/src/components/customers/customer-list-table/customer-list-row-actions.tsx +48 -0
- package/src/components/customers/customer-list-table/customer-list-table.tsx +124 -0
- package/src/components/customers/customer-list-table/index.ts +2 -0
- package/src/components/customers/customer-list-table/locales/de.ts +16 -0
- package/src/components/customers/customer-list-table/locales/sl.ts +16 -0
- package/src/components/customers/customers.hooks.test.ts +348 -0
- package/src/components/customers/customers.hooks.ts +57 -0
- package/src/components/customers/index.ts +5 -0
- package/src/components/dashboard/chart-empty-state.tsx +29 -0
- package/src/components/dashboard/collection-rate-card/collection-rate-card.tsx +80 -0
- package/src/components/dashboard/collection-rate-card/index.ts +4 -0
- package/src/components/dashboard/collection-rate-card/locales/sl.ts +3 -0
- package/src/components/dashboard/collection-rate-card/use-collection-rate.ts +74 -0
- package/src/components/dashboard/index.ts +54 -0
- package/src/components/dashboard/invoice-status-chart/index.ts +4 -0
- package/src/components/dashboard/invoice-status-chart/invoice-status-chart.tsx +130 -0
- package/src/components/dashboard/invoice-status-chart/locales/sl.ts +9 -0
- package/src/components/dashboard/invoice-status-chart/use-invoice-status.ts +105 -0
- package/src/components/dashboard/loading-card.tsx +19 -0
- package/src/components/dashboard/payment-methods-chart/index.ts +4 -0
- package/src/components/dashboard/payment-methods-chart/locales/sl.ts +12 -0
- package/src/components/dashboard/payment-methods-chart/payment-methods-chart.tsx +152 -0
- package/src/components/dashboard/payment-methods-chart/use-payment-methods.ts +50 -0
- package/src/components/dashboard/payment-trend-chart/index.ts +4 -0
- package/src/components/dashboard/payment-trend-chart/locales/sl.ts +5 -0
- package/src/components/dashboard/payment-trend-chart/payment-trend-chart.tsx +137 -0
- package/src/components/dashboard/payment-trend-chart/use-payment-trend.ts +92 -0
- package/src/components/dashboard/revenue-card.tsx +49 -0
- package/src/components/dashboard/revenue-trend-chart/index.ts +4 -0
- package/src/components/dashboard/revenue-trend-chart/locales/sl.ts +5 -0
- package/src/components/dashboard/revenue-trend-chart/revenue-trend-chart.tsx +137 -0
- package/src/components/dashboard/revenue-trend-chart/use-revenue-trend.ts +93 -0
- package/src/components/dashboard/shared/index.ts +5 -0
- package/src/components/dashboard/shared/use-revenue-data.ts +160 -0
- package/src/components/dashboard/shared/use-stats-counts.ts +89 -0
- package/src/components/dashboard/shared/use-stats-query.ts +38 -0
- package/src/components/dashboard/stat-card.tsx +41 -0
- package/src/components/dashboard/tax-collected-card/index.ts +2 -0
- package/src/components/dashboard/tax-collected-card/tax-collected-card.tsx +77 -0
- package/src/components/dashboard/tax-collected-card/use-tax-collected.ts +145 -0
- package/src/components/dashboard/top-customers-chart/index.ts +4 -0
- package/src/components/dashboard/top-customers-chart/locales/sl.ts +5 -0
- package/src/components/dashboard/top-customers-chart/top-customers-chart.tsx +130 -0
- package/src/components/dashboard/top-customers-chart/use-top-customers.ts +72 -0
- package/src/components/documents/create/document-add-item-form.tsx +379 -0
- package/src/components/documents/create/document-add-item-tax-rate-field.tsx +120 -0
- package/src/components/documents/create/document-details-section.tsx +597 -0
- package/src/components/documents/create/document-items-section.tsx +133 -0
- package/src/components/documents/create/document-recipient-section.tsx +101 -0
- package/src/components/documents/create/form-types.ts +36 -0
- package/src/components/documents/create/index.ts +9 -0
- package/src/components/documents/create/live-preview.tsx +235 -0
- package/src/components/documents/create/mark-as-paid-section.tsx +82 -0
- package/src/components/documents/create/prepare-document-submission.test.ts +132 -0
- package/src/components/documents/create/prepare-document-submission.ts +187 -0
- package/src/components/documents/create/prepare-preview-data.test.ts +155 -0
- package/src/components/documents/create/prepare-preview-data.ts +16 -0
- package/src/components/documents/create/smart-code-insert-button.tsx +139 -0
- package/src/components/documents/create/use-document-customer-form.ts +161 -0
- package/src/components/documents/document-preview.tsx +13 -0
- package/src/components/documents/documents.hooks.ts +146 -0
- package/src/components/documents/index.ts +23 -0
- package/src/components/documents/shared/document-preview-display.tsx +172 -0
- package/src/components/documents/shared/index.ts +3 -0
- package/src/components/documents/shared/scaled-document-preview.tsx +70 -0
- package/src/components/documents/shared/use-a4-scaling.ts +62 -0
- package/src/components/documents/types.ts +61 -0
- package/src/components/documents/view/document-actions-bar.tsx +328 -0
- package/src/components/documents/view/document-details-card.tsx +179 -0
- package/src/components/documents/view/document-payments-list.tsx +256 -0
- package/src/components/documents/view/index.ts +4 -0
- package/src/components/documents/view/locales/de.ts +85 -0
- package/src/components/documents/view/locales/sl.ts +84 -0
- package/src/components/documents/view/use-document-download.ts +125 -0
- package/src/components/entities/create-entity-form.tsx +105 -0
- package/src/components/entities/entities.hooks.ts +50 -0
- package/src/components/entities/entity-settings-form/email-template-variables-info.tsx +103 -0
- package/src/components/entities/entity-settings-form/entity-settings-form.tsx +1326 -0
- package/src/components/entities/entity-settings-form/image-upload-with-crop.tsx +222 -0
- package/src/components/entities/entity-settings-form/index.ts +2 -0
- package/src/components/entities/entity-settings-form/input-with-preview.tsx +190 -0
- package/src/components/entities/entity-settings-form/locales/de.ts +192 -0
- package/src/components/entities/entity-settings-form/locales/sl.ts +188 -0
- package/src/components/entities/furs-settings-form/furs-settings-form.tsx +410 -0
- package/src/components/entities/furs-settings-form/furs-settings.hooks.ts +320 -0
- package/src/components/entities/furs-settings-form/index.ts +3 -0
- package/src/components/entities/furs-settings-form/locales/de.ts +233 -0
- package/src/components/entities/furs-settings-form/locales/en.ts +194 -0
- package/src/components/entities/furs-settings-form/locales/sl.ts +196 -0
- package/src/components/entities/furs-settings-form/sections/certificate-settings-section.tsx +242 -0
- package/src/components/entities/furs-settings-form/sections/enable-fiscalization-section.tsx +139 -0
- package/src/components/entities/furs-settings-form/sections/general-settings-section.tsx +252 -0
- package/src/components/entities/furs-settings-form/sections/premises-management-section.tsx +370 -0
- package/src/components/entities/furs-settings-form/sections/register-premise-dialog.tsx +420 -0
- package/src/components/entities/keys.ts +2 -0
- package/src/components/entities/settings/branding-settings-form.tsx +274 -0
- package/src/components/entities/settings/company-settings-form.tsx +256 -0
- package/src/components/entities/settings/defaults-settings-form.tsx +501 -0
- package/src/components/entities/settings/email-settings-form.tsx +288 -0
- package/src/components/entities/settings/eslog-settings-form.tsx +113 -0
- package/src/components/entities/settings/index.ts +8 -0
- package/src/components/entities/settings/number-format-settings-form.tsx +244 -0
- package/src/components/entities/settings/pdf-template-selector/demo-invoice-data.ts +164 -0
- package/src/components/entities/settings/pdf-template-selector/index.ts +2 -0
- package/src/components/entities/settings/pdf-template-selector/locales/de.ts +18 -0
- package/src/components/entities/settings/pdf-template-selector/locales/sl.ts +18 -0
- package/src/components/entities/settings/pdf-template-selector/pdf-template-cards.tsx +49 -0
- package/src/components/entities/settings/settings-footer.tsx +16 -0
- package/src/components/entities/settings/tax-rules-settings-form.tsx +346 -0
- package/src/components/estimates/create/create-estimate-form.tsx +384 -0
- package/src/components/estimates/create/locales/de.ts +64 -0
- package/src/components/estimates/create/locales/sl.ts +63 -0
- package/src/components/estimates/create/prepare-estimate-submission.ts +39 -0
- package/src/components/estimates/create/use-estimate-customer-form.ts +5 -0
- package/src/components/estimates/estimates.hooks.ts +15 -0
- package/src/components/estimates/index.ts +6 -0
- package/src/components/estimates/list/index.ts +3 -0
- package/src/components/estimates/list/list-row-actions.tsx +103 -0
- package/src/components/estimates/list/list-table.tsx +171 -0
- package/src/components/estimates/list/locales/de.ts +26 -0
- package/src/components/estimates/list/locales/sl.ts +26 -0
- package/src/components/estimates/list/use-estimate-download.ts +63 -0
- package/src/components/export/document-export-form.tsx +288 -0
- package/src/components/export/index.ts +2 -0
- package/src/components/form/form-input.tsx +89 -0
- package/src/components/form/index.ts +1 -0
- package/src/components/invoices/create/create-invoice-form.tsx +852 -0
- package/src/components/invoices/create/eslog-validation.test.ts +242 -0
- package/src/components/invoices/create/eslog-validation.ts +208 -0
- package/src/components/invoices/create/locales/de.ts +118 -0
- package/src/components/invoices/create/locales/sl.ts +114 -0
- package/src/components/invoices/create/prepare-invoice-submission.test.ts +777 -0
- package/src/components/invoices/create/prepare-invoice-submission.ts +79 -0
- package/src/components/invoices/create/use-invoice-customer-form.ts +5 -0
- package/src/components/invoices/index.ts +9 -0
- package/src/components/invoices/invoices-furs.hooks.ts +28 -0
- package/src/components/invoices/invoices.hooks.ts +110 -0
- package/src/components/invoices/list/index.ts +3 -0
- package/src/components/invoices/list/list-row-actions.tsx +132 -0
- package/src/components/invoices/list/list-table.tsx +165 -0
- package/src/components/invoices/list/locales/de.ts +33 -0
- package/src/components/invoices/list/locales/sl.ts +33 -0
- package/src/components/invoices/list/use-invoice-download.ts +62 -0
- package/src/components/invoices/send-email-dialog/index.ts +1 -0
- package/src/components/invoices/send-email-dialog/locales/de.ts +18 -0
- package/src/components/invoices/send-email-dialog/locales/sl.ts +17 -0
- package/src/components/invoices/send-email-dialog/send-email-dialog.tsx +289 -0
- package/src/components/invoices/send-email-dialog.tsx +2 -0
- package/src/components/invoices/shared/index.ts +2 -0
- package/src/components/invoices/shared/scaled-document-preview.tsx +32 -0
- package/src/components/invoices/shared/use-a4-scaling.tsx +39 -0
- package/src/components/invoices/view/eslog-info-display.tsx +160 -0
- package/src/components/invoices/view/furs-info-display.tsx +213 -0
- package/src/components/items/create-item-form/create-item-form.tsx +155 -0
- package/src/components/items/create-item-form/locales/de.ts +14 -0
- package/src/components/items/create-item-form/locales/en.ts +9 -0
- package/src/components/items/create-item-form/locales/sl.ts +14 -0
- package/src/components/items/item-combobox.tsx +147 -0
- package/src/components/items/item-list-table/item-list-header.tsx +33 -0
- package/src/components/items/item-list-table/item-list-row-actions.tsx +48 -0
- package/src/components/items/item-list-table/item-list-row.tsx +32 -0
- package/src/components/items/item-list-table/item-list-table.tsx +76 -0
- package/src/components/items/item-list-table/locales/de.ts +10 -0
- package/src/components/items/item-list-table/locales/en.ts +10 -0
- package/src/components/items/item-list-table/locales/sl.ts +10 -0
- package/src/components/items/items.hooks.ts +63 -0
- package/src/components/loading-spinner.tsx +24 -0
- package/src/components/payments/create-payment-form/create-payment-form.tsx +222 -0
- package/src/components/payments/create-payment-form/locales/de.ts +20 -0
- package/src/components/payments/create-payment-form/locales/sl.ts +20 -0
- package/src/components/payments/edit-payment-form/edit-payment-form.tsx +230 -0
- package/src/components/payments/edit-payment-form/index.ts +1 -0
- package/src/components/payments/edit-payment-form/locales/de.ts +20 -0
- package/src/components/payments/edit-payment-form/locales/sl.ts +20 -0
- package/src/components/payments/index.ts +4 -0
- package/src/components/payments/list/index.ts +2 -0
- package/src/components/payments/list/list-row-actions.tsx +98 -0
- package/src/components/payments/list/list-table.tsx +186 -0
- package/src/components/payments/list/locales/de.ts +19 -0
- package/src/components/payments/list/locales/sl.ts +19 -0
- package/src/components/payments/payments.hooks.ts +15 -0
- package/src/components/request-logs/index.ts +3 -0
- package/src/components/request-logs/request-log-detail.tsx +242 -0
- package/src/components/request-logs/request-log-list-table.tsx +266 -0
- package/src/components/request-logs/request-logs-page.tsx +10 -0
- package/src/components/table/README.md +410 -0
- package/src/components/table/data-table.tsx +251 -0
- package/src/components/table/date-cell.tsx +35 -0
- package/src/components/table/filter-bar.tsx +114 -0
- package/src/components/table/filter-panel.tsx +407 -0
- package/src/components/table/hooks/use-table-fetch.ts +17 -0
- package/src/components/table/hooks/use-table-query.ts +36 -0
- package/src/components/table/hooks/use-table-state.ts +293 -0
- package/src/components/table/index.ts +35 -0
- package/src/components/table/search-input.tsx +85 -0
- package/src/components/table/sortable-header.tsx +56 -0
- package/src/components/table/table-empty-state.tsx +40 -0
- package/src/components/table/table-no-results.tsx +41 -0
- package/src/components/table/table-pagination.tsx +42 -0
- package/src/components/table/table-skeleton.tsx +54 -0
- package/src/components/table/types.ts +136 -0
- package/src/components/tax-reports/index.ts +1 -0
- package/src/components/tax-reports/kir-export-form.tsx +172 -0
- package/src/components/taxes/create-tax-form/create-tax-form.tsx +112 -0
- package/src/components/taxes/create-tax-form/locales/de.ts +8 -0
- package/src/components/taxes/create-tax-form/locales/en.ts +7 -0
- package/src/components/taxes/create-tax-form/locales/sl.ts +8 -0
- package/src/components/taxes/tax-list-table/locales/de.ts +11 -0
- package/src/components/taxes/tax-list-table/locales/en.ts +10 -0
- package/src/components/taxes/tax-list-table/locales/sl.ts +11 -0
- package/src/components/taxes/tax-list-table/tax-list-header.tsx +29 -0
- package/src/components/taxes/tax-list-table/tax-list-row-actions.tsx +43 -0
- package/src/components/taxes/tax-list-table/tax-list-row.tsx +46 -0
- package/src/components/taxes/tax-list-table/tax-list-table.tsx +59 -0
- package/src/components/taxes/taxes.hooks.ts +35 -0
- package/src/components/ui/alert-dialog.tsx +61 -0
- package/src/components/ui/alert.tsx +72 -0
- package/src/components/ui/badge.tsx +48 -0
- package/src/components/ui/breadcrumb.tsx +132 -0
- package/src/components/ui/button.tsx +61 -0
- package/src/components/ui/calendar.tsx +213 -0
- package/src/components/ui/card.tsx +94 -0
- package/src/components/ui/chart.tsx +380 -0
- package/src/components/ui/checkbox.tsx +27 -0
- package/src/components/ui/collapsible.tsx +56 -0
- package/src/components/ui/command.tsx +187 -0
- package/src/components/ui/dialog.tsx +187 -0
- package/src/components/ui/drawer.tsx +123 -0
- package/src/components/ui/dropdown-menu.tsx +291 -0
- package/src/components/ui/form.tsx +166 -0
- package/src/components/ui/input-group.tsx +149 -0
- package/src/components/ui/input.tsx +20 -0
- package/src/components/ui/label.tsx +18 -0
- package/src/components/ui/loading-spinner.tsx +16 -0
- package/src/components/ui/popover.tsx +108 -0
- package/src/components/ui/radio-group.tsx +37 -0
- package/src/components/ui/select.tsx +200 -0
- package/src/components/ui/separator.tsx +23 -0
- package/src/components/ui/sheet.tsx +145 -0
- package/src/components/ui/sidebar.tsx +771 -0
- package/src/components/ui/skeleton.tsx +13 -0
- package/src/components/ui/sonner.tsx +60 -0
- package/src/components/ui/spinner.tsx +10 -0
- package/src/components/ui/sticky-form-footer.tsx +55 -0
- package/src/components/ui/switch.tsx +30 -0
- package/src/components/ui/table.tsx +101 -0
- package/src/components/ui/tabs.tsx +80 -0
- package/src/components/ui/textarea.tsx +18 -0
- package/src/components/ui/tooltip.tsx +89 -0
- package/src/components/wl-subscription/index.ts +2 -0
- package/src/components/wl-subscription/locked-feature.tsx +173 -0
- package/src/components/wl-subscription/upgrade-modal.tsx +209 -0
- package/src/frontend.tsx +28 -0
- package/src/generate-schemas.ts +265 -0
- package/src/generated/schemas/advanceinvoice.ts +177 -0
- package/src/generated/schemas/creditnote.ts +187 -0
- package/src/generated/schemas/customer.ts +29 -0
- package/src/generated/schemas/entity.ts +252 -0
- package/src/generated/schemas/estimate.ts +159 -0
- package/src/generated/schemas/furssettings.ts +25 -0
- package/src/generated/schemas/index.ts +24 -0
- package/src/generated/schemas/invoice.ts +167 -0
- package/src/generated/schemas/item.ts +38 -0
- package/src/generated/schemas/payment.ts +44 -0
- package/src/generated/schemas/previewadvanceinvoice_body.ts +354 -0
- package/src/generated/schemas/previewestimate_body.ts +309 -0
- package/src/generated/schemas/registerfursmovablepremise_body.ts +22 -0
- package/src/generated/schemas/registerfursrealestatepremise_body.ts +32 -0
- package/src/generated/schemas/renderdocument_body.ts +594 -0
- package/src/generated/schemas/sendemail_body.ts +26 -0
- package/src/generated/schemas/startpdfexport_body.ts +20 -0
- package/src/generated/schemas/tax.ts +48 -0
- package/src/generated/schemas/uploadfile_body.ts +23 -0
- package/src/generated/schemas/uploadfurscertificate_body.ts +20 -0
- package/src/generated/schemas/userfurssettings.ts +19 -0
- package/src/hooks/create-resource-hooks.test.ts +483 -0
- package/src/hooks/create-resource-hooks.ts +300 -0
- package/src/hooks/use-debounce.ts +12 -0
- package/src/hooks/use-duplicate-document.ts +185 -0
- package/src/hooks/use-media-query.tsx +19 -0
- package/src/hooks/use-mobile.ts +39 -0
- package/src/hooks/use-next-document-number.ts +57 -0
- package/src/hooks/use-resource-mutation.ts +118 -0
- package/src/hooks/use-vies-check.ts +130 -0
- package/src/index.css +11 -0
- package/src/index.html +13 -0
- package/src/index.tsx +12 -0
- package/src/lib/auth.ts +4 -0
- package/src/lib/browser-cookies.ts +70 -0
- package/src/lib/constants.ts +287 -0
- package/src/lib/cookies.ts +36 -0
- package/src/lib/schemas/advance-invoice.ts +43 -0
- package/src/lib/schemas/credit-note.ts +32 -0
- package/src/lib/schemas/estimate.ts +31 -0
- package/src/lib/schemas/index.ts +18 -0
- package/src/lib/schemas/invoice.ts +43 -0
- package/src/lib/schemas/shared.ts +79 -0
- package/src/lib/translation.ts +38 -0
- package/src/lib/utils.ts +6 -0
- package/src/providers/entities-context.tsx +41 -0
- package/src/providers/entities-provider.tsx +201 -0
- package/src/providers/form-footer-context.tsx +72 -0
- package/src/providers/sdk-provider.tsx +164 -0
- package/src/providers/white-label-provider.tsx +91 -0
- package/src/providers/wl-subscription-provider.tsx +277 -0
- package/src/utils/string-helpers.ts +111 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Column definition for table headers and cells
|
|
5
|
+
*/
|
|
6
|
+
export type Column<T> = {
|
|
7
|
+
/** Unique identifier for the column */
|
|
8
|
+
id: string;
|
|
9
|
+
/** Header label or component */
|
|
10
|
+
header: ReactNode;
|
|
11
|
+
/** Cell renderer function - returns content for each row */
|
|
12
|
+
cell: (item: T) => ReactNode;
|
|
13
|
+
/** Field name for sorting (if different from id) */
|
|
14
|
+
sortField?: string;
|
|
15
|
+
/** Whether this column is sortable */
|
|
16
|
+
sortable?: boolean;
|
|
17
|
+
/** Text alignment */
|
|
18
|
+
align?: "left" | "center" | "right";
|
|
19
|
+
/** Optional CSS class for the column */
|
|
20
|
+
className?: string;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Query parameters for table data fetching
|
|
25
|
+
*/
|
|
26
|
+
export type TableQueryParams = {
|
|
27
|
+
order_by?: string;
|
|
28
|
+
search?: string;
|
|
29
|
+
prev_cursor?: string;
|
|
30
|
+
next_cursor?: string;
|
|
31
|
+
entity_id?: string;
|
|
32
|
+
limit?: number;
|
|
33
|
+
query?: string; // JSON string for API query filters (built from filter_* params)
|
|
34
|
+
// URL-friendly filter params (used for URL state, converted to query for API)
|
|
35
|
+
filter_date_field?: string;
|
|
36
|
+
filter_date_from?: string; // YYYY-MM-DD
|
|
37
|
+
filter_date_to?: string; // YYYY-MM-DD
|
|
38
|
+
filter_status?: string; // comma-separated: "paid,unpaid,overdue,voided"
|
|
39
|
+
// HTTP-specific filter params (for request logs)
|
|
40
|
+
filter_method?: string; // GET, POST, PATCH, PUT, DELETE
|
|
41
|
+
filter_http_status?: string; // 2xx, 4xx, 5xx
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Date range for filtering
|
|
46
|
+
*/
|
|
47
|
+
export type DateRange = {
|
|
48
|
+
from?: Date;
|
|
49
|
+
to?: Date;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Date filter state
|
|
54
|
+
*/
|
|
55
|
+
export type DateFilter = {
|
|
56
|
+
field: string;
|
|
57
|
+
range: DateRange;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Status filter options (invoice status)
|
|
62
|
+
*/
|
|
63
|
+
export type StatusFilter = "paid" | "unpaid" | "overdue" | "voided";
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* HTTP method filter options
|
|
67
|
+
*/
|
|
68
|
+
export type HttpMethodFilter = "GET" | "POST" | "PATCH" | "PUT" | "DELETE";
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* HTTP status code filter options (prefix patterns like 2xx, 4xx, 5xx)
|
|
72
|
+
*/
|
|
73
|
+
export type HttpStatusCodeFilter = "2xx" | "4xx" | "5xx";
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Filterable date field definition
|
|
77
|
+
*/
|
|
78
|
+
export type FilterableDateField = {
|
|
79
|
+
id: string;
|
|
80
|
+
label: string;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Filter configuration for tables
|
|
85
|
+
*/
|
|
86
|
+
export type FilterConfig = {
|
|
87
|
+
dateFields?: FilterableDateField[];
|
|
88
|
+
statusFilter?: boolean;
|
|
89
|
+
/** Enable HTTP method filter (for request logs) */
|
|
90
|
+
httpMethodFilter?: boolean;
|
|
91
|
+
/** Enable HTTP status code filter (for request logs) */
|
|
92
|
+
httpStatusCodeFilter?: boolean;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Current filter state
|
|
97
|
+
*/
|
|
98
|
+
export type FilterState = {
|
|
99
|
+
dateFilter?: DateFilter;
|
|
100
|
+
statusFilters?: StatusFilter[];
|
|
101
|
+
/** Selected HTTP method (for request logs) */
|
|
102
|
+
httpMethod?: HttpMethodFilter;
|
|
103
|
+
/** Selected HTTP status code pattern (for request logs) */
|
|
104
|
+
httpStatusCode?: HttpStatusCodeFilter;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Pagination metadata structure
|
|
109
|
+
*/
|
|
110
|
+
export type PaginationMetadata = {
|
|
111
|
+
total: number;
|
|
112
|
+
next_cursor: string | null;
|
|
113
|
+
prev_cursor: string | null;
|
|
114
|
+
has_more: boolean;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Response structure from table data fetch
|
|
119
|
+
*/
|
|
120
|
+
export type TableQueryResponse<T> = {
|
|
121
|
+
data: T[];
|
|
122
|
+
pagination: PaginationMetadata;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Props for list table components
|
|
127
|
+
*/
|
|
128
|
+
export type ListTableProps<T> = {
|
|
129
|
+
createNewTrigger?: ReactNode;
|
|
130
|
+
queryParams?: TableQueryParams;
|
|
131
|
+
onChangeParams?: (params: TableQueryParams) => void;
|
|
132
|
+
/** When true, disables URL sync entirely (for embedded tables like dashboard) */
|
|
133
|
+
disableUrlSync?: boolean;
|
|
134
|
+
onRowClick?: (item: T) => void;
|
|
135
|
+
entityId?: string;
|
|
136
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { KirExportForm } from "./kir-export-form";
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import type SDK from "@spaceinvoices/js-sdk";
|
|
2
|
+
|
|
3
|
+
type TFunction = (key: string, options?: Record<string, unknown>) => string;
|
|
4
|
+
|
|
5
|
+
import { Download, Loader2 } from "lucide-react";
|
|
6
|
+
import { useRef, useState } from "react";
|
|
7
|
+
import { Button } from "../ui/button";
|
|
8
|
+
import { Label } from "../ui/label";
|
|
9
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/select";
|
|
10
|
+
|
|
11
|
+
type PeriodType = "month" | "quarter";
|
|
12
|
+
|
|
13
|
+
function getCurrentYear(): number {
|
|
14
|
+
return new Date().getFullYear();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function getPreviousMonth(): { year: number; month: number } {
|
|
18
|
+
const now = new Date();
|
|
19
|
+
const prevMonth = now.getMonth(); // 0-indexed, so this is already previous month
|
|
20
|
+
const year = prevMonth === 0 ? now.getFullYear() - 1 : now.getFullYear();
|
|
21
|
+
const month = prevMonth === 0 ? 12 : prevMonth;
|
|
22
|
+
return { year, month };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
type KirExportFormProps = {
|
|
26
|
+
sdk: SDK;
|
|
27
|
+
entityId: string;
|
|
28
|
+
t: TFunction;
|
|
29
|
+
onSuccess?: (fileName: string) => void;
|
|
30
|
+
onError?: (error: Error) => void;
|
|
31
|
+
onLoadingChange?: (isLoading: boolean, toastId: string | number | null) => void;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export function KirExportForm({ sdk, entityId, t, onSuccess, onError, onLoadingChange }: KirExportFormProps) {
|
|
35
|
+
const defaultPeriod = getPreviousMonth();
|
|
36
|
+
const [year, setYear] = useState(defaultPeriod.year);
|
|
37
|
+
const [periodType, setPeriodType] = useState<PeriodType>("month");
|
|
38
|
+
const [month, setMonth] = useState(defaultPeriod.month);
|
|
39
|
+
const [quarter, setQuarter] = useState(Math.ceil(defaultPeriod.month / 3));
|
|
40
|
+
const [isExporting, setIsExporting] = useState(false);
|
|
41
|
+
|
|
42
|
+
const toastIdRef = useRef<string | number | null>(null);
|
|
43
|
+
|
|
44
|
+
// Generate year options (current year + 5 previous years)
|
|
45
|
+
const currentYear = getCurrentYear();
|
|
46
|
+
const yearOptions = Array.from({ length: 6 }, (_, i) => currentYear - i);
|
|
47
|
+
|
|
48
|
+
const handleExport = async () => {
|
|
49
|
+
setIsExporting(true);
|
|
50
|
+
onLoadingChange?.(true, null);
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
const blob = await sdk.taxReports.generateKirExport(
|
|
54
|
+
{
|
|
55
|
+
year: year.toString(),
|
|
56
|
+
month: periodType === "month" ? month.toString() : undefined,
|
|
57
|
+
quarter: periodType === "quarter" ? quarter.toString() : undefined,
|
|
58
|
+
},
|
|
59
|
+
{ entity_id: entityId },
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
// Generate filename
|
|
63
|
+
const fileName = `KIR_${year}_${periodType === "month" ? `M${month}` : `Q${quarter}`}.zip`;
|
|
64
|
+
|
|
65
|
+
// Download the file
|
|
66
|
+
const downloadUrl = window.URL.createObjectURL(blob);
|
|
67
|
+
const link = document.createElement("a");
|
|
68
|
+
link.href = downloadUrl;
|
|
69
|
+
link.download = fileName;
|
|
70
|
+
document.body.appendChild(link);
|
|
71
|
+
link.click();
|
|
72
|
+
setTimeout(() => {
|
|
73
|
+
document.body.removeChild(link);
|
|
74
|
+
window.URL.revokeObjectURL(downloadUrl);
|
|
75
|
+
}, 1000);
|
|
76
|
+
|
|
77
|
+
onSuccess?.(fileName);
|
|
78
|
+
} catch (error) {
|
|
79
|
+
console.error("KIR export error:", error);
|
|
80
|
+
onError?.(error instanceof Error ? error : new Error("Unknown error"));
|
|
81
|
+
} finally {
|
|
82
|
+
setIsExporting(false);
|
|
83
|
+
onLoadingChange?.(false, toastIdRef.current);
|
|
84
|
+
toastIdRef.current = null;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<div className="space-y-4">
|
|
90
|
+
{/* Year Selection */}
|
|
91
|
+
<div className="space-y-2">
|
|
92
|
+
<Label htmlFor="kir-year">{t("kir-export.year")}</Label>
|
|
93
|
+
<Select value={year.toString()} onValueChange={(v) => setYear(Number(v))}>
|
|
94
|
+
<SelectTrigger id="kir-year">
|
|
95
|
+
<SelectValue />
|
|
96
|
+
</SelectTrigger>
|
|
97
|
+
<SelectContent>
|
|
98
|
+
{yearOptions.map((y) => (
|
|
99
|
+
<SelectItem key={y} value={y.toString()}>
|
|
100
|
+
{y}
|
|
101
|
+
</SelectItem>
|
|
102
|
+
))}
|
|
103
|
+
</SelectContent>
|
|
104
|
+
</Select>
|
|
105
|
+
</div>
|
|
106
|
+
|
|
107
|
+
{/* Period Type Selection */}
|
|
108
|
+
<div className="space-y-2">
|
|
109
|
+
<Label htmlFor="kir-period-type">{t("kir-export.period-type")}</Label>
|
|
110
|
+
<Select value={periodType} onValueChange={(v) => setPeriodType(v as PeriodType)}>
|
|
111
|
+
<SelectTrigger id="kir-period-type">
|
|
112
|
+
<SelectValue />
|
|
113
|
+
</SelectTrigger>
|
|
114
|
+
<SelectContent>
|
|
115
|
+
<SelectItem value="month">{t("kir-export.period-types.month")}</SelectItem>
|
|
116
|
+
<SelectItem value="quarter">{t("kir-export.period-types.quarter")}</SelectItem>
|
|
117
|
+
</SelectContent>
|
|
118
|
+
</Select>
|
|
119
|
+
</div>
|
|
120
|
+
|
|
121
|
+
{/* Month/Quarter Selection */}
|
|
122
|
+
{periodType === "month" ? (
|
|
123
|
+
<div className="space-y-2">
|
|
124
|
+
<Label htmlFor="kir-month">{t("kir-export.month")}</Label>
|
|
125
|
+
<Select value={month.toString()} onValueChange={(v) => setMonth(Number(v))}>
|
|
126
|
+
<SelectTrigger id="kir-month">
|
|
127
|
+
<SelectValue />
|
|
128
|
+
</SelectTrigger>
|
|
129
|
+
<SelectContent>
|
|
130
|
+
{Array.from({ length: 12 }, (_, i) => i + 1).map((m) => (
|
|
131
|
+
<SelectItem key={m} value={m.toString()}>
|
|
132
|
+
{t(`kir-export.months.${m}`)}
|
|
133
|
+
</SelectItem>
|
|
134
|
+
))}
|
|
135
|
+
</SelectContent>
|
|
136
|
+
</Select>
|
|
137
|
+
</div>
|
|
138
|
+
) : (
|
|
139
|
+
<div className="space-y-2">
|
|
140
|
+
<Label htmlFor="kir-quarter">{t("kir-export.quarter")}</Label>
|
|
141
|
+
<Select value={quarter.toString()} onValueChange={(v) => setQuarter(Number(v))}>
|
|
142
|
+
<SelectTrigger id="kir-quarter">
|
|
143
|
+
<SelectValue />
|
|
144
|
+
</SelectTrigger>
|
|
145
|
+
<SelectContent>
|
|
146
|
+
{[1, 2, 3, 4].map((q) => (
|
|
147
|
+
<SelectItem key={q} value={q.toString()}>
|
|
148
|
+
{t(`kir-export.quarters.${q}`)}
|
|
149
|
+
</SelectItem>
|
|
150
|
+
))}
|
|
151
|
+
</SelectContent>
|
|
152
|
+
</Select>
|
|
153
|
+
</div>
|
|
154
|
+
)}
|
|
155
|
+
|
|
156
|
+
{/* Export Button */}
|
|
157
|
+
<Button onClick={handleExport} disabled={isExporting} className="w-full">
|
|
158
|
+
{isExporting ? (
|
|
159
|
+
<>
|
|
160
|
+
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
|
161
|
+
{t("kir-export.exporting")}
|
|
162
|
+
</>
|
|
163
|
+
) : (
|
|
164
|
+
<>
|
|
165
|
+
<Download className="mr-2 h-4 w-4" />
|
|
166
|
+
{t("kir-export.export-button")}
|
|
167
|
+
</>
|
|
168
|
+
)}
|
|
169
|
+
</Button>
|
|
170
|
+
</div>
|
|
171
|
+
);
|
|
172
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { zodResolver } from "@hookform/resolvers/zod";
|
|
2
|
+
import type { CreateTaxRequest, Tax } from "@spaceinvoices/js-sdk";
|
|
3
|
+
import { useForm } from "react-hook-form";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { FormInput } from "@/ui/components/form";
|
|
6
|
+
import { Checkbox } from "@/ui/components/ui/checkbox";
|
|
7
|
+
import { Form, FormControl, FormField, FormItem, FormLabel } from "@/ui/components/ui/form";
|
|
8
|
+
import { createTaxSchema as baseCreateTaxSchema } from "@/ui/generated/schemas";
|
|
9
|
+
import type { ComponentTranslationProps } from "@/ui/lib/translation";
|
|
10
|
+
import { createTranslation } from "@/ui/lib/translation";
|
|
11
|
+
|
|
12
|
+
// Extend base schema with is_default field
|
|
13
|
+
const createTaxSchema = baseCreateTaxSchema.extend({
|
|
14
|
+
is_default: z.boolean().optional(),
|
|
15
|
+
});
|
|
16
|
+
type CreateTaxSchema = z.infer<typeof createTaxSchema>;
|
|
17
|
+
|
|
18
|
+
import { useCreateTax } from "../taxes.hooks";
|
|
19
|
+
import de from "./locales/de";
|
|
20
|
+
import sl from "./locales/sl";
|
|
21
|
+
|
|
22
|
+
const translations = {
|
|
23
|
+
sl,
|
|
24
|
+
de,
|
|
25
|
+
} as const;
|
|
26
|
+
|
|
27
|
+
type CreateTaxFormProps = {
|
|
28
|
+
entityId: string;
|
|
29
|
+
onSuccess?: (tax: Tax) => void;
|
|
30
|
+
onError?: (error: Error) => void;
|
|
31
|
+
renderSubmitButton?: (props: { isSubmitting: boolean; submit: () => void }) => React.ReactNode;
|
|
32
|
+
} & ComponentTranslationProps;
|
|
33
|
+
|
|
34
|
+
export default function CreateTaxForm({
|
|
35
|
+
entityId,
|
|
36
|
+
onSuccess,
|
|
37
|
+
onError,
|
|
38
|
+
renderSubmitButton,
|
|
39
|
+
...i18nProps
|
|
40
|
+
}: CreateTaxFormProps) {
|
|
41
|
+
const t = createTranslation({
|
|
42
|
+
...i18nProps,
|
|
43
|
+
translations,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const form = useForm<CreateTaxSchema>({
|
|
47
|
+
resolver: zodResolver(createTaxSchema),
|
|
48
|
+
defaultValues: {
|
|
49
|
+
name: "",
|
|
50
|
+
tax_rates: [{ rate: undefined }],
|
|
51
|
+
is_default: false,
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const { mutate: createTax, isPending } = useCreateTax({
|
|
56
|
+
entityId,
|
|
57
|
+
onSuccess: (tax, _variables, _context) => {
|
|
58
|
+
onSuccess?.(tax);
|
|
59
|
+
form.reset();
|
|
60
|
+
},
|
|
61
|
+
onError: (error, _variables, _context) => {
|
|
62
|
+
form.setError("root", {
|
|
63
|
+
type: "submit",
|
|
64
|
+
message: t("There was an error creating the tax"),
|
|
65
|
+
});
|
|
66
|
+
onError?.(error);
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const onSubmit = async (values: CreateTaxSchema) => {
|
|
71
|
+
// SDK accepts both Date and string for date fields, no conversion needed
|
|
72
|
+
createTax(values as CreateTaxRequest);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const handleSubmitClick = () => {
|
|
76
|
+
form.handleSubmit(onSubmit)();
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<Form {...form}>
|
|
81
|
+
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
|
|
82
|
+
<FormInput control={form.control} name="name" label={t("Name")} placeholder={t("Enter name")} />
|
|
83
|
+
|
|
84
|
+
<FormInput
|
|
85
|
+
control={form.control}
|
|
86
|
+
name="tax_rates.0.rate"
|
|
87
|
+
label={t("Rate (%)")}
|
|
88
|
+
placeholder={t("Enter rate")}
|
|
89
|
+
type="number"
|
|
90
|
+
/>
|
|
91
|
+
|
|
92
|
+
<FormField
|
|
93
|
+
control={form.control}
|
|
94
|
+
name="is_default"
|
|
95
|
+
render={({ field }) => (
|
|
96
|
+
<FormItem className="flex flex-row items-center space-x-3 space-y-0">
|
|
97
|
+
<FormControl>
|
|
98
|
+
<Checkbox checked={field.value} onCheckedChange={field.onChange} />
|
|
99
|
+
</FormControl>
|
|
100
|
+
<FormLabel className="font-normal">{t("Set as default tax")}</FormLabel>
|
|
101
|
+
</FormItem>
|
|
102
|
+
)}
|
|
103
|
+
/>
|
|
104
|
+
|
|
105
|
+
{renderSubmitButton?.({
|
|
106
|
+
isSubmitting: isPending || form.formState.isSubmitting,
|
|
107
|
+
submit: handleSubmitClick,
|
|
108
|
+
})}
|
|
109
|
+
</form>
|
|
110
|
+
</Form>
|
|
111
|
+
);
|
|
112
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
Name: "Name",
|
|
3
|
+
"Enter name": "Name eingeben",
|
|
4
|
+
"Rate (%)": "Satz (%)",
|
|
5
|
+
"Enter rate": "Satz eingeben",
|
|
6
|
+
"Set as default tax": "Als Standardsteuer festlegen",
|
|
7
|
+
"There was an error creating the tax": "Beim Erstellen der Steuer ist ein Fehler aufgetreten",
|
|
8
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
Name: "Ime",
|
|
3
|
+
"Enter name": "Vnesite ime",
|
|
4
|
+
"Rate (%)": "Stopnja (%)",
|
|
5
|
+
"Enter rate": "Vnesite stopnjo",
|
|
6
|
+
"Set as default tax": "Nastavi kot privzeti davek",
|
|
7
|
+
"There was an error creating the tax": "Pri ustvarjanju davka je prišlo do napake",
|
|
8
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
Name: "Name",
|
|
3
|
+
"Tax Rates": "Steuersätze",
|
|
4
|
+
Created: "Erstellt",
|
|
5
|
+
Default: "Standard",
|
|
6
|
+
"Unnamed Tax": "Unbenannte Steuer",
|
|
7
|
+
"Open menu": "Menü öffnen",
|
|
8
|
+
Actions: "Aktionen",
|
|
9
|
+
"Copy tax ID": "Steuer-ID kopieren",
|
|
10
|
+
"View tax": "Steuer anzeigen",
|
|
11
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
Name: "Ime",
|
|
3
|
+
"Tax Rates": "Davčne stopnje",
|
|
4
|
+
Created: "Ustvarjeno",
|
|
5
|
+
Default: "Privzeto",
|
|
6
|
+
"Unnamed Tax": "Neimenovan davek",
|
|
7
|
+
"Open menu": "Odpri meni",
|
|
8
|
+
Actions: "Akcije",
|
|
9
|
+
"Copy tax ID": "Kopiraj ID davka",
|
|
10
|
+
"View tax": "Poglej davek",
|
|
11
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { TableHead, TableHeader, TableRow } from "@/ui/components/ui/table";
|
|
2
|
+
import { SortableHeader } from "../../table/sortable-header";
|
|
3
|
+
|
|
4
|
+
type TaxListHeaderProps = {
|
|
5
|
+
orderBy?: string;
|
|
6
|
+
onSort?: (order: string | null) => void;
|
|
7
|
+
t: (key: string) => string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default function TaxListHeader({ orderBy, onSort, t }: TaxListHeaderProps) {
|
|
11
|
+
return (
|
|
12
|
+
<TableHeader>
|
|
13
|
+
<TableRow>
|
|
14
|
+
<TableHead>
|
|
15
|
+
<SortableHeader field="name" currentOrder={orderBy} onSort={onSort}>
|
|
16
|
+
{t("Name")}
|
|
17
|
+
</SortableHeader>
|
|
18
|
+
</TableHead>
|
|
19
|
+
<TableHead>{t("Tax Rates")}</TableHead>
|
|
20
|
+
<TableHead>
|
|
21
|
+
<SortableHeader field="created_at" currentOrder={orderBy} onSort={onSort}>
|
|
22
|
+
{t("Created")}
|
|
23
|
+
</SortableHeader>
|
|
24
|
+
</TableHead>
|
|
25
|
+
<TableHead className="text-right" />
|
|
26
|
+
</TableRow>
|
|
27
|
+
</TableHeader>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Tax } from "@spaceinvoices/js-sdk";
|
|
2
|
+
import { MoreHorizontal } from "lucide-react";
|
|
3
|
+
import { Button } from "@/ui/components/ui/button";
|
|
4
|
+
import {
|
|
5
|
+
DropdownMenu,
|
|
6
|
+
DropdownMenuContent,
|
|
7
|
+
DropdownMenuItem,
|
|
8
|
+
DropdownMenuLabel,
|
|
9
|
+
DropdownMenuSeparator,
|
|
10
|
+
DropdownMenuTrigger,
|
|
11
|
+
} from "@/ui/components/ui/dropdown-menu";
|
|
12
|
+
|
|
13
|
+
type TaxListRowActionsProps = {
|
|
14
|
+
tax: Tax;
|
|
15
|
+
t: (key: string) => string;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default function TaxListRowActions({ tax, t }: TaxListRowActionsProps) {
|
|
19
|
+
const handleViewTax = () => {
|
|
20
|
+
window.location.href = `/app/taxes/${tax.id}`;
|
|
21
|
+
};
|
|
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(tax.id)}>
|
|
34
|
+
{t("Copy tax ID")}
|
|
35
|
+
</DropdownMenuItem>
|
|
36
|
+
<DropdownMenuSeparator />
|
|
37
|
+
<DropdownMenuItem className="cursor-pointer" onClick={handleViewTax}>
|
|
38
|
+
{t("View tax")}
|
|
39
|
+
</DropdownMenuItem>
|
|
40
|
+
</DropdownMenuContent>
|
|
41
|
+
</DropdownMenu>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Tax } from "@spaceinvoices/js-sdk";
|
|
2
|
+
import { Percent } from "lucide-react";
|
|
3
|
+
import { Badge } from "@/ui/components/ui/badge";
|
|
4
|
+
import { TableCell, TableRow } from "@/ui/components/ui/table";
|
|
5
|
+
import { Button } from "../../ui/button";
|
|
6
|
+
import TaxListRowActions from "./tax-list-row-actions";
|
|
7
|
+
|
|
8
|
+
type TaxListRowProps = {
|
|
9
|
+
tax: Tax;
|
|
10
|
+
onRowClick?: (tax: Tax) => void;
|
|
11
|
+
t: (key: string) => string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default function TaxListRow({ tax, onRowClick, t }: TaxListRowProps) {
|
|
15
|
+
const formatTaxRates = (taxRates: Tax["tax_rates"]) => {
|
|
16
|
+
if (!taxRates || taxRates.length === 0) return "-";
|
|
17
|
+
return taxRates.map((rate) => `${rate.rate}%`).join(", ");
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const formatDate = (date: string | Date) => {
|
|
21
|
+
return new Date(date).toLocaleDateString();
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<TableRow>
|
|
26
|
+
<TableCell className="font-medium">
|
|
27
|
+
<div className="flex items-center gap-2">
|
|
28
|
+
<Button variant="link" className="py-0 underline" onClick={() => onRowClick?.(tax)}>
|
|
29
|
+
<Percent className="h-4 w-4 flex-shrink-0" />
|
|
30
|
+
{tax.name || t("Unnamed Tax")}
|
|
31
|
+
</Button>
|
|
32
|
+
{tax.is_default && (
|
|
33
|
+
<Badge variant="secondary" className="text-xs">
|
|
34
|
+
{t("Default")}
|
|
35
|
+
</Badge>
|
|
36
|
+
)}
|
|
37
|
+
</div>
|
|
38
|
+
</TableCell>
|
|
39
|
+
<TableCell>{formatTaxRates(tax.tax_rates)}</TableCell>
|
|
40
|
+
<TableCell>{formatDate(tax.created_at)}</TableCell>
|
|
41
|
+
<TableCell className="text-right">
|
|
42
|
+
<TaxListRowActions tax={tax} t={t} />
|
|
43
|
+
</TableCell>
|
|
44
|
+
</TableRow>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Tax } from "@spaceinvoices/js-sdk";
|
|
2
|
+
import type { ComponentTranslationProps } from "@/ui/lib/translation";
|
|
3
|
+
import { createTranslation } from "@/ui/lib/translation";
|
|
4
|
+
import { useSDK } from "@/ui/providers/sdk-provider";
|
|
5
|
+
import { DataTable } from "../../table/data-table";
|
|
6
|
+
import { useTableFetch } from "../../table/hooks/use-table-fetch";
|
|
7
|
+
import type { ListTableProps, TableQueryParams } from "../../table/types";
|
|
8
|
+
import { TAXES_CACHE_KEY } from "../taxes.hooks";
|
|
9
|
+
import de from "./locales/de";
|
|
10
|
+
import sl from "./locales/sl";
|
|
11
|
+
import TaxListHeader from "./tax-list-header";
|
|
12
|
+
import TaxListRow from "./tax-list-row";
|
|
13
|
+
|
|
14
|
+
const translations = {
|
|
15
|
+
sl,
|
|
16
|
+
de,
|
|
17
|
+
} as const;
|
|
18
|
+
|
|
19
|
+
type TaxListTableProps = {
|
|
20
|
+
entityId?: string;
|
|
21
|
+
} & ListTableProps<Tax> &
|
|
22
|
+
ComponentTranslationProps;
|
|
23
|
+
|
|
24
|
+
export default function TaxListTable({
|
|
25
|
+
queryParams,
|
|
26
|
+
createNewTrigger,
|
|
27
|
+
onRowClick,
|
|
28
|
+
onChangeParams,
|
|
29
|
+
entityId,
|
|
30
|
+
...i18nProps
|
|
31
|
+
}: TaxListTableProps) {
|
|
32
|
+
const t = createTranslation({ translations, ...i18nProps });
|
|
33
|
+
const { sdk } = useSDK();
|
|
34
|
+
|
|
35
|
+
const handleFetch = useTableFetch((params: TableQueryParams) => {
|
|
36
|
+
if (!sdk) throw new Error("SDK not initialized");
|
|
37
|
+
return sdk.taxes.list(params as any);
|
|
38
|
+
}, entityId);
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<DataTable
|
|
42
|
+
columns={[
|
|
43
|
+
{ id: "name", header: t("Name"), sortable: true },
|
|
44
|
+
{ id: "tax_rates", header: t("Tax Rates") },
|
|
45
|
+
{ id: "created_at", header: t("Created"), sortable: true },
|
|
46
|
+
{ id: "actions", header: "", align: "right" },
|
|
47
|
+
]}
|
|
48
|
+
renderRow={(tax) => <TaxListRow tax={tax} key={tax.id} onRowClick={(tax) => onRowClick?.(tax)} t={t} />}
|
|
49
|
+
renderHeader={(headerProps) => <TaxListHeader orderBy={headerProps.orderBy} onSort={headerProps.onSort} t={t} />}
|
|
50
|
+
queryParams={queryParams}
|
|
51
|
+
resourceName="tax"
|
|
52
|
+
cacheKey={TAXES_CACHE_KEY}
|
|
53
|
+
createNewTrigger={createNewTrigger}
|
|
54
|
+
onFetch={handleFetch}
|
|
55
|
+
onChangeParams={onChangeParams}
|
|
56
|
+
entityId={entityId}
|
|
57
|
+
/>
|
|
58
|
+
);
|
|
59
|
+
}
|