@carlonicora/nextjs-jsonapi 1.65.0 → 1.66.0
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/dist/{AuthComponent-B4rNZRYE.d.ts → AuthComponent-DL1D3y7f.d.ts} +1 -1
- package/dist/{AuthComponent-nzabiz68.d.mts → AuthComponent-NwQ_ZXsv.d.mts} +1 -1
- package/dist/{BlockNoteEditor-Y5XAD6NR.js → BlockNoteEditor-GQM2TZG2.js} +14 -14
- package/dist/{BlockNoteEditor-Y5XAD6NR.js.map → BlockNoteEditor-GQM2TZG2.js.map} +1 -1
- package/dist/{BlockNoteEditor-SCQGD6F2.mjs → BlockNoteEditor-KCJMA6LW.mjs} +4 -4
- package/dist/{auth.interface-C1WjZ0fM.d.ts → auth.interface-BX_1qZZJ.d.ts} +1 -1
- package/dist/{auth.interface-fBFqIrw4.d.mts → auth.interface-yeLelxdI.d.mts} +1 -1
- package/dist/billing/index.js +346 -346
- package/dist/billing/index.mjs +3 -3
- package/dist/{chunk-G7PGWMFO.mjs → chunk-35GWVOYZ.mjs} +61 -1
- package/dist/{chunk-G7PGWMFO.mjs.map → chunk-35GWVOYZ.mjs.map} +1 -1
- package/dist/{chunk-OLNMWVOV.mjs → chunk-4E74ZTRT.mjs} +2115 -1834
- package/dist/chunk-4E74ZTRT.mjs.map +1 -0
- package/dist/{chunk-LRXJT656.js → chunk-NVXYOQFW.js} +61 -1
- package/dist/chunk-NVXYOQFW.js.map +1 -0
- package/dist/{chunk-RA4RYKYB.js → chunk-OQRBY22T.js} +11 -11
- package/dist/{chunk-RA4RYKYB.js.map → chunk-OQRBY22T.js.map} +1 -1
- package/dist/{chunk-5ODPC3YX.js → chunk-QIFM4G7T.js} +1174 -893
- package/dist/chunk-QIFM4G7T.js.map +1 -0
- package/dist/{chunk-5KMKI23S.mjs → chunk-UXGPZZ6V.mjs} +2 -2
- package/dist/client/index.d.mts +6 -6
- package/dist/client/index.d.ts +6 -6
- package/dist/client/index.js +4 -4
- package/dist/client/index.mjs +3 -3
- package/dist/components/index.d.mts +42 -7
- package/dist/components/index.d.ts +42 -7
- package/dist/components/index.js +14 -4
- package/dist/components/index.js.map +1 -1
- package/dist/components/index.mjs +13 -3
- package/dist/{config-DZWAFB7H.d.ts → config-CyCAWW-d.d.ts} +1 -1
- package/dist/{config-ndRJIQsP.d.mts → config-D-mqttuF.d.mts} +1 -1
- package/dist/{content.interface-B5ySfiOE.d.mts → content.interface-8T5-G84c.d.mts} +1 -1
- package/dist/{content.interface-mmz0uMwm.d.ts → content.interface-D-xdYxjt.d.ts} +1 -1
- package/dist/contexts/index.d.mts +2 -2
- package/dist/contexts/index.d.ts +2 -2
- package/dist/contexts/index.js +4 -4
- package/dist/contexts/index.mjs +3 -3
- package/dist/core/index.d.mts +29 -9
- package/dist/core/index.d.ts +29 -9
- package/dist/core/index.js +2 -2
- package/dist/core/index.mjs +1 -1
- package/dist/index.d.mts +8 -8
- package/dist/index.d.ts +8 -8
- package/dist/index.js +3 -3
- package/dist/index.mjs +2 -2
- package/dist/{notification.interface-DG7cq9oG.d.mts → notification.interface-C6UcmJqu.d.mts} +20 -0
- package/dist/{notification.interface-COKHDQeE.d.ts → notification.interface-ItBxq2au.d.ts} +20 -0
- package/dist/{s3.service-ppn9iGJU.d.ts → s3.service-DIR6Su9B.d.ts} +3 -3
- package/dist/{s3.service-BoRPFx82.d.mts → s3.service-XchHd3ii.d.mts} +3 -3
- package/dist/server/index.d.mts +4 -4
- package/dist/server/index.d.ts +4 -4
- package/dist/server/index.js +3 -3
- package/dist/server/index.mjs +1 -1
- package/dist/{useRbacState-DhuYYr0S.d.mts → useRbacState-Btk1gkQg.d.mts} +1 -1
- package/dist/{useRbacState-NnzNL2ED.d.ts → useRbacState-CUj0hp8t.d.ts} +1 -1
- package/dist/{useSocket-bsV-K4qR.d.ts → useSocket-BSUN9s3p.d.ts} +1 -1
- package/dist/{useSocket-CtfuR5wD.d.mts → useSocket-DKI92Fbg.d.mts} +1 -1
- package/package.json +2 -1
- package/src/components/containers/RoundPageContainer.tsx +1 -1
- package/src/components/fiscal/FiscalDataDisplay.tsx +26 -0
- package/src/components/fiscal/ItalianFiscalData.tsx +120 -0
- package/src/components/fiscal/ItalianFiscalDataDisplay.tsx +24 -0
- package/src/components/fiscal/index.ts +4 -0
- package/src/components/index.ts +2 -0
- package/src/components/navigations/Breadcrumb.tsx +4 -4
- package/src/components/navigations/RecentPagesNavigator.tsx +3 -3
- package/src/features/company/components/details/CompanyContent.tsx +105 -0
- package/src/features/company/components/details/CompanyDetails.tsx +2 -19
- package/src/features/company/components/details/index.ts +1 -0
- package/src/features/company/components/forms/CompanyConfigurationEditor.tsx +38 -70
- package/src/features/company/components/forms/CompanyEditor.tsx +214 -172
- package/src/features/company/data/company.interface.ts +20 -0
- package/src/features/company/data/company.ts +73 -0
- package/src/utils/fiscal-utils.ts +7 -0
- package/src/utils/italian-validators.ts +79 -0
- package/dist/chunk-5ODPC3YX.js.map +0 -1
- package/dist/chunk-LRXJT656.js.map +0 -1
- package/dist/chunk-OLNMWVOV.mjs.map +0 -1
- /package/dist/{BlockNoteEditor-SCQGD6F2.mjs.map → BlockNoteEditor-KCJMA6LW.mjs.map} +0 -0
- /package/dist/{chunk-5KMKI23S.mjs.map → chunk-UXGPZZ6V.mjs.map} +0 -0
package/dist/{notification.interface-DG7cq9oG.d.mts → notification.interface-C6UcmJqu.d.mts}
RENAMED
|
@@ -109,6 +109,16 @@ type CompanyInput = {
|
|
|
109
109
|
availableExtraTokens?: number;
|
|
110
110
|
featureIds?: string[];
|
|
111
111
|
moduleIds?: string[];
|
|
112
|
+
legal_address?: string;
|
|
113
|
+
street_number?: string;
|
|
114
|
+
street?: string;
|
|
115
|
+
city?: string;
|
|
116
|
+
province?: string;
|
|
117
|
+
region?: string;
|
|
118
|
+
postcode?: string;
|
|
119
|
+
country?: string;
|
|
120
|
+
country_code?: string;
|
|
121
|
+
fiscal_data?: string;
|
|
112
122
|
};
|
|
113
123
|
interface CompanyInterface extends ApiDataInterface {
|
|
114
124
|
get name(): string;
|
|
@@ -121,6 +131,16 @@ interface CompanyInterface extends ApiDataInterface {
|
|
|
121
131
|
get availableExtraTokens(): number;
|
|
122
132
|
get features(): FeatureInterface[];
|
|
123
133
|
get modules(): ModuleInterface[];
|
|
134
|
+
get legal_address(): string | undefined;
|
|
135
|
+
get street_number(): string | undefined;
|
|
136
|
+
get street(): string | undefined;
|
|
137
|
+
get city(): string | undefined;
|
|
138
|
+
get province(): string | undefined;
|
|
139
|
+
get region(): string | undefined;
|
|
140
|
+
get postcode(): string | undefined;
|
|
141
|
+
get country(): string | undefined;
|
|
142
|
+
get country_code(): string | undefined;
|
|
143
|
+
get fiscal_data(): string | undefined;
|
|
124
144
|
}
|
|
125
145
|
|
|
126
146
|
type RoleInput = {
|
|
@@ -109,6 +109,16 @@ type CompanyInput = {
|
|
|
109
109
|
availableExtraTokens?: number;
|
|
110
110
|
featureIds?: string[];
|
|
111
111
|
moduleIds?: string[];
|
|
112
|
+
legal_address?: string;
|
|
113
|
+
street_number?: string;
|
|
114
|
+
street?: string;
|
|
115
|
+
city?: string;
|
|
116
|
+
province?: string;
|
|
117
|
+
region?: string;
|
|
118
|
+
postcode?: string;
|
|
119
|
+
country?: string;
|
|
120
|
+
country_code?: string;
|
|
121
|
+
fiscal_data?: string;
|
|
112
122
|
};
|
|
113
123
|
interface CompanyInterface extends ApiDataInterface {
|
|
114
124
|
get name(): string;
|
|
@@ -121,6 +131,16 @@ interface CompanyInterface extends ApiDataInterface {
|
|
|
121
131
|
get availableExtraTokens(): number;
|
|
122
132
|
get features(): FeatureInterface[];
|
|
123
133
|
get modules(): ModuleInterface[];
|
|
134
|
+
get legal_address(): string | undefined;
|
|
135
|
+
get street_number(): string | undefined;
|
|
136
|
+
get street(): string | undefined;
|
|
137
|
+
get city(): string | undefined;
|
|
138
|
+
get province(): string | undefined;
|
|
139
|
+
get region(): string | undefined;
|
|
140
|
+
get postcode(): string | undefined;
|
|
141
|
+
get country(): string | undefined;
|
|
142
|
+
get country_code(): string | undefined;
|
|
143
|
+
get fiscal_data(): string | undefined;
|
|
124
144
|
}
|
|
125
145
|
|
|
126
146
|
type RoleInput = {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { F as FeatureInterface } from './feature.interface-CIWxo8NP.js';
|
|
2
|
-
import { R as RoleInterface, U as UserInterface, k as UserInput, h as CompanyInterface, C as CompanyInput, N as NotificationInterface } from './notification.interface-
|
|
2
|
+
import { R as RoleInterface, U as UserInterface, k as UserInput, h as CompanyInterface, C as CompanyInput, N as NotificationInterface } from './notification.interface-ItBxq2au.js';
|
|
3
3
|
import { A as ApiDataInterface, J as JsonApiHydratedDataInterface } from './ApiDataInterface-DPP8s46n.js';
|
|
4
|
-
import { A as AuthInput, b as AuthInterface } from './auth.interface-
|
|
5
|
-
import { a as ContentInterface } from './content.interface-
|
|
4
|
+
import { A as AuthInput, b as AuthInterface } from './auth.interface-BX_1qZZJ.js';
|
|
5
|
+
import { a as ContentInterface } from './content.interface-D-xdYxjt.js';
|
|
6
6
|
import { A as ApiRequestDataTypeInterface } from './ApiRequestDataTypeInterface-CYEcRUrh.js';
|
|
7
7
|
|
|
8
8
|
declare enum HttpMethod {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { F as FeatureInterface } from './feature.interface-BxFFOPNq.mjs';
|
|
2
|
-
import { R as RoleInterface, U as UserInterface, k as UserInput, h as CompanyInterface, C as CompanyInput, N as NotificationInterface } from './notification.interface-
|
|
2
|
+
import { R as RoleInterface, U as UserInterface, k as UserInput, h as CompanyInterface, C as CompanyInput, N as NotificationInterface } from './notification.interface-C6UcmJqu.mjs';
|
|
3
3
|
import { A as ApiDataInterface, J as JsonApiHydratedDataInterface } from './ApiDataInterface-DPP8s46n.mjs';
|
|
4
|
-
import { A as AuthInput, b as AuthInterface } from './auth.interface-
|
|
5
|
-
import { a as ContentInterface } from './content.interface-
|
|
4
|
+
import { A as AuthInput, b as AuthInterface } from './auth.interface-yeLelxdI.mjs';
|
|
5
|
+
import { a as ContentInterface } from './content.interface-8T5-G84c.mjs';
|
|
6
6
|
import { A as ApiRequestDataTypeInterface } from './ApiRequestDataTypeInterface-CYEcRUrh.mjs';
|
|
7
7
|
|
|
8
8
|
declare enum HttpMethod {
|
package/dist/server/index.d.mts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { A as ApiData } from '../ApiData-DPKNfY-9.mjs';
|
|
2
|
-
import { M as ModuleWithPermissions, A as Action } from '../notification.interface-
|
|
2
|
+
import { M as ModuleWithPermissions, A as Action } from '../notification.interface-C6UcmJqu.mjs';
|
|
3
3
|
import { A as ApiRequestDataTypeInterface } from '../ApiRequestDataTypeInterface-CYEcRUrh.mjs';
|
|
4
4
|
import { A as ApiResponseInterface } from '../ApiResponseInterface-zeewugD7.mjs';
|
|
5
|
-
export { A as ServerAuthService, C as ServerCompanyService, a as ServerContentService, F as ServerFeatureService, N as ServerNotificationService, P as ServerPushService, R as ServerRoleService, S as ServerS3Service, U as ServerUserService } from '../s3.service-
|
|
5
|
+
export { A as ServerAuthService, C as ServerCompanyService, a as ServerContentService, F as ServerFeatureService, N as ServerNotificationService, P as ServerPushService, R as ServerRoleService, S as ServerS3Service, U as ServerUserService } from '../s3.service-XchHd3ii.mjs';
|
|
6
6
|
import 'lucide-react';
|
|
7
7
|
import '../ApiDataInterface-DPP8s46n.mjs';
|
|
8
8
|
import '../feature.interface-BxFFOPNq.mjs';
|
|
9
|
-
import '../auth.interface-
|
|
10
|
-
import '../content.interface-
|
|
9
|
+
import '../auth.interface-yeLelxdI.mjs';
|
|
10
|
+
import '../content.interface-8T5-G84c.mjs';
|
|
11
11
|
|
|
12
12
|
type CacheProfile = "seconds" | "minutes" | "hours" | "days" | "weeks" | "max" | "default";
|
|
13
13
|
/**
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { A as ApiData } from '../ApiData-DPKNfY-9.js';
|
|
2
|
-
import { M as ModuleWithPermissions, A as Action } from '../notification.interface-
|
|
2
|
+
import { M as ModuleWithPermissions, A as Action } from '../notification.interface-ItBxq2au.js';
|
|
3
3
|
import { A as ApiRequestDataTypeInterface } from '../ApiRequestDataTypeInterface-CYEcRUrh.js';
|
|
4
4
|
import { A as ApiResponseInterface } from '../ApiResponseInterface-CAIAeP5d.js';
|
|
5
|
-
export { A as ServerAuthService, C as ServerCompanyService, a as ServerContentService, F as ServerFeatureService, N as ServerNotificationService, P as ServerPushService, R as ServerRoleService, S as ServerS3Service, U as ServerUserService } from '../s3.service-
|
|
5
|
+
export { A as ServerAuthService, C as ServerCompanyService, a as ServerContentService, F as ServerFeatureService, N as ServerNotificationService, P as ServerPushService, R as ServerRoleService, S as ServerS3Service, U as ServerUserService } from '../s3.service-DIR6Su9B.js';
|
|
6
6
|
import 'lucide-react';
|
|
7
7
|
import '../ApiDataInterface-DPP8s46n.js';
|
|
8
8
|
import '../feature.interface-CIWxo8NP.js';
|
|
9
|
-
import '../auth.interface-
|
|
10
|
-
import '../content.interface-
|
|
9
|
+
import '../auth.interface-BX_1qZZJ.js';
|
|
10
|
+
import '../content.interface-D-xdYxjt.js';
|
|
11
11
|
|
|
12
12
|
type CacheProfile = "seconds" | "minutes" | "hours" | "days" | "weeks" | "max" | "default";
|
|
13
13
|
/**
|
package/dist/server/index.js
CHANGED
|
@@ -15,7 +15,7 @@ var _chunk3ZPK4QOBjs = require('../chunk-3ZPK4QOB.js');
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
var
|
|
18
|
+
var _chunkNVXYOQFWjs = require('../chunk-NVXYOQFW.js');
|
|
19
19
|
require('../chunk-LXKSUWAV.js');
|
|
20
20
|
require('../chunk-IBS6NI7D.js');
|
|
21
21
|
|
|
@@ -86,7 +86,7 @@ var ServerSession = class {
|
|
|
86
86
|
if (!rawModules) return false;
|
|
87
87
|
const modules = JSON.parse(_pako2.default.ungzip(Buffer.from(rawModules, "base64"), { to: "string" }));
|
|
88
88
|
const selectedModule = modules.find((module) => module.id === params.module.moduleId);
|
|
89
|
-
return
|
|
89
|
+
return _chunkNVXYOQFWjs.checkPermissionsFromServer.call(void 0, {
|
|
90
90
|
module: params.module,
|
|
91
91
|
action: params.action,
|
|
92
92
|
data: params.data,
|
|
@@ -296,5 +296,5 @@ _chunk7QVYU63Ejs.__name.call(void 0, ServerJsonApiDelete, "ServerJsonApiDelete")
|
|
|
296
296
|
|
|
297
297
|
|
|
298
298
|
|
|
299
|
-
exports.ServerAuthService =
|
|
299
|
+
exports.ServerAuthService = _chunkNVXYOQFWjs.AuthService; exports.ServerCompanyService = _chunkNVXYOQFWjs.CompanyService; exports.ServerContentService = _chunkNVXYOQFWjs.ContentService; exports.ServerFeatureService = _chunkNVXYOQFWjs.FeatureService; exports.ServerJsonApiDelete = ServerJsonApiDelete; exports.ServerJsonApiGet = ServerJsonApiGet; exports.ServerJsonApiPatch = ServerJsonApiPatch; exports.ServerJsonApiPost = ServerJsonApiPost; exports.ServerJsonApiPut = ServerJsonApiPut; exports.ServerNotificationService = _chunkNVXYOQFWjs.NotificationService; exports.ServerPushService = _chunkNVXYOQFWjs.PushService; exports.ServerRoleService = _chunkNVXYOQFWjs.RoleService; exports.ServerS3Service = _chunkNVXYOQFWjs.S3Service; exports.ServerSession = ServerSession; exports.ServerUserService = _chunkNVXYOQFWjs.UserService; exports.configureServerJsonApi = configureServerJsonApi; exports.getServerApiUrl = getServerApiUrl; exports.getServerAppUrl = getServerAppUrl; exports.getServerToken = _chunkYUO55Q5Ajs.getServerToken; exports.getServerTrackablePages = getServerTrackablePages; exports.invalidateCacheTag = invalidateCacheTag; exports.invalidateCacheTags = invalidateCacheTags; exports.serverRequest = _chunk3ZPK4QOBjs.serverRequest;
|
|
300
300
|
//# sourceMappingURL=index.js.map
|
package/dist/server/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { F as FeatureInterface } from './feature.interface-BxFFOPNq.mjs';
|
|
2
|
-
import { R as RoleInterface } from './notification.interface-
|
|
2
|
+
import { R as RoleInterface } from './notification.interface-C6UcmJqu.mjs';
|
|
3
3
|
import { P as PermissionMappingInterface, M as ModulePathsInterface, A as ActionType, a as PermissionValue, b as PermissionsMap } from './ModulePathsInterface-49EWvbWy.mjs';
|
|
4
4
|
|
|
5
5
|
type PageInfo = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { F as FeatureInterface } from './feature.interface-CIWxo8NP.js';
|
|
2
|
-
import { R as RoleInterface } from './notification.interface-
|
|
2
|
+
import { R as RoleInterface } from './notification.interface-ItBxq2au.js';
|
|
3
3
|
import { P as PermissionMappingInterface, M as ModulePathsInterface, A as ActionType, a as PermissionValue, b as PermissionsMap } from './ModulePathsInterface-wVS5Raa4.js';
|
|
4
4
|
|
|
5
5
|
type PageInfo = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@carlonicora/nextjs-jsonapi",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.66.0",
|
|
4
4
|
"description": "Next.js JSON:API client with server/client support and caching",
|
|
5
5
|
"author": "Carlo Nicora",
|
|
6
6
|
"license": "GPL-3.0-or-later",
|
|
@@ -116,6 +116,7 @@
|
|
|
116
116
|
"class-variance-authority": "^0.7.1",
|
|
117
117
|
"clsx": "^2.1.1",
|
|
118
118
|
"cmdk": "^1.1.1",
|
|
119
|
+
"codice-fiscale-js": "^2.3.23",
|
|
119
120
|
"commander": "^14.0.2",
|
|
120
121
|
"cookies-next": "^6.1.1",
|
|
121
122
|
"d3": "^7.9.0",
|
|
@@ -62,7 +62,7 @@ export function RoundPageContainer({
|
|
|
62
62
|
)}
|
|
63
63
|
<div className="flex h-full w-full overflow-hidden">
|
|
64
64
|
<div className={cn(`grow overflow-y-auto p-4`, fullWidth && `p-0`)}>
|
|
65
|
-
<div className={cn(`mx-auto max-w-6xl space-y-12 p-8`, fullWidth && `max-w-full w-full p-0`)}>
|
|
65
|
+
<div className={cn(`mx-auto max-w-6xl space-y-12 p-8`, fullWidth && `max-w-full w-full p-0 h-full`)}>
|
|
66
66
|
{tabs ? (
|
|
67
67
|
<Tabs
|
|
68
68
|
value={activeTab}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { parseFiscalData } from "../../utils/fiscal-utils";
|
|
4
|
+
import { ItalianFiscalDataDisplay } from "./ItalianFiscalDataDisplay";
|
|
5
|
+
|
|
6
|
+
type FiscalDataDisplayProps = {
|
|
7
|
+
fiscalData: string;
|
|
8
|
+
country?: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
function hasNonEmptyValues(data: Record<string, string>): boolean {
|
|
12
|
+
return Object.values(data).some((v) => v && v.trim() !== "");
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function FiscalDataDisplay({ fiscalData, country = "it" }: FiscalDataDisplayProps) {
|
|
16
|
+
const data = parseFiscalData(fiscalData);
|
|
17
|
+
|
|
18
|
+
if (!hasNonEmptyValues(data)) return null;
|
|
19
|
+
|
|
20
|
+
switch (country) {
|
|
21
|
+
case "it":
|
|
22
|
+
return <ItalianFiscalDataDisplay data={data} />;
|
|
23
|
+
default:
|
|
24
|
+
return <ItalianFiscalDataDisplay data={data} />;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { validateItalianTaxCode, validatePartitaIva } from "../../utils/italian-validators";
|
|
4
|
+
import { Field, FieldError, FieldLabel, Input } from "../../shadcnui";
|
|
5
|
+
import { useTranslations } from "next-intl";
|
|
6
|
+
import { forwardRef, useCallback, useImperativeHandle, useRef, useState } from "react";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
|
|
9
|
+
export interface FiscalDataHandle {
|
|
10
|
+
validate: () => boolean;
|
|
11
|
+
getData: () => Record<string, string>;
|
|
12
|
+
isDirty: () => boolean;
|
|
13
|
+
reset: (initialData: Record<string, string>) => void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ItalianFiscalDataProps {
|
|
17
|
+
initialData: Record<string, string>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const ItalianFiscalData = forwardRef<FiscalDataHandle, ItalianFiscalDataProps>(function ItalianFiscalData(
|
|
21
|
+
{ initialData },
|
|
22
|
+
ref,
|
|
23
|
+
) {
|
|
24
|
+
const t = useTranslations();
|
|
25
|
+
const initialRef = useRef<Record<string, string>>(initialData);
|
|
26
|
+
const [fiscalData, setFiscalData] = useState<Record<string, string>>(initialData);
|
|
27
|
+
const fiscalDataRef = useRef<Record<string, string>>(initialData);
|
|
28
|
+
const [fiscalErrors, setFiscalErrors] = useState<Record<string, string>>({});
|
|
29
|
+
|
|
30
|
+
const updateFiscalField = useCallback((key: string, value: string) => {
|
|
31
|
+
setFiscalData((prev) => {
|
|
32
|
+
const next = { ...prev, [key]: value };
|
|
33
|
+
fiscalDataRef.current = next;
|
|
34
|
+
return next;
|
|
35
|
+
});
|
|
36
|
+
setFiscalErrors((prev) => {
|
|
37
|
+
const next = { ...prev };
|
|
38
|
+
delete next[key];
|
|
39
|
+
return next;
|
|
40
|
+
});
|
|
41
|
+
}, []);
|
|
42
|
+
|
|
43
|
+
useImperativeHandle(ref, () => ({
|
|
44
|
+
validate: (): boolean => {
|
|
45
|
+
const data = fiscalDataRef.current;
|
|
46
|
+
const errors: Record<string, string> = {};
|
|
47
|
+
|
|
48
|
+
if (data.codice_fiscale && !validateItalianTaxCode(data.codice_fiscale, "codiceFiscale")) {
|
|
49
|
+
errors.codice_fiscale = t("common.fields.codice_fiscale.error");
|
|
50
|
+
}
|
|
51
|
+
if (data.partita_iva && !validatePartitaIva(data.partita_iva)) {
|
|
52
|
+
errors.partita_iva = t("common.fields.partita_iva.error");
|
|
53
|
+
}
|
|
54
|
+
if (data.pec && !z.string().email().safeParse(data.pec).success) {
|
|
55
|
+
errors.pec = t("common.fields.pec.error");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
setFiscalErrors(errors);
|
|
59
|
+
return Object.keys(errors).length === 0;
|
|
60
|
+
},
|
|
61
|
+
getData: (): Record<string, string> => fiscalDataRef.current,
|
|
62
|
+
isDirty: (): boolean => JSON.stringify(fiscalDataRef.current) !== JSON.stringify(initialRef.current),
|
|
63
|
+
reset: (newInitialData: Record<string, string>) => {
|
|
64
|
+
initialRef.current = newInitialData;
|
|
65
|
+
fiscalDataRef.current = newInitialData;
|
|
66
|
+
setFiscalData(newInitialData);
|
|
67
|
+
setFiscalErrors({});
|
|
68
|
+
},
|
|
69
|
+
}));
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<div className="grid grid-cols-1 gap-4 md:grid-cols-3">
|
|
73
|
+
<Field data-invalid={!!fiscalErrors.codice_fiscale}>
|
|
74
|
+
<FieldLabel>{t("common.fields.codice_fiscale.label")}</FieldLabel>
|
|
75
|
+
<Input
|
|
76
|
+
value={fiscalData.codice_fiscale || ""}
|
|
77
|
+
onChange={(e) => updateFiscalField("codice_fiscale", e.target.value)}
|
|
78
|
+
placeholder={t("common.fields.codice_fiscale.placeholder")}
|
|
79
|
+
/>
|
|
80
|
+
{fiscalErrors.codice_fiscale && <FieldError>{fiscalErrors.codice_fiscale}</FieldError>}
|
|
81
|
+
</Field>
|
|
82
|
+
<Field data-invalid={!!fiscalErrors.partita_iva}>
|
|
83
|
+
<FieldLabel>{t("common.fields.partita_iva.label")}</FieldLabel>
|
|
84
|
+
<Input
|
|
85
|
+
value={fiscalData.partita_iva || ""}
|
|
86
|
+
onChange={(e) => updateFiscalField("partita_iva", e.target.value)}
|
|
87
|
+
placeholder={t("common.fields.partita_iva.placeholder")}
|
|
88
|
+
/>
|
|
89
|
+
{fiscalErrors.partita_iva && <FieldError>{fiscalErrors.partita_iva}</FieldError>}
|
|
90
|
+
</Field>
|
|
91
|
+
<Field>
|
|
92
|
+
<FieldLabel>{t("common.fields.sdi.label")}</FieldLabel>
|
|
93
|
+
<Input
|
|
94
|
+
value={fiscalData.sdi || ""}
|
|
95
|
+
onChange={(e) => updateFiscalField("sdi", e.target.value)}
|
|
96
|
+
placeholder={t("common.fields.sdi.placeholder")}
|
|
97
|
+
/>
|
|
98
|
+
</Field>
|
|
99
|
+
<Field>
|
|
100
|
+
<FieldLabel>{t("common.fields.rea.label")}</FieldLabel>
|
|
101
|
+
<Input
|
|
102
|
+
value={fiscalData.rea || ""}
|
|
103
|
+
onChange={(e) => updateFiscalField("rea", e.target.value)}
|
|
104
|
+
placeholder={t("common.fields.rea.placeholder")}
|
|
105
|
+
/>
|
|
106
|
+
</Field>
|
|
107
|
+
<Field data-invalid={!!fiscalErrors.pec}>
|
|
108
|
+
<FieldLabel>{t("common.fields.pec.label")}</FieldLabel>
|
|
109
|
+
<Input
|
|
110
|
+
value={fiscalData.pec || ""}
|
|
111
|
+
onChange={(e) => updateFiscalField("pec", e.target.value)}
|
|
112
|
+
placeholder={t("common.fields.pec.placeholder")}
|
|
113
|
+
/>
|
|
114
|
+
{fiscalErrors.pec && <FieldError>{fiscalErrors.pec}</FieldError>}
|
|
115
|
+
</Field>
|
|
116
|
+
</div>
|
|
117
|
+
);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
export default ItalianFiscalData;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { AttributeElement } from "../contents";
|
|
4
|
+
import { useTranslations } from "next-intl";
|
|
5
|
+
|
|
6
|
+
type ItalianFiscalDataDisplayProps = {
|
|
7
|
+
data: Record<string, string>;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export function ItalianFiscalDataDisplay({ data }: ItalianFiscalDataDisplayProps) {
|
|
11
|
+
const t = useTranslations();
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<div className="grid grid-cols-1 gap-4 md:grid-cols-3">
|
|
15
|
+
{data.codice_fiscale && (
|
|
16
|
+
<AttributeElement title={t("common.fields.codice_fiscale.label")} value={data.codice_fiscale} />
|
|
17
|
+
)}
|
|
18
|
+
{data.partita_iva && <AttributeElement title={t("common.fields.partita_iva.label")} value={data.partita_iva} />}
|
|
19
|
+
{data.sdi && <AttributeElement title={t("common.fields.sdi.label")} value={data.sdi} />}
|
|
20
|
+
{data.rea && <AttributeElement title={t("common.fields.rea.label")} value={data.rea} />}
|
|
21
|
+
{data.pec && <AttributeElement title={t("common.fields.pec.label")} value={data.pec} />}
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { default as ItalianFiscalData } from "./ItalianFiscalData";
|
|
2
|
+
export type { FiscalDataHandle, ItalianFiscalDataProps } from "./ItalianFiscalData";
|
|
3
|
+
export { ItalianFiscalDataDisplay } from "./ItalianFiscalDataDisplay";
|
|
4
|
+
export { FiscalDataDisplay } from "./FiscalDataDisplay";
|
package/src/components/index.ts
CHANGED
|
@@ -10,6 +10,8 @@ export * from "./forms";
|
|
|
10
10
|
export * from "./navigations";
|
|
11
11
|
export * from "./pages";
|
|
12
12
|
export * from "./tables";
|
|
13
|
+
export * from "./fiscal";
|
|
14
|
+
export { parseFiscalData } from "../utils/fiscal-utils";
|
|
13
15
|
|
|
14
16
|
// Feature components
|
|
15
17
|
export * from "../features/auth/components";
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
|
|
20
20
|
type BreadcrumbProps = { items: BreadcrumbItemData[] };
|
|
21
21
|
|
|
22
|
-
const ITEMS_TO_DISPLAY =
|
|
22
|
+
const ITEMS_TO_DISPLAY = 4;
|
|
23
23
|
|
|
24
24
|
export function BreadcrumbNavigation({ items }: BreadcrumbProps) {
|
|
25
25
|
const generateUrl = usePageUrlGenerator();
|
|
@@ -47,7 +47,7 @@ export function BreadcrumbNavigation({ items }: BreadcrumbProps) {
|
|
|
47
47
|
<BreadcrumbEllipsis className="h-4 w-4" />
|
|
48
48
|
</DropdownMenuTrigger>
|
|
49
49
|
<DropdownMenuContent align="start">
|
|
50
|
-
{items.slice(1, -ITEMS_TO_DISPLAY +
|
|
50
|
+
{items.slice(1, -ITEMS_TO_DISPLAY + 2).map((item, index) => (
|
|
51
51
|
<DropdownMenuItem key={index}>
|
|
52
52
|
<Link href={item.href ? item.href : "#"}>{item.name}</Link>
|
|
53
53
|
</DropdownMenuItem>
|
|
@@ -56,12 +56,12 @@ export function BreadcrumbNavigation({ items }: BreadcrumbProps) {
|
|
|
56
56
|
</DropdownMenu>
|
|
57
57
|
</BreadcrumbItem>
|
|
58
58
|
<BreadcrumbSeparator />
|
|
59
|
-
{items.slice(-ITEMS_TO_DISPLAY +
|
|
59
|
+
{items.slice(-ITEMS_TO_DISPLAY + 2).map((item, index) => (
|
|
60
60
|
<Fragment key={index}>
|
|
61
61
|
<BreadcrumbItem>
|
|
62
62
|
{item.href ? <Link href={item.href}>{item.name}</Link> : <>{item.name}</>}
|
|
63
63
|
</BreadcrumbItem>
|
|
64
|
-
{index < items.slice(-ITEMS_TO_DISPLAY +
|
|
64
|
+
{index < items.slice(-ITEMS_TO_DISPLAY + 2).length - 1 && <BreadcrumbSeparator />}
|
|
65
65
|
</Fragment>
|
|
66
66
|
))}
|
|
67
67
|
</>
|
|
@@ -26,10 +26,10 @@ export function RecentPagesNavigator() {
|
|
|
26
26
|
|
|
27
27
|
return (
|
|
28
28
|
<DropdownMenu>
|
|
29
|
-
<DropdownMenuTrigger>
|
|
30
|
-
<
|
|
29
|
+
<DropdownMenuTrigger render={<span />} nativeButton={false}>
|
|
30
|
+
<span className="flex w-full cursor-pointer items-center gap-2">
|
|
31
31
|
{state === "collapsed" ? <HistoryIcon className="h-4 w-4" /> : <span>{t(`common.recent_pages`)}</span>}
|
|
32
|
-
</
|
|
32
|
+
</span>
|
|
33
33
|
</DropdownMenuTrigger>
|
|
34
34
|
<DropdownMenuContent align="start" className="w-96">
|
|
35
35
|
<DropdownMenuLabel>{t(`common.recent_pages`)}</DropdownMenuLabel>
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { MapPinIcon } from "lucide-react";
|
|
4
|
+
import { useTranslations } from "next-intl";
|
|
5
|
+
import Image from "next/image";
|
|
6
|
+
import { ReactNode } from "react";
|
|
7
|
+
import { AttributeElement } from "../../../../components";
|
|
8
|
+
import { FiscalDataDisplay } from "../../../../components/fiscal/FiscalDataDisplay";
|
|
9
|
+
import { CompanyInterface } from "../../data";
|
|
10
|
+
|
|
11
|
+
type CompanyContentProps = {
|
|
12
|
+
company?: CompanyInterface;
|
|
13
|
+
actions?: ReactNode;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
function hasAddressDetails(company: CompanyInterface): boolean {
|
|
17
|
+
return !!(
|
|
18
|
+
company.street ||
|
|
19
|
+
company.street_number ||
|
|
20
|
+
company.city ||
|
|
21
|
+
company.province ||
|
|
22
|
+
company.region ||
|
|
23
|
+
company.postcode ||
|
|
24
|
+
company.country
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function CompanyContent({ company, actions }: CompanyContentProps) {
|
|
29
|
+
const t = useTranslations();
|
|
30
|
+
|
|
31
|
+
if (!company) return null;
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<div className="flex flex-col gap-y-8">
|
|
35
|
+
{/* Title Row */}
|
|
36
|
+
<div className="flex w-full items-center justify-between">
|
|
37
|
+
<h2 className="text-lg font-semibold">{company.name}</h2>
|
|
38
|
+
{actions && <div className="flex items-center gap-x-2">{actions}</div>}
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
{/* Hero Section */}
|
|
42
|
+
<div className="flex items-start gap-x-6">
|
|
43
|
+
{company.logo && (
|
|
44
|
+
<Image src={company.logo} alt={company.name} width={150} height={150} className="rounded-md" />
|
|
45
|
+
)}
|
|
46
|
+
<div className="flex flex-col gap-y-2">
|
|
47
|
+
{company.legal_address && (
|
|
48
|
+
<div className="text-muted-foreground flex items-center gap-x-2 text-sm">
|
|
49
|
+
<MapPinIcon className="h-4 w-4 shrink-0" />
|
|
50
|
+
{company.legal_address}
|
|
51
|
+
</div>
|
|
52
|
+
)}
|
|
53
|
+
<div className="flex flex-col gap-y-1">
|
|
54
|
+
{company.configurations?.country && (
|
|
55
|
+
<div className="text-muted-foreground text-sm">
|
|
56
|
+
<span className="font-medium">{t("features.configuration.country")}:</span>{" "}
|
|
57
|
+
{company.configurations.country}
|
|
58
|
+
</div>
|
|
59
|
+
)}
|
|
60
|
+
{company.configurations?.currency && (
|
|
61
|
+
<div className="text-muted-foreground text-sm">
|
|
62
|
+
<span className="font-medium">{t("features.configuration.currency")}:</span>{" "}
|
|
63
|
+
{company.configurations.currency}
|
|
64
|
+
</div>
|
|
65
|
+
)}
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
{/* Fiscal Data Section */}
|
|
71
|
+
{company.fiscal_data && (
|
|
72
|
+
<div className="flex flex-col gap-y-3">
|
|
73
|
+
<h3 className="text-muted-foreground text-xs font-semibold tracking-wider uppercase">
|
|
74
|
+
{t("company.sections.fiscal_data")}
|
|
75
|
+
</h3>
|
|
76
|
+
<FiscalDataDisplay fiscalData={company.fiscal_data} />
|
|
77
|
+
</div>
|
|
78
|
+
)}
|
|
79
|
+
|
|
80
|
+
{/* Address Details Section */}
|
|
81
|
+
{hasAddressDetails(company) && (
|
|
82
|
+
<div className="flex flex-col gap-y-3">
|
|
83
|
+
<h3 className="text-muted-foreground text-xs font-semibold tracking-wider uppercase">
|
|
84
|
+
{t("company.sections.address_details")}
|
|
85
|
+
</h3>
|
|
86
|
+
<div className="grid grid-cols-1 gap-4 md:grid-cols-3">
|
|
87
|
+
{company.street && <AttributeElement title={t("company.fields.street.label")} value={company.street} />}
|
|
88
|
+
{company.street_number && (
|
|
89
|
+
<AttributeElement title={t("company.fields.street_number.label")} value={company.street_number} />
|
|
90
|
+
)}
|
|
91
|
+
{company.city && <AttributeElement title={t("company.fields.city.label")} value={company.city} />}
|
|
92
|
+
{company.province && (
|
|
93
|
+
<AttributeElement title={t("company.fields.province.label")} value={company.province} />
|
|
94
|
+
)}
|
|
95
|
+
{company.region && <AttributeElement title={t("company.fields.region.label")} value={company.region} />}
|
|
96
|
+
{company.postcode && (
|
|
97
|
+
<AttributeElement title={t("company.fields.postcode.label")} value={company.postcode} />
|
|
98
|
+
)}
|
|
99
|
+
{company.country && <AttributeElement title={t("company.fields.country.label")} value={company.country} />}
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
)}
|
|
103
|
+
</div>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { useTranslations } from "next-intl";
|
|
4
|
-
import Image from "next/image";
|
|
5
3
|
import { Modules } from "../../../../";
|
|
6
4
|
import { ContentTitle } from "../../../../components";
|
|
7
5
|
import { useSharedContext } from "../../../../contexts";
|
|
8
6
|
import { usePageUrlGenerator } from "../../../../hooks";
|
|
9
7
|
import { useCompanyContext } from "../../contexts/CompanyContext";
|
|
8
|
+
import { CompanyContent } from "./CompanyContent";
|
|
10
9
|
import { TokenStatusIndicator } from "./TokenStatusIndicator";
|
|
11
10
|
|
|
12
11
|
export function CompanyDetails() {
|
|
13
|
-
const t = useTranslations();
|
|
14
12
|
const { title } = useSharedContext();
|
|
15
13
|
const _generateUrl = usePageUrlGenerator();
|
|
16
14
|
|
|
@@ -20,23 +18,8 @@ export function CompanyDetails() {
|
|
|
20
18
|
return (
|
|
21
19
|
<div className="flex w-full flex-col gap-y-2">
|
|
22
20
|
<ContentTitle module={Modules.Company} type={title.type} element={title.element} functions={title.functions} />
|
|
23
|
-
{company.logo && (
|
|
24
|
-
<Image src={company.logo} alt={company.name} width={150} height={150} className="mb-4 rounded-md" />
|
|
25
|
-
)}
|
|
26
21
|
<TokenStatusIndicator size="md" />
|
|
27
|
-
<
|
|
28
|
-
{company.configurations?.country && (
|
|
29
|
-
<div className="text-muted-foreground text-sm">
|
|
30
|
-
<span className="font-medium">{t("features.configuration.country")}:</span> {company.configurations.country}
|
|
31
|
-
</div>
|
|
32
|
-
)}
|
|
33
|
-
{company.configurations?.currency && (
|
|
34
|
-
<div className="text-muted-foreground text-sm">
|
|
35
|
-
<span className="font-medium">{t("features.configuration.currency")}:</span>{" "}
|
|
36
|
-
{company.configurations.currency}
|
|
37
|
-
</div>
|
|
38
|
-
)}
|
|
39
|
-
</div>
|
|
22
|
+
<CompanyContent company={company} />
|
|
40
23
|
</div>
|
|
41
24
|
);
|
|
42
25
|
}
|