@spaceinvoices/react-ui 0.4.1 → 0.4.2
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 +45 -2
- package/src/components/advance-invoices/list/locales/de.ts +3 -0
- package/src/components/advance-invoices/list/locales/en.ts +3 -0
- package/src/components/advance-invoices/list/locales/es.ts +3 -0
- package/src/components/advance-invoices/list/locales/fr.ts +3 -0
- package/src/components/advance-invoices/list/locales/hr.ts +3 -0
- package/src/components/advance-invoices/list/locales/it.ts +3 -0
- package/src/components/advance-invoices/list/locales/nl.ts +3 -0
- package/src/components/advance-invoices/list/locales/pl.ts +3 -0
- package/src/components/advance-invoices/list/locales/pt.ts +3 -0
- package/src/components/advance-invoices/list/locales/sl.ts +3 -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 +45 -2
- package/src/components/credit-notes/list/locales/de.ts +3 -0
- package/src/components/credit-notes/list/locales/en.ts +3 -0
- package/src/components/credit-notes/list/locales/es.ts +3 -0
- package/src/components/credit-notes/list/locales/fr.ts +3 -0
- package/src/components/credit-notes/list/locales/hr.ts +3 -0
- package/src/components/credit-notes/list/locales/it.ts +3 -0
- package/src/components/credit-notes/list/locales/nl.ts +3 -0
- package/src/components/credit-notes/list/locales/pl.ts +3 -0
- package/src/components/credit-notes/list/locales/pt.ts +3 -0
- package/src/components/credit-notes/list/locales/sl.ts +3 -0
- package/src/components/customers/create-customer-form/create-customer-form.tsx +0 -1
- package/src/components/documents/create/document-details-section.tsx +67 -1
- package/src/components/documents/create/mark-as-paid-section.tsx +11 -2
- package/src/components/documents/view/document-actions-bar.tsx +30 -0
- package/src/components/documents/view/locales/de.ts +5 -0
- package/src/components/documents/view/locales/es.ts +5 -0
- package/src/components/documents/view/locales/fr.ts +5 -0
- package/src/components/documents/view/locales/hr.ts +5 -0
- package/src/components/documents/view/locales/it.ts +5 -0
- package/src/components/documents/view/locales/nl.ts +5 -0
- package/src/components/documents/view/locales/pl.ts +5 -0
- package/src/components/documents/view/locales/pt.ts +5 -0
- package/src/components/documents/view/locales/sl.ts +5 -0
- 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 +365 -35
- package/src/components/entities/fina-settings-form/fina-settings.hooks.ts +101 -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 +24 -10
- package/src/components/entities/furs-settings-form/furs-settings.hooks.ts +5 -9
- 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 +15 -2
- 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.hooks.ts +32 -2
- package/src/components/invoices/list/list-row-actions.tsx +23 -8
- package/src/components/invoices/list/list-table.tsx +53 -2
- package/src/components/invoices/list/locales/de.ts +4 -0
- package/src/components/invoices/list/locales/en.ts +4 -0
- package/src/components/invoices/list/locales/es.ts +4 -0
- package/src/components/invoices/list/locales/fr.ts +4 -0
- package/src/components/invoices/list/locales/hr.ts +4 -0
- package/src/components/invoices/list/locales/it.ts +4 -0
- package/src/components/invoices/list/locales/nl.ts +4 -0
- package/src/components/invoices/list/locales/pl.ts +4 -0
- package/src/components/invoices/list/locales/pt.ts +4 -0
- package/src/components/invoices/list/locales/sl.ts +4 -0
- package/src/components/invoices/view/fiscalization-status-card.tsx +4 -1
- package/src/components/items/item-list-table/item-list-row-actions.tsx +3 -7
- package/src/components/items/item-list-table/item-list-row.tsx +3 -2
- 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/entity.ts +1 -1
- package/src/generated/schemas/index.ts +39 -28
- package/src/generated/schemas/order.ts +127 -0
- package/src/generated/schemas/orderintegration.ts +51 -0
- package/src/generated/schemas/payment.ts +2 -0
- package/src/generated/schemas/recurringinvoice.ts +61 -0
- package/src/generated/schemas/renderadvanceinvoicepreview_body.ts +107 -140
- package/src/generated/schemas/rendercreditnotepreview_body.ts +108 -141
- package/src/generated/schemas/renderestimatepreview_body.ts +78 -82
- package/src/generated/schemas/renderinvoicepreview_body.ts +108 -141
- package/src/generated/schemas/webhook.ts +42 -0
- 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/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;
|
|
@@ -77,6 +94,36 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
77
94
|
[onStepChange],
|
|
78
95
|
);
|
|
79
96
|
|
|
97
|
+
// Entity info state
|
|
98
|
+
const [entityTaxNumber, setEntityTaxNumber] = useState("");
|
|
99
|
+
const [entityAddress, setEntityAddress] = useState("");
|
|
100
|
+
const [entityCity, setEntityCity] = useState("");
|
|
101
|
+
const [entityPostCode, setEntityPostCode] = useState("");
|
|
102
|
+
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
setEntityTaxNumber(entity.tax_number || "");
|
|
105
|
+
setEntityAddress(entity.address || "");
|
|
106
|
+
setEntityCity(entity.city || "");
|
|
107
|
+
setEntityPostCode(entity.post_code || "");
|
|
108
|
+
}, [entity.tax_number, entity.address, entity.city, entity.post_code]);
|
|
109
|
+
|
|
110
|
+
const { mutate: updateEntity, isPending: isEntityUpdatePending } = useUpdateEntity({
|
|
111
|
+
onSuccess: () => onSuccess?.(),
|
|
112
|
+
onError: (error) => onError?.(error),
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const handleSaveEntityInfo = () => {
|
|
116
|
+
updateEntity({
|
|
117
|
+
id: entity.id,
|
|
118
|
+
data: {
|
|
119
|
+
tax_number: entityTaxNumber || null,
|
|
120
|
+
address: entityAddress || null,
|
|
121
|
+
city: entityCity || null,
|
|
122
|
+
post_code: entityPostCode || null,
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
};
|
|
126
|
+
|
|
80
127
|
// Fetch FINA settings and premises
|
|
81
128
|
const { data: finaSettings, isLoading: settingsLoading } = useFinaSettings(entity.id);
|
|
82
129
|
const { data: premises, isLoading: premisesLoading } = useFinaPremises(entity.id);
|
|
@@ -90,7 +137,36 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
90
137
|
},
|
|
91
138
|
});
|
|
92
139
|
|
|
93
|
-
//
|
|
140
|
+
// User FINA operator settings (per-user, stored in user.settings)
|
|
141
|
+
const { data: userFinaSettings, isLoading: userSettingsLoading } = useUserFinaSettings(entity.id);
|
|
142
|
+
const [userOperatorOib, setUserOperatorOib] = useState("");
|
|
143
|
+
const [userOperatorLabel, setUserOperatorLabel] = useState("");
|
|
144
|
+
|
|
145
|
+
useEffect(() => {
|
|
146
|
+
if (userFinaSettings) {
|
|
147
|
+
setUserOperatorOib(userFinaSettings.operator_oib || "");
|
|
148
|
+
setUserOperatorLabel(userFinaSettings.operator_label || "");
|
|
149
|
+
}
|
|
150
|
+
}, [userFinaSettings]);
|
|
151
|
+
|
|
152
|
+
const { mutate: updateUserSettings, isPending: isUserSettingsPending } = useUpdateUserFinaSettings({
|
|
153
|
+
onSuccess: () => onSuccess?.(),
|
|
154
|
+
onError: (error) => onError?.(error),
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
const handleSaveUserSettings = () => {
|
|
158
|
+
if (userOperatorOibError) return;
|
|
159
|
+
updateUserSettings({
|
|
160
|
+
entityId: entity.id,
|
|
161
|
+
data: {
|
|
162
|
+
operator_oib: userOperatorOib || undefined,
|
|
163
|
+
operator_label: userOperatorLabel || undefined,
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// Form state for entity-level settings (API default)
|
|
169
|
+
const [isAdvancedOpen, setIsAdvancedOpen] = useState(false);
|
|
94
170
|
const [formData, setFormData] = useState({
|
|
95
171
|
enabled: false,
|
|
96
172
|
numbering_sequence: "N" as "N" | "P",
|
|
@@ -113,6 +189,12 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
113
189
|
}, [finaSettings]);
|
|
114
190
|
|
|
115
191
|
// Determine completion status
|
|
192
|
+
const hasEntityTaxNumber = !!entity.tax_number;
|
|
193
|
+
// Operator OIB is required by CIS protocol (minOccurs="1" in FiskalizacijaSchema.xsd)
|
|
194
|
+
// Can come from user settings or entity-level FINA settings
|
|
195
|
+
const hasOperatorSettings =
|
|
196
|
+
(!!userFinaSettings?.operator_oib && !!userFinaSettings?.operator_label) ||
|
|
197
|
+
(!!finaSettings?.operator_oib && !!finaSettings?.operator_label);
|
|
116
198
|
const hasCertificate = finaSettings?.has_certificate || false;
|
|
117
199
|
const certificateValid = finaSettings?.certificate_status === "valid";
|
|
118
200
|
const hasPremises = (premises?.length || 0) > 0;
|
|
@@ -120,16 +202,23 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
120
202
|
hasPremises && premises?.some((premise: any) => premise.Devices && premise.Devices.length > 0);
|
|
121
203
|
|
|
122
204
|
const finaEnabled = finaSettings?.enabled || false;
|
|
123
|
-
const
|
|
124
|
-
const
|
|
205
|
+
const canAccessCertificate = hasEntityTaxNumber && hasOperatorSettings;
|
|
206
|
+
const canAccessPremises = hasEntityTaxNumber && hasOperatorSettings && hasCertificate && certificateValid;
|
|
207
|
+
const canAccessEnable =
|
|
208
|
+
hasEntityTaxNumber && hasOperatorSettings && certificateValid && hasPremises && hasPremiseWithDevice;
|
|
125
209
|
|
|
126
210
|
const steps = [
|
|
127
|
-
{
|
|
211
|
+
{
|
|
212
|
+
id: "settings" as const,
|
|
213
|
+
title: translate("General Settings"),
|
|
214
|
+
complete: hasEntityTaxNumber && hasOperatorSettings,
|
|
215
|
+
unlocked: true,
|
|
216
|
+
},
|
|
128
217
|
{
|
|
129
218
|
id: "certificate" as const,
|
|
130
219
|
title: translate("Certificate"),
|
|
131
220
|
complete: hasCertificate && certificateValid,
|
|
132
|
-
unlocked:
|
|
221
|
+
unlocked: canAccessCertificate,
|
|
133
222
|
},
|
|
134
223
|
{
|
|
135
224
|
id: "premises" as const,
|
|
@@ -196,10 +285,23 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
196
285
|
|
|
197
286
|
const isSandboxMode = entity.environment === "sandbox";
|
|
198
287
|
|
|
288
|
+
const userOperatorOibError =
|
|
289
|
+
userOperatorOib !== "" && !/^\d{11}$/.test(userOperatorOib) ? translate("OIB must be exactly 11 digits") : "";
|
|
290
|
+
|
|
291
|
+
const operatorOibError =
|
|
292
|
+
formData.operator_oib !== "" && !/^\d{11}$/.test(formData.operator_oib)
|
|
293
|
+
? translate("OIB must be exactly 11 digits")
|
|
294
|
+
: "";
|
|
295
|
+
|
|
199
296
|
const handleSaveSettings = () => {
|
|
297
|
+
if (operatorOibError) return;
|
|
200
298
|
updateSettings({
|
|
201
299
|
entityId: entity.id,
|
|
202
|
-
data:
|
|
300
|
+
data: {
|
|
301
|
+
...formData,
|
|
302
|
+
operator_oib: formData.operator_oib || undefined,
|
|
303
|
+
operator_label: formData.operator_label || undefined,
|
|
304
|
+
},
|
|
203
305
|
});
|
|
204
306
|
};
|
|
205
307
|
|
|
@@ -218,10 +320,24 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
218
320
|
const isLocked = !step.unlocked;
|
|
219
321
|
let tooltipText = "";
|
|
220
322
|
if (isLocked) {
|
|
221
|
-
if (step.id === "
|
|
222
|
-
|
|
323
|
+
if (step.id === "certificate") {
|
|
324
|
+
if (!hasEntityTaxNumber) {
|
|
325
|
+
tooltipText = translate("Set entity OIB in General Settings first");
|
|
326
|
+
} else {
|
|
327
|
+
tooltipText = translate("Set operator OIB and label in General Settings first");
|
|
328
|
+
}
|
|
329
|
+
} else if (step.id === "premises") {
|
|
330
|
+
if (!hasEntityTaxNumber) {
|
|
331
|
+
tooltipText = translate("Set entity OIB in General Settings first");
|
|
332
|
+
} else if (!hasOperatorSettings) {
|
|
333
|
+
tooltipText = translate("Set operator OIB and label in General Settings first");
|
|
334
|
+
} else {
|
|
335
|
+
tooltipText = translate("Upload and validate digital certificate first");
|
|
336
|
+
}
|
|
223
337
|
} else if (step.id === "enable") {
|
|
224
|
-
if (!
|
|
338
|
+
if (!hasEntityTaxNumber || !hasOperatorSettings) {
|
|
339
|
+
tooltipText = translate("Complete General Settings first");
|
|
340
|
+
} else if (!certificateValid) {
|
|
225
341
|
tooltipText = translate("Upload and validate digital certificate first");
|
|
226
342
|
} else if (!hasPremises) {
|
|
227
343
|
tooltipText = translate("Register at least one business premise first");
|
|
@@ -295,6 +411,97 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
295
411
|
{/* Settings step */}
|
|
296
412
|
{activeStep === "settings" && (
|
|
297
413
|
<div className="space-y-6">
|
|
414
|
+
{wrapSection(
|
|
415
|
+
"entity-info",
|
|
416
|
+
<div className="space-y-4">
|
|
417
|
+
<div className="flex items-center gap-3">
|
|
418
|
+
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-orange-500/10">
|
|
419
|
+
<Building2 className="h-5 w-5 text-orange-600 dark:text-orange-400" />
|
|
420
|
+
</div>
|
|
421
|
+
<div>
|
|
422
|
+
<h3 className="font-semibold text-lg">{translate("Entity Information")}</h3>
|
|
423
|
+
<p className="text-muted-foreground text-sm">
|
|
424
|
+
{translate("Required company details for FINA fiscalization")}
|
|
425
|
+
</p>
|
|
426
|
+
</div>
|
|
427
|
+
</div>
|
|
428
|
+
|
|
429
|
+
{!entity.tax_number && (
|
|
430
|
+
<Alert variant="destructive">
|
|
431
|
+
<AlertTriangle className="h-4 w-4" />
|
|
432
|
+
<AlertDescription>{translate("Entity OIB is required for FINA fiscalization")}</AlertDescription>
|
|
433
|
+
</Alert>
|
|
434
|
+
)}
|
|
435
|
+
|
|
436
|
+
<div className="space-y-4">
|
|
437
|
+
<div>
|
|
438
|
+
<label htmlFor="entity-tax-number" className="font-medium text-sm">
|
|
439
|
+
{translate("Entity OIB")}
|
|
440
|
+
</label>
|
|
441
|
+
<Input
|
|
442
|
+
id="entity-tax-number"
|
|
443
|
+
placeholder="12345678901"
|
|
444
|
+
value={entityTaxNumber}
|
|
445
|
+
onChange={(e) => setEntityTaxNumber(e.target.value)}
|
|
446
|
+
className={cn("mt-2 h-10", !entity.tax_number && "border-destructive")}
|
|
447
|
+
maxLength={11}
|
|
448
|
+
/>
|
|
449
|
+
<p className="mt-1 text-muted-foreground text-xs">
|
|
450
|
+
{translate("Your company's OIB (must match FINA certificate)")}
|
|
451
|
+
</p>
|
|
452
|
+
</div>
|
|
453
|
+
|
|
454
|
+
<div>
|
|
455
|
+
<label htmlFor="entity-address" className="font-medium text-sm">
|
|
456
|
+
{translate("Address")}
|
|
457
|
+
</label>
|
|
458
|
+
<Input
|
|
459
|
+
id="entity-address"
|
|
460
|
+
value={entityAddress}
|
|
461
|
+
onChange={(e) => setEntityAddress(e.target.value)}
|
|
462
|
+
className="mt-2 h-10"
|
|
463
|
+
/>
|
|
464
|
+
</div>
|
|
465
|
+
|
|
466
|
+
<div className="grid grid-cols-2 gap-4">
|
|
467
|
+
<div>
|
|
468
|
+
<label htmlFor="entity-post-code" className="font-medium text-sm">
|
|
469
|
+
{translate("Post Code")}
|
|
470
|
+
</label>
|
|
471
|
+
<Input
|
|
472
|
+
id="entity-post-code"
|
|
473
|
+
value={entityPostCode}
|
|
474
|
+
onChange={(e) => setEntityPostCode(e.target.value)}
|
|
475
|
+
className="mt-2 h-10"
|
|
476
|
+
/>
|
|
477
|
+
</div>
|
|
478
|
+
<div>
|
|
479
|
+
<label htmlFor="entity-city" className="font-medium text-sm">
|
|
480
|
+
{translate("City")}
|
|
481
|
+
</label>
|
|
482
|
+
<Input
|
|
483
|
+
id="entity-city"
|
|
484
|
+
value={entityCity}
|
|
485
|
+
onChange={(e) => setEntityCity(e.target.value)}
|
|
486
|
+
className="mt-2 h-10"
|
|
487
|
+
/>
|
|
488
|
+
</div>
|
|
489
|
+
</div>
|
|
490
|
+
|
|
491
|
+
<Button
|
|
492
|
+
type="button"
|
|
493
|
+
onClick={handleSaveEntityInfo}
|
|
494
|
+
disabled={isEntityUpdatePending}
|
|
495
|
+
className="cursor-pointer"
|
|
496
|
+
>
|
|
497
|
+
{isEntityUpdatePending ? translate("Saving...") : translate("Save Entity Info")}
|
|
498
|
+
</Button>
|
|
499
|
+
</div>
|
|
500
|
+
</div>,
|
|
501
|
+
)}
|
|
502
|
+
|
|
503
|
+
<Separator />
|
|
504
|
+
|
|
298
505
|
{wrapSection(
|
|
299
506
|
"numbering",
|
|
300
507
|
<div className="space-y-4">
|
|
@@ -319,6 +526,8 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
319
526
|
</div>,
|
|
320
527
|
)}
|
|
321
528
|
|
|
529
|
+
<Separator />
|
|
530
|
+
|
|
322
531
|
{wrapSection(
|
|
323
532
|
"operator",
|
|
324
533
|
<div className="space-y-4">
|
|
@@ -332,36 +541,150 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
332
541
|
<Label>{translate("Entity is registered in the Croatian PDV (VAT) system")}</Label>
|
|
333
542
|
</div>
|
|
334
543
|
</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
544
|
</div>,
|
|
357
545
|
)}
|
|
358
546
|
|
|
359
547
|
<div className="grid items-start gap-6 lg:grid-cols-[1fr_280px]">
|
|
360
|
-
<Button onClick={handleSaveSettings} disabled={isPending}>
|
|
548
|
+
<Button onClick={handleSaveSettings} disabled={isPending || !!operatorOibError}>
|
|
361
549
|
{isPending ? translate("Saving...") : translate("Save Settings")}
|
|
362
550
|
</Button>
|
|
363
551
|
<div className="hidden lg:block" />
|
|
364
552
|
</div>
|
|
553
|
+
|
|
554
|
+
<Separator />
|
|
555
|
+
|
|
556
|
+
{/* Per-user operator settings */}
|
|
557
|
+
{wrapSection(
|
|
558
|
+
"user-operator",
|
|
559
|
+
<div className="space-y-4">
|
|
560
|
+
<div className="flex items-center gap-3">
|
|
561
|
+
<div className="flex h-10 w-10 items-center justify-center rounded-lg bg-blue-500/10">
|
|
562
|
+
<User className="h-5 w-5 text-blue-600 dark:text-blue-400" />
|
|
563
|
+
</div>
|
|
564
|
+
<div>
|
|
565
|
+
<h3 className="font-semibold text-lg">{translate("Your Operator Settings")}</h3>
|
|
566
|
+
<p className="text-muted-foreground text-sm">
|
|
567
|
+
{translate("Your personal operator info for FINA invoices")}
|
|
568
|
+
</p>
|
|
569
|
+
</div>
|
|
570
|
+
</div>
|
|
571
|
+
|
|
572
|
+
{(!userFinaSettings?.operator_oib || !userFinaSettings?.operator_label) && (
|
|
573
|
+
<Alert variant="destructive">
|
|
574
|
+
<AlertTriangle className="h-4 w-4" />
|
|
575
|
+
<AlertDescription>
|
|
576
|
+
{translate("Operator OIB and label are required for FINA fiscalization")}
|
|
577
|
+
</AlertDescription>
|
|
578
|
+
</Alert>
|
|
579
|
+
)}
|
|
580
|
+
|
|
581
|
+
<div className="space-y-4">
|
|
582
|
+
<div>
|
|
583
|
+
<Label className="font-medium text-sm">{translate("Operator OIB")}</Label>
|
|
584
|
+
<Input
|
|
585
|
+
type="text"
|
|
586
|
+
value={userOperatorOib}
|
|
587
|
+
onChange={(e) => {
|
|
588
|
+
const val = e.target.value.replace(/[^0-9]/g, "");
|
|
589
|
+
setUserOperatorOib(val);
|
|
590
|
+
}}
|
|
591
|
+
placeholder={translate("OIB of the operator (11 digits)")}
|
|
592
|
+
className={cn("mt-1", userOperatorOibError && "border-destructive")}
|
|
593
|
+
maxLength={11}
|
|
594
|
+
disabled={userSettingsLoading}
|
|
595
|
+
/>
|
|
596
|
+
{userOperatorOibError && <p className="mt-1 text-destructive text-xs">{userOperatorOibError}</p>}
|
|
597
|
+
</div>
|
|
598
|
+
<div>
|
|
599
|
+
<Label className="font-medium text-sm">{translate("Operator Label")}</Label>
|
|
600
|
+
<Input
|
|
601
|
+
type="text"
|
|
602
|
+
value={userOperatorLabel}
|
|
603
|
+
onChange={(e) => setUserOperatorLabel(e.target.value)}
|
|
604
|
+
placeholder={translate("e.g. Cashier 1")}
|
|
605
|
+
className="mt-1"
|
|
606
|
+
disabled={userSettingsLoading}
|
|
607
|
+
/>
|
|
608
|
+
</div>
|
|
609
|
+
|
|
610
|
+
<Button
|
|
611
|
+
type="button"
|
|
612
|
+
onClick={handleSaveUserSettings}
|
|
613
|
+
disabled={isUserSettingsPending || userSettingsLoading || !!userOperatorOibError}
|
|
614
|
+
className="cursor-pointer"
|
|
615
|
+
>
|
|
616
|
+
{isUserSettingsPending ? translate("Saving...") : translate("Save Operator Settings")}
|
|
617
|
+
</Button>
|
|
618
|
+
</div>
|
|
619
|
+
</div>,
|
|
620
|
+
)}
|
|
621
|
+
|
|
622
|
+
<Separator />
|
|
623
|
+
|
|
624
|
+
{/* API Default Operator (advanced/entity-level) */}
|
|
625
|
+
{wrapSection(
|
|
626
|
+
"advanced",
|
|
627
|
+
<div>
|
|
628
|
+
<button
|
|
629
|
+
type="button"
|
|
630
|
+
onClick={() => setIsAdvancedOpen(!isAdvancedOpen)}
|
|
631
|
+
className="flex w-full items-center gap-2 py-2 text-muted-foreground hover:text-foreground"
|
|
632
|
+
>
|
|
633
|
+
<ChevronRight className={cn("h-4 w-4 transition-transform", isAdvancedOpen && "rotate-90")} />
|
|
634
|
+
<span className="font-medium text-sm">{translate("Advanced Settings")}</span>
|
|
635
|
+
</button>
|
|
636
|
+
{isAdvancedOpen && (
|
|
637
|
+
<div className="pt-4">
|
|
638
|
+
<div className="space-y-4 rounded-lg border p-4">
|
|
639
|
+
<div>
|
|
640
|
+
<h4 className="font-medium text-sm">{translate("API Default Operator")}</h4>
|
|
641
|
+
<p className="text-muted-foreground text-xs">
|
|
642
|
+
{translate("Default operator settings for API key usage (when no user context)")}
|
|
643
|
+
</p>
|
|
644
|
+
</div>
|
|
645
|
+
|
|
646
|
+
<div className="space-y-4">
|
|
647
|
+
<div>
|
|
648
|
+
<Label className="text-sm">{translate("Operator OIB")}</Label>
|
|
649
|
+
<Input
|
|
650
|
+
type="text"
|
|
651
|
+
value={formData.operator_oib}
|
|
652
|
+
onChange={(e) => {
|
|
653
|
+
const val = e.target.value.replace(/[^0-9]/g, "");
|
|
654
|
+
setFormData((prev) => ({ ...prev, operator_oib: val }));
|
|
655
|
+
}}
|
|
656
|
+
placeholder={translate("OIB of the operator (11 digits)")}
|
|
657
|
+
className={cn("mt-1", operatorOibError && "border-destructive")}
|
|
658
|
+
maxLength={11}
|
|
659
|
+
/>
|
|
660
|
+
{operatorOibError && <p className="mt-1 text-destructive text-xs">{operatorOibError}</p>}
|
|
661
|
+
<p className="mt-1 text-muted-foreground text-xs">
|
|
662
|
+
{translate("OIB for API key usage (optional)")}
|
|
663
|
+
</p>
|
|
664
|
+
</div>
|
|
665
|
+
<div>
|
|
666
|
+
<Label className="text-sm">{translate("Operator Label")}</Label>
|
|
667
|
+
<Input
|
|
668
|
+
type="text"
|
|
669
|
+
value={formData.operator_label}
|
|
670
|
+
onChange={(e) => setFormData((prev) => ({ ...prev, operator_label: e.target.value }))}
|
|
671
|
+
placeholder="API Default"
|
|
672
|
+
className="mt-1"
|
|
673
|
+
/>
|
|
674
|
+
<p className="mt-1 text-muted-foreground text-xs">
|
|
675
|
+
{translate("Operator label for API key usage (optional)")}
|
|
676
|
+
</p>
|
|
677
|
+
</div>
|
|
678
|
+
</div>
|
|
679
|
+
|
|
680
|
+
<Button onClick={handleSaveSettings} disabled={isPending || !!operatorOibError} size="sm">
|
|
681
|
+
{isPending ? translate("Saving...") : translate("Save Settings")}
|
|
682
|
+
</Button>
|
|
683
|
+
</div>
|
|
684
|
+
</div>
|
|
685
|
+
)}
|
|
686
|
+
</div>,
|
|
687
|
+
)}
|
|
365
688
|
</div>
|
|
366
689
|
)}
|
|
367
690
|
|
|
@@ -431,7 +754,14 @@ export const FinaSettingsForm: FC<FinaSettingsFormProps> = ({
|
|
|
431
754
|
setFormData((prev) => ({ ...prev, enabled: checked }));
|
|
432
755
|
updateSettings({
|
|
433
756
|
entityId: entity.id,
|
|
434
|
-
data:
|
|
757
|
+
data: checked
|
|
758
|
+
? {
|
|
759
|
+
...formData,
|
|
760
|
+
enabled: true,
|
|
761
|
+
operator_oib: formData.operator_oib || undefined,
|
|
762
|
+
operator_label: formData.operator_label || undefined,
|
|
763
|
+
}
|
|
764
|
+
: { enabled: false },
|
|
435
765
|
});
|
|
436
766
|
}}
|
|
437
767
|
/>
|