@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,67 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
Recipient: "Prejemnik",
|
|
3
|
+
Name: "Ime",
|
|
4
|
+
Details: "Podrobnosti",
|
|
5
|
+
Number: "Številka",
|
|
6
|
+
Date: "Datum",
|
|
7
|
+
"Pick a date": "Izberi datum",
|
|
8
|
+
"Due Date": "Rok plačila",
|
|
9
|
+
"Valid Until": "Veljavno do",
|
|
10
|
+
Items: "Postavke",
|
|
11
|
+
"Add item": "Dodaj postavko",
|
|
12
|
+
Save: "Shrani",
|
|
13
|
+
"Save as Draft": "Shrani kot osnutek",
|
|
14
|
+
Quantity: "Količina",
|
|
15
|
+
Price: "Cena",
|
|
16
|
+
Unit: "Enota",
|
|
17
|
+
Discount: "Popust",
|
|
18
|
+
Tax: "Davek",
|
|
19
|
+
"Tax rate": "Davčna stopnja",
|
|
20
|
+
"Add tax": "Dodaj davek",
|
|
21
|
+
"Select tax...": "Izberi davek...",
|
|
22
|
+
"Loading...": "Nalaganje...",
|
|
23
|
+
"No taxes found": "Ni najdenih davkov",
|
|
24
|
+
"Add new tax...": "Dodaj nov davek...",
|
|
25
|
+
Description: "Opis",
|
|
26
|
+
"Mark as Paid": "Označi kot plačano",
|
|
27
|
+
Paid: "Plačano",
|
|
28
|
+
"Credit note will be marked as fully paid upon creation": "Dobropis bo označen kot plačan ob ustvarjanju",
|
|
29
|
+
"Payment Type": "Vrsta plačila",
|
|
30
|
+
"Select payment type": "Izberite vrsto plačila",
|
|
31
|
+
Cash: "Gotovina",
|
|
32
|
+
"Bank Transfer": "Bančno nakazilo",
|
|
33
|
+
Card: "Kartica",
|
|
34
|
+
Check: "Ček",
|
|
35
|
+
Other: "Drugo",
|
|
36
|
+
// Note field
|
|
37
|
+
Note: "Opomba",
|
|
38
|
+
"Insert variable": "Vstavi spremenljivko",
|
|
39
|
+
"Add payment instructions, terms, or other notes...": "Dodajte navodila za plačilo, pogoje ali druge opombe...",
|
|
40
|
+
// Payment terms field
|
|
41
|
+
"Payment Terms": "Plačilni pogoji",
|
|
42
|
+
"Add payment terms...": "Dodajte plačilne pogoje...",
|
|
43
|
+
// Recipient fields
|
|
44
|
+
"Search or create customer...": "Išči ali ustvari stranko...",
|
|
45
|
+
Clear: "Počisti",
|
|
46
|
+
Address: "Naslov",
|
|
47
|
+
"Address 2": "Naslov 2",
|
|
48
|
+
"Post Code": "Poštna številka",
|
|
49
|
+
City: "Mesto",
|
|
50
|
+
State: "Regija",
|
|
51
|
+
Country: "Država",
|
|
52
|
+
"Tax Number": "Davčna številka",
|
|
53
|
+
// Currency
|
|
54
|
+
Currency: "Valuta",
|
|
55
|
+
"Select currency": "Izberi valuto",
|
|
56
|
+
// Discount types
|
|
57
|
+
"Percentage discount": "Odstotni popust",
|
|
58
|
+
"Fixed amount discount": "Fiksni popust",
|
|
59
|
+
Percentage: "Odstotek",
|
|
60
|
+
"Fixed amount": "Fiksni znesek",
|
|
61
|
+
"Taxes disabled": "Davki onemogočeni",
|
|
62
|
+
// Gross price support
|
|
63
|
+
"Gross price": "Bruto cena",
|
|
64
|
+
"Net price": "Neto cena",
|
|
65
|
+
"Gross price (tax included)": "Bruto cena (z davkom)",
|
|
66
|
+
"Net price (before tax)": "Neto cena (brez davka)",
|
|
67
|
+
} as const;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Credit note hooks using the shared createResourceHooks factory
|
|
3
|
+
*
|
|
4
|
+
* This provides:
|
|
5
|
+
* - Optimistic updates
|
|
6
|
+
* - Automatic cache invalidation
|
|
7
|
+
* - Consistent error handling
|
|
8
|
+
* - Less code duplication
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { CreateCreditNoteRequest, CreditNote } from "@spaceinvoices/js-sdk";
|
|
12
|
+
import { createResourceHooks } from "@/ui/hooks/create-resource-hooks";
|
|
13
|
+
|
|
14
|
+
export const CREDIT_NOTES_CACHE_KEY = "credit-notes";
|
|
15
|
+
|
|
16
|
+
const {
|
|
17
|
+
useCreateResource: useCreateCreditNote,
|
|
18
|
+
useUpdateResource: useUpdateCreditNote,
|
|
19
|
+
useDeleteResource: useDeleteCreditNote,
|
|
20
|
+
} = createResourceHooks<CreditNote, CreateCreditNoteRequest>("creditNotes", CREDIT_NOTES_CACHE_KEY);
|
|
21
|
+
|
|
22
|
+
export { useCreateCreditNote, useUpdateCreditNote, useDeleteCreditNote };
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { Copy, Download, Eye, Link2Off, Loader2, MoreHorizontal, Plus } from "lucide-react";
|
|
2
|
+
import { Button } from "@/ui/components/ui/button";
|
|
3
|
+
import {
|
|
4
|
+
DropdownMenu,
|
|
5
|
+
DropdownMenuContent,
|
|
6
|
+
DropdownMenuGroup,
|
|
7
|
+
DropdownMenuItem,
|
|
8
|
+
DropdownMenuLabel,
|
|
9
|
+
DropdownMenuSeparator,
|
|
10
|
+
DropdownMenuTrigger,
|
|
11
|
+
} from "@/ui/components/ui/dropdown-menu";
|
|
12
|
+
import type { ComponentTranslationProps } from "@/ui/lib/translation";
|
|
13
|
+
import { createTranslation } from "@/ui/lib/translation";
|
|
14
|
+
import { useCreditNoteDownload } from "./use-credit-note-download";
|
|
15
|
+
|
|
16
|
+
// Type for credit note - using any until SDK is regenerated
|
|
17
|
+
type CreditNote = any;
|
|
18
|
+
|
|
19
|
+
type CreditNoteListRowActionsProps = {
|
|
20
|
+
creditNote: CreditNote;
|
|
21
|
+
onAddPayment?: (creditNote: CreditNote) => void;
|
|
22
|
+
onDuplicate?: (creditNote: CreditNote) => void;
|
|
23
|
+
onDownloadStart?: () => void;
|
|
24
|
+
onDownloadSuccess?: (fileName: string) => void;
|
|
25
|
+
onDownloadError?: (error: string) => void;
|
|
26
|
+
onUnshare?: (creditNote: CreditNote) => Promise<void>;
|
|
27
|
+
isUnsharing?: boolean;
|
|
28
|
+
} & ComponentTranslationProps;
|
|
29
|
+
|
|
30
|
+
export default function CreditNoteListRowActions({
|
|
31
|
+
creditNote,
|
|
32
|
+
onAddPayment,
|
|
33
|
+
onDuplicate,
|
|
34
|
+
onDownloadStart,
|
|
35
|
+
onDownloadSuccess,
|
|
36
|
+
onDownloadError,
|
|
37
|
+
onUnshare,
|
|
38
|
+
isUnsharing,
|
|
39
|
+
...i18nProps
|
|
40
|
+
}: CreditNoteListRowActionsProps) {
|
|
41
|
+
const t = createTranslation(i18nProps);
|
|
42
|
+
const { isDownloading, downloadPDF } = useCreditNoteDownload({
|
|
43
|
+
onDownloadStart,
|
|
44
|
+
onDownloadSuccess,
|
|
45
|
+
onDownloadError,
|
|
46
|
+
...i18nProps,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<DropdownMenu>
|
|
51
|
+
<DropdownMenuTrigger asChild>
|
|
52
|
+
<Button variant="ghost" className="h-8 w-8 cursor-pointer p-0" id="action-menu-trigger">
|
|
53
|
+
<span className="sr-only">{t("Open menu")}</span>
|
|
54
|
+
<MoreHorizontal className="h-4 w-4" />
|
|
55
|
+
</Button>
|
|
56
|
+
</DropdownMenuTrigger>
|
|
57
|
+
<DropdownMenuContent align="end">
|
|
58
|
+
<DropdownMenuLabel>{t("Actions")}</DropdownMenuLabel>
|
|
59
|
+
<DropdownMenuGroup>
|
|
60
|
+
<DropdownMenuItem className="cursor-pointer" onClick={() => navigator.clipboard.writeText(creditNote.id)}>
|
|
61
|
+
<Copy className="h-4 w-4" />
|
|
62
|
+
{t("Copy credit note ID")}
|
|
63
|
+
</DropdownMenuItem>
|
|
64
|
+
</DropdownMenuGroup>
|
|
65
|
+
<DropdownMenuSeparator />
|
|
66
|
+
<DropdownMenuGroup>
|
|
67
|
+
<DropdownMenuItem
|
|
68
|
+
className="cursor-pointer"
|
|
69
|
+
onClick={() => {
|
|
70
|
+
window.location.href = `/app/documents/view/${creditNote.id}`;
|
|
71
|
+
}}
|
|
72
|
+
>
|
|
73
|
+
<Eye className="h-4 w-4" />
|
|
74
|
+
{t("View credit note")}
|
|
75
|
+
</DropdownMenuItem>
|
|
76
|
+
<DropdownMenuItem className="cursor-pointer" onClick={() => downloadPDF(creditNote)} disabled={isDownloading}>
|
|
77
|
+
<Download className="h-4 w-4" />
|
|
78
|
+
{isDownloading ? t("Downloading...") : t("Download PDF")}
|
|
79
|
+
</DropdownMenuItem>
|
|
80
|
+
{onDuplicate && (
|
|
81
|
+
<DropdownMenuItem className="cursor-pointer" onClick={() => onDuplicate(creditNote)}>
|
|
82
|
+
<Copy className="h-4 w-4" />
|
|
83
|
+
{t("Duplicate")}
|
|
84
|
+
</DropdownMenuItem>
|
|
85
|
+
)}
|
|
86
|
+
</DropdownMenuGroup>
|
|
87
|
+
{!creditNote.paid_in_full && (
|
|
88
|
+
<>
|
|
89
|
+
<DropdownMenuSeparator />
|
|
90
|
+
<DropdownMenuGroup>
|
|
91
|
+
<DropdownMenuItem className="cursor-pointer" onClick={() => onAddPayment?.(creditNote)}>
|
|
92
|
+
<Plus className="h-4 w-4" />
|
|
93
|
+
{t("Add Payment")}
|
|
94
|
+
</DropdownMenuItem>
|
|
95
|
+
</DropdownMenuGroup>
|
|
96
|
+
</>
|
|
97
|
+
)}
|
|
98
|
+
{creditNote.shareable_id && onUnshare && (
|
|
99
|
+
<>
|
|
100
|
+
<DropdownMenuSeparator />
|
|
101
|
+
<DropdownMenuGroup>
|
|
102
|
+
<DropdownMenuItem
|
|
103
|
+
className="cursor-pointer text-destructive focus:text-destructive"
|
|
104
|
+
onClick={() => onUnshare(creditNote)}
|
|
105
|
+
disabled={isUnsharing}
|
|
106
|
+
>
|
|
107
|
+
{isUnsharing ? <Loader2 className="h-4 w-4 animate-spin" /> : <Link2Off className="h-4 w-4" />}
|
|
108
|
+
{t("Unshare")}
|
|
109
|
+
</DropdownMenuItem>
|
|
110
|
+
</DropdownMenuGroup>
|
|
111
|
+
</>
|
|
112
|
+
)}
|
|
113
|
+
</DropdownMenuContent>
|
|
114
|
+
</DropdownMenu>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import type { CreditNote } from "@spaceinvoices/js-sdk";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
import { DataTable } from "@/ui/components/table/data-table";
|
|
4
|
+
import { FormattedDate } from "@/ui/components/table/date-cell";
|
|
5
|
+
import { useTableFetch } from "@/ui/components/table/hooks/use-table-fetch";
|
|
6
|
+
import type {
|
|
7
|
+
Column,
|
|
8
|
+
FilterConfig,
|
|
9
|
+
ListTableProps,
|
|
10
|
+
TableQueryParams,
|
|
11
|
+
TableQueryResponse,
|
|
12
|
+
} from "@/ui/components/table/types";
|
|
13
|
+
import { Badge } from "@/ui/components/ui/badge";
|
|
14
|
+
import { Button } from "@/ui/components/ui/button";
|
|
15
|
+
import { createTranslation } from "@/ui/lib/translation";
|
|
16
|
+
import { useSDK } from "@/ui/providers/sdk-provider";
|
|
17
|
+
|
|
18
|
+
import CreditNoteListRowActions from "./list-row-actions";
|
|
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 CreditNoteListTableProps = {
|
|
28
|
+
t?: (key: string) => string;
|
|
29
|
+
namespace?: string;
|
|
30
|
+
locale?: string;
|
|
31
|
+
entityId?: string;
|
|
32
|
+
onAddPayment?: (creditNote: CreditNote) => void;
|
|
33
|
+
onDuplicate?: (creditNote: CreditNote) => void;
|
|
34
|
+
onDownloadStart?: () => void;
|
|
35
|
+
onDownloadSuccess?: (fileName: string) => void;
|
|
36
|
+
onDownloadError?: (error: string) => void;
|
|
37
|
+
} & ListTableProps<CreditNote>;
|
|
38
|
+
|
|
39
|
+
export default function CreditNoteListTable({
|
|
40
|
+
queryParams,
|
|
41
|
+
onRowClick,
|
|
42
|
+
onAddPayment,
|
|
43
|
+
onDuplicate,
|
|
44
|
+
onChangeParams,
|
|
45
|
+
entityId,
|
|
46
|
+
onDownloadStart,
|
|
47
|
+
onDownloadSuccess,
|
|
48
|
+
onDownloadError,
|
|
49
|
+
...i18nProps
|
|
50
|
+
}: CreditNoteListTableProps) {
|
|
51
|
+
const t = createTranslation({
|
|
52
|
+
translations,
|
|
53
|
+
...i18nProps,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const { sdk } = useSDK();
|
|
57
|
+
|
|
58
|
+
const handleFetch = useTableFetch(async (params: TableQueryParams) => {
|
|
59
|
+
if (!sdk) throw new Error("SDK not initialized");
|
|
60
|
+
if (!params.entity_id) throw new Error("Entity ID required");
|
|
61
|
+
|
|
62
|
+
const response = await sdk.creditNotes.list({
|
|
63
|
+
entity_id: params.entity_id,
|
|
64
|
+
limit: params.limit,
|
|
65
|
+
next_cursor: params.next_cursor,
|
|
66
|
+
prev_cursor: params.prev_cursor,
|
|
67
|
+
order_by: params.order_by,
|
|
68
|
+
search: params.search,
|
|
69
|
+
query: params.query,
|
|
70
|
+
});
|
|
71
|
+
return response as unknown as TableQueryResponse<CreditNote>;
|
|
72
|
+
}, entityId);
|
|
73
|
+
|
|
74
|
+
const filterConfig: FilterConfig = useMemo(
|
|
75
|
+
() => ({
|
|
76
|
+
dateFields: [
|
|
77
|
+
{ id: "date", label: t("Date") },
|
|
78
|
+
{ id: "created_at", label: t("Created At") },
|
|
79
|
+
],
|
|
80
|
+
statusFilter: true, // Credit notes have payment status
|
|
81
|
+
}),
|
|
82
|
+
[t],
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
const columns: Column<CreditNote>[] = useMemo(
|
|
86
|
+
() => [
|
|
87
|
+
{
|
|
88
|
+
id: "number",
|
|
89
|
+
header: t("Number"),
|
|
90
|
+
sortable: true,
|
|
91
|
+
cell: (creditNote) => (
|
|
92
|
+
<div className="flex items-center gap-2">
|
|
93
|
+
<Button variant="link" className="cursor-pointer py-0 underline" onClick={() => onRowClick?.(creditNote)}>
|
|
94
|
+
{creditNote.number}
|
|
95
|
+
</Button>
|
|
96
|
+
{(creditNote as any).is_draft && (
|
|
97
|
+
<Badge
|
|
98
|
+
variant="outline"
|
|
99
|
+
className="border-amber-500 bg-amber-50 text-amber-700 dark:bg-amber-950 dark:text-amber-400"
|
|
100
|
+
>
|
|
101
|
+
{t("Draft")}
|
|
102
|
+
</Badge>
|
|
103
|
+
)}
|
|
104
|
+
</div>
|
|
105
|
+
),
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
id: "customer",
|
|
109
|
+
header: t("Customer"),
|
|
110
|
+
cell: (creditNote) => creditNote.customer?.name ?? "-",
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
id: "date",
|
|
114
|
+
header: t("Date"),
|
|
115
|
+
sortable: true,
|
|
116
|
+
cell: (creditNote) => <FormattedDate date={creditNote.date} />,
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
id: "total",
|
|
120
|
+
header: t("Total"),
|
|
121
|
+
sortable: true,
|
|
122
|
+
align: "right",
|
|
123
|
+
cell: (creditNote) => creditNote.total,
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
id: "total_with_tax",
|
|
127
|
+
header: t("Total with Tax"),
|
|
128
|
+
sortable: true,
|
|
129
|
+
align: "right",
|
|
130
|
+
cell: (creditNote) => creditNote.total_with_tax,
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
id: "status",
|
|
134
|
+
header: t("Status"),
|
|
135
|
+
cell: (creditNote) => <PaymentStatusBadge creditNote={creditNote} />,
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
id: "actions",
|
|
139
|
+
header: "",
|
|
140
|
+
align: "right",
|
|
141
|
+
cell: (creditNote) => (
|
|
142
|
+
<CreditNoteListRowActions
|
|
143
|
+
creditNote={creditNote}
|
|
144
|
+
onAddPayment={onAddPayment}
|
|
145
|
+
onDuplicate={onDuplicate}
|
|
146
|
+
onDownloadStart={onDownloadStart}
|
|
147
|
+
onDownloadSuccess={onDownloadSuccess}
|
|
148
|
+
onDownloadError={onDownloadError}
|
|
149
|
+
{...i18nProps}
|
|
150
|
+
/>
|
|
151
|
+
),
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
[t, onRowClick, onAddPayment, onDuplicate, onDownloadStart, onDownloadSuccess, onDownloadError, i18nProps],
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
return (
|
|
158
|
+
<DataTable
|
|
159
|
+
columns={columns}
|
|
160
|
+
queryParams={queryParams}
|
|
161
|
+
resourceName="credit_note"
|
|
162
|
+
cacheKey="credit-notes"
|
|
163
|
+
createNewLink="/app/documents/add/credit_note"
|
|
164
|
+
onFetch={handleFetch}
|
|
165
|
+
onChangeParams={onChangeParams}
|
|
166
|
+
entityId={entityId}
|
|
167
|
+
filterConfig={filterConfig}
|
|
168
|
+
t={t}
|
|
169
|
+
locale={i18nProps.locale}
|
|
170
|
+
/>
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** Payment status badge for credit notes */
|
|
175
|
+
function PaymentStatusBadge({ creditNote }: { creditNote: CreditNote }) {
|
|
176
|
+
if (creditNote.paid_in_full) {
|
|
177
|
+
return <span className="rounded-full bg-green-100 px-2 py-1 text-green-800 text-xs">Paid</span>;
|
|
178
|
+
}
|
|
179
|
+
if (creditNote.total_paid > 0) {
|
|
180
|
+
return <span className="rounded-full bg-yellow-100 px-2 py-1 text-xs text-yellow-800">Partial</span>;
|
|
181
|
+
}
|
|
182
|
+
return <span className="rounded-full bg-gray-100 px-2 py-1 text-gray-800 text-xs">Unpaid</span>;
|
|
183
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
Draft: "Entwurf",
|
|
3
|
+
Number: "Nummer",
|
|
4
|
+
Customer: "Kunde",
|
|
5
|
+
Date: "Datum",
|
|
6
|
+
Total: "Gesamt",
|
|
7
|
+
"Total with Tax": "Gesamt mit MwSt.",
|
|
8
|
+
Status: "Status",
|
|
9
|
+
Actions: "Aktionen",
|
|
10
|
+
"Open menu": "Menü öffnen",
|
|
11
|
+
"Copy credit note ID": "Gutschrift-ID kopieren",
|
|
12
|
+
"View credit note": "Gutschrift anzeigen",
|
|
13
|
+
"Download PDF": "PDF herunterladen",
|
|
14
|
+
"Downloading...": "Wird heruntergeladen...",
|
|
15
|
+
"Add Payment": "Zahlung hinzufügen",
|
|
16
|
+
Duplicate: "Duplizieren",
|
|
17
|
+
"Failed to download PDF": "PDF-Download fehlgeschlagen",
|
|
18
|
+
"Credit Note": "Gutschrift",
|
|
19
|
+
"No credit notes found": "Keine Gutschriften gefunden",
|
|
20
|
+
"Create Credit Note": "Gutschrift erstellen",
|
|
21
|
+
// Filter translations
|
|
22
|
+
"Search...": "Suchen...",
|
|
23
|
+
Filters: "Filter",
|
|
24
|
+
"Date Range": "Datumsbereich",
|
|
25
|
+
From: "Von",
|
|
26
|
+
To: "Bis",
|
|
27
|
+
"Clear filters": "Filter löschen",
|
|
28
|
+
Paid: "Bezahlt",
|
|
29
|
+
Unpaid: "Unbezahlt",
|
|
30
|
+
Overdue: "Überfällig",
|
|
31
|
+
Voided: "Storniert",
|
|
32
|
+
"Created At": "Erstellt am",
|
|
33
|
+
} as const;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
Draft: "Osnutek",
|
|
3
|
+
Number: "Številka",
|
|
4
|
+
Customer: "Stranka",
|
|
5
|
+
Date: "Datum",
|
|
6
|
+
Total: "Skupaj",
|
|
7
|
+
"Total with Tax": "Skupaj z DDV",
|
|
8
|
+
Status: "Status",
|
|
9
|
+
Actions: "Dejanja",
|
|
10
|
+
"Open menu": "Odpri meni",
|
|
11
|
+
"Copy credit note ID": "Kopiraj ID dobropisa",
|
|
12
|
+
"View credit note": "Prikaži dobropis",
|
|
13
|
+
"Download PDF": "Prenesi PDF",
|
|
14
|
+
"Downloading...": "Prenašanje...",
|
|
15
|
+
"Add Payment": "Dodaj plačilo",
|
|
16
|
+
Duplicate: "Podvoji",
|
|
17
|
+
"Failed to download PDF": "Prenos PDF ni uspel",
|
|
18
|
+
"Credit Note": "Dobropis",
|
|
19
|
+
"No credit notes found": "Ni najdenih dobropisov",
|
|
20
|
+
"Create Credit Note": "Ustvari dobropis",
|
|
21
|
+
// Filter translations
|
|
22
|
+
"Search...": "Iskanje...",
|
|
23
|
+
Filters: "Filtri",
|
|
24
|
+
"Date Range": "Datumski razpon",
|
|
25
|
+
From: "Od",
|
|
26
|
+
To: "Do",
|
|
27
|
+
"Clear filters": "Počisti filtre",
|
|
28
|
+
Paid: "Plačano",
|
|
29
|
+
Unpaid: "Neplačano",
|
|
30
|
+
Overdue: "Zapadlo",
|
|
31
|
+
Voided: "Stornirano",
|
|
32
|
+
"Created At": "Ustvarjeno",
|
|
33
|
+
} as const;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import type { ComponentTranslationProps } from "@/ui/lib/translation";
|
|
3
|
+
import { createTranslation } from "@/ui/lib/translation";
|
|
4
|
+
import { useEntities } from "@/ui/providers/entities-context";
|
|
5
|
+
import { useSDK } from "@/ui/providers/sdk-provider";
|
|
6
|
+
|
|
7
|
+
// Type for credit note - using any until SDK is regenerated
|
|
8
|
+
type CreditNote = any;
|
|
9
|
+
|
|
10
|
+
type UseCreditNoteDownloadProps = {
|
|
11
|
+
onDownloadStart?: () => void;
|
|
12
|
+
onDownloadSuccess?: (fileName: string) => void;
|
|
13
|
+
onDownloadError?: (error: string) => void;
|
|
14
|
+
} & ComponentTranslationProps;
|
|
15
|
+
|
|
16
|
+
export function useCreditNoteDownload({
|
|
17
|
+
onDownloadStart,
|
|
18
|
+
onDownloadSuccess,
|
|
19
|
+
onDownloadError,
|
|
20
|
+
...i18nProps
|
|
21
|
+
}: UseCreditNoteDownloadProps) {
|
|
22
|
+
const [isDownloading, setIsDownloading] = useState(false);
|
|
23
|
+
const { activeEntity } = useEntities();
|
|
24
|
+
const { sdk } = useSDK();
|
|
25
|
+
const t = createTranslation(i18nProps);
|
|
26
|
+
|
|
27
|
+
const downloadPDF = async (creditNote: CreditNote) => {
|
|
28
|
+
if (!activeEntity?.id || !sdk) {
|
|
29
|
+
console.error("Missing SDK or active entity for PDF download");
|
|
30
|
+
onDownloadError?.(t("Failed to download PDF"));
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
setIsDownloading(true);
|
|
35
|
+
onDownloadStart?.();
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
// SDK signature: renderPdf(id, params?, SDKMethodOptions?)
|
|
39
|
+
// entity_id goes in SDKMethodOptions (last arg), not params
|
|
40
|
+
// Note: renderPdf is on invoices module but works with any document ID
|
|
41
|
+
const blob = await sdk.invoices.renderPdf(creditNote.id, {}, { entity_id: activeEntity.id });
|
|
42
|
+
const downloadUrl = window.URL.createObjectURL(blob);
|
|
43
|
+
const link = document.createElement("a");
|
|
44
|
+
link.href = downloadUrl;
|
|
45
|
+
const fileName = `${t("Credit Note")} ${creditNote.number}.pdf`;
|
|
46
|
+
link.download = fileName;
|
|
47
|
+
document.body.appendChild(link);
|
|
48
|
+
link.click();
|
|
49
|
+
document.body.removeChild(link);
|
|
50
|
+
window.URL.revokeObjectURL(downloadUrl);
|
|
51
|
+
|
|
52
|
+
onDownloadSuccess?.(fileName);
|
|
53
|
+
} catch (error) {
|
|
54
|
+
console.error("Error downloading PDF:", error);
|
|
55
|
+
onDownloadError?.(t("Failed to download PDF"));
|
|
56
|
+
} finally {
|
|
57
|
+
setIsDownloading(false);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
isDownloading,
|
|
63
|
+
downloadPDF,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { zodResolver } from "@hookform/resolvers/zod";
|
|
2
|
+
import type { CompanyRegistryResult, CreateCustomerRequest, Customer } from "@spaceinvoices/js-sdk";
|
|
3
|
+
import { useForm } from "react-hook-form";
|
|
4
|
+
import type z from "zod";
|
|
5
|
+
import { CompanyRegistryAutocomplete } from "@/ui/components/company-registry";
|
|
6
|
+
import { FormInput } from "@/ui/components/form";
|
|
7
|
+
import { Form } from "@/ui/components/ui/form";
|
|
8
|
+
import type { CreateCustomerSchema } from "@/ui/generated/schemas";
|
|
9
|
+
import { createCustomerSchema } from "@/ui/generated/schemas";
|
|
10
|
+
import type { ComponentTranslationProps } from "@/ui/lib/translation";
|
|
11
|
+
import { createTranslation } from "@/ui/lib/translation";
|
|
12
|
+
import { useCreateCustomer } from "../customers.hooks";
|
|
13
|
+
import de from "./locales/de";
|
|
14
|
+
import sl from "./locales/sl";
|
|
15
|
+
|
|
16
|
+
const translations = {
|
|
17
|
+
sl,
|
|
18
|
+
de,
|
|
19
|
+
} as const;
|
|
20
|
+
|
|
21
|
+
type CreateCustomerFormProps = {
|
|
22
|
+
entityId: string;
|
|
23
|
+
/**
|
|
24
|
+
* Entity's ISO 3166-1 alpha-2 country code (e.g., "SI", "AT")
|
|
25
|
+
* Used to enable company registry autocomplete for supported countries
|
|
26
|
+
*/
|
|
27
|
+
entityCountryCode?: string;
|
|
28
|
+
onSuccess?: (customer: Customer) => void;
|
|
29
|
+
onError?: (error: Error) => void;
|
|
30
|
+
renderSubmitButton?: (props: { isSubmitting: boolean; submit: () => void }) => React.ReactNode;
|
|
31
|
+
} & ComponentTranslationProps;
|
|
32
|
+
|
|
33
|
+
export default function CreateCustomerForm({
|
|
34
|
+
entityId,
|
|
35
|
+
entityCountryCode,
|
|
36
|
+
onSuccess,
|
|
37
|
+
onError,
|
|
38
|
+
renderSubmitButton,
|
|
39
|
+
...i18nProps
|
|
40
|
+
}: CreateCustomerFormProps) {
|
|
41
|
+
const t = createTranslation({
|
|
42
|
+
...i18nProps,
|
|
43
|
+
translations,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Handle company selection from registry autocomplete
|
|
48
|
+
* Auto-fills form fields with company data
|
|
49
|
+
*/
|
|
50
|
+
const handleCompanySelect = (company: CompanyRegistryResult) => {
|
|
51
|
+
form.setValue("name", company.name);
|
|
52
|
+
if (company.address) form.setValue("address", company.address);
|
|
53
|
+
if (company.post_code) form.setValue("post_code", company.post_code);
|
|
54
|
+
if (company.city) form.setValue("city", company.city);
|
|
55
|
+
if (company.tax_number) form.setValue("tax_number", company.tax_number);
|
|
56
|
+
// Note: country is intentionally not set - keep entity's country or let user choose
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const form = useForm<CreateCustomerSchema>({
|
|
60
|
+
resolver: zodResolver(createCustomerSchema),
|
|
61
|
+
defaultValues: {
|
|
62
|
+
name: "",
|
|
63
|
+
address: "",
|
|
64
|
+
post_code: "",
|
|
65
|
+
city: "",
|
|
66
|
+
state: "",
|
|
67
|
+
country: "",
|
|
68
|
+
tax_number: "",
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const { mutate: createCustomer, isPending } = useCreateCustomer({
|
|
73
|
+
entityId,
|
|
74
|
+
onSuccess: (customer, _variables, _context) => {
|
|
75
|
+
onSuccess?.(customer);
|
|
76
|
+
form.reset(); // Reset form after successful submission
|
|
77
|
+
},
|
|
78
|
+
onError: (error, _variables, _context) => {
|
|
79
|
+
form.setError("root", {
|
|
80
|
+
type: "submit",
|
|
81
|
+
message: t("There was an error creating the customer"),
|
|
82
|
+
});
|
|
83
|
+
onError?.(error);
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const onSubmit = async (values: z.infer<typeof createCustomerSchema>) => {
|
|
88
|
+
// Zod validation ensures required fields are present before this is called
|
|
89
|
+
// The type cast is safe because React Hook Form's DeepPartial doesn't reflect runtime validation
|
|
90
|
+
createCustomer(values as CreateCustomerRequest);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const handleSubmitClick = () => {
|
|
94
|
+
form.handleSubmit(onSubmit)();
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<Form {...form}>
|
|
99
|
+
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
|
|
100
|
+
{/* Company Registry Autocomplete - only shown for supported countries */}
|
|
101
|
+
{entityCountryCode && (
|
|
102
|
+
<div className="mb-4 rounded-lg border bg-muted/30 p-4">
|
|
103
|
+
<CompanyRegistryAutocomplete
|
|
104
|
+
countryCode={entityCountryCode}
|
|
105
|
+
onSelect={handleCompanySelect}
|
|
106
|
+
placeholder={t("Search by company name or tax number")}
|
|
107
|
+
/>
|
|
108
|
+
</div>
|
|
109
|
+
)}
|
|
110
|
+
|
|
111
|
+
<FormInput control={form.control} name="name" label={t("Name")} placeholder={t("Enter name")} />
|
|
112
|
+
|
|
113
|
+
<FormInput control={form.control} name="address" label={t("Address")} placeholder={t("Enter address")} />
|
|
114
|
+
|
|
115
|
+
<div className="grid grid-cols-2 gap-4">
|
|
116
|
+
<FormInput control={form.control} name="post_code" label={t("Post Code")} />
|
|
117
|
+
<FormInput control={form.control} name="city" label={t("City")} />
|
|
118
|
+
</div>
|
|
119
|
+
|
|
120
|
+
<div className="grid grid-cols-2 gap-4">
|
|
121
|
+
<FormInput control={form.control} name="state" label={t("State")} />
|
|
122
|
+
<FormInput control={form.control} name="country" label={t("Country")} />
|
|
123
|
+
</div>
|
|
124
|
+
|
|
125
|
+
<FormInput control={form.control} name="tax_number" label={t("Tax Number")} />
|
|
126
|
+
|
|
127
|
+
{renderSubmitButton?.({
|
|
128
|
+
isSubmitting: isPending || form.formState.isSubmitting,
|
|
129
|
+
submit: handleSubmitClick,
|
|
130
|
+
})}
|
|
131
|
+
</form>
|
|
132
|
+
</Form>
|
|
133
|
+
);
|
|
134
|
+
}
|