@spaceinvoices/react-ui 0.4.1 → 0.4.3
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/registry.json +25 -0
- package/src/components/advance-invoices/advance-invoices.hooks.ts +32 -2
- package/src/components/advance-invoices/create/create-advance-invoice-form.tsx +109 -4
- package/src/components/advance-invoices/create/locales/de.ts +2 -0
- package/src/components/advance-invoices/create/locales/es.ts +2 -0
- package/src/components/advance-invoices/create/locales/fr.ts +2 -0
- package/src/components/advance-invoices/create/locales/hr.ts +2 -0
- package/src/components/advance-invoices/create/locales/it.ts +2 -0
- package/src/components/advance-invoices/create/locales/nl.ts +2 -0
- package/src/components/advance-invoices/create/locales/pl.ts +2 -0
- package/src/components/advance-invoices/create/locales/pt.ts +2 -0
- package/src/components/advance-invoices/create/locales/sl.ts +2 -0
- package/src/components/advance-invoices/create/prepare-advance-invoice-submission.ts +17 -0
- package/src/components/advance-invoices/list/list-row-actions.tsx +3 -6
- package/src/components/advance-invoices/list/list-table.tsx +105 -2
- package/src/components/advance-invoices/list/locales/de.ts +4 -0
- package/src/components/advance-invoices/list/locales/en.ts +4 -0
- package/src/components/advance-invoices/list/locales/es.ts +4 -0
- package/src/components/advance-invoices/list/locales/fr.ts +4 -0
- package/src/components/advance-invoices/list/locales/hr.ts +4 -0
- package/src/components/advance-invoices/list/locales/it.ts +4 -0
- package/src/components/advance-invoices/list/locales/nl.ts +4 -0
- package/src/components/advance-invoices/list/locales/pl.ts +4 -0
- package/src/components/advance-invoices/list/locales/pt.ts +4 -0
- package/src/components/advance-invoices/list/locales/sl.ts +4 -0
- package/src/components/credit-notes/create/create-credit-note-form.tsx +177 -6
- package/src/components/credit-notes/create/locales/de.ts +8 -0
- package/src/components/credit-notes/create/locales/es.ts +8 -0
- package/src/components/credit-notes/create/locales/fr.ts +7 -0
- package/src/components/credit-notes/create/locales/hr.ts +7 -0
- package/src/components/credit-notes/create/locales/it.ts +9 -0
- package/src/components/credit-notes/create/locales/nl.ts +7 -0
- package/src/components/credit-notes/create/locales/pl.ts +7 -0
- package/src/components/credit-notes/create/locales/pt.ts +7 -0
- package/src/components/credit-notes/create/locales/sl.ts +7 -0
- package/src/components/credit-notes/credit-notes.hooks.ts +30 -0
- package/src/components/credit-notes/list/list-row-actions.tsx +3 -6
- package/src/components/credit-notes/list/list-table.tsx +79 -8
- package/src/components/credit-notes/list/locales/de.ts +4 -1
- package/src/components/credit-notes/list/locales/en.ts +5 -0
- package/src/components/credit-notes/list/locales/es.ts +4 -1
- package/src/components/credit-notes/list/locales/fr.ts +4 -1
- package/src/components/credit-notes/list/locales/hr.ts +4 -1
- package/src/components/credit-notes/list/locales/it.ts +4 -1
- package/src/components/credit-notes/list/locales/nl.ts +4 -1
- package/src/components/credit-notes/list/locales/pl.ts +4 -1
- package/src/components/credit-notes/list/locales/pt.ts +4 -1
- package/src/components/credit-notes/list/locales/sl.ts +4 -1
- package/src/components/customers/create-customer-form/create-customer-form.tsx +0 -1
- package/src/components/dashboard/collection-rate-card/use-collection-rate.ts +2 -2
- package/src/components/dashboard/invoice-status-chart/use-invoice-status.ts +3 -3
- package/src/components/dashboard/payment-methods-chart/use-payment-methods.ts +1 -1
- package/src/components/dashboard/payment-trend-chart/use-payment-trend.ts +1 -1
- package/src/components/dashboard/revenue-trend-chart/use-revenue-trend.ts +1 -1
- package/src/components/dashboard/shared/use-revenue-data.ts +4 -4
- package/src/components/dashboard/shared/use-stats-counts.ts +4 -4
- package/src/components/dashboard/shared/use-stats-query.ts +1 -1
- package/src/components/dashboard/tax-collected-card/use-tax-collected.ts +2 -2
- package/src/components/dashboard/top-customers-chart/use-top-customers.ts +1 -1
- package/src/components/delivery-notes/create/create-delivery-note-form.tsx +332 -0
- package/src/components/delivery-notes/create/locales/de.ts +50 -0
- package/src/components/delivery-notes/create/locales/es.ts +49 -0
- package/src/components/delivery-notes/create/locales/fr.ts +50 -0
- package/src/components/delivery-notes/create/locales/hr.ts +49 -0
- package/src/components/delivery-notes/create/locales/it.ts +49 -0
- package/src/components/delivery-notes/create/locales/nl.ts +50 -0
- package/src/components/delivery-notes/create/locales/pl.ts +49 -0
- package/src/components/delivery-notes/create/locales/pt.ts +50 -0
- package/src/components/delivery-notes/create/locales/sl.ts +49 -0
- package/src/components/delivery-notes/create/prepare-delivery-note-submission.ts +38 -0
- package/src/components/delivery-notes/create/use-delivery-note-customer-form.ts +1 -0
- package/src/components/delivery-notes/delivery-notes.hooks.ts +15 -0
- package/src/components/delivery-notes/list/index.ts +3 -0
- package/src/components/delivery-notes/list/list-row-actions.tsx +103 -0
- package/src/components/delivery-notes/list/list-table.tsx +214 -0
- package/src/components/delivery-notes/list/locales/de.ts +9 -0
- package/src/components/delivery-notes/list/locales/en.ts +11 -0
- package/src/components/delivery-notes/list/locales/es.ts +9 -0
- package/src/components/delivery-notes/list/locales/fr.ts +9 -0
- package/src/components/delivery-notes/list/locales/hr.ts +9 -0
- package/src/components/delivery-notes/list/locales/it.ts +9 -0
- package/src/components/delivery-notes/list/locales/nl.ts +9 -0
- package/src/components/delivery-notes/list/locales/pl.ts +9 -0
- package/src/components/delivery-notes/list/locales/pt.ts +9 -0
- package/src/components/delivery-notes/list/locales/sl.ts +9 -0
- package/src/components/delivery-notes/list/use-delivery-note-download.ts +63 -0
- package/src/components/documents/create/document-details-section.tsx +103 -33
- package/src/components/documents/create/live-preview.tsx +37 -10
- package/src/components/documents/create/mark-as-paid-section.tsx +11 -2
- package/src/components/documents/create/prepare-document-submission.ts +1 -1
- package/src/components/documents/documents.hooks.ts +2 -1
- package/src/components/documents/shared/document-preview-display.tsx +12 -5
- package/src/components/documents/types.ts +10 -1
- package/src/components/documents/view/document-actions-bar.tsx +30 -0
- package/src/components/documents/view/document-details-card.tsx +3 -3
- package/src/components/documents/view/document-payments-list.tsx +3 -3
- package/src/components/documents/view/document-relations-list.tsx +105 -0
- package/src/components/documents/view/locales/de.ts +26 -0
- package/src/components/documents/view/locales/es.ts +26 -0
- package/src/components/documents/view/locales/fr.ts +26 -0
- package/src/components/documents/view/locales/hr.ts +26 -0
- package/src/components/documents/view/locales/it.ts +26 -0
- package/src/components/documents/view/locales/nl.ts +26 -0
- package/src/components/documents/view/locales/pl.ts +26 -0
- package/src/components/documents/view/locales/pt.ts +26 -0
- package/src/components/documents/view/locales/sl.ts +26 -0
- package/src/components/documents/view/use-document-download.ts +5 -3
- package/src/components/entities/create-entity-form.tsx +1 -1
- package/src/components/entities/entity-settings-form/entity-settings-form.tsx +2 -3
- package/src/components/entities/entity-settings-form/locales/es.ts +2 -0
- package/src/components/entities/entity-settings-form/locales/fr.ts +2 -0
- package/src/components/entities/entity-settings-form/locales/hr.ts +2 -0
- package/src/components/entities/entity-settings-form/locales/it.ts +2 -0
- package/src/components/entities/entity-settings-form/locales/nl.ts +2 -0
- package/src/components/entities/entity-settings-form/locales/pl.ts +2 -0
- package/src/components/entities/entity-settings-form/locales/pt.ts +2 -0
- package/src/components/entities/fina-settings-form/fina-operator-required-dialog.tsx +109 -0
- package/src/components/entities/fina-settings-form/fina-settings-form.tsx +377 -35
- package/src/components/entities/fina-settings-form/fina-settings.hooks.ts +106 -20
- package/src/components/entities/fina-settings-form/index.ts +1 -0
- package/src/components/entities/fina-settings-form/locales/de.ts +54 -34
- package/src/components/entities/fina-settings-form/locales/en.ts +51 -34
- package/src/components/entities/fina-settings-form/locales/es.ts +50 -34
- package/src/components/entities/fina-settings-form/locales/fr.ts +50 -34
- package/src/components/entities/fina-settings-form/locales/hr.ts +50 -34
- package/src/components/entities/fina-settings-form/locales/it.ts +50 -34
- package/src/components/entities/fina-settings-form/locales/nl.ts +50 -34
- package/src/components/entities/fina-settings-form/locales/pl.ts +50 -34
- package/src/components/entities/fina-settings-form/locales/pt.ts +50 -34
- package/src/components/entities/fina-settings-form/locales/sl.ts +50 -34
- package/src/components/entities/fina-settings-form/sections/certificate-settings-section.tsx +18 -0
- package/src/components/entities/fina-settings-form/sections/premises-management-section.tsx +64 -89
- package/src/components/entities/fina-settings-form/sections/register-premise-dialog.tsx +51 -323
- package/src/components/entities/furs-settings-form/furs-operator-required-dialog.tsx +106 -0
- package/src/components/entities/furs-settings-form/furs-settings-form.tsx +33 -10
- package/src/components/entities/furs-settings-form/furs-settings.hooks.ts +12 -11
- package/src/components/entities/furs-settings-form/index.ts +1 -0
- package/src/components/entities/furs-settings-form/locales/de.ts +27 -3
- package/src/components/entities/furs-settings-form/locales/en.ts +17 -3
- package/src/components/entities/furs-settings-form/locales/es.ts +26 -3
- package/src/components/entities/furs-settings-form/locales/fr.ts +26 -3
- package/src/components/entities/furs-settings-form/locales/hr.ts +26 -3
- package/src/components/entities/furs-settings-form/locales/it.ts +26 -3
- package/src/components/entities/furs-settings-form/locales/nl.ts +26 -3
- package/src/components/entities/furs-settings-form/locales/pl.ts +26 -3
- package/src/components/entities/furs-settings-form/locales/pt.ts +26 -3
- package/src/components/entities/furs-settings-form/locales/sl.ts +16 -3
- package/src/components/entities/furs-settings-form/sections/certificate-settings-section.tsx +22 -0
- package/src/components/entities/furs-settings-form/sections/general-settings-section.tsx +26 -5
- package/src/components/entities/furs-settings-form/sections/register-premise-dialog.tsx +14 -2
- package/src/components/entities/settings/tax-rules-settings-form.tsx +4 -4
- package/src/components/estimates/list/list-row-actions.tsx +3 -7
- package/src/components/estimates/list/list-table.tsx +35 -2
- package/src/components/estimates/list/locales/de.ts +3 -0
- package/src/components/estimates/list/locales/en.ts +3 -0
- package/src/components/estimates/list/locales/es.ts +3 -0
- package/src/components/estimates/list/locales/fr.ts +3 -0
- package/src/components/estimates/list/locales/hr.ts +3 -0
- package/src/components/estimates/list/locales/it.ts +3 -0
- package/src/components/estimates/list/locales/nl.ts +3 -0
- package/src/components/estimates/list/locales/pl.ts +3 -0
- package/src/components/estimates/list/locales/pt.ts +3 -0
- package/src/components/estimates/list/locales/sl.ts +3 -0
- package/src/components/export/document-export-form.tsx +34 -34
- package/src/components/invoices/create/create-invoice-form.tsx +107 -5
- package/src/components/invoices/create/prepare-invoice-submission.ts +17 -0
- package/src/components/invoices/invoices-furs.hooks.ts +24 -9
- package/src/components/invoices/invoices.hooks.ts +32 -2
- package/src/components/invoices/list/list-row-actions.tsx +26 -11
- package/src/components/invoices/list/list-table.tsx +121 -5
- package/src/components/invoices/list/locales/de.ts +5 -0
- package/src/components/invoices/list/locales/en.ts +5 -0
- package/src/components/invoices/list/locales/es.ts +5 -0
- package/src/components/invoices/list/locales/fr.ts +5 -0
- package/src/components/invoices/list/locales/hr.ts +5 -0
- package/src/components/invoices/list/locales/it.ts +5 -0
- package/src/components/invoices/list/locales/nl.ts +5 -0
- package/src/components/invoices/list/locales/pl.ts +5 -0
- package/src/components/invoices/list/locales/pt.ts +5 -0
- package/src/components/invoices/list/locales/sl.ts +5 -0
- package/src/components/invoices/view/fiscalization-status-card.tsx +4 -1
- package/src/components/items/item-list-table/item-list-row-actions.tsx +5 -8
- package/src/components/items/item-list-table/item-list-row.tsx +5 -3
- package/src/components/items/item-list-table/item-list-table.tsx +5 -1
- package/src/components/recurring-invoices/create-recurring-invoice-form/create-recurring-invoice-form.tsx +418 -0
- package/src/components/recurring-invoices/create-recurring-invoice-form/locales/de.ts +45 -0
- package/src/components/recurring-invoices/create-recurring-invoice-form/locales/es.ts +44 -0
- package/src/components/recurring-invoices/create-recurring-invoice-form/locales/fr.ts +44 -0
- package/src/components/recurring-invoices/create-recurring-invoice-form/locales/hr.ts +44 -0
- package/src/components/recurring-invoices/create-recurring-invoice-form/locales/it.ts +44 -0
- package/src/components/recurring-invoices/create-recurring-invoice-form/locales/nl.ts +44 -0
- package/src/components/recurring-invoices/create-recurring-invoice-form/locales/pl.ts +44 -0
- package/src/components/recurring-invoices/create-recurring-invoice-form/locales/pt.ts +44 -0
- package/src/components/recurring-invoices/create-recurring-invoice-form/locales/sl.ts +44 -0
- package/src/components/recurring-invoices/index.ts +3 -0
- package/src/components/recurring-invoices/list/index.ts +2 -0
- package/src/components/recurring-invoices/list/list-row-actions.tsx +139 -0
- package/src/components/recurring-invoices/list/list-table.tsx +179 -0
- package/src/components/recurring-invoices/list/locales/de.ts +27 -0
- package/src/components/recurring-invoices/list/locales/en.ts +5 -0
- package/src/components/recurring-invoices/list/locales/es.ts +27 -0
- package/src/components/recurring-invoices/list/locales/fr.ts +27 -0
- package/src/components/recurring-invoices/list/locales/hr.ts +27 -0
- package/src/components/recurring-invoices/list/locales/it.ts +27 -0
- package/src/components/recurring-invoices/list/locales/nl.ts +27 -0
- package/src/components/recurring-invoices/list/locales/pl.ts +27 -0
- package/src/components/recurring-invoices/list/locales/pt.ts +27 -0
- package/src/components/recurring-invoices/list/locales/sl.ts +27 -0
- package/src/components/recurring-invoices/recurring-invoices.hooks.ts +28 -0
- package/src/components/table/data-table.tsx +122 -5
- package/src/components/table/selection-toolbar.tsx +36 -0
- package/src/components/tax-reports/kir-export-form.tsx +75 -55
- package/src/components/taxes/tax-list-table/tax-list-row-actions.tsx +3 -6
- package/src/components/taxes/tax-list-table/tax-list-row.tsx +3 -2
- package/src/components/taxes/tax-list-table/tax-list-table.tsx +5 -1
- package/src/components/ui/checkbox.tsx +5 -5
- package/src/generate-schemas.ts +45 -18
- package/src/generated/schemas/authorizeshopify_body.ts +22 -0
- package/src/generated/schemas/creditnote.ts +0 -2
- package/src/generated/schemas/deliverynote.ts +134 -0
- package/src/generated/schemas/entity.ts +5 -1
- package/src/generated/schemas/index.ts +42 -28
- package/src/generated/schemas/order.ts +129 -0
- package/src/generated/schemas/orderintegration.ts +51 -0
- package/src/generated/schemas/payment.ts +24 -2
- package/src/generated/schemas/recurringinvoice.ts +61 -0
- package/src/generated/schemas/renderadvanceinvoicepreview_body.ts +108 -140
- package/src/generated/schemas/rendercreditnotepreview_body.ts +109 -141
- package/src/generated/schemas/renderdeliverynotepreview_body.ts +185 -0
- package/src/generated/schemas/renderestimatepreview_body.ts +79 -82
- package/src/generated/schemas/renderinvoicepreview_body.ts +109 -141
- package/src/generated/schemas/startpdfexport_body.ts +18 -2
- package/src/generated/schemas/userfinasettings.ts +19 -0
- package/src/generated/schemas/webhook.ts +54 -0
- package/src/hooks/use-duplicate-document.ts +11 -3
- package/src/hooks/use-next-document-number.ts +2 -2
- package/src/lib/furs-error-utils.ts +36 -0
- package/src/lib/schemas/advance-invoice.ts +3 -3
- package/src/lib/schemas/credit-note.ts +3 -3
- package/src/lib/schemas/estimate.ts +3 -3
- package/src/lib/schemas/invoice.ts +3 -3
- package/src/providers/sdk-provider.tsx +5 -7
- package/src/providers/white-label-provider.tsx +3 -0
|
@@ -1,17 +1,26 @@
|
|
|
1
|
-
import { AlertCircle, CheckCircle2, Info } from "lucide-react";
|
|
1
|
+
import { AlertCircle, AlertTriangle, Building2, CheckCircle2, ChevronRight, Info, User } from "lucide-react";
|
|
2
2
|
import { type FC, type ReactNode, useCallback, useEffect, useState } from "react";
|
|
3
|
+
import { useUpdateEntity } from "@/ui/components/entities/entities.hooks";
|
|
3
4
|
import { Alert, AlertDescription, AlertTitle } from "@/ui/components/ui/alert";
|
|
4
5
|
import { Button } from "@/ui/components/ui/button";
|
|
6
|
+
import { Input } from "@/ui/components/ui/input";
|
|
5
7
|
import { Label } from "@/ui/components/ui/label";
|
|
6
8
|
import { PageLoadingSpinner } from "@/ui/components/ui/loading-spinner";
|
|
7
9
|
import { RadioGroup, RadioGroupItem } from "@/ui/components/ui/radio-group";
|
|
10
|
+
import { Separator } from "@/ui/components/ui/separator";
|
|
8
11
|
import { Switch } from "@/ui/components/ui/switch";
|
|
9
12
|
import { Tabs, TabsList, TabsTrigger } from "@/ui/components/ui/tabs";
|
|
10
13
|
import { Tooltip, TooltipContent, TooltipTrigger } from "@/ui/components/ui/tooltip";
|
|
11
14
|
import type { ComponentTranslationProps } from "@/ui/lib/translation";
|
|
12
15
|
import { createTranslation } from "@/ui/lib/translation";
|
|
13
16
|
import { cn } from "@/ui/lib/utils";
|
|
14
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
useFinaPremises,
|
|
19
|
+
useFinaSettings,
|
|
20
|
+
useUpdateFinaSettings,
|
|
21
|
+
useUpdateUserFinaSettings,
|
|
22
|
+
useUserFinaSettings,
|
|
23
|
+
} from "./fina-settings.hooks";
|
|
15
24
|
import de from "./locales/de";
|
|
16
25
|
import en from "./locales/en";
|
|
17
26
|
import es from "./locales/es";
|
|
@@ -28,7 +37,15 @@ import { PremisesManagementSection } from "./sections/premises-management-sectio
|
|
|
28
37
|
const translations = { sl, de, en, it, fr, es, pt, nl, pl, hr } as const;
|
|
29
38
|
|
|
30
39
|
export type FinaStepType = "settings" | "certificate" | "premises" | "enable";
|
|
31
|
-
export type FinaSectionType =
|
|
40
|
+
export type FinaSectionType =
|
|
41
|
+
| "entity-info"
|
|
42
|
+
| "operator"
|
|
43
|
+
| "numbering"
|
|
44
|
+
| "certificate-upload"
|
|
45
|
+
| "premises-list"
|
|
46
|
+
| "enable-toggle"
|
|
47
|
+
| "user-operator"
|
|
48
|
+
| "advanced";
|
|
32
49
|
|
|
33
50
|
interface FinaSettingsFormProps extends ComponentTranslationProps {
|
|
34
51
|
entity: any;
|
|
@@ -37,6 +54,11 @@ interface FinaSettingsFormProps extends ComponentTranslationProps {
|
|
|
37
54
|
initialStep?: FinaStepType;
|
|
38
55
|
onStepChange?: (step: FinaStepType) => void;
|
|
39
56
|
renderSection?: (section: FinaSectionType, content: ReactNode) => ReactNode;
|
|
57
|
+
/**
|
|
58
|
+
* Hide user-specific operator section (for embed/API key contexts without user session).
|
|
59
|
+
* When true, the "Advanced Settings" entity-level operator fields are auto-expanded instead.
|
|
60
|
+
*/
|
|
61
|
+
hideUserOperatorSection?: boolean;
|
|
40
62
|
}
|
|
41
63
|
|
|
42
64
|
/**
|
|
@@ -58,6 +80,7 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
58
80
|
initialStep = "settings",
|
|
59
81
|
onStepChange,
|
|
60
82
|
renderSection,
|
|
83
|
+
hideUserOperatorSection,
|
|
61
84
|
}) => {
|
|
62
85
|
const [activeStep, setActiveStep] = useState<FinaStepType>(initialStep);
|
|
63
86
|
const [hasInitializedStep, setHasInitializedStep] = useState(false);
|
|
@@ -77,6 +100,36 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
77
100
|
[onStepChange],
|
|
78
101
|
);
|
|
79
102
|
|
|
103
|
+
// Entity info state
|
|
104
|
+
const [entityTaxNumber, setEntityTaxNumber] = useState("");
|
|
105
|
+
const [entityAddress, setEntityAddress] = useState("");
|
|
106
|
+
const [entityCity, setEntityCity] = useState("");
|
|
107
|
+
const [entityPostCode, setEntityPostCode] = useState("");
|
|
108
|
+
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
setEntityTaxNumber(entity.tax_number || "");
|
|
111
|
+
setEntityAddress(entity.address || "");
|
|
112
|
+
setEntityCity(entity.city || "");
|
|
113
|
+
setEntityPostCode(entity.post_code || "");
|
|
114
|
+
}, [entity.tax_number, entity.address, entity.city, entity.post_code]);
|
|
115
|
+
|
|
116
|
+
const { mutate: updateEntity, isPending: isEntityUpdatePending } = useUpdateEntity({
|
|
117
|
+
onSuccess: () => onSuccess?.(),
|
|
118
|
+
onError: (error) => onError?.(error),
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const handleSaveEntityInfo = () => {
|
|
122
|
+
updateEntity({
|
|
123
|
+
id: entity.id,
|
|
124
|
+
data: {
|
|
125
|
+
tax_number: entityTaxNumber || null,
|
|
126
|
+
address: entityAddress || null,
|
|
127
|
+
city: entityCity || null,
|
|
128
|
+
post_code: entityPostCode || null,
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
};
|
|
132
|
+
|
|
80
133
|
// Fetch FINA settings and premises
|
|
81
134
|
const { data: finaSettings, isLoading: settingsLoading } = useFinaSettings(entity.id);
|
|
82
135
|
const { data: premises, isLoading: premisesLoading } = useFinaPremises(entity.id);
|
|
@@ -90,7 +143,38 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
90
143
|
},
|
|
91
144
|
});
|
|
92
145
|
|
|
93
|
-
//
|
|
146
|
+
// User FINA operator settings (per-user, stored in user.settings)
|
|
147
|
+
const { data: userFinaSettings, isLoading: userSettingsLoading } = useUserFinaSettings(entity.id, {
|
|
148
|
+
enabled: !hideUserOperatorSection,
|
|
149
|
+
});
|
|
150
|
+
const [userOperatorOib, setUserOperatorOib] = useState("");
|
|
151
|
+
const [userOperatorLabel, setUserOperatorLabel] = useState("");
|
|
152
|
+
|
|
153
|
+
useEffect(() => {
|
|
154
|
+
if (userFinaSettings) {
|
|
155
|
+
setUserOperatorOib(userFinaSettings.operator_oib || "");
|
|
156
|
+
setUserOperatorLabel(userFinaSettings.operator_label || "");
|
|
157
|
+
}
|
|
158
|
+
}, [userFinaSettings]);
|
|
159
|
+
|
|
160
|
+
const { mutate: updateUserSettings, isPending: isUserSettingsPending } = useUpdateUserFinaSettings({
|
|
161
|
+
onSuccess: () => onSuccess?.(),
|
|
162
|
+
onError: (error) => onError?.(error),
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
const handleSaveUserSettings = () => {
|
|
166
|
+
if (userOperatorOibError) return;
|
|
167
|
+
updateUserSettings({
|
|
168
|
+
entityId: entity.id,
|
|
169
|
+
data: {
|
|
170
|
+
operator_oib: userOperatorOib || undefined,
|
|
171
|
+
operator_label: userOperatorLabel || undefined,
|
|
172
|
+
},
|
|
173
|
+
});
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
// Form state for entity-level settings (API default)
|
|
177
|
+
const [isAdvancedOpen, setIsAdvancedOpen] = useState(!!hideUserOperatorSection);
|
|
94
178
|
const [formData, setFormData] = useState({
|
|
95
179
|
enabled: false,
|
|
96
180
|
numbering_sequence: "N" as "N" | "P",
|
|
@@ -113,6 +197,12 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
113
197
|
}, [finaSettings]);
|
|
114
198
|
|
|
115
199
|
// Determine completion status
|
|
200
|
+
const hasEntityTaxNumber = !!entity.tax_number;
|
|
201
|
+
// Operator OIB is required by CIS protocol (minOccurs="1" in FiskalizacijaSchema.xsd)
|
|
202
|
+
// Can come from user settings or entity-level FINA settings
|
|
203
|
+
const hasOperatorSettings =
|
|
204
|
+
(!!userFinaSettings?.operator_oib && !!userFinaSettings?.operator_label) ||
|
|
205
|
+
(!!finaSettings?.operator_oib && !!finaSettings?.operator_label);
|
|
116
206
|
const hasCertificate = finaSettings?.has_certificate || false;
|
|
117
207
|
const certificateValid = finaSettings?.certificate_status === "valid";
|
|
118
208
|
const hasPremises = (premises?.length || 0) > 0;
|
|
@@ -120,16 +210,23 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
120
210
|
hasPremises && premises?.some((premise: any) => premise.Devices && premise.Devices.length > 0);
|
|
121
211
|
|
|
122
212
|
const finaEnabled = finaSettings?.enabled || false;
|
|
123
|
-
const
|
|
124
|
-
const
|
|
213
|
+
const canAccessCertificate = hasEntityTaxNumber && hasOperatorSettings;
|
|
214
|
+
const canAccessPremises = hasEntityTaxNumber && hasOperatorSettings && hasCertificate && certificateValid;
|
|
215
|
+
const canAccessEnable =
|
|
216
|
+
hasEntityTaxNumber && hasOperatorSettings && certificateValid && hasPremises && hasPremiseWithDevice;
|
|
125
217
|
|
|
126
218
|
const steps = [
|
|
127
|
-
{
|
|
219
|
+
{
|
|
220
|
+
id: "settings" as const,
|
|
221
|
+
title: translate("General Settings"),
|
|
222
|
+
complete: hasEntityTaxNumber && hasOperatorSettings,
|
|
223
|
+
unlocked: true,
|
|
224
|
+
},
|
|
128
225
|
{
|
|
129
226
|
id: "certificate" as const,
|
|
130
227
|
title: translate("Certificate"),
|
|
131
228
|
complete: hasCertificate && certificateValid,
|
|
132
|
-
unlocked:
|
|
229
|
+
unlocked: canAccessCertificate,
|
|
133
230
|
},
|
|
134
231
|
{
|
|
135
232
|
id: "premises" as const,
|
|
@@ -196,10 +293,23 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
196
293
|
|
|
197
294
|
const isSandboxMode = entity.environment === "sandbox";
|
|
198
295
|
|
|
296
|
+
const userOperatorOibError =
|
|
297
|
+
userOperatorOib !== "" && !/^\d{11}$/.test(userOperatorOib) ? translate("OIB must be exactly 11 digits") : "";
|
|
298
|
+
|
|
299
|
+
const operatorOibError =
|
|
300
|
+
formData.operator_oib !== "" && !/^\d{11}$/.test(formData.operator_oib)
|
|
301
|
+
? translate("OIB must be exactly 11 digits")
|
|
302
|
+
: "";
|
|
303
|
+
|
|
199
304
|
const handleSaveSettings = () => {
|
|
305
|
+
if (operatorOibError) return;
|
|
200
306
|
updateSettings({
|
|
201
307
|
entityId: entity.id,
|
|
202
|
-
data:
|
|
308
|
+
data: {
|
|
309
|
+
...formData,
|
|
310
|
+
operator_oib: formData.operator_oib || undefined,
|
|
311
|
+
operator_label: formData.operator_label || undefined,
|
|
312
|
+
},
|
|
203
313
|
});
|
|
204
314
|
};
|
|
205
315
|
|
|
@@ -218,10 +328,24 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
218
328
|
const isLocked = !step.unlocked;
|
|
219
329
|
let tooltipText = "";
|
|
220
330
|
if (isLocked) {
|
|
221
|
-
if (step.id === "
|
|
222
|
-
|
|
331
|
+
if (step.id === "certificate") {
|
|
332
|
+
if (!hasEntityTaxNumber) {
|
|
333
|
+
tooltipText = translate("Set entity OIB in General Settings first");
|
|
334
|
+
} else {
|
|
335
|
+
tooltipText = translate("Set operator OIB and label in General Settings first");
|
|
336
|
+
}
|
|
337
|
+
} else if (step.id === "premises") {
|
|
338
|
+
if (!hasEntityTaxNumber) {
|
|
339
|
+
tooltipText = translate("Set entity OIB in General Settings first");
|
|
340
|
+
} else if (!hasOperatorSettings) {
|
|
341
|
+
tooltipText = translate("Set operator OIB and label in General Settings first");
|
|
342
|
+
} else {
|
|
343
|
+
tooltipText = translate("Upload and validate digital certificate first");
|
|
344
|
+
}
|
|
223
345
|
} else if (step.id === "enable") {
|
|
224
|
-
if (!
|
|
346
|
+
if (!hasEntityTaxNumber || !hasOperatorSettings) {
|
|
347
|
+
tooltipText = translate("Complete General Settings first");
|
|
348
|
+
} else if (!certificateValid) {
|
|
225
349
|
tooltipText = translate("Upload and validate digital certificate first");
|
|
226
350
|
} else if (!hasPremises) {
|
|
227
351
|
tooltipText = translate("Register at least one business premise first");
|
|
@@ -295,6 +419,97 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
295
419
|
{/* Settings step */}
|
|
296
420
|
{activeStep === "settings" && (
|
|
297
421
|
<div className="space-y-6">
|
|
422
|
+
{wrapSection(
|
|
423
|
+
"entity-info",
|
|
424
|
+
<div className="space-y-4">
|
|
425
|
+
<div className="flex items-center gap-3">
|
|
426
|
+
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-orange-500/10">
|
|
427
|
+
<Building2 className="h-5 w-5 text-orange-600 dark:text-orange-400" />
|
|
428
|
+
</div>
|
|
429
|
+
<div>
|
|
430
|
+
<h3 className="font-semibold text-lg">{translate("Entity Information")}</h3>
|
|
431
|
+
<p className="text-muted-foreground text-sm">
|
|
432
|
+
{translate("Required company details for FINA fiscalization")}
|
|
433
|
+
</p>
|
|
434
|
+
</div>
|
|
435
|
+
</div>
|
|
436
|
+
|
|
437
|
+
{!entity.tax_number && (
|
|
438
|
+
<Alert variant="destructive">
|
|
439
|
+
<AlertTriangle className="h-4 w-4" />
|
|
440
|
+
<AlertDescription>{translate("Entity OIB is required for FINA fiscalization")}</AlertDescription>
|
|
441
|
+
</Alert>
|
|
442
|
+
)}
|
|
443
|
+
|
|
444
|
+
<div className="space-y-4">
|
|
445
|
+
<div>
|
|
446
|
+
<label htmlFor="entity-tax-number" className="font-medium text-sm">
|
|
447
|
+
{translate("Entity OIB")}
|
|
448
|
+
</label>
|
|
449
|
+
<Input
|
|
450
|
+
id="entity-tax-number"
|
|
451
|
+
placeholder="12345678901"
|
|
452
|
+
value={entityTaxNumber}
|
|
453
|
+
onChange={(e) => setEntityTaxNumber(e.target.value)}
|
|
454
|
+
className={cn("mt-2 h-10", !entity.tax_number && "border-destructive")}
|
|
455
|
+
maxLength={11}
|
|
456
|
+
/>
|
|
457
|
+
<p className="mt-1 text-muted-foreground text-xs">
|
|
458
|
+
{translate("Your company's OIB (must match FINA certificate)")}
|
|
459
|
+
</p>
|
|
460
|
+
</div>
|
|
461
|
+
|
|
462
|
+
<div>
|
|
463
|
+
<label htmlFor="entity-address" className="font-medium text-sm">
|
|
464
|
+
{translate("Address")}
|
|
465
|
+
</label>
|
|
466
|
+
<Input
|
|
467
|
+
id="entity-address"
|
|
468
|
+
value={entityAddress}
|
|
469
|
+
onChange={(e) => setEntityAddress(e.target.value)}
|
|
470
|
+
className="mt-2 h-10"
|
|
471
|
+
/>
|
|
472
|
+
</div>
|
|
473
|
+
|
|
474
|
+
<div className="grid grid-cols-2 gap-4">
|
|
475
|
+
<div>
|
|
476
|
+
<label htmlFor="entity-post-code" className="font-medium text-sm">
|
|
477
|
+
{translate("Post Code")}
|
|
478
|
+
</label>
|
|
479
|
+
<Input
|
|
480
|
+
id="entity-post-code"
|
|
481
|
+
value={entityPostCode}
|
|
482
|
+
onChange={(e) => setEntityPostCode(e.target.value)}
|
|
483
|
+
className="mt-2 h-10"
|
|
484
|
+
/>
|
|
485
|
+
</div>
|
|
486
|
+
<div>
|
|
487
|
+
<label htmlFor="entity-city" className="font-medium text-sm">
|
|
488
|
+
{translate("City")}
|
|
489
|
+
</label>
|
|
490
|
+
<Input
|
|
491
|
+
id="entity-city"
|
|
492
|
+
value={entityCity}
|
|
493
|
+
onChange={(e) => setEntityCity(e.target.value)}
|
|
494
|
+
className="mt-2 h-10"
|
|
495
|
+
/>
|
|
496
|
+
</div>
|
|
497
|
+
</div>
|
|
498
|
+
|
|
499
|
+
<Button
|
|
500
|
+
type="button"
|
|
501
|
+
onClick={handleSaveEntityInfo}
|
|
502
|
+
disabled={isEntityUpdatePending}
|
|
503
|
+
className="cursor-pointer"
|
|
504
|
+
>
|
|
505
|
+
{isEntityUpdatePending ? translate("Saving...") : translate("Save Entity Info")}
|
|
506
|
+
</Button>
|
|
507
|
+
</div>
|
|
508
|
+
</div>,
|
|
509
|
+
)}
|
|
510
|
+
|
|
511
|
+
<Separator />
|
|
512
|
+
|
|
298
513
|
{wrapSection(
|
|
299
514
|
"numbering",
|
|
300
515
|
<div className="space-y-4">
|
|
@@ -319,6 +534,8 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
319
534
|
</div>,
|
|
320
535
|
)}
|
|
321
536
|
|
|
537
|
+
<Separator />
|
|
538
|
+
|
|
322
539
|
{wrapSection(
|
|
323
540
|
"operator",
|
|
324
541
|
<div className="space-y-4">
|
|
@@ -332,36 +549,154 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
332
549
|
<Label>{translate("Entity is registered in the Croatian PDV (VAT) system")}</Label>
|
|
333
550
|
</div>
|
|
334
551
|
</div>
|
|
335
|
-
<div>
|
|
336
|
-
<Label className="font-medium text-sm">{translate("Operator OIB")}</Label>
|
|
337
|
-
<input
|
|
338
|
-
type="text"
|
|
339
|
-
value={formData.operator_oib}
|
|
340
|
-
onChange={(e) => setFormData((prev) => ({ ...prev, operator_oib: e.target.value }))}
|
|
341
|
-
placeholder={translate("OIB of the operator (11 digits, optional)")}
|
|
342
|
-
className="mt-1 block w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
|
|
343
|
-
maxLength={11}
|
|
344
|
-
/>
|
|
345
|
-
</div>
|
|
346
|
-
<div>
|
|
347
|
-
<Label className="font-medium text-sm">{translate("Operator Label")}</Label>
|
|
348
|
-
<input
|
|
349
|
-
type="text"
|
|
350
|
-
value={formData.operator_label}
|
|
351
|
-
onChange={(e) => setFormData((prev) => ({ ...prev, operator_label: e.target.value }))}
|
|
352
|
-
placeholder={translate("Descriptive label for the operator (optional)")}
|
|
353
|
-
className="mt-1 block w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
|
|
354
|
-
/>
|
|
355
|
-
</div>
|
|
356
552
|
</div>,
|
|
357
553
|
)}
|
|
358
554
|
|
|
359
555
|
<div className="grid items-start gap-6 lg:grid-cols-[1fr_280px]">
|
|
360
|
-
<Button onClick={handleSaveSettings} disabled={isPending}>
|
|
556
|
+
<Button onClick={handleSaveSettings} disabled={isPending || !!operatorOibError}>
|
|
361
557
|
{isPending ? translate("Saving...") : translate("Save Settings")}
|
|
362
558
|
</Button>
|
|
363
559
|
<div className="hidden lg:block" />
|
|
364
560
|
</div>
|
|
561
|
+
|
|
562
|
+
<Separator />
|
|
563
|
+
|
|
564
|
+
{/* Per-user operator settings (hidden in embed/API key mode) */}
|
|
565
|
+
{!hideUserOperatorSection && (
|
|
566
|
+
<>
|
|
567
|
+
{wrapSection(
|
|
568
|
+
"user-operator",
|
|
569
|
+
<div className="space-y-4">
|
|
570
|
+
<div className="flex items-center gap-3">
|
|
571
|
+
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-blue-500/10">
|
|
572
|
+
<User className="h-5 w-5 text-blue-600 dark:text-blue-400" />
|
|
573
|
+
</div>
|
|
574
|
+
<div>
|
|
575
|
+
<h3 className="font-semibold text-lg">{translate("Your Operator Settings")}</h3>
|
|
576
|
+
<p className="text-muted-foreground text-sm">
|
|
577
|
+
{translate("Your personal operator info for FINA invoices")}
|
|
578
|
+
</p>
|
|
579
|
+
</div>
|
|
580
|
+
</div>
|
|
581
|
+
|
|
582
|
+
{(!userFinaSettings?.operator_oib || !userFinaSettings?.operator_label) && (
|
|
583
|
+
<Alert variant="destructive">
|
|
584
|
+
<AlertTriangle className="h-4 w-4" />
|
|
585
|
+
<AlertDescription>
|
|
586
|
+
{translate("Operator OIB and label are required for FINA fiscalization")}
|
|
587
|
+
</AlertDescription>
|
|
588
|
+
</Alert>
|
|
589
|
+
)}
|
|
590
|
+
|
|
591
|
+
<div className="space-y-4">
|
|
592
|
+
<div>
|
|
593
|
+
<Label className="font-medium text-sm">{translate("Operator OIB")}</Label>
|
|
594
|
+
<Input
|
|
595
|
+
type="text"
|
|
596
|
+
value={userOperatorOib}
|
|
597
|
+
onChange={(e) => {
|
|
598
|
+
const val = e.target.value.replace(/[^0-9]/g, "");
|
|
599
|
+
setUserOperatorOib(val);
|
|
600
|
+
}}
|
|
601
|
+
placeholder={translate("OIB of the operator (11 digits)")}
|
|
602
|
+
className={cn("mt-1", userOperatorOibError && "border-destructive")}
|
|
603
|
+
maxLength={11}
|
|
604
|
+
disabled={userSettingsLoading}
|
|
605
|
+
/>
|
|
606
|
+
{userOperatorOibError && <p className="mt-1 text-destructive text-xs">{userOperatorOibError}</p>}
|
|
607
|
+
</div>
|
|
608
|
+
<div>
|
|
609
|
+
<Label className="font-medium text-sm">{translate("Operator Label")}</Label>
|
|
610
|
+
<Input
|
|
611
|
+
type="text"
|
|
612
|
+
value={userOperatorLabel}
|
|
613
|
+
onChange={(e) => setUserOperatorLabel(e.target.value)}
|
|
614
|
+
placeholder={translate("e.g. Cashier 1")}
|
|
615
|
+
className="mt-1"
|
|
616
|
+
disabled={userSettingsLoading}
|
|
617
|
+
/>
|
|
618
|
+
</div>
|
|
619
|
+
|
|
620
|
+
<Button
|
|
621
|
+
type="button"
|
|
622
|
+
onClick={handleSaveUserSettings}
|
|
623
|
+
disabled={isUserSettingsPending || userSettingsLoading || !!userOperatorOibError}
|
|
624
|
+
className="cursor-pointer"
|
|
625
|
+
>
|
|
626
|
+
{isUserSettingsPending ? translate("Saving...") : translate("Save Operator Settings")}
|
|
627
|
+
</Button>
|
|
628
|
+
</div>
|
|
629
|
+
</div>,
|
|
630
|
+
)}
|
|
631
|
+
|
|
632
|
+
<Separator />
|
|
633
|
+
</>
|
|
634
|
+
)}
|
|
635
|
+
|
|
636
|
+
{/* API Default Operator (advanced/entity-level) */}
|
|
637
|
+
{wrapSection(
|
|
638
|
+
"advanced",
|
|
639
|
+
<div>
|
|
640
|
+
<button
|
|
641
|
+
type="button"
|
|
642
|
+
onClick={() => setIsAdvancedOpen(!isAdvancedOpen)}
|
|
643
|
+
className="flex w-full items-center gap-2 py-2 text-muted-foreground hover:text-foreground"
|
|
644
|
+
>
|
|
645
|
+
<ChevronRight className={cn("h-4 w-4 transition-transform", isAdvancedOpen && "rotate-90")} />
|
|
646
|
+
<span className="font-medium text-sm">{translate("Advanced Settings")}</span>
|
|
647
|
+
</button>
|
|
648
|
+
{isAdvancedOpen && (
|
|
649
|
+
<div className="pt-4">
|
|
650
|
+
<div className="space-y-4 rounded-lg border p-4">
|
|
651
|
+
<div>
|
|
652
|
+
<h4 className="font-medium text-sm">{translate("API Default Operator")}</h4>
|
|
653
|
+
<p className="text-muted-foreground text-xs">
|
|
654
|
+
{translate("Default operator settings for API key usage (when no user context)")}
|
|
655
|
+
</p>
|
|
656
|
+
</div>
|
|
657
|
+
|
|
658
|
+
<div className="space-y-4">
|
|
659
|
+
<div>
|
|
660
|
+
<Label className="text-sm">{translate("Operator OIB")}</Label>
|
|
661
|
+
<Input
|
|
662
|
+
type="text"
|
|
663
|
+
value={formData.operator_oib}
|
|
664
|
+
onChange={(e) => {
|
|
665
|
+
const val = e.target.value.replace(/[^0-9]/g, "");
|
|
666
|
+
setFormData((prev) => ({ ...prev, operator_oib: val }));
|
|
667
|
+
}}
|
|
668
|
+
placeholder={translate("OIB of the operator (11 digits)")}
|
|
669
|
+
className={cn("mt-1", operatorOibError && "border-destructive")}
|
|
670
|
+
maxLength={11}
|
|
671
|
+
/>
|
|
672
|
+
{operatorOibError && <p className="mt-1 text-destructive text-xs">{operatorOibError}</p>}
|
|
673
|
+
<p className="mt-1 text-muted-foreground text-xs">
|
|
674
|
+
{translate("OIB for API key usage (optional)")}
|
|
675
|
+
</p>
|
|
676
|
+
</div>
|
|
677
|
+
<div>
|
|
678
|
+
<Label className="text-sm">{translate("Operator Label")}</Label>
|
|
679
|
+
<Input
|
|
680
|
+
type="text"
|
|
681
|
+
value={formData.operator_label}
|
|
682
|
+
onChange={(e) => setFormData((prev) => ({ ...prev, operator_label: e.target.value }))}
|
|
683
|
+
placeholder="API Default"
|
|
684
|
+
className="mt-1"
|
|
685
|
+
/>
|
|
686
|
+
<p className="mt-1 text-muted-foreground text-xs">
|
|
687
|
+
{translate("Operator label for API key usage (optional)")}
|
|
688
|
+
</p>
|
|
689
|
+
</div>
|
|
690
|
+
</div>
|
|
691
|
+
|
|
692
|
+
<Button onClick={handleSaveSettings} disabled={isPending || !!operatorOibError} size="sm">
|
|
693
|
+
{isPending ? translate("Saving...") : translate("Save Settings")}
|
|
694
|
+
</Button>
|
|
695
|
+
</div>
|
|
696
|
+
</div>
|
|
697
|
+
)}
|
|
698
|
+
</div>,
|
|
699
|
+
)}
|
|
365
700
|
</div>
|
|
366
701
|
)}
|
|
367
702
|
|
|
@@ -431,7 +766,14 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
431
766
|
setFormData((prev) => ({ ...prev, enabled: checked }));
|
|
432
767
|
updateSettings({
|
|
433
768
|
entityId: entity.id,
|
|
434
|
-
data:
|
|
769
|
+
data: checked
|
|
770
|
+
? {
|
|
771
|
+
...formData,
|
|
772
|
+
enabled: true,
|
|
773
|
+
operator_oib: formData.operator_oib || undefined,
|
|
774
|
+
operator_label: formData.operator_label || undefined,
|
|
775
|
+
}
|
|
776
|
+
: { enabled: false },
|
|
435
777
|
});
|
|
436
778
|
}}
|
|
437
779
|
/>
|