@carlonicora/nextjs-jsonapi 1.65.1 → 1.67.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-QGNV6E4X.js → BlockNoteEditor-QHWPE3BJ.js} +14 -14
- package/dist/{BlockNoteEditor-QGNV6E4X.js.map → BlockNoteEditor-QHWPE3BJ.js.map} +1 -1
- package/dist/{BlockNoteEditor-CZOW7J5K.mjs → BlockNoteEditor-TIX3GDVZ.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-CDCGQFIA.js → chunk-3BWYWS3A.js} +2118 -1659
- package/dist/chunk-3BWYWS3A.js.map +1 -0
- package/dist/{chunk-LRXJT656.js → chunk-CJY63D6U.js} +72 -5
- package/dist/chunk-CJY63D6U.js.map +1 -0
- package/dist/{chunk-RA4RYKYB.js → chunk-KFIQTY4O.js} +11 -11
- package/dist/{chunk-RA4RYKYB.js.map → chunk-KFIQTY4O.js.map} +1 -1
- package/dist/{chunk-G7PGWMFO.mjs → chunk-RIG2BEXJ.mjs} +72 -5
- package/dist/{chunk-G7PGWMFO.mjs.map → chunk-RIG2BEXJ.mjs.map} +1 -1
- package/dist/{chunk-ESGUCYJS.mjs → chunk-WWP32QYC.mjs} +3534 -3075
- package/dist/chunk-WWP32QYC.mjs.map +1 -0
- package/dist/{chunk-5KMKI23S.mjs → chunk-ZYAAJMZZ.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 +69 -12
- package/dist/components/index.d.ts +69 -12
- package/dist/components/index.js +18 -4
- package/dist/components/index.js.map +1 -1
- package/dist/components/index.mjs +19 -5
- 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 +3 -3
- package/dist/contexts/index.d.ts +3 -3
- 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-Cg5TmbU_.d.ts} +6 -3
- package/dist/{s3.service-BoRPFx82.d.mts → s3.service-DLf_a0xS.d.mts} +6 -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/EditableAvatar.tsx +175 -0
- 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 +3 -0
- 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 +212 -172
- package/src/features/company/data/company.interface.ts +20 -0
- package/src/features/company/data/company.ts +73 -0
- package/src/features/role/components/forms/FormRoles.tsx +5 -4
- package/src/features/user/components/containers/AllUsersListContainer.tsx +36 -0
- package/src/features/user/components/containers/UserContainer.tsx +10 -13
- package/src/features/user/components/containers/UsersListContainer.tsx +15 -24
- package/src/features/user/components/containers/index.ts +1 -0
- package/src/features/user/components/details/UserContent.tsx +92 -0
- package/src/features/user/components/details/index.ts +1 -1
- package/src/features/user/components/forms/UserEditor.tsx +233 -233
- package/src/features/user/components/lists/CompanyUsersList.tsx +3 -1
- package/src/features/user/contexts/UserContext.tsx +1 -6
- package/src/features/user/data/user.service.ts +9 -0
- package/src/features/user/data/user.ts +3 -4
- package/src/utils/fiscal-utils.ts +7 -0
- package/src/utils/italian-validators.ts +79 -0
- package/dist/chunk-CDCGQFIA.js.map +0 -1
- package/dist/chunk-ESGUCYJS.mjs.map +0 -1
- package/dist/chunk-LRXJT656.js.map +0 -1
- package/src/features/user/components/details/UserDetails.tsx +0 -74
- /package/dist/{BlockNoteEditor-CZOW7J5K.mjs.map → BlockNoteEditor-TIX3GDVZ.mjs.map} +0 -0
- /package/dist/{chunk-5KMKI23S.mjs.map → chunk-ZYAAJMZZ.mjs.map} +0 -0
|
@@ -18,6 +18,17 @@ export class Company extends AbstractApiData implements CompanyInterface {
|
|
|
18
18
|
private _features?: FeatureInterface[];
|
|
19
19
|
private _modules?: ModuleInterface[];
|
|
20
20
|
|
|
21
|
+
private _legal_address?: string;
|
|
22
|
+
private _street_number?: string;
|
|
23
|
+
private _street?: string;
|
|
24
|
+
private _city?: string;
|
|
25
|
+
private _province?: string;
|
|
26
|
+
private _region?: string;
|
|
27
|
+
private _postcode?: string;
|
|
28
|
+
private _country?: string;
|
|
29
|
+
private _country_code?: string;
|
|
30
|
+
private _fiscal_data?: string;
|
|
31
|
+
|
|
21
32
|
get name(): string {
|
|
22
33
|
if (this._name === undefined) throw new Error("Name is not defined");
|
|
23
34
|
return this._name;
|
|
@@ -59,6 +70,46 @@ export class Company extends AbstractApiData implements CompanyInterface {
|
|
|
59
70
|
return this._configurations;
|
|
60
71
|
}
|
|
61
72
|
|
|
73
|
+
get legal_address(): string | undefined {
|
|
74
|
+
return this._legal_address;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
get street_number(): string | undefined {
|
|
78
|
+
return this._street_number;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
get street(): string | undefined {
|
|
82
|
+
return this._street;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
get city(): string | undefined {
|
|
86
|
+
return this._city;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
get province(): string | undefined {
|
|
90
|
+
return this._province;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
get region(): string | undefined {
|
|
94
|
+
return this._region;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
get postcode(): string | undefined {
|
|
98
|
+
return this._postcode;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
get country(): string | undefined {
|
|
102
|
+
return this._country;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
get country_code(): string | undefined {
|
|
106
|
+
return this._country_code;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
get fiscal_data(): string | undefined {
|
|
110
|
+
return this._fiscal_data;
|
|
111
|
+
}
|
|
112
|
+
|
|
62
113
|
rehydrate(data: JsonApiHydratedDataInterface): this {
|
|
63
114
|
super.rehydrate(data);
|
|
64
115
|
|
|
@@ -73,6 +124,17 @@ export class Company extends AbstractApiData implements CompanyInterface {
|
|
|
73
124
|
this._availableMonthlyTokens = data.jsonApi.attributes.availableMonthlyTokens ?? 0;
|
|
74
125
|
this._availableExtraTokens = data.jsonApi.attributes.availableExtraTokens ?? 0;
|
|
75
126
|
|
|
127
|
+
this._legal_address = data.jsonApi.attributes.legal_address;
|
|
128
|
+
this._street_number = data.jsonApi.attributes.street_number;
|
|
129
|
+
this._street = data.jsonApi.attributes.street;
|
|
130
|
+
this._city = data.jsonApi.attributes.city;
|
|
131
|
+
this._province = data.jsonApi.attributes.province;
|
|
132
|
+
this._region = data.jsonApi.attributes.region;
|
|
133
|
+
this._postcode = data.jsonApi.attributes.postcode;
|
|
134
|
+
this._country = data.jsonApi.attributes.country;
|
|
135
|
+
this._country_code = data.jsonApi.attributes.country_code;
|
|
136
|
+
this._fiscal_data = data.jsonApi.attributes.fiscal_data;
|
|
137
|
+
|
|
76
138
|
this._features = this._readIncluded<FeatureInterface>(data, "features", Modules.Feature) as FeatureInterface[];
|
|
77
139
|
this._modules = this._readIncluded<ModuleInterface>(data, "modules", Modules.Module) as ModuleInterface[];
|
|
78
140
|
|
|
@@ -100,6 +162,17 @@ export class Company extends AbstractApiData implements CompanyInterface {
|
|
|
100
162
|
if (data.availableExtraTokens !== undefined)
|
|
101
163
|
response.data.attributes.availableExtraTokens = data.availableExtraTokens;
|
|
102
164
|
|
|
165
|
+
if (data.legal_address !== undefined) response.data.attributes.legal_address = data.legal_address;
|
|
166
|
+
if (data.street_number !== undefined) response.data.attributes.street_number = data.street_number;
|
|
167
|
+
if (data.street !== undefined) response.data.attributes.street = data.street;
|
|
168
|
+
if (data.city !== undefined) response.data.attributes.city = data.city;
|
|
169
|
+
if (data.province !== undefined) response.data.attributes.province = data.province;
|
|
170
|
+
if (data.region !== undefined) response.data.attributes.region = data.region;
|
|
171
|
+
if (data.postcode !== undefined) response.data.attributes.postcode = data.postcode;
|
|
172
|
+
if (data.country !== undefined) response.data.attributes.country = data.country;
|
|
173
|
+
if (data.country_code !== undefined) response.data.attributes.country_code = data.country_code;
|
|
174
|
+
if (data.fiscal_data !== undefined) response.data.attributes.fiscal_data = data.fiscal_data;
|
|
175
|
+
|
|
103
176
|
if (data.featureIds && data.featureIds.length > 0) {
|
|
104
177
|
response.data.relationships.features = {
|
|
105
178
|
data: data.featureIds.map((featureId) => ({
|
|
@@ -22,7 +22,7 @@ export function FormRoles({ form, id, name, roles }: FormRolesProps) {
|
|
|
22
22
|
<div className="flex w-full flex-col">
|
|
23
23
|
<FormFieldWrapper form={form} name={id} label={name}>
|
|
24
24
|
{(field) => (
|
|
25
|
-
<div>
|
|
25
|
+
<div className="flex w-full flex-col gap-y-1">
|
|
26
26
|
{roles
|
|
27
27
|
.filter((role: RoleInterface) => role.isSelectable)
|
|
28
28
|
.sort((a: RoleInterface, b: RoleInterface) => a.name.localeCompare(b.name))
|
|
@@ -30,9 +30,10 @@ export function FormRoles({ form, id, name, roles }: FormRolesProps) {
|
|
|
30
30
|
if (role.requiredFeature && !hasAccesToFeature(role.requiredFeature.id)) return null;
|
|
31
31
|
|
|
32
32
|
return (
|
|
33
|
-
<div key={role.id}>
|
|
33
|
+
<div key={role.id} className="flex w-full items-center">
|
|
34
34
|
<Checkbox
|
|
35
|
-
|
|
35
|
+
id={`role-${role.id}`}
|
|
36
|
+
checked={(field.value as string[]).some((roleId: string) => roleId === role.id)}
|
|
36
37
|
onCheckedChange={(checked) => {
|
|
37
38
|
if (checked) {
|
|
38
39
|
form.setValue(id, [...(field.value as string[]), role.id]);
|
|
@@ -46,7 +47,7 @@ export function FormRoles({ form, id, name, roles }: FormRolesProps) {
|
|
|
46
47
|
/>
|
|
47
48
|
<Tooltip>
|
|
48
49
|
<TooltipTrigger>
|
|
49
|
-
<FieldLabel className="ml-3 font-normal">
|
|
50
|
+
<FieldLabel htmlFor={`role-${role.id}`} className="ml-3 cursor-pointer font-normal">
|
|
50
51
|
{t(`role.roles`, { role: role.id.replaceAll(`-`, ``) })}
|
|
51
52
|
</FieldLabel>
|
|
52
53
|
</TooltipTrigger>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useTranslations } from "next-intl";
|
|
4
|
+
import { CompanyUsersList, Tab, TabsContainer } from "../../../../components";
|
|
5
|
+
import { Modules } from "../../../../core";
|
|
6
|
+
import { Action } from "../../../../permissions";
|
|
7
|
+
import { useCurrentUserContext } from "../../contexts";
|
|
8
|
+
import { UserInterface } from "../../data";
|
|
9
|
+
|
|
10
|
+
function AllUsersListContainerInternal() {
|
|
11
|
+
const { hasPermissionToModule } = useCurrentUserContext<UserInterface>();
|
|
12
|
+
const t = useTranslations();
|
|
13
|
+
|
|
14
|
+
if (!hasPermissionToModule({ module: Modules.User, action: Action.Delete })) return <CompanyUsersList />;
|
|
15
|
+
|
|
16
|
+
const tabs: Tab[] = [
|
|
17
|
+
{
|
|
18
|
+
label: t(`entities.users`, { count: 2 }),
|
|
19
|
+
content: <CompanyUsersList />,
|
|
20
|
+
modules: [Modules.Company],
|
|
21
|
+
action: Action.Read,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
label: t(`user.deleted`),
|
|
25
|
+
content: <CompanyUsersList isDeleted={true} />,
|
|
26
|
+
modules: [Modules.Company],
|
|
27
|
+
action: Action.Update,
|
|
28
|
+
},
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
return <TabsContainer tabs={tabs} />;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function AllUsersListContainer() {
|
|
35
|
+
return <AllUsersListContainerInternal />;
|
|
36
|
+
}
|
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { RoundPageContainer, Tab } from "@/components";
|
|
4
|
+
import { Modules } from "@/core";
|
|
4
5
|
import { useUserContext } from "../../contexts";
|
|
5
|
-
import {
|
|
6
|
+
import { UserContent } from "../details";
|
|
6
7
|
|
|
7
8
|
export function UserContainer() {
|
|
8
9
|
const { user } = useUserContext();
|
|
9
10
|
if (!user) return null;
|
|
10
11
|
|
|
11
|
-
const
|
|
12
|
+
const tabs: Tab[] = [
|
|
13
|
+
{
|
|
14
|
+
label: "Details",
|
|
15
|
+
content: <UserContent user={user} />,
|
|
16
|
+
},
|
|
17
|
+
];
|
|
12
18
|
|
|
13
|
-
return
|
|
14
|
-
<div className="flex w-full gap-x-4">
|
|
15
|
-
<div className="w-2xl flex h-[calc(100vh-theme(spacing.20))] flex-col justify-between border-r pr-4">
|
|
16
|
-
<div className="flex h-full overflow-y-auto">
|
|
17
|
-
<UserDetails user={user} />
|
|
18
|
-
</div>
|
|
19
|
-
</div>
|
|
20
|
-
<div className="flex w-full flex-col gap-y-4"></div>
|
|
21
|
-
</div>
|
|
22
|
-
);
|
|
19
|
+
return <RoundPageContainer module={Modules.User} tabs={tabs} />;
|
|
23
20
|
}
|
|
@@ -1,36 +1,27 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { CompanyUsersList, Tab, TabsContainer } from "../../../../components";
|
|
3
|
+
import { CompanyUsersList, RoundPageContainer } from "../../../../components";
|
|
5
4
|
import { Modules } from "../../../../core";
|
|
6
5
|
import { Action } from "../../../../permissions";
|
|
7
6
|
import { useCurrentUserContext } from "../../contexts";
|
|
8
7
|
import { UserInterface } from "../../data";
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
type UsersListContainerProps = {
|
|
10
|
+
fullWidth?: boolean;
|
|
11
|
+
};
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
function UsersListContainerInternal({ fullWidth }: UsersListContainerProps) {
|
|
14
|
+
return (
|
|
15
|
+
<RoundPageContainer module={Modules.User} fullWidth={fullWidth}>
|
|
16
|
+
<CompanyUsersList fullWidth={fullWidth} />
|
|
17
|
+
</RoundPageContainer>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
15
20
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
label: t(`entities.users`, { count: 2 }),
|
|
19
|
-
content: <CompanyUsersList />,
|
|
20
|
-
modules: [Modules.Company],
|
|
21
|
-
action: Action.Read,
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
label: t(`user.deleted`),
|
|
25
|
-
content: <CompanyUsersList isDeleted={true} />,
|
|
26
|
-
modules: [Modules.Company],
|
|
27
|
-
action: Action.Update,
|
|
28
|
-
},
|
|
29
|
-
];
|
|
21
|
+
export function UsersListContainer({ fullWidth }: UsersListContainerProps) {
|
|
22
|
+
const { hasPermissionToModule } = useCurrentUserContext<UserInterface>();
|
|
30
23
|
|
|
31
|
-
|
|
32
|
-
}
|
|
24
|
+
if (!hasPermissionToModule({ module: Modules.User, action: Action.Read })) return null;
|
|
33
25
|
|
|
34
|
-
|
|
35
|
-
return <UsersListContainerInternal />;
|
|
26
|
+
return <UsersListContainerInternal fullWidth={fullWidth} />;
|
|
36
27
|
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useTranslations } from "next-intl";
|
|
4
|
+
import { AttributeElement } from "../../../../components/contents";
|
|
5
|
+
import { EditableAvatar } from "../../../../components/EditableAvatar";
|
|
6
|
+
import { getInitials } from "../../../../utils/getInitials";
|
|
7
|
+
import { Modules } from "../../../../core";
|
|
8
|
+
import { usePageUrlGenerator } from "../../../../hooks";
|
|
9
|
+
import { Badge, Link } from "../../../../shadcnui";
|
|
10
|
+
import { RoleInterface } from "../../../role";
|
|
11
|
+
import { UserInterface } from "../../data";
|
|
12
|
+
import { UserService } from "../../data/user.service";
|
|
13
|
+
import { useUserContext } from "../../contexts";
|
|
14
|
+
import { BriefcaseIcon, MailIcon, PhoneIcon } from "lucide-react";
|
|
15
|
+
|
|
16
|
+
type UserContentProps = {
|
|
17
|
+
user: UserInterface;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export function UserContent({ user }: UserContentProps) {
|
|
21
|
+
const t = useTranslations();
|
|
22
|
+
const generateUrl = usePageUrlGenerator();
|
|
23
|
+
const { setUser } = useUserContext();
|
|
24
|
+
|
|
25
|
+
const hasBio = !!user.bio;
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div className="flex flex-col gap-y-8">
|
|
29
|
+
{/* Hero Section */}
|
|
30
|
+
<div className="flex items-start gap-x-6">
|
|
31
|
+
<EditableAvatar
|
|
32
|
+
entityId={user.id}
|
|
33
|
+
module={Modules.User}
|
|
34
|
+
image={user.avatar}
|
|
35
|
+
fallback={getInitials(user.name)}
|
|
36
|
+
alt={user.name}
|
|
37
|
+
patchImage={async (imageKey) => {
|
|
38
|
+
const updated = await UserService.patch({ id: user.id, avatar: imageKey });
|
|
39
|
+
setUser(updated);
|
|
40
|
+
}}
|
|
41
|
+
className="h-24 w-24"
|
|
42
|
+
fallbackClassName="text-2xl"
|
|
43
|
+
/>
|
|
44
|
+
<div className="flex flex-col gap-y-2">
|
|
45
|
+
{user.roles && user.roles.length > 0 && (
|
|
46
|
+
<div className="flex flex-wrap gap-2">
|
|
47
|
+
{user.roles.map((role: RoleInterface) => (
|
|
48
|
+
<Link key={role.id} href={generateUrl({ page: Modules.Role, id: role.id })}>
|
|
49
|
+
<Badge variant="default">{t(`role.roles`, { role: role.id.replaceAll(`-`, ``) })}</Badge>
|
|
50
|
+
</Link>
|
|
51
|
+
))}
|
|
52
|
+
</div>
|
|
53
|
+
)}
|
|
54
|
+
{user.isDeleted ? (
|
|
55
|
+
<div>
|
|
56
|
+
<Badge variant="destructive">{t(`user.errors.deleted`)}</Badge>
|
|
57
|
+
</div>
|
|
58
|
+
) : (
|
|
59
|
+
<>
|
|
60
|
+
{!user.isActivated && (
|
|
61
|
+
<div>
|
|
62
|
+
<Badge variant="destructive">{t(`user.errors.inactive`)}</Badge>
|
|
63
|
+
</div>
|
|
64
|
+
)}
|
|
65
|
+
</>
|
|
66
|
+
)}
|
|
67
|
+
{user.title && (
|
|
68
|
+
<div className="text-muted-foreground flex items-center gap-x-2 text-sm">
|
|
69
|
+
<BriefcaseIcon className="h-4 w-4 shrink-0" />
|
|
70
|
+
{user.title}
|
|
71
|
+
</div>
|
|
72
|
+
)}
|
|
73
|
+
{user.email && (
|
|
74
|
+
<div className="text-muted-foreground flex items-center gap-x-2 text-sm">
|
|
75
|
+
<MailIcon className="h-4 w-4 shrink-0" />
|
|
76
|
+
{user.email}
|
|
77
|
+
</div>
|
|
78
|
+
)}
|
|
79
|
+
{user.phone && (
|
|
80
|
+
<div className="text-muted-foreground flex items-center gap-x-2 text-sm">
|
|
81
|
+
<PhoneIcon className="h-4 w-4 shrink-0" />
|
|
82
|
+
{user.phone}
|
|
83
|
+
</div>
|
|
84
|
+
)}
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
{/* Bio Section */}
|
|
89
|
+
{hasBio && <AttributeElement title={t(`user.fields.bio.label`)} value={user.bio} />}
|
|
90
|
+
</div>
|
|
91
|
+
);
|
|
92
|
+
}
|