@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,151 @@
|
|
|
1
|
+
import type { CompanyRegistryResult } from "@spaceinvoices/js-sdk";
|
|
2
|
+
import { Building2 } from "lucide-react";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { Autocomplete } from "@/ui/common/autocomplete";
|
|
5
|
+
import { useCompanyRegistrySearch, useIsCountrySupported } from "./company-registry.hooks";
|
|
6
|
+
|
|
7
|
+
const MAX_TEXT_LENGTH = 80;
|
|
8
|
+
|
|
9
|
+
const truncateText = (text: string, maxLength: number = MAX_TEXT_LENGTH): string => {
|
|
10
|
+
return text.length > maxLength ? `${text.substring(0, maxLength)}...` : text;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
type CompanyRegistryAutocompleteProps = {
|
|
14
|
+
/**
|
|
15
|
+
* ISO 3166-1 alpha-2 country code (e.g., "SI", "AT")
|
|
16
|
+
* Typically from the entity's country_code
|
|
17
|
+
*/
|
|
18
|
+
countryCode: string;
|
|
19
|
+
/**
|
|
20
|
+
* Callback when a company is selected
|
|
21
|
+
* Use this to auto-fill customer form fields
|
|
22
|
+
*/
|
|
23
|
+
onSelect?: (company: CompanyRegistryResult) => void;
|
|
24
|
+
/**
|
|
25
|
+
* Placeholder text for the search input
|
|
26
|
+
*/
|
|
27
|
+
placeholder?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Additional CSS classes
|
|
30
|
+
*/
|
|
31
|
+
className?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Whether the autocomplete is disabled
|
|
34
|
+
*/
|
|
35
|
+
disabled?: boolean;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Company Registry Autocomplete
|
|
40
|
+
*
|
|
41
|
+
* Searches public company registries (e.g., AJPES for Slovenia) and allows
|
|
42
|
+
* users to select a company to auto-fill customer details.
|
|
43
|
+
*
|
|
44
|
+
* Features:
|
|
45
|
+
* - Searches by company name or tax number
|
|
46
|
+
* - Displays company address and legal form
|
|
47
|
+
* - Shows bank accounts if available
|
|
48
|
+
* - Only renders if country has registry data available
|
|
49
|
+
*
|
|
50
|
+
* Usage:
|
|
51
|
+
* ```tsx
|
|
52
|
+
* <CompanyRegistryAutocomplete
|
|
53
|
+
* countryCode={entity.country_code}
|
|
54
|
+
* onSelect={(company) => {
|
|
55
|
+
* form.setValue("name", company.name);
|
|
56
|
+
* form.setValue("address", company.address);
|
|
57
|
+
* form.setValue("tax_number", company.tax_number);
|
|
58
|
+
* // etc.
|
|
59
|
+
* }}
|
|
60
|
+
* />
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export function CompanyRegistryAutocomplete({
|
|
64
|
+
countryCode,
|
|
65
|
+
onSelect,
|
|
66
|
+
placeholder = "Search company registry...",
|
|
67
|
+
className,
|
|
68
|
+
disabled,
|
|
69
|
+
}: CompanyRegistryAutocompleteProps) {
|
|
70
|
+
const [search, setSearch] = useState("");
|
|
71
|
+
|
|
72
|
+
const { isSupported, isLoading: isCheckingSupport } = useIsCountrySupported(countryCode);
|
|
73
|
+
const { data: searchData, isLoading: isSearching } = useCompanyRegistrySearch(countryCode, search);
|
|
74
|
+
|
|
75
|
+
const companies = searchData?.data || [];
|
|
76
|
+
|
|
77
|
+
// Don't render if country doesn't have registry data
|
|
78
|
+
if (isCheckingSupport) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (!isSupported) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const options = companies.map((company) => {
|
|
87
|
+
const truncatedName = truncateText(company.name);
|
|
88
|
+
const addressParts = [company.address, company.city].filter(Boolean);
|
|
89
|
+
const address = addressParts.join(", ");
|
|
90
|
+
const truncatedAddress = truncateText(address);
|
|
91
|
+
|
|
92
|
+
// Build subtitle with legal form and bank account indicator
|
|
93
|
+
const subtitleParts: string[] = [];
|
|
94
|
+
if (company.legal_form) {
|
|
95
|
+
subtitleParts.push(company.legal_form);
|
|
96
|
+
}
|
|
97
|
+
if (company.tax_number) {
|
|
98
|
+
subtitleParts.push(`Tax: ${company.tax_number}`);
|
|
99
|
+
}
|
|
100
|
+
if (company.bank_accounts && company.bank_accounts.length > 0) {
|
|
101
|
+
subtitleParts.push(`${company.bank_accounts.length} bank account(s)`);
|
|
102
|
+
}
|
|
103
|
+
const subtitle = subtitleParts.join(" • ");
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
value: company.id,
|
|
107
|
+
label: (
|
|
108
|
+
<div className="flex flex-col overflow-hidden py-1">
|
|
109
|
+
<span className="truncate font-medium">{truncatedName}</span>
|
|
110
|
+
{truncatedAddress && <span className="truncate text-muted-foreground text-xs">{truncatedAddress}</span>}
|
|
111
|
+
{subtitle && <span className="truncate text-muted-foreground text-xs">{subtitle}</span>}
|
|
112
|
+
</div>
|
|
113
|
+
),
|
|
114
|
+
company, // Pass full company object for selection
|
|
115
|
+
};
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const handleValueChange = (selectedValue: string) => {
|
|
119
|
+
const selectedOption = options.find((o) => o.value === selectedValue);
|
|
120
|
+
if (selectedOption?.company && onSelect) {
|
|
121
|
+
onSelect(selectedOption.company);
|
|
122
|
+
// Clear search after selection
|
|
123
|
+
setSearch("");
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const handleSearch = (value: string) => {
|
|
128
|
+
setSearch(value);
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
return (
|
|
132
|
+
<div className={className}>
|
|
133
|
+
<div className="mb-2 flex items-center gap-2">
|
|
134
|
+
<Building2 className="size-4 text-muted-foreground" />
|
|
135
|
+
<span className="font-medium text-muted-foreground text-sm">Search {countryCode} company registry</span>
|
|
136
|
+
</div>
|
|
137
|
+
<Autocomplete
|
|
138
|
+
searchValue={search}
|
|
139
|
+
onSearch={handleSearch}
|
|
140
|
+
onValueChange={handleValueChange}
|
|
141
|
+
options={options}
|
|
142
|
+
placeholder={placeholder}
|
|
143
|
+
disabled={disabled}
|
|
144
|
+
loading={isSearching}
|
|
145
|
+
emptyText={search.length < 2 ? "Type at least 2 characters" : "No companies found"}
|
|
146
|
+
/>
|
|
147
|
+
</div>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export default CompanyRegistryAutocomplete;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { CompanyRegistryResult } from "@spaceinvoices/js-sdk";
|
|
2
|
+
import { useQuery } from "@tanstack/react-query";
|
|
3
|
+
import { useDebounce } from "@/ui/hooks/use-debounce";
|
|
4
|
+
import { useSDK } from "@/ui/providers/sdk-provider";
|
|
5
|
+
|
|
6
|
+
// Cache key for company registry queries
|
|
7
|
+
export const COMPANY_REGISTRY_CACHE_KEY = "company-registry";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Search company registry for autocomplete
|
|
11
|
+
* Debounced to reduce API calls while typing
|
|
12
|
+
*/
|
|
13
|
+
export function useCompanyRegistrySearch(countryCode: string, query: string) {
|
|
14
|
+
const { sdk } = useSDK();
|
|
15
|
+
const debouncedQuery = useDebounce(query, 300);
|
|
16
|
+
|
|
17
|
+
return useQuery({
|
|
18
|
+
queryKey: [COMPANY_REGISTRY_CACHE_KEY, "search", countryCode, debouncedQuery],
|
|
19
|
+
queryFn: async (): Promise<{ data: CompanyRegistryResult[] }> => {
|
|
20
|
+
if (!debouncedQuery || debouncedQuery.length < 2) {
|
|
21
|
+
return { data: [] };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// SDK auto-unwraps response - returns CompanyRegistrySearchResponse directly
|
|
25
|
+
const response = await sdk.companyRegistry.searchCompanyRegistry({
|
|
26
|
+
country_code: countryCode,
|
|
27
|
+
q: debouncedQuery,
|
|
28
|
+
limit: "10",
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
return { data: response.data };
|
|
32
|
+
},
|
|
33
|
+
enabled: Boolean(countryCode && debouncedQuery && debouncedQuery.length >= 2),
|
|
34
|
+
staleTime: 1000 * 60 * 5, // Cache for 5 minutes
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Get list of countries that have company registry data available
|
|
40
|
+
*/
|
|
41
|
+
export function useSupportedCountries() {
|
|
42
|
+
const { sdk } = useSDK();
|
|
43
|
+
|
|
44
|
+
return useQuery({
|
|
45
|
+
queryKey: [COMPANY_REGISTRY_CACHE_KEY, "countries"],
|
|
46
|
+
queryFn: async (): Promise<{ data: string[] }> => {
|
|
47
|
+
// SDK method renamed to `list`, auto-unwraps response
|
|
48
|
+
const response = await sdk.companyRegistry.list();
|
|
49
|
+
return { data: response.data };
|
|
50
|
+
},
|
|
51
|
+
staleTime: 1000 * 60 * 60, // Cache for 1 hour - doesn't change often
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Check if company registry is available for a specific country
|
|
57
|
+
*/
|
|
58
|
+
export function useIsCountrySupported(countryCode: string) {
|
|
59
|
+
const { data: countriesData, isLoading } = useSupportedCountries();
|
|
60
|
+
|
|
61
|
+
const isSupported = countriesData?.data?.includes(countryCode) ?? false;
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
isSupported,
|
|
65
|
+
isLoading,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
import { zodResolver } from "@hookform/resolvers/zod";
|
|
2
|
+
import type { CreateCreditNoteRequest, CreditNote } from "@spaceinvoices/js-sdk";
|
|
3
|
+
import { useQueryClient } from "@tanstack/react-query";
|
|
4
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
5
|
+
import type { Resolver } from "react-hook-form";
|
|
6
|
+
import { useForm, useWatch } from "react-hook-form";
|
|
7
|
+
import type { z } from "zod";
|
|
8
|
+
import { Form } from "@/ui/components/ui/form";
|
|
9
|
+
import { createCreditNoteSchema } from "@/ui/generated/schemas";
|
|
10
|
+
import { useNextDocumentNumber } from "@/ui/hooks/use-next-document-number";
|
|
11
|
+
import type { ComponentTranslationProps } from "@/ui/lib/translation";
|
|
12
|
+
import { createTranslation } from "@/ui/lib/translation";
|
|
13
|
+
import { useEntities } from "@/ui/providers/entities-context";
|
|
14
|
+
import { useFormFooterRegistration } from "@/ui/providers/form-footer-context";
|
|
15
|
+
import { CUSTOMERS_CACHE_KEY } from "../../customers/customers.hooks";
|
|
16
|
+
import {
|
|
17
|
+
DocumentDetailsSection,
|
|
18
|
+
DocumentNoteField,
|
|
19
|
+
DocumentPaymentTermsField,
|
|
20
|
+
} from "../../documents/create/document-details-section";
|
|
21
|
+
import { DocumentItemsSection, type PriceModesMap } from "../../documents/create/document-items-section";
|
|
22
|
+
import { DocumentRecipientSection } from "../../documents/create/document-recipient-section";
|
|
23
|
+
import { MarkAsPaidSection } from "../../documents/create/mark-as-paid-section";
|
|
24
|
+
import { prepareDocumentSubmission } from "../../documents/create/prepare-document-submission";
|
|
25
|
+
import { useDocumentCustomerForm } from "../../documents/create/use-document-customer-form";
|
|
26
|
+
import type { DocumentTypes } from "../../documents/types";
|
|
27
|
+
import { useCreateCreditNote } from "../credit-notes.hooks";
|
|
28
|
+
import de from "./locales/de";
|
|
29
|
+
import sl from "./locales/sl";
|
|
30
|
+
|
|
31
|
+
const translations = {
|
|
32
|
+
sl,
|
|
33
|
+
de,
|
|
34
|
+
} as const;
|
|
35
|
+
|
|
36
|
+
// Form values: extend schema with local-only fields (number is for display, not sent to API)
|
|
37
|
+
type CreateCreditNoteFormValues = z.infer<typeof createCreditNoteSchema> & {
|
|
38
|
+
number?: string;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/** Preview payload extends request with display-only fields */
|
|
42
|
+
type CreditNotePreviewPayload = Partial<CreateCreditNoteRequest> & { number?: string };
|
|
43
|
+
|
|
44
|
+
type CreateCreditNoteFormProps = {
|
|
45
|
+
type: DocumentTypes;
|
|
46
|
+
entityId: string;
|
|
47
|
+
onSuccess?: (data: CreditNote) => void;
|
|
48
|
+
onError?: (error: unknown) => void;
|
|
49
|
+
onChange?: (data: CreditNotePreviewPayload) => void;
|
|
50
|
+
onAddNewTax?: () => void;
|
|
51
|
+
/** Initial values for form fields (used for document duplication) */
|
|
52
|
+
initialValues?: Partial<CreateCreditNoteRequest>;
|
|
53
|
+
} & ComponentTranslationProps;
|
|
54
|
+
|
|
55
|
+
export default function CreateCreditNoteForm({
|
|
56
|
+
type: _type,
|
|
57
|
+
entityId,
|
|
58
|
+
onSuccess,
|
|
59
|
+
onError,
|
|
60
|
+
onChange,
|
|
61
|
+
onAddNewTax,
|
|
62
|
+
initialValues,
|
|
63
|
+
t: translateProp,
|
|
64
|
+
namespace,
|
|
65
|
+
locale,
|
|
66
|
+
}: CreateCreditNoteFormProps) {
|
|
67
|
+
const t = createTranslation({
|
|
68
|
+
t: translateProp,
|
|
69
|
+
namespace,
|
|
70
|
+
locale,
|
|
71
|
+
translations,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const { activeEntity } = useEntities();
|
|
75
|
+
const queryClient = useQueryClient();
|
|
76
|
+
|
|
77
|
+
// Fetch next credit note number
|
|
78
|
+
const { data: nextNumberData } = useNextDocumentNumber(entityId, "credit_note", {
|
|
79
|
+
enabled: !!entityId,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// UI-only state (not part of API schema)
|
|
83
|
+
const [markAsPaid, setMarkAsPaid] = useState(false);
|
|
84
|
+
const [paymentType, setPaymentType] = useState("bank_transfer");
|
|
85
|
+
const [isDraftPending, setIsDraftPending] = useState(false);
|
|
86
|
+
|
|
87
|
+
// Price modes per item (gross vs net) - collected from component state at submit
|
|
88
|
+
const initialPriceModes = useMemo(() => {
|
|
89
|
+
if (!initialValues?.items) return {};
|
|
90
|
+
return initialValues.items.reduce((acc, item, index) => {
|
|
91
|
+
acc[index] = item.gross_price != null;
|
|
92
|
+
return acc;
|
|
93
|
+
}, {} as PriceModesMap);
|
|
94
|
+
}, [initialValues?.items]);
|
|
95
|
+
const priceModesRef = useRef<PriceModesMap>(initialPriceModes);
|
|
96
|
+
|
|
97
|
+
// Get default payment terms from entity settings
|
|
98
|
+
const defaultPaymentTerms = (activeEntity?.settings as any)?.default_credit_note_payment_terms || "";
|
|
99
|
+
|
|
100
|
+
const form = useForm<CreateCreditNoteFormValues>({
|
|
101
|
+
// Cast resolver to accept extended form type (includes UI-only fields)
|
|
102
|
+
resolver: zodResolver(createCreditNoteSchema) as Resolver<CreateCreditNoteFormValues>,
|
|
103
|
+
defaultValues: {
|
|
104
|
+
number: "",
|
|
105
|
+
date: initialValues?.date || new Date().toISOString(),
|
|
106
|
+
customer_id: initialValues?.customer_id ?? undefined,
|
|
107
|
+
// Cast customer to form schema type (API type may have additional fields)
|
|
108
|
+
customer: (initialValues?.customer as CreateCreditNoteFormValues["customer"]) ?? undefined,
|
|
109
|
+
items: initialValues?.items?.length
|
|
110
|
+
? initialValues.items.map((item) => ({
|
|
111
|
+
name: item.name || "",
|
|
112
|
+
description: item.description || "",
|
|
113
|
+
quantity: item.quantity ?? 1,
|
|
114
|
+
// Use gross_price if set, otherwise use price
|
|
115
|
+
price: item.gross_price ?? item.price,
|
|
116
|
+
taxes: item.taxes || [],
|
|
117
|
+
}))
|
|
118
|
+
: [
|
|
119
|
+
{
|
|
120
|
+
name: "",
|
|
121
|
+
description: "",
|
|
122
|
+
quantity: 1,
|
|
123
|
+
price: undefined,
|
|
124
|
+
taxes: [],
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
currency_code: initialValues?.currency_code || activeEntity?.currency_code || "EUR",
|
|
128
|
+
note: initialValues?.note ?? "",
|
|
129
|
+
payment_terms: initialValues?.payment_terms ?? defaultPaymentTerms,
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const formValues = useWatch({
|
|
134
|
+
control: form.control,
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// Extract customer management logic into a shared hook
|
|
138
|
+
const {
|
|
139
|
+
originalCustomer,
|
|
140
|
+
showCustomerForm,
|
|
141
|
+
shouldFocusName,
|
|
142
|
+
selectedCustomerId,
|
|
143
|
+
initialCustomerName,
|
|
144
|
+
handleCustomerSelect,
|
|
145
|
+
handleCustomerClear,
|
|
146
|
+
} = useDocumentCustomerForm(form);
|
|
147
|
+
|
|
148
|
+
// Pre-fill credit note number from preview
|
|
149
|
+
useEffect(() => {
|
|
150
|
+
if (nextNumberData?.number) {
|
|
151
|
+
form.setValue("number", nextNumberData.number);
|
|
152
|
+
}
|
|
153
|
+
}, [nextNumberData?.number, form]);
|
|
154
|
+
|
|
155
|
+
const { mutate: createCreditNote, isPending } = useCreateCreditNote({
|
|
156
|
+
entityId,
|
|
157
|
+
onSuccess: (data) => {
|
|
158
|
+
// Invalidate customers cache when a customer was created/linked
|
|
159
|
+
if (data.customer_id) {
|
|
160
|
+
queryClient.invalidateQueries({ queryKey: [CUSTOMERS_CACHE_KEY] });
|
|
161
|
+
}
|
|
162
|
+
onSuccess?.(data);
|
|
163
|
+
},
|
|
164
|
+
onError,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// Shared submit logic for both regular save and save as draft
|
|
168
|
+
const submitCreditNote = useCallback(
|
|
169
|
+
(values: CreateCreditNoteFormValues, isDraft: boolean) => {
|
|
170
|
+
const payload = prepareDocumentSubmission(values, {
|
|
171
|
+
originalCustomer,
|
|
172
|
+
wasCustomerFormShown: showCustomerForm,
|
|
173
|
+
markAsPaid: isDraft ? false : markAsPaid,
|
|
174
|
+
paymentType,
|
|
175
|
+
documentType: "credit_note",
|
|
176
|
+
priceModes: priceModesRef.current,
|
|
177
|
+
isDraft,
|
|
178
|
+
});
|
|
179
|
+
createCreditNote(payload as CreateCreditNoteRequest);
|
|
180
|
+
},
|
|
181
|
+
[createCreditNote, markAsPaid, originalCustomer, paymentType, showCustomerForm],
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
// Handle save as draft
|
|
185
|
+
const handleSaveAsDraft = useCallback(async () => {
|
|
186
|
+
setIsDraftPending(true);
|
|
187
|
+
try {
|
|
188
|
+
const isValid = await form.trigger();
|
|
189
|
+
if (isValid) {
|
|
190
|
+
const values = form.getValues();
|
|
191
|
+
submitCreditNote(values, true);
|
|
192
|
+
}
|
|
193
|
+
} finally {
|
|
194
|
+
setIsDraftPending(false);
|
|
195
|
+
}
|
|
196
|
+
}, [form, submitCreditNote]);
|
|
197
|
+
|
|
198
|
+
useFormFooterRegistration({
|
|
199
|
+
formId: "create-credit-note-form",
|
|
200
|
+
isPending,
|
|
201
|
+
isDirty: form.formState.isDirty,
|
|
202
|
+
label: t("Save"),
|
|
203
|
+
secondaryAction: {
|
|
204
|
+
label: t("Save as Draft"),
|
|
205
|
+
onClick: handleSaveAsDraft,
|
|
206
|
+
isPending: isDraftPending,
|
|
207
|
+
},
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// Set default note and payment terms from entity settings when entity data is available
|
|
211
|
+
useEffect(() => {
|
|
212
|
+
const entityDefaultNote = (activeEntity?.settings as any)?.default_credit_note_note;
|
|
213
|
+
if (entityDefaultNote && !form.getValues("note")) {
|
|
214
|
+
form.setValue("note", entityDefaultNote);
|
|
215
|
+
}
|
|
216
|
+
const entityDefaultPaymentTerms = (activeEntity?.settings as any)?.default_credit_note_payment_terms;
|
|
217
|
+
if (entityDefaultPaymentTerms && !form.getValues("payment_terms")) {
|
|
218
|
+
form.setValue("payment_terms", entityDefaultPaymentTerms);
|
|
219
|
+
}
|
|
220
|
+
}, [activeEntity, form]);
|
|
221
|
+
|
|
222
|
+
// Auto-add tax field for tax subject entities
|
|
223
|
+
useEffect(() => {
|
|
224
|
+
if (activeEntity?.is_tax_subject) {
|
|
225
|
+
const items = form.getValues("items") || [];
|
|
226
|
+
if (items.length > 0 && (!items[0].taxes || items[0].taxes.length === 0)) {
|
|
227
|
+
form.setValue("items.0.taxes", [{ tax_id: undefined }]);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}, [activeEntity?.is_tax_subject, form]);
|
|
231
|
+
|
|
232
|
+
useEffect(() => {
|
|
233
|
+
if (onChange) {
|
|
234
|
+
const currentItems = form.getValues("items") || [];
|
|
235
|
+
|
|
236
|
+
// Transform items to use gross_price when price mode is gross
|
|
237
|
+
const transformedItems = currentItems.map((item: any, index: number) => {
|
|
238
|
+
const { price, ...rest } = item;
|
|
239
|
+
const isGross = priceModesRef.current[index] ?? false;
|
|
240
|
+
if (isGross) {
|
|
241
|
+
return { ...rest, gross_price: price };
|
|
242
|
+
}
|
|
243
|
+
return { ...rest, price };
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
// Build preview payload (includes number for display)
|
|
247
|
+
const payload: CreditNotePreviewPayload = {
|
|
248
|
+
number: formValues.number,
|
|
249
|
+
date: formValues.date,
|
|
250
|
+
customer_id: formValues.customer_id,
|
|
251
|
+
customer: formValues.customer,
|
|
252
|
+
items: transformedItems,
|
|
253
|
+
currency_code: formValues.currency_code,
|
|
254
|
+
note: formValues.note,
|
|
255
|
+
payment_terms: formValues.payment_terms,
|
|
256
|
+
};
|
|
257
|
+
onChange(payload);
|
|
258
|
+
}
|
|
259
|
+
}, [formValues, onChange, form]);
|
|
260
|
+
|
|
261
|
+
const onSubmit = (values: CreateCreditNoteFormValues) => {
|
|
262
|
+
submitCreditNote(values, false);
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
return (
|
|
266
|
+
<Form {...form}>
|
|
267
|
+
<form id="create-credit-note-form" onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
|
|
268
|
+
<div className="flex w-full flex-col md:flex-row md:gap-6">
|
|
269
|
+
<DocumentRecipientSection
|
|
270
|
+
control={form.control}
|
|
271
|
+
entityId={entityId}
|
|
272
|
+
onCustomerSelect={handleCustomerSelect}
|
|
273
|
+
onCustomerClear={handleCustomerClear}
|
|
274
|
+
showCustomerForm={showCustomerForm}
|
|
275
|
+
shouldFocusName={shouldFocusName}
|
|
276
|
+
selectedCustomerId={selectedCustomerId}
|
|
277
|
+
initialCustomerName={initialCustomerName}
|
|
278
|
+
t={t}
|
|
279
|
+
/>
|
|
280
|
+
<DocumentDetailsSection control={form.control} documentType={_type} t={t}>
|
|
281
|
+
{/* Credit note specific: Mark as paid section (UI-only state, not in form schema) */}
|
|
282
|
+
<MarkAsPaidSection
|
|
283
|
+
checked={markAsPaid}
|
|
284
|
+
onCheckedChange={setMarkAsPaid}
|
|
285
|
+
paymentType={paymentType}
|
|
286
|
+
onPaymentTypeChange={setPaymentType}
|
|
287
|
+
t={t}
|
|
288
|
+
/>
|
|
289
|
+
</DocumentDetailsSection>
|
|
290
|
+
</div>
|
|
291
|
+
|
|
292
|
+
<DocumentItemsSection
|
|
293
|
+
control={form.control}
|
|
294
|
+
watch={form.watch}
|
|
295
|
+
setValue={form.setValue}
|
|
296
|
+
getValues={form.getValues}
|
|
297
|
+
entityId={entityId}
|
|
298
|
+
currencyCode={activeEntity?.currency_code ?? undefined}
|
|
299
|
+
onAddNewTax={onAddNewTax}
|
|
300
|
+
t={t}
|
|
301
|
+
maxTaxesPerItem={activeEntity?.country_rules?.max_taxes_per_item}
|
|
302
|
+
priceModesRef={priceModesRef}
|
|
303
|
+
initialPriceModes={initialPriceModes}
|
|
304
|
+
/>
|
|
305
|
+
|
|
306
|
+
<DocumentNoteField
|
|
307
|
+
control={form.control}
|
|
308
|
+
t={t}
|
|
309
|
+
entity={activeEntity}
|
|
310
|
+
document={{
|
|
311
|
+
number: formValues.number,
|
|
312
|
+
date: formValues.date,
|
|
313
|
+
currency_code: formValues.currency_code,
|
|
314
|
+
customer: formValues.customer as any,
|
|
315
|
+
}}
|
|
316
|
+
/>
|
|
317
|
+
|
|
318
|
+
<DocumentPaymentTermsField
|
|
319
|
+
control={form.control}
|
|
320
|
+
t={t}
|
|
321
|
+
entity={activeEntity}
|
|
322
|
+
document={{
|
|
323
|
+
number: formValues.number,
|
|
324
|
+
date: formValues.date,
|
|
325
|
+
currency_code: formValues.currency_code,
|
|
326
|
+
customer: formValues.customer as any,
|
|
327
|
+
}}
|
|
328
|
+
/>
|
|
329
|
+
</form>
|
|
330
|
+
</Form>
|
|
331
|
+
);
|
|
332
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as CreateCreditNoteForm } from "./create-credit-note-form";
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
Recipient: "Empfänger",
|
|
3
|
+
Name: "Name",
|
|
4
|
+
Details: "Details",
|
|
5
|
+
Number: "Nummer",
|
|
6
|
+
Date: "Datum",
|
|
7
|
+
"Pick a date": "Datum auswählen",
|
|
8
|
+
"Due Date": "Fälligkeitsdatum",
|
|
9
|
+
"Valid Until": "Gültig bis",
|
|
10
|
+
Items: "Artikel",
|
|
11
|
+
"Add item": "Artikel hinzufügen",
|
|
12
|
+
Save: "Speichern",
|
|
13
|
+
"Save as Draft": "Als Entwurf speichern",
|
|
14
|
+
Quantity: "Menge",
|
|
15
|
+
Price: "Preis",
|
|
16
|
+
Unit: "Einheit",
|
|
17
|
+
Discount: "Rabatt",
|
|
18
|
+
Tax: "Steuer",
|
|
19
|
+
"Tax rate": "Steuersatz",
|
|
20
|
+
"Add tax": "Steuer hinzufügen",
|
|
21
|
+
"Select tax...": "Steuer auswählen...",
|
|
22
|
+
"Loading...": "Laden...",
|
|
23
|
+
"No taxes found": "Keine Steuern gefunden",
|
|
24
|
+
"Add new tax...": "Neue Steuer hinzufügen...",
|
|
25
|
+
Description: "Beschreibung",
|
|
26
|
+
"Mark as Paid": "Als bezahlt markieren",
|
|
27
|
+
Paid: "Bezahlt",
|
|
28
|
+
"Credit note will be marked as fully paid upon creation":
|
|
29
|
+
"Gutschrift wird bei Erstellung als vollständig bezahlt markiert",
|
|
30
|
+
"Payment Type": "Zahlungsart",
|
|
31
|
+
"Select payment type": "Zahlungsart auswählen",
|
|
32
|
+
Cash: "Bargeld",
|
|
33
|
+
"Bank Transfer": "Banküberweisung",
|
|
34
|
+
Card: "Karte",
|
|
35
|
+
Check: "Scheck",
|
|
36
|
+
Other: "Andere",
|
|
37
|
+
// Note field
|
|
38
|
+
Note: "Notiz",
|
|
39
|
+
"Insert variable": "Variable einfügen",
|
|
40
|
+
"Add payment instructions, terms, or other notes...":
|
|
41
|
+
"Zahlungsanweisungen, Bedingungen oder andere Notizen hinzufügen...",
|
|
42
|
+
// Payment terms field
|
|
43
|
+
"Payment Terms": "Zahlungsbedingungen",
|
|
44
|
+
"Add payment terms...": "Zahlungsbedingungen hinzufügen...",
|
|
45
|
+
// Recipient fields
|
|
46
|
+
"Search or create customer...": "Kunde suchen oder erstellen...",
|
|
47
|
+
Clear: "Löschen",
|
|
48
|
+
Address: "Adresse",
|
|
49
|
+
"Address 2": "Adresse 2",
|
|
50
|
+
"Post Code": "Postleitzahl",
|
|
51
|
+
City: "Stadt",
|
|
52
|
+
State: "Bundesland",
|
|
53
|
+
Country: "Land",
|
|
54
|
+
"Tax Number": "Steuernummer",
|
|
55
|
+
// Currency
|
|
56
|
+
Currency: "Währung",
|
|
57
|
+
"Select currency": "Währung auswählen",
|
|
58
|
+
// Discount types
|
|
59
|
+
"Percentage discount": "Prozentualer Rabatt",
|
|
60
|
+
"Fixed amount discount": "Fester Rabatt",
|
|
61
|
+
Percentage: "Prozent",
|
|
62
|
+
"Fixed amount": "Fester Betrag",
|
|
63
|
+
"Taxes disabled": "Steuern deaktiviert",
|
|
64
|
+
// Gross price support
|
|
65
|
+
"Gross price": "Bruttopreis",
|
|
66
|
+
"Net price": "Nettopreis",
|
|
67
|
+
"Gross price (tax included)": "Bruttopreis (inkl. MwSt.)",
|
|
68
|
+
"Net price (before tax)": "Nettopreis (exkl. MwSt.)",
|
|
69
|
+
} as const;
|