@spaceinvoices/react-ui 0.4.8 → 0.4.10
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/cli/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/common/autocomplete.tsx +69 -6
- package/src/components/advance-invoices/create/create-advance-invoice-form.tsx +124 -285
- package/src/components/advance-invoices/list/list-table.tsx +10 -3
- package/src/components/advance-invoices/list/locales/de.ts +2 -0
- package/src/components/advance-invoices/list/locales/en.ts +1 -0
- package/src/components/advance-invoices/list/locales/es.ts +1 -0
- package/src/components/advance-invoices/list/locales/fr.ts +1 -0
- package/src/components/advance-invoices/list/locales/hr.ts +1 -0
- package/src/components/advance-invoices/list/locales/it.ts +1 -0
- package/src/components/advance-invoices/list/locales/nl.ts +1 -0
- package/src/components/advance-invoices/list/locales/pl.ts +1 -0
- package/src/components/advance-invoices/list/locales/pt.ts +1 -0
- package/src/components/advance-invoices/list/locales/sl.ts +1 -0
- package/src/components/advance-invoices/list/use-advance-invoice-download.ts +1 -12
- package/src/components/credit-notes/create/create-credit-note-form.tsx +116 -238
- package/src/components/credit-notes/list/list-table.tsx +6 -3
- package/src/components/credit-notes/list/use-credit-note-download.ts +1 -12
- package/src/components/customers/customer-autocomplete.tsx +64 -11
- package/src/components/customers/customer-list-table/customer-list-table.tsx +3 -2
- package/src/components/dashboard/collection-rate-card/collection-rate-card.tsx +9 -1
- package/src/components/dashboard/collection-rate-card/locales/bg.ts +3 -0
- package/src/components/dashboard/collection-rate-card/locales/cs.ts +3 -0
- package/src/components/dashboard/collection-rate-card/locales/et.ts +3 -0
- package/src/components/dashboard/collection-rate-card/locales/fi.ts +3 -0
- package/src/components/dashboard/collection-rate-card/locales/is.ts +3 -0
- package/src/components/dashboard/collection-rate-card/locales/nb.ts +3 -0
- package/src/components/dashboard/collection-rate-card/locales/sk.ts +3 -0
- package/src/components/dashboard/collection-rate-card/locales/sv.ts +3 -0
- package/src/components/dashboard/invoice-status-chart/invoice-status-chart.tsx +10 -2
- package/src/components/dashboard/invoice-status-chart/locales/bg.ts +10 -0
- package/src/components/dashboard/invoice-status-chart/locales/cs.ts +10 -0
- package/src/components/dashboard/invoice-status-chart/locales/de.ts +1 -0
- package/src/components/dashboard/invoice-status-chart/locales/es.ts +1 -0
- package/src/components/dashboard/invoice-status-chart/locales/et.ts +10 -0
- package/src/components/dashboard/invoice-status-chart/locales/fi.ts +10 -0
- package/src/components/dashboard/invoice-status-chart/locales/fr.ts +1 -0
- package/src/components/dashboard/invoice-status-chart/locales/hr.ts +1 -0
- package/src/components/dashboard/invoice-status-chart/locales/is.ts +10 -0
- package/src/components/dashboard/invoice-status-chart/locales/it.ts +1 -0
- package/src/components/dashboard/invoice-status-chart/locales/nb.ts +10 -0
- package/src/components/dashboard/invoice-status-chart/locales/nl.ts +1 -0
- package/src/components/dashboard/invoice-status-chart/locales/pl.ts +1 -0
- package/src/components/dashboard/invoice-status-chart/locales/pt.ts +1 -0
- package/src/components/dashboard/invoice-status-chart/locales/sk.ts +10 -0
- package/src/components/dashboard/invoice-status-chart/locales/sl.ts +1 -0
- package/src/components/dashboard/invoice-status-chart/locales/sv.ts +10 -0
- package/src/components/dashboard/payment-methods-chart/locales/bg.ts +12 -0
- package/src/components/dashboard/payment-methods-chart/locales/cs.ts +12 -0
- package/src/components/dashboard/payment-methods-chart/locales/et.ts +12 -0
- package/src/components/dashboard/payment-methods-chart/locales/fi.ts +12 -0
- package/src/components/dashboard/payment-methods-chart/locales/is.ts +12 -0
- package/src/components/dashboard/payment-methods-chart/locales/nb.ts +12 -0
- package/src/components/dashboard/payment-methods-chart/locales/sk.ts +12 -0
- package/src/components/dashboard/payment-methods-chart/locales/sv.ts +12 -0
- package/src/components/dashboard/payment-methods-chart/payment-methods-chart.tsx +9 -1
- package/src/components/dashboard/payment-trend-chart/locales/bg.ts +6 -0
- package/src/components/dashboard/payment-trend-chart/locales/cs.ts +6 -0
- package/src/components/dashboard/payment-trend-chart/locales/de.ts +1 -0
- package/src/components/dashboard/payment-trend-chart/locales/es.ts +1 -0
- package/src/components/dashboard/payment-trend-chart/locales/et.ts +6 -0
- package/src/components/dashboard/payment-trend-chart/locales/fi.ts +6 -0
- package/src/components/dashboard/payment-trend-chart/locales/fr.ts +1 -0
- package/src/components/dashboard/payment-trend-chart/locales/hr.ts +1 -0
- package/src/components/dashboard/payment-trend-chart/locales/is.ts +6 -0
- package/src/components/dashboard/payment-trend-chart/locales/it.ts +1 -0
- package/src/components/dashboard/payment-trend-chart/locales/nb.ts +6 -0
- package/src/components/dashboard/payment-trend-chart/locales/nl.ts +1 -0
- package/src/components/dashboard/payment-trend-chart/locales/pl.ts +1 -0
- package/src/components/dashboard/payment-trend-chart/locales/pt.ts +1 -0
- package/src/components/dashboard/payment-trend-chart/locales/sk.ts +6 -0
- package/src/components/dashboard/payment-trend-chart/locales/sl.ts +1 -0
- package/src/components/dashboard/payment-trend-chart/locales/sv.ts +6 -0
- package/src/components/dashboard/payment-trend-chart/payment-trend-chart.tsx +15 -8
- package/src/components/dashboard/revenue-trend-chart/locales/bg.ts +6 -0
- package/src/components/dashboard/revenue-trend-chart/locales/cs.ts +6 -0
- package/src/components/dashboard/revenue-trend-chart/locales/de.ts +1 -0
- package/src/components/dashboard/revenue-trend-chart/locales/es.ts +1 -0
- package/src/components/dashboard/revenue-trend-chart/locales/et.ts +6 -0
- package/src/components/dashboard/revenue-trend-chart/locales/fi.ts +6 -0
- package/src/components/dashboard/revenue-trend-chart/locales/fr.ts +1 -0
- package/src/components/dashboard/revenue-trend-chart/locales/hr.ts +1 -0
- package/src/components/dashboard/revenue-trend-chart/locales/is.ts +6 -0
- package/src/components/dashboard/revenue-trend-chart/locales/it.ts +1 -0
- package/src/components/dashboard/revenue-trend-chart/locales/nb.ts +6 -0
- package/src/components/dashboard/revenue-trend-chart/locales/nl.ts +1 -0
- package/src/components/dashboard/revenue-trend-chart/locales/pl.ts +1 -0
- package/src/components/dashboard/revenue-trend-chart/locales/pt.ts +1 -0
- package/src/components/dashboard/revenue-trend-chart/locales/sk.ts +6 -0
- package/src/components/dashboard/revenue-trend-chart/locales/sl.ts +1 -0
- package/src/components/dashboard/revenue-trend-chart/locales/sv.ts +6 -0
- package/src/components/dashboard/revenue-trend-chart/revenue-trend-chart.tsx +15 -8
- package/src/components/dashboard/tax-collected-card/locales.ts +110 -0
- package/src/components/dashboard/tax-collected-card/tax-collected-card.tsx +8 -2
- package/src/components/dashboard/tax-collected-card/use-tax-collected.ts +4 -4
- package/src/components/dashboard/top-customers-chart/locales/bg.ts +7 -0
- package/src/components/dashboard/top-customers-chart/locales/cs.ts +7 -0
- package/src/components/dashboard/top-customers-chart/locales/de.ts +2 -0
- package/src/components/dashboard/top-customers-chart/locales/es.ts +2 -0
- package/src/components/dashboard/top-customers-chart/locales/et.ts +7 -0
- package/src/components/dashboard/top-customers-chart/locales/fi.ts +7 -0
- package/src/components/dashboard/top-customers-chart/locales/fr.ts +2 -0
- package/src/components/dashboard/top-customers-chart/locales/hr.ts +2 -0
- package/src/components/dashboard/top-customers-chart/locales/is.ts +7 -0
- package/src/components/dashboard/top-customers-chart/locales/it.ts +2 -0
- package/src/components/dashboard/top-customers-chart/locales/nb.ts +7 -0
- package/src/components/dashboard/top-customers-chart/locales/nl.ts +2 -0
- package/src/components/dashboard/top-customers-chart/locales/pl.ts +2 -0
- package/src/components/dashboard/top-customers-chart/locales/pt.ts +2 -0
- package/src/components/dashboard/top-customers-chart/locales/sk.ts +7 -0
- package/src/components/dashboard/top-customers-chart/locales/sl.ts +2 -0
- package/src/components/dashboard/top-customers-chart/locales/sv.ts +7 -0
- package/src/components/dashboard/top-customers-chart/top-customers-chart.tsx +23 -12
- package/src/components/delivery-notes/create/create-delivery-note-form.tsx +33 -20
- package/src/components/delivery-notes/list/list-table.tsx +22 -13
- package/src/components/delivery-notes/list/locales/de.ts +2 -0
- package/src/components/delivery-notes/list/locales/en.ts +1 -0
- package/src/components/delivery-notes/list/locales/es.ts +1 -0
- package/src/components/delivery-notes/list/locales/fr.ts +1 -0
- package/src/components/delivery-notes/list/locales/hr.ts +1 -0
- package/src/components/delivery-notes/list/locales/it.ts +1 -0
- package/src/components/delivery-notes/list/locales/nl.ts +1 -0
- package/src/components/delivery-notes/list/locales/pl.ts +1 -0
- package/src/components/delivery-notes/list/locales/pt.ts +1 -0
- package/src/components/delivery-notes/list/locales/sl.ts +1 -0
- package/src/components/delivery-notes/list/use-delivery-note-download.ts +1 -12
- package/src/components/documents/create/document-add-item-form.tsx +28 -16
- package/src/components/documents/create/document-add-item-tax-rate-field.tsx +12 -2
- package/src/components/documents/create/document-items-section.tsx +70 -39
- package/src/components/documents/create/document-recipient-section.tsx +10 -1
- package/src/components/documents/create/live-preview.tsx +113 -15
- package/src/components/documents/create/prepare-document-submission.ts +35 -16
- package/src/components/documents/create/use-document-customer-form.ts +14 -3
- package/src/components/documents/documents.hooks.ts +7 -2
- package/src/components/documents/shared/document-preview-display.tsx +136 -67
- package/src/components/documents/shared/scaled-document-preview.tsx +45 -5
- package/src/components/documents/view/document-actions-bar.tsx +284 -182
- package/src/components/documents/view/document-activities-list.tsx +3 -0
- package/src/components/documents/view/document-payments-list.tsx +3 -0
- package/src/components/documents/view/locales/de.ts +8 -0
- package/src/components/documents/view/locales/es.ts +8 -0
- package/src/components/documents/view/locales/fr.ts +8 -0
- package/src/components/documents/view/locales/hr.ts +8 -0
- package/src/components/documents/view/locales/it.ts +8 -0
- package/src/components/documents/view/locales/nl.ts +8 -0
- package/src/components/documents/view/locales/pl.ts +8 -0
- package/src/components/documents/view/locales/pt.ts +8 -0
- package/src/components/documents/view/locales/sl.ts +8 -0
- package/src/components/documents/view/use-document-download.ts +14 -25
- package/src/components/entities/create-entity-form.tsx +101 -16
- package/src/components/entities/fina-settings-form/fina-operator-required-dialog.tsx +3 -3
- package/src/components/entities/fina-settings-form/fina-settings-form.tsx +78 -124
- package/src/components/entities/fina-settings-form/sections/certificate-settings-section.tsx +8 -1
- package/src/components/entities/fina-settings-form/sections/premises-management-section.tsx +14 -2
- package/src/components/entities/fina-settings-form/sections/register-premise-dialog.tsx +7 -2
- package/src/components/entities/furs-settings-form/furs-settings-form.tsx +56 -130
- package/src/components/entities/furs-settings-form/sections/certificate-settings-section.tsx +8 -1
- package/src/components/entities/furs-settings-form/sections/enable-fiscalization-section.tsx +1 -0
- package/src/components/entities/furs-settings-form/sections/general-settings-section.tsx +15 -2
- package/src/components/entities/furs-settings-form/sections/premises-management-section.tsx +20 -3
- package/src/components/entities/furs-settings-form/sections/register-premise-dialog.tsx +38 -12
- package/src/components/entities/settings/eslog-settings-form.tsx +13 -1
- package/src/components/entities/settings/pdf-template-selector/demo-invoice-data.ts +3 -22
- package/src/components/entities/shared/fiscalization-step-flow.ts +77 -0
- package/src/components/entities/shared/fiscalization-step-tabs.tsx +71 -0
- package/src/components/estimates/create/create-estimate-form.tsx +34 -21
- package/src/components/estimates/list/list-table.tsx +23 -14
- package/src/components/estimates/list/locales/de.ts +2 -0
- package/src/components/estimates/list/locales/en.ts +1 -0
- package/src/components/estimates/list/locales/es.ts +1 -0
- package/src/components/estimates/list/locales/fr.ts +1 -0
- package/src/components/estimates/list/locales/hr.ts +1 -0
- package/src/components/estimates/list/locales/it.ts +1 -0
- package/src/components/estimates/list/locales/nl.ts +1 -0
- package/src/components/estimates/list/locales/pl.ts +1 -0
- package/src/components/estimates/list/locales/pt.ts +1 -0
- package/src/components/estimates/list/locales/sl.ts +1 -0
- package/src/components/estimates/list/use-estimate-download.ts +1 -12
- package/src/components/export/document-export-form.tsx +33 -7
- package/src/components/export/sales-per-item-export-form.tsx +23 -7
- package/src/components/invoices/create/create-invoice-form.tsx +295 -329
- package/src/components/invoices/create/prepare-invoice-submission.ts +0 -8
- package/src/components/invoices/list/list-table.tsx +7 -4
- package/src/components/invoices/list/use-invoice-download.ts +1 -11
- package/src/components/invoices/send-email-dialog/locales/de.ts +2 -0
- package/src/components/invoices/send-email-dialog/locales/es.ts +2 -0
- package/src/components/invoices/send-email-dialog/locales/fr.ts +2 -0
- package/src/components/invoices/send-email-dialog/locales/hr.ts +2 -0
- package/src/components/invoices/send-email-dialog/locales/it.ts +2 -0
- package/src/components/invoices/send-email-dialog/locales/nl.ts +2 -0
- package/src/components/invoices/send-email-dialog/locales/pl.ts +2 -0
- package/src/components/invoices/send-email-dialog/locales/pt.ts +2 -0
- package/src/components/invoices/send-email-dialog/locales/sl.ts +2 -0
- package/src/components/invoices/send-email-dialog/send-email-dialog.tsx +77 -8
- package/src/components/invoices/view/eslog-info-display.tsx +17 -1
- package/src/components/invoices/view/fiscalization-status-card.tsx +7 -3
- package/src/components/items/item-combobox.tsx +26 -6
- package/src/components/items/item-list-table/item-list-table.tsx +5 -2
- package/src/components/payments/list/list-table.tsx +14 -4
- package/src/components/recurring-invoices/list/list-table.tsx +7 -4
- package/src/components/request-logs/locales.ts +412 -0
- package/src/components/request-logs/request-log-detail.tsx +37 -21
- package/src/components/request-logs/request-log-list-table.tsx +57 -11
- package/src/components/table/data-table.tsx +5 -2
- package/src/components/table/date-cell.tsx +3 -1
- package/src/components/table/filter-bar.tsx +14 -2
- package/src/components/table/hooks/use-table-query.ts +1 -1
- package/src/components/table/locales.ts +1116 -0
- package/src/components/table/search-input.tsx +12 -3
- package/src/components/table/selection-toolbar.tsx +23 -6
- package/src/components/table/table-empty-state.tsx +43 -3
- package/src/components/table/table-no-results.tsx +3 -3
- package/src/components/table/table-pagination.tsx +4 -3
- package/src/components/table/types.ts +1 -0
- package/src/components/tax-reports/index.ts +1 -0
- package/src/components/tax-reports/kir-export-form.tsx +46 -8
- package/src/components/tax-reports/slovenia-tax-profile-step.tsx +191 -0
- package/src/components/tax-reports/slovenia-yearly-export-form.tsx +509 -0
- package/src/components/tax-reports/slovenia-yearly-review-step.tsx +253 -0
- package/src/components/tax-reports/slovenia-yearly-summary.tsx +19 -0
- package/src/components/taxes/tax-list-table/tax-list-table.tsx +3 -2
- package/src/components/ui/sticky-form-footer.tsx +7 -1
- package/src/components/webhook-logs/index.ts +6 -0
- package/src/components/webhook-logs/locales.ts +392 -0
- package/src/components/webhook-logs/webhook-delivery-detail.tsx +255 -0
- package/src/components/webhook-logs/webhook-delivery-list-table.tsx +278 -0
- package/src/components/wl-subscription/index.ts +1 -0
- package/src/components/wl-subscription/locked-feature.tsx +1 -0
- package/src/components/wl-subscription/paywall.tsx +193 -0
- package/src/components/wl-subscription/upgrade-modal.tsx +93 -29
- package/src/generate-schemas.ts +10 -5
- package/src/generated/schemas/customer.ts +2 -0
- package/src/generated/schemas/entity.ts +34 -0
- package/src/generated/schemas/me.ts +20 -1
- package/src/generated/schemas/renderadvanceinvoicepreview_body.ts +40 -34
- package/src/generated/schemas/rendercreditnotepreview_body.ts +42 -36
- package/src/generated/schemas/renderdeliverynotepreview_body.ts +23 -13
- package/src/generated/schemas/renderestimatepreview_body.ts +23 -13
- package/src/generated/schemas/renderinvoicepreview_body.ts +40 -34
- package/src/generated/schemas/sendemail_body.ts +44 -0
- package/src/generated/schemas/startpdfexport_body.ts +91 -1
- package/src/generated/schemas/webhook.ts +10 -0
- package/src/hooks/use-duplicate-document.ts +51 -13
- package/src/hooks/use-eslog-validation.ts +59 -0
- package/src/hooks/use-premise-selection.ts +186 -0
- package/src/lib/browser-cookies.ts +4 -4
- package/src/lib/date-fns-locale.ts +48 -0
- package/src/lib/fiscalization-options.ts +81 -0
- package/src/lib/locale.ts +38 -0
- package/src/lib/template-variables.tsx +1 -1
- package/src/lib/translation.ts +14 -3
- package/src/providers/entities-context.tsx +1 -0
- package/src/providers/entities-provider.tsx +102 -3
- package/src/providers/form-footer-context.tsx +37 -4
- package/src/providers/sdk-provider.tsx +7 -2
- package/src/providers/white-label-provider.tsx +4 -1
- package/src/providers/wl-subscription-provider.tsx +90 -3
|
@@ -122,6 +122,14 @@ export default {
|
|
|
122
122
|
Dutch: "Neerlandês",
|
|
123
123
|
Polish: "Polaco",
|
|
124
124
|
Croatian: "Croata",
|
|
125
|
+
Swedish: "Sueco",
|
|
126
|
+
Finnish: "Finlandês",
|
|
127
|
+
Estonian: "Estónio",
|
|
128
|
+
Bulgarian: "Búlgaro",
|
|
129
|
+
Czech: "Checo",
|
|
130
|
+
Slovak: "Eslovaco",
|
|
131
|
+
Norwegian: "Norueguês",
|
|
132
|
+
Icelandic: "Islandês",
|
|
125
133
|
|
|
126
134
|
// Linked documents
|
|
127
135
|
"Linked documents": "Documentos vinculados",
|
|
@@ -123,6 +123,14 @@ export default {
|
|
|
123
123
|
Dutch: "Nizozemščina",
|
|
124
124
|
Polish: "Poljščina",
|
|
125
125
|
Croatian: "Hrvaščina",
|
|
126
|
+
Swedish: "Švedščina",
|
|
127
|
+
Finnish: "Finščina",
|
|
128
|
+
Estonian: "Estonščina",
|
|
129
|
+
Bulgarian: "Bolgarščina",
|
|
130
|
+
Czech: "Češčina",
|
|
131
|
+
Slovak: "Slovaščina",
|
|
132
|
+
Norwegian: "Norveščina",
|
|
133
|
+
Icelandic: "Islandščina",
|
|
126
134
|
|
|
127
135
|
// Linked documents
|
|
128
136
|
"Linked documents": "Povezani dokumenti",
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
type AdvanceInvoice,
|
|
3
|
+
type CreditNote,
|
|
4
|
+
type DeliveryNote,
|
|
5
|
+
downloadBlob,
|
|
6
|
+
type Estimate,
|
|
7
|
+
type Invoice,
|
|
8
|
+
} from "@spaceinvoices/js-sdk";
|
|
2
9
|
import { useState } from "react";
|
|
3
10
|
import { useEntities } from "@/ui/providers/entities-context";
|
|
4
11
|
import { useSDK } from "@/ui/providers/sdk-provider";
|
|
@@ -36,11 +43,10 @@ export function useDocumentDownload({
|
|
|
36
43
|
const [isDownloadingEslog, setIsDownloadingEslog] = useState(false);
|
|
37
44
|
|
|
38
45
|
/**
|
|
39
|
-
* Download PDF with optional
|
|
40
|
-
*
|
|
41
|
-
* The language param only changes labels/translations on the PDF.
|
|
46
|
+
* Download PDF with optional locale override.
|
|
47
|
+
* When a locale is selected, it is sent as both the formatting locale and label language.
|
|
42
48
|
*/
|
|
43
|
-
const downloadPdf = async (document: Document, documentType: DocumentType,
|
|
49
|
+
const downloadPdf = async (document: Document, documentType: DocumentType, locale?: string) => {
|
|
44
50
|
if (!sdk || !activeEntity?.id) {
|
|
45
51
|
onDownloadError?.("Download failed");
|
|
46
52
|
return;
|
|
@@ -53,21 +59,11 @@ export function useDocumentDownload({
|
|
|
53
59
|
// SDK signature: renderPdf(id, params?, SDKMethodOptions?)
|
|
54
60
|
// entity_id goes in SDKMethodOptions (last arg), not params
|
|
55
61
|
// Note: renderPdf is on invoices module but works with any document ID via /documents/{id}/pdf
|
|
56
|
-
|
|
57
|
-
const params = language ? { language } : {};
|
|
58
|
-
const blob = await sdk.invoices.renderPdf(document.id, params, { entity_id: activeEntity.id });
|
|
59
|
-
const downloadUrl = window.URL.createObjectURL(blob);
|
|
60
|
-
const link = window.document.createElement("a");
|
|
61
|
-
link.href = downloadUrl;
|
|
62
|
-
|
|
62
|
+
const params = locale ? { locale, language: locale } : {};
|
|
63
63
|
const typeLabel = TYPE_LABELS[documentType] || "Document";
|
|
64
64
|
const fileName = `${typeLabel} ${document.number}.pdf`;
|
|
65
|
-
link.download = fileName;
|
|
66
65
|
|
|
67
|
-
|
|
68
|
-
link.click();
|
|
69
|
-
window.document.body.removeChild(link);
|
|
70
|
-
window.URL.revokeObjectURL(downloadUrl);
|
|
66
|
+
await sdk.invoices.downloadPdf(document.id, fileName, params, { entity_id: activeEntity.id });
|
|
71
67
|
|
|
72
68
|
onDownloadSuccess?.(fileName);
|
|
73
69
|
} catch (error) {
|
|
@@ -106,14 +102,7 @@ export function useDocumentDownload({
|
|
|
106
102
|
const xml = await eSlogModule.download(document.id, typeMap[documentType], { entity_id: activeEntity.id });
|
|
107
103
|
|
|
108
104
|
const blob = new Blob([xml], { type: "application/xml" });
|
|
109
|
-
|
|
110
|
-
const a = window.document.createElement("a");
|
|
111
|
-
a.href = url;
|
|
112
|
-
a.download = `${document.number}.xml`;
|
|
113
|
-
window.document.body.appendChild(a);
|
|
114
|
-
a.click();
|
|
115
|
-
window.URL.revokeObjectURL(url);
|
|
116
|
-
window.document.body.removeChild(a);
|
|
105
|
+
downloadBlob(blob, `${document.number}.xml`);
|
|
117
106
|
} catch (error) {
|
|
118
107
|
console.error("Error downloading e-SLOG:", error);
|
|
119
108
|
onDownloadError?.("e-SLOG download failed");
|
|
@@ -10,6 +10,7 @@ import { Button } from "@/ui/components/ui/button";
|
|
|
10
10
|
import { Checkbox } from "@/ui/components/ui/checkbox";
|
|
11
11
|
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/ui/components/ui/form";
|
|
12
12
|
import { type CreateEntitySchema, createEntitySchema } from "@/ui/generated/schemas";
|
|
13
|
+
import { createTranslation } from "@/ui/lib/translation";
|
|
13
14
|
|
|
14
15
|
import ButtonLoader from "../button-loader";
|
|
15
16
|
import { useCreateEntity } from "./entities.hooks";
|
|
@@ -27,10 +28,85 @@ export type CreateEntityFormProps = {
|
|
|
27
28
|
onError?: (error: unknown) => void;
|
|
28
29
|
};
|
|
29
30
|
|
|
30
|
-
const
|
|
31
|
+
const translations = {
|
|
32
|
+
en: {
|
|
33
|
+
name: "Name",
|
|
34
|
+
"search-hint": "Search companies by name",
|
|
35
|
+
"no-results": "No companies found",
|
|
36
|
+
country: "Country",
|
|
37
|
+
address: "Address",
|
|
38
|
+
"address-2": "Address 2",
|
|
39
|
+
"post-code": "Post Code",
|
|
40
|
+
city: "City",
|
|
41
|
+
state: "State",
|
|
42
|
+
"tax-number": "Tax Number",
|
|
43
|
+
"is-tax-subject": "Tax subject",
|
|
44
|
+
"company-number": "Company Number",
|
|
45
|
+
submit: "Create entity",
|
|
46
|
+
},
|
|
47
|
+
} as const;
|
|
48
|
+
|
|
49
|
+
const ISO_COUNTRY_CODES = [
|
|
50
|
+
"AD", "AE", "AF", "AG", "AL", "AM", "AO", "AR", "AT", "AU", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI",
|
|
51
|
+
"BJ", "BN", "BO", "BR", "BS", "BT", "BW", "BY", "BZ", "CA", "CD", "CF", "CG", "CH", "CI", "CL", "CM", "CN", "CO",
|
|
52
|
+
"CR", "CU", "CV", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE", "EG", "ER", "ES", "ET", "FI", "FJ",
|
|
53
|
+
"FM", "FR", "GA", "GB", "GD", "GE", "GH", "GM", "GN", "GQ", "GR", "GT", "GW", "GY", "HK", "HN", "HR", "HT", "HU",
|
|
54
|
+
"ID", "IE", "IL", "IN", "IQ", "IR", "IS", "IT", "JM", "JO", "JP", "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR",
|
|
55
|
+
"KW", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "ME", "MG", "MH",
|
|
56
|
+
"MK", "ML", "MM", "MN", "MR", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NE", "NG", "NI", "NL", "NO", "NP",
|
|
57
|
+
"NR", "NZ", "OM", "PA", "PE", "PG", "PH", "PK", "PL", "PT", "PW", "PY", "QA", "RO", "RS", "RU", "RW", "SA", "SB",
|
|
58
|
+
"SC", "SD", "SE", "SG", "SI", "SK", "SL", "SM", "SN", "SO", "SR", "SS", "ST", "SV", "SY", "SZ", "TD", "TG", "TH",
|
|
59
|
+
"TJ", "TL", "TM", "TN", "TO", "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "US", "UY", "UZ", "VA", "VC", "VE", "VN",
|
|
60
|
+
"VU", "WS", "XK", "YE", "ZA", "ZM", "ZW",
|
|
61
|
+
] as const;
|
|
62
|
+
|
|
63
|
+
const COUNTRY_CODE_ALIASES: Record<string, string> = {
|
|
64
|
+
uk: "GB",
|
|
65
|
+
"u.k.": "GB",
|
|
66
|
+
usa: "US",
|
|
67
|
+
"u.s.": "US",
|
|
68
|
+
"u.s.a.": "US",
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
function normalizeCountryName(value: string): string {
|
|
72
|
+
return value
|
|
73
|
+
.normalize("NFKD")
|
|
74
|
+
.replace(/\p{Diacritic}/gu, "")
|
|
75
|
+
.replace(/[.'’]/g, "")
|
|
76
|
+
.replace(/\s+/g, " ")
|
|
77
|
+
.trim()
|
|
78
|
+
.toLowerCase();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function resolveCountryCodeFromName(value: string | undefined, locale: string): string | undefined {
|
|
82
|
+
const trimmed = value?.trim();
|
|
83
|
+
if (!trimmed) return undefined;
|
|
84
|
+
|
|
85
|
+
const alias = COUNTRY_CODE_ALIASES[normalizeCountryName(trimmed)];
|
|
86
|
+
if (alias) return alias;
|
|
87
|
+
|
|
88
|
+
const upper = trimmed.toUpperCase();
|
|
89
|
+
if (upper.length === 2 && ISO_COUNTRY_CODES.includes(upper as (typeof ISO_COUNTRY_CODES)[number])) {
|
|
90
|
+
return upper;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const localesToTry = Array.from(new Set([locale, "en", "en-US"]));
|
|
94
|
+
|
|
95
|
+
for (const candidateLocale of localesToTry) {
|
|
96
|
+
const displayNames = new Intl.DisplayNames([candidateLocale], { type: "region" });
|
|
97
|
+
for (const code of ISO_COUNTRY_CODES) {
|
|
98
|
+
const label = displayNames.of(code);
|
|
99
|
+
if (label && normalizeCountryName(label) === normalizeCountryName(trimmed)) {
|
|
100
|
+
return code;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
31
107
|
|
|
32
108
|
export function CreateEntityForm({
|
|
33
|
-
t
|
|
109
|
+
t,
|
|
34
110
|
namespace = "",
|
|
35
111
|
accountId,
|
|
36
112
|
environment,
|
|
@@ -41,7 +117,7 @@ export function CreateEntityForm({
|
|
|
41
117
|
onSuccess,
|
|
42
118
|
onError,
|
|
43
119
|
}: CreateEntityFormProps) {
|
|
44
|
-
const translate = (
|
|
120
|
+
const translate = createTranslation({ t, namespace, locale, translations });
|
|
45
121
|
|
|
46
122
|
const countryName = countryCode ? new Intl.DisplayNames([locale], { type: "region" }).of(countryCode) : undefined;
|
|
47
123
|
|
|
@@ -50,12 +126,13 @@ export function CreateEntityForm({
|
|
|
50
126
|
const autoFilledCountryRef = useRef(countryName);
|
|
51
127
|
|
|
52
128
|
// Company registry autocomplete state
|
|
129
|
+
// showAutocomplete is based on the initial countryCode prop to avoid component switch mid-typing
|
|
53
130
|
const [nameSearch, setNameSearch] = useState("");
|
|
54
|
-
const { isSupported: isRegistrySupported } = useIsCountrySupported(
|
|
131
|
+
const { isSupported: isRegistrySupported } = useIsCountrySupported(countryCode || "");
|
|
55
132
|
const { data: searchData, isLoading: isSearching } = useCompanyRegistrySearch(activeCountryCode || "", nameSearch);
|
|
56
133
|
const companies = searchData?.data || [];
|
|
57
134
|
|
|
58
|
-
const showAutocomplete = !!
|
|
135
|
+
const showAutocomplete = !!countryCode && isRegistrySupported;
|
|
59
136
|
|
|
60
137
|
const nameOptions = companies.map((company) => {
|
|
61
138
|
const addressParts = [company.address, company.city].filter(Boolean);
|
|
@@ -97,13 +174,14 @@ export function CreateEntityForm({
|
|
|
97
174
|
// Watch country field — clear activeCountryCode when user edits away from auto-filled value
|
|
98
175
|
const countryValue = form.watch("country");
|
|
99
176
|
useEffect(() => {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
177
|
+
const nextCountryCode =
|
|
178
|
+
countryValue === autoFilledCountryRef.current
|
|
179
|
+
? countryCode
|
|
180
|
+
: resolveCountryCodeFromName(countryValue, locale) || undefined;
|
|
181
|
+
|
|
182
|
+
setActiveCountryCode(nextCountryCode);
|
|
183
|
+
form.setValue("country_code", nextCountryCode || "");
|
|
184
|
+
}, [countryValue, countryCode, form, locale]);
|
|
107
185
|
|
|
108
186
|
const handleCompanySelect = (company: CompanyRegistryResult) => {
|
|
109
187
|
form.setValue("name", company.name);
|
|
@@ -133,9 +211,10 @@ export function CreateEntityForm({
|
|
|
133
211
|
|
|
134
212
|
const onSubmit = async (values: CreateEntitySchema) => {
|
|
135
213
|
try {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
214
|
+
const resolvedCountryCode = values.country_code || resolveCountryCodeFromName(values.country, locale);
|
|
215
|
+
const { country_code: _countryCode, ...rest } = values;
|
|
216
|
+
const payload = resolvedCountryCode ? { ...rest, country_code: resolvedCountryCode } : rest;
|
|
217
|
+
createEntity(payload as CreateEntityRequest);
|
|
139
218
|
} catch (e) {
|
|
140
219
|
onError?.(e);
|
|
141
220
|
form.setError("root", {
|
|
@@ -259,7 +338,13 @@ export function CreateEntityForm({
|
|
|
259
338
|
placeholder={translate("company-number")}
|
|
260
339
|
/>
|
|
261
340
|
|
|
262
|
-
<Button
|
|
341
|
+
<Button
|
|
342
|
+
type="submit"
|
|
343
|
+
className="w-full cursor-pointer"
|
|
344
|
+
disabled={isPending}
|
|
345
|
+
aria-busy={isPending}
|
|
346
|
+
data-testid="entity-create-submit"
|
|
347
|
+
>
|
|
263
348
|
{isPending ? <ButtonLoader /> : translate("submit")}
|
|
264
349
|
</Button>
|
|
265
350
|
</form>
|
|
@@ -40,18 +40,18 @@ export const FinaOperatorRequiredDialog: FC<FinaOperatorRequiredDialogProps> = (
|
|
|
40
40
|
const handleSubmit = (e: React.FormEvent) => {
|
|
41
41
|
e.preventDefault();
|
|
42
42
|
e.stopPropagation();
|
|
43
|
-
if (!operatorOib
|
|
43
|
+
if (!operatorOib) return;
|
|
44
44
|
updateUserSettings({
|
|
45
45
|
entityId,
|
|
46
46
|
data: {
|
|
47
47
|
operator_oib: operatorOib,
|
|
48
|
-
operator_label: operatorLabel,
|
|
48
|
+
operator_label: operatorLabel || undefined,
|
|
49
49
|
},
|
|
50
50
|
});
|
|
51
51
|
};
|
|
52
52
|
|
|
53
53
|
const oibError = operatorOib !== "" && !/^\d{11}$/.test(operatorOib);
|
|
54
|
-
const isValid = /^\d{11}$/.test(operatorOib)
|
|
54
|
+
const isValid = /^\d{11}$/.test(operatorOib);
|
|
55
55
|
|
|
56
56
|
return (
|
|
57
57
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AlertCircle, AlertTriangle, Building2, CheckCircle2, ChevronRight, Info, User } from "lucide-react";
|
|
2
|
-
import { type FC, type ReactNode,
|
|
2
|
+
import { type FC, type ReactNode, useEffect, useState } from "react";
|
|
3
3
|
import { useUpdateEntity } from "@/ui/components/entities/entities.hooks";
|
|
4
4
|
import { Alert, AlertDescription, AlertTitle } from "@/ui/components/ui/alert";
|
|
5
5
|
import { Button } from "@/ui/components/ui/button";
|
|
@@ -9,11 +9,11 @@ import { PageLoadingSpinner } from "@/ui/components/ui/loading-spinner";
|
|
|
9
9
|
import { RadioGroup, RadioGroupItem } from "@/ui/components/ui/radio-group";
|
|
10
10
|
import { Separator } from "@/ui/components/ui/separator";
|
|
11
11
|
import { Switch } from "@/ui/components/ui/switch";
|
|
12
|
-
import { Tabs, TabsList, TabsTrigger } from "@/ui/components/ui/tabs";
|
|
13
|
-
import { Tooltip, TooltipContent, TooltipTrigger } from "@/ui/components/ui/tooltip";
|
|
14
12
|
import type { ComponentTranslationProps } from "@/ui/lib/translation";
|
|
15
13
|
import { createTranslation } from "@/ui/lib/translation";
|
|
16
14
|
import { cn } from "@/ui/lib/utils";
|
|
15
|
+
import { type FiscalizationStepConfig, useFiscalizationStepFlow } from "../shared/fiscalization-step-flow";
|
|
16
|
+
import { FiscalizationStepTabs } from "../shared/fiscalization-step-tabs";
|
|
17
17
|
import {
|
|
18
18
|
useFinaPremises,
|
|
19
19
|
useFinaSettings,
|
|
@@ -82,9 +82,6 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
82
82
|
renderSection,
|
|
83
83
|
hideUserOperatorSection,
|
|
84
84
|
}) => {
|
|
85
|
-
const [activeStep, setActiveStep] = useState<FinaStepType>(initialStep);
|
|
86
|
-
const [hasInitializedStep, setHasInitializedStep] = useState(false);
|
|
87
|
-
|
|
88
85
|
const translate = createTranslation({
|
|
89
86
|
t: translateFn,
|
|
90
87
|
namespace,
|
|
@@ -92,14 +89,6 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
92
89
|
translations,
|
|
93
90
|
});
|
|
94
91
|
|
|
95
|
-
const handleStepChange = useCallback(
|
|
96
|
-
(newStep: FinaStepType) => {
|
|
97
|
-
setActiveStep(newStep);
|
|
98
|
-
onStepChange?.(newStep);
|
|
99
|
-
},
|
|
100
|
-
[onStepChange],
|
|
101
|
-
);
|
|
102
|
-
|
|
103
92
|
// Entity info state
|
|
104
93
|
const [entityTaxNumber, setEntityTaxNumber] = useState("");
|
|
105
94
|
const [entityAddress, setEntityAddress] = useState("");
|
|
@@ -201,10 +190,9 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
201
190
|
// Determine completion status
|
|
202
191
|
const hasEntityTaxNumber = !!entity.tax_number;
|
|
203
192
|
// Operator OIB is required by CIS protocol (minOccurs="1" in FiskalizacijaSchema.xsd)
|
|
204
|
-
// Can come from user settings or entity-level FINA settings
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
(!!finaSettings?.operator_oib && !!finaSettings?.operator_label);
|
|
193
|
+
// Can come from user settings or entity-level FINA settings.
|
|
194
|
+
// operator_label is optional metadata and must not block setup.
|
|
195
|
+
const hasOperatorSettings = !!userFinaSettings?.operator_oib || !!finaSettings?.operator_oib;
|
|
208
196
|
const hasCertificate = finaSettings?.has_certificate || false;
|
|
209
197
|
const certificateValid = finaSettings?.certificate_status === "valid";
|
|
210
198
|
const hasPremises = (premises?.length || 0) > 0;
|
|
@@ -217,7 +205,7 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
217
205
|
const canAccessEnable =
|
|
218
206
|
hasEntityTaxNumber && hasOperatorSettings && certificateValid && hasPremises && hasPremiseWithDevice;
|
|
219
207
|
|
|
220
|
-
const steps = [
|
|
208
|
+
const steps: FiscalizationStepConfig<FinaStepType>[] = [
|
|
221
209
|
{
|
|
222
210
|
id: "settings" as const,
|
|
223
211
|
title: translate("General Settings"),
|
|
@@ -233,14 +221,14 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
233
221
|
{
|
|
234
222
|
id: "premises" as const,
|
|
235
223
|
title: translate("Business Premises"),
|
|
236
|
-
complete:
|
|
237
|
-
unlocked: canAccessPremises,
|
|
224
|
+
complete: Boolean(hasPremiseWithDevice),
|
|
225
|
+
unlocked: Boolean(canAccessPremises),
|
|
238
226
|
},
|
|
239
227
|
{
|
|
240
228
|
id: "enable" as const,
|
|
241
229
|
title: translate("Enable Fiscalization"),
|
|
242
|
-
complete: finaEnabled,
|
|
243
|
-
unlocked: canAccessEnable,
|
|
230
|
+
complete: Boolean(finaEnabled),
|
|
231
|
+
unlocked: Boolean(canAccessEnable),
|
|
244
232
|
},
|
|
245
233
|
];
|
|
246
234
|
|
|
@@ -255,27 +243,13 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
255
243
|
return "settings";
|
|
256
244
|
};
|
|
257
245
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
setHasInitializedStep(true);
|
|
266
|
-
}
|
|
267
|
-
}, [settingsLoading, premisesLoading, hasInitializedStep]);
|
|
268
|
-
|
|
269
|
-
// biome-ignore lint/correctness/useExhaustiveDependencies: steps is recreated on each render but values are stable
|
|
270
|
-
useEffect(() => {
|
|
271
|
-
const currentStepInfo = steps.find((s) => s.id === activeStep);
|
|
272
|
-
if (currentStepInfo && !currentStepInfo.unlocked) {
|
|
273
|
-
const firstUnlockedStep = steps.find((s) => s.unlocked);
|
|
274
|
-
if (firstUnlockedStep) {
|
|
275
|
-
handleStepChange(firstUnlockedStep.id);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
}, [activeStep, handleStepChange]);
|
|
246
|
+
const { activeStep, handleStepChange } = useFiscalizationStepFlow({
|
|
247
|
+
initialStep,
|
|
248
|
+
isReady: !settingsLoading && !premisesLoading,
|
|
249
|
+
steps,
|
|
250
|
+
getDefaultStep,
|
|
251
|
+
onStepChange,
|
|
252
|
+
});
|
|
279
253
|
|
|
280
254
|
if (entity.country_code !== "HR") {
|
|
281
255
|
return (
|
|
@@ -322,82 +296,39 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
322
296
|
return content;
|
|
323
297
|
};
|
|
324
298
|
|
|
325
|
-
const
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
const trigger = (
|
|
361
|
-
<TabsTrigger
|
|
362
|
-
value={step.id}
|
|
363
|
-
disabled={isLocked}
|
|
364
|
-
className={cn("cursor-pointer justify-center", !step.unlocked && "opacity-50")}
|
|
365
|
-
>
|
|
366
|
-
<span className="flex items-center gap-2">
|
|
367
|
-
{step.complete ? (
|
|
368
|
-
<CheckCircle2 className="h-4 w-4 text-green-500" />
|
|
369
|
-
) : (
|
|
370
|
-
<span className="text-xs">{index + 1}</span>
|
|
371
|
-
)}
|
|
372
|
-
{step.title}
|
|
373
|
-
</span>
|
|
374
|
-
</TabsTrigger>
|
|
375
|
-
);
|
|
376
|
-
|
|
377
|
-
if (isLocked) {
|
|
378
|
-
return (
|
|
379
|
-
<Tooltip key={step.id} delayDuration={0}>
|
|
380
|
-
<TooltipTrigger asChild>
|
|
381
|
-
<span className="flex cursor-not-allowed justify-center">{trigger}</span>
|
|
382
|
-
</TooltipTrigger>
|
|
383
|
-
<TooltipContent>
|
|
384
|
-
<p>{tooltipText}</p>
|
|
385
|
-
</TooltipContent>
|
|
386
|
-
</Tooltip>
|
|
387
|
-
);
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
return (
|
|
391
|
-
<span key={step.id} className="flex justify-center">
|
|
392
|
-
{trigger}
|
|
393
|
-
</span>
|
|
394
|
-
);
|
|
395
|
-
})}
|
|
396
|
-
</TabsList>
|
|
397
|
-
</Tabs>
|
|
398
|
-
<div className="hidden lg:block" />
|
|
399
|
-
</div>
|
|
400
|
-
);
|
|
299
|
+
const getStepTooltipText = (step: (typeof steps)[number]) => {
|
|
300
|
+
if (step.id === "certificate") {
|
|
301
|
+
if (!hasEntityTaxNumber) {
|
|
302
|
+
return translate("Set entity OIB in General Settings first");
|
|
303
|
+
}
|
|
304
|
+
return translate("Set operator OIB in General Settings first");
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
if (step.id === "premises") {
|
|
308
|
+
if (!hasEntityTaxNumber) {
|
|
309
|
+
return translate("Set entity OIB in General Settings first");
|
|
310
|
+
}
|
|
311
|
+
if (!hasOperatorSettings) {
|
|
312
|
+
return translate("Set operator OIB in General Settings first");
|
|
313
|
+
}
|
|
314
|
+
return translate("Upload and validate digital certificate first");
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (step.id === "enable") {
|
|
318
|
+
if (!hasEntityTaxNumber || !hasOperatorSettings) {
|
|
319
|
+
return translate("Complete General Settings first");
|
|
320
|
+
}
|
|
321
|
+
if (!certificateValid) {
|
|
322
|
+
return translate("Upload and validate digital certificate first");
|
|
323
|
+
}
|
|
324
|
+
if (!hasPremises) {
|
|
325
|
+
return translate("Register at least one business premise first");
|
|
326
|
+
}
|
|
327
|
+
return translate("Register at least one electronic device first");
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return "";
|
|
331
|
+
};
|
|
401
332
|
|
|
402
333
|
return (
|
|
403
334
|
<div className="space-y-6">
|
|
@@ -416,7 +347,13 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
416
347
|
</div>
|
|
417
348
|
)}
|
|
418
349
|
|
|
419
|
-
|
|
350
|
+
<FiscalizationStepTabs
|
|
351
|
+
activeStep={activeStep}
|
|
352
|
+
steps={steps}
|
|
353
|
+
onStepChange={handleStepChange}
|
|
354
|
+
getTooltipText={getStepTooltipText}
|
|
355
|
+
testIdPrefix="fina-tab"
|
|
356
|
+
/>
|
|
420
357
|
|
|
421
358
|
{/* Settings step */}
|
|
422
359
|
{activeStep === "settings" && (
|
|
@@ -503,6 +440,7 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
503
440
|
onClick={handleSaveEntityInfo}
|
|
504
441
|
disabled={isEntityUpdatePending}
|
|
505
442
|
className="cursor-pointer"
|
|
443
|
+
data-testid="fina-entity-info-save"
|
|
506
444
|
>
|
|
507
445
|
{isEntityUpdatePending ? translate("Saving...") : translate("Save Entity Info")}
|
|
508
446
|
</Button>
|
|
@@ -568,7 +506,11 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
568
506
|
)}
|
|
569
507
|
|
|
570
508
|
<div className="grid items-start gap-6 lg:grid-cols-[1fr_280px]">
|
|
571
|
-
<Button
|
|
509
|
+
<Button
|
|
510
|
+
onClick={handleSaveSettings}
|
|
511
|
+
disabled={isPending || !!operatorOibError}
|
|
512
|
+
data-testid="fina-settings-save"
|
|
513
|
+
>
|
|
572
514
|
{isPending ? translate("Saving...") : translate("Save Settings")}
|
|
573
515
|
</Button>
|
|
574
516
|
<div className="hidden lg:block" />
|
|
@@ -594,7 +536,7 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
594
536
|
</div>
|
|
595
537
|
</div>
|
|
596
538
|
|
|
597
|
-
{
|
|
539
|
+
{!userFinaSettings?.operator_oib && (
|
|
598
540
|
<Alert variant="destructive">
|
|
599
541
|
<AlertTriangle className="h-4 w-4" />
|
|
600
542
|
<AlertDescription>
|
|
@@ -617,6 +559,7 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
617
559
|
className={cn("mt-1", userOperatorOibError && "border-destructive")}
|
|
618
560
|
maxLength={11}
|
|
619
561
|
disabled={userSettingsLoading}
|
|
562
|
+
data-testid="fina-user-operator-oib-input"
|
|
620
563
|
/>
|
|
621
564
|
{userOperatorOibError && <p className="mt-1 text-destructive text-xs">{userOperatorOibError}</p>}
|
|
622
565
|
</div>
|
|
@@ -629,6 +572,7 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
629
572
|
placeholder={translate("e.g. Cashier 1")}
|
|
630
573
|
className="mt-1"
|
|
631
574
|
disabled={userSettingsLoading}
|
|
575
|
+
data-testid="fina-user-operator-label-input"
|
|
632
576
|
/>
|
|
633
577
|
</div>
|
|
634
578
|
|
|
@@ -637,6 +581,7 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
637
581
|
onClick={handleSaveUserSettings}
|
|
638
582
|
disabled={isUserSettingsPending || userSettingsLoading || !!userOperatorOibError}
|
|
639
583
|
className="cursor-pointer"
|
|
584
|
+
data-testid="fina-operator-settings-save"
|
|
640
585
|
>
|
|
641
586
|
{isUserSettingsPending ? translate("Saving...") : translate("Save Operator Settings")}
|
|
642
587
|
</Button>
|
|
@@ -656,6 +601,7 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
656
601
|
type="button"
|
|
657
602
|
onClick={() => setIsAdvancedOpen(!isAdvancedOpen)}
|
|
658
603
|
className="flex w-full items-center gap-2 py-2 text-muted-foreground hover:text-foreground"
|
|
604
|
+
data-testid="fina-advanced-toggle"
|
|
659
605
|
>
|
|
660
606
|
<ChevronRight className={cn("h-4 w-4 transition-transform", isAdvancedOpen && "rotate-90")} />
|
|
661
607
|
<span className="font-medium text-sm">{translate("Advanced Settings")}</span>
|
|
@@ -683,6 +629,7 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
683
629
|
placeholder={translate("OIB of the operator (11 digits)")}
|
|
684
630
|
className={cn("mt-1", operatorOibError && "border-destructive")}
|
|
685
631
|
maxLength={11}
|
|
632
|
+
data-testid="fina-api-operator-oib-input"
|
|
686
633
|
/>
|
|
687
634
|
{operatorOibError && <p className="mt-1 text-destructive text-xs">{operatorOibError}</p>}
|
|
688
635
|
<p className="mt-1 text-muted-foreground text-xs">
|
|
@@ -697,6 +644,7 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
697
644
|
onChange={(e) => setFormData((prev) => ({ ...prev, operator_label: e.target.value }))}
|
|
698
645
|
placeholder="API Default"
|
|
699
646
|
className="mt-1"
|
|
647
|
+
data-testid="fina-api-operator-label-input"
|
|
700
648
|
/>
|
|
701
649
|
<p className="mt-1 text-muted-foreground text-xs">
|
|
702
650
|
{translate("Operator label for API key usage (optional)")}
|
|
@@ -704,7 +652,12 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
704
652
|
</div>
|
|
705
653
|
</div>
|
|
706
654
|
|
|
707
|
-
<Button
|
|
655
|
+
<Button
|
|
656
|
+
onClick={handleSaveSettings}
|
|
657
|
+
disabled={isPending || !!operatorOibError}
|
|
658
|
+
size="sm"
|
|
659
|
+
data-testid="fina-advanced-settings-save"
|
|
660
|
+
>
|
|
708
661
|
{isPending ? translate("Saving...") : translate("Save Settings")}
|
|
709
662
|
</Button>
|
|
710
663
|
</div>
|
|
@@ -791,6 +744,7 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
791
744
|
: { enabled: false },
|
|
792
745
|
});
|
|
793
746
|
}}
|
|
747
|
+
data-testid="fina-enable-switch"
|
|
794
748
|
/>
|
|
795
749
|
<Label>{translate("Enable FINA Fiscalization")}</Label>
|
|
796
750
|
</div>
|