357 lines
13 KiB
TypeScript
357 lines
13 KiB
TypeScript
import WarningIcon from "@Assets/images/warning.png";
|
|
//import OfficeRoles from "@Front/Api/LeCoffreApi/Admin/OfficeRoles/OfficeRoles";
|
|
import Roles from "@Front/Api/LeCoffreApi/Admin/Roles/Roles";
|
|
import LiveVotes from "@Front/Api/LeCoffreApi/SuperAdmin/LiveVotes/LiveVotes";
|
|
import Users from "@Front/Api/LeCoffreApi/SuperAdmin/Users/Users";
|
|
import Button, { EButtonVariant } from "@Front/Components/DesignSystem/Button";
|
|
import Confirm from "@Front/Components/DesignSystem/OldModal/Confirm";
|
|
import Switch from "@Front/Components/DesignSystem/Switch";
|
|
import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography";
|
|
import DefaultUserDashboard from "@Front/Components/LayoutTemplates/DefaultUserDashboard";
|
|
import JwtService from "@Front/Services/JwtService/JwtService";
|
|
import Toasts from "@Front/Stores/Toasts";
|
|
import User, { Appointment, Vote } from "le-coffre-resources/dist/SuperAdmin";
|
|
import { EAppointmentStatus, EVote } from "le-coffre-resources/dist/SuperAdmin/Appointment";
|
|
import Image from "next/image";
|
|
import { useRouter } from "next/router";
|
|
import { useCallback, useEffect, useState } from "react";
|
|
|
|
import classes from "./classes.module.scss";
|
|
import OfficeRoles from "@Front/Api/LeCoffreApi/Admin/OfficeRoles/OfficeRoles";
|
|
import Loader from "@Front/Components/DesignSystem/Loader";
|
|
|
|
type IProps = {};
|
|
export default function UserInformations(props: IProps) {
|
|
const router = useRouter();
|
|
let { userUid } = router.query;
|
|
|
|
const [userSelected, setUserSelected] = useState<User | null>(null);
|
|
|
|
const [isSuperAdminModalOpened, setIsSuperAdminModalOpened] = useState<boolean>(false);
|
|
const [superAdminModalType, setSuperAdminModalType] = useState<"add" | "remove">("add");
|
|
const [adminModalType, setAdminModalType] = useState<"add" | "remove">("add");
|
|
|
|
const [isSuperAdminChecked, setIsSuperAdminChecked] = useState<boolean>(false);
|
|
const [isAdminChecked, setIsAdminChecked] = useState<boolean>(false);
|
|
const [isAdminModalOpened, setIsAdminModalOpened] = useState<boolean>(false);
|
|
|
|
const [currentAppointment, setCurrentAppointment] = useState<Appointment | null>(null);
|
|
|
|
const [isLoading, setIsLoading] = useState<boolean>(true);
|
|
/** When page change, get the user of the page */
|
|
|
|
const getUser = useCallback(async () => {
|
|
if (!userUid) return;
|
|
setIsLoading(true);
|
|
const user = await Users.getInstance().getByUid(userUid as string, {
|
|
q: {
|
|
contact: true,
|
|
office_role: true,
|
|
office_membership: true,
|
|
role: true,
|
|
appointment: {
|
|
include: {
|
|
votes: {
|
|
include: {
|
|
voter: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
votes: true,
|
|
},
|
|
});
|
|
if (!user) return;
|
|
const roles = await OfficeRoles.getInstance().get({
|
|
where: {
|
|
office: { uid: user.office_membership?.uid },
|
|
NOT: { OR: [{ name: "super-admin" }, { name: "admin" }] },
|
|
},
|
|
});
|
|
if (!roles) return;
|
|
setIsLoading(false);
|
|
setUserSelected(user);
|
|
}, [userUid]);
|
|
|
|
useEffect(() => {
|
|
getUser();
|
|
}, [getUser, userUid]);
|
|
|
|
useEffect(() => {
|
|
if (!userSelected) return;
|
|
setCurrentAppointment(
|
|
userSelected?.appointment?.find(
|
|
(appointment) => appointment.status === EAppointmentStatus.OPEN && appointment.votes?.length != 0,
|
|
) ?? null,
|
|
);
|
|
}, [userSelected]);
|
|
|
|
/** Functions for the admin modal */
|
|
const openAdminModal = () => {
|
|
setIsAdminModalOpened(true);
|
|
};
|
|
|
|
const closeAdminModal = useCallback(() => {
|
|
setIsAdminModalOpened(false);
|
|
setIsAdminChecked(userSelected?.role?.name === "admin");
|
|
}, [userSelected]);
|
|
|
|
const handleAdminChanged = (checked: boolean) => {
|
|
setIsAdminChecked(checked);
|
|
setAdminModalType(checked ? "add" : "remove");
|
|
openAdminModal();
|
|
};
|
|
|
|
const handleAdminModalAccepted = useCallback(async () => {
|
|
if (!userSelected) return;
|
|
if (adminModalType === "add") {
|
|
const adminRole = await Roles.getInstance().getOne({
|
|
where: {
|
|
name: "admin",
|
|
},
|
|
});
|
|
|
|
if (!adminRole) return;
|
|
await Users.getInstance().put(
|
|
userSelected?.uid as string,
|
|
User.hydrate<User>({
|
|
uid: userSelected?.uid as string,
|
|
office_role: undefined,
|
|
role: adminRole,
|
|
}),
|
|
);
|
|
} else {
|
|
const defaultRole = await Roles.getInstance().getOne({
|
|
where: {
|
|
name: "default",
|
|
},
|
|
});
|
|
|
|
if (!defaultRole) return;
|
|
await Users.getInstance().put(
|
|
userSelected?.uid as string,
|
|
User.hydrate<User>({
|
|
uid: userSelected?.uid as string,
|
|
office_role: undefined,
|
|
role: defaultRole,
|
|
}),
|
|
);
|
|
}
|
|
getUser();
|
|
setIsAdminModalOpened(false);
|
|
}, [userSelected, adminModalType, getUser]);
|
|
|
|
/** Functions for the super admin modal */
|
|
const openSuperAdminModal = () => {
|
|
setIsSuperAdminModalOpened(true);
|
|
};
|
|
|
|
const closeSuperAdminModal = useCallback(() => {
|
|
setIsSuperAdminModalOpened(false);
|
|
setIsSuperAdminChecked(userSelected?.role?.name === "super-admin");
|
|
}, [userSelected]);
|
|
|
|
const handleSuperAdminChanged = (checked: boolean) => {
|
|
setIsSuperAdminChecked(checked);
|
|
setSuperAdminModalType(checked ? "add" : "remove");
|
|
openSuperAdminModal();
|
|
};
|
|
|
|
const handleSuperAdminModalAccepted = useCallback(async () => {
|
|
if (!userSelected) return;
|
|
|
|
let vote = Vote.hydrate<Vote>({
|
|
appointment: Appointment.hydrate<Appointment>({
|
|
uid: currentAppointment?.uid ?? undefined,
|
|
user: User.hydrate<User>({
|
|
uid: userSelected.uid,
|
|
}),
|
|
choice: superAdminModalType === "add" ? EVote.NOMINATE : EVote.DISMISS,
|
|
}),
|
|
});
|
|
|
|
const liveVote = await LiveVotes.getInstance().post(vote);
|
|
|
|
if (liveVote.appointment.votes?.length === 3) {
|
|
if (superAdminModalType === "add") {
|
|
Toasts.getInstance().open({
|
|
title: `Le titre de super-administrateur a été attribué à ${userSelected.contact?.first_name} ${userSelected.contact?.last_name} `,
|
|
});
|
|
} else {
|
|
Toasts.getInstance().open({
|
|
title: `Le titre de super-administrateur a été retiré à ${userSelected.contact?.first_name} ${userSelected.contact?.last_name} `,
|
|
});
|
|
}
|
|
}
|
|
await getUser();
|
|
setIsSuperAdminModalOpened(false);
|
|
}, [userSelected, currentAppointment, superAdminModalType, getUser]);
|
|
|
|
/** Reset switch state when userSelect change */
|
|
useEffect(() => {
|
|
if (!userSelected) return;
|
|
setIsSuperAdminChecked(userSelected.role?.name === "super-admin");
|
|
setIsAdminChecked(userSelected.role?.name === "admin");
|
|
}, [userSelected]);
|
|
|
|
const userHasVoted = useCallback(() => {
|
|
if (!currentAppointment) return false;
|
|
const user = JwtService.getInstance().decodeJwt();
|
|
return currentAppointment.votes?.find((vote) => vote.voter?.uid === user?.userId) !== undefined;
|
|
}, [currentAppointment]);
|
|
|
|
const deleteMyVote = useCallback(async () => {
|
|
if (!currentAppointment) return;
|
|
const user = JwtService.getInstance().decodeJwt();
|
|
const vote = currentAppointment.votes?.find((vote) => vote.voter?.uid === user?.userId);
|
|
if (!vote) return;
|
|
await LiveVotes.getInstance().delete({ uid: vote.uid });
|
|
await getUser();
|
|
}, [currentAppointment, getUser]);
|
|
|
|
return (
|
|
<DefaultUserDashboard mobileBackText={"Liste des utilisateurs"}>
|
|
{!isLoading && (
|
|
<div className={classes["root"]}>
|
|
<div className={classes["header"]}>
|
|
<Typography typo={ETypo.TITLE_H1}>
|
|
{userSelected?.contact?.first_name + " " + userSelected?.contact?.last_name}
|
|
</Typography>
|
|
<Typography typo={ETypo.TITLE_H5} color={ETypoColor.COLOR_NEUTRAL_500}>
|
|
Office {userSelected?.office_membership?.name.toLocaleUpperCase()}
|
|
</Typography>
|
|
</div>
|
|
<div className={classes["user-infos"]}>
|
|
<div className={classes["user-infos-row"]}>
|
|
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.COLOR_NEUTRAL_500}>
|
|
Nom
|
|
</Typography>
|
|
<Typography typo={ETypo.TEXT_LG_REGULAR}>{userSelected?.contact?.first_name}</Typography>
|
|
</div>
|
|
<div className={classes["user-infos-row"]}>
|
|
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.COLOR_NEUTRAL_500}>
|
|
Prénom
|
|
</Typography>
|
|
<Typography typo={ETypo.TEXT_LG_REGULAR}>{userSelected?.contact?.last_name}</Typography>
|
|
</div>
|
|
<div className={classes["user-infos-row"]}>
|
|
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.COLOR_NEUTRAL_500}>
|
|
Numéro de téléphone
|
|
</Typography>
|
|
<Typography typo={ETypo.TEXT_LG_REGULAR}>{userSelected?.contact?.cell_phone_number}</Typography>
|
|
</div>
|
|
<div className={classes["user-infos-row"]}>
|
|
<Typography typo={ETypo.TEXT_MD_REGULAR} color={ETypoColor.COLOR_NEUTRAL_500}>
|
|
Email
|
|
</Typography>
|
|
<Typography typo={ETypo.TEXT_LG_REGULAR}>{userSelected?.contact?.email}</Typography>
|
|
</div>
|
|
</div>
|
|
|
|
<div className={classes["role-container"]}>
|
|
<div className={classes["part"]}>
|
|
<div className={classes["first-line"]}>
|
|
<Typography typo={ETypo.TEXT_LG_SEMIBOLD}>Rôle au sein de son office</Typography>
|
|
</div>
|
|
<div className={classes["second-line"]}>
|
|
<Typography typo={ETypo.TEXT_LG_REGULAR}>
|
|
{userSelected?.office_role ? userSelected?.office_role?.name : "Utilisateur restreint"}
|
|
</Typography>
|
|
</div>
|
|
</div>
|
|
<div className={classes["part"]}>
|
|
<div className={classes["first-line"]}>
|
|
<Typography typo={ETypo.TEXT_LG_SEMIBOLD}>Attribuer un titre</Typography>
|
|
</div>
|
|
<div className={classes["second-line"]}>
|
|
{!isSuperAdminChecked && !currentAppointment && (
|
|
<Switch label="Admin de son office" checked={isAdminChecked} onChange={handleAdminChanged} />
|
|
)}
|
|
|
|
<Switch
|
|
label="Super-admin LEcoffre.io"
|
|
checked={isSuperAdminChecked}
|
|
disabled={userHasVoted()}
|
|
onChange={handleSuperAdminChanged}
|
|
/>
|
|
{currentAppointment && (
|
|
<div className={classes["votes-block"]}>
|
|
<div className={classes["left"]}>
|
|
<Image src={WarningIcon} alt="warning" width={28} height={28} />
|
|
</div>
|
|
<div className={classes["right"]}>
|
|
<div>
|
|
<Typography typo={ETypo.TEXT_LG_SEMIBOLD}>{currentAppointment.votes?.length}/3</Typography>
|
|
</div>
|
|
<div>
|
|
<Typography typo={ETypo.TEXT_SM_REGULAR}>
|
|
{currentAppointment.choice === EVote.NOMINATE
|
|
? `Un ou des collaborateurs souhaitent attribuer le titre de Super Admin à ce collaborateur. Il manque ${
|
|
3 - currentAppointment.votes?.length!
|
|
} vote(s) pour que le collaborateur se voit attribuer le titre.`
|
|
: `Un ou des collaborateurs souhaitent retirer le titre de Super Admin à ce collaborateur. Il manque ${
|
|
3 - currentAppointment.votes?.length!
|
|
} vote(s) pour que le collaborateur se voit retirer le titre.`}
|
|
</Typography>
|
|
</div>
|
|
{userHasVoted() && (
|
|
<div className={classes["remove-my-vote"]}>
|
|
<Button variant={EButtonVariant.SECONDARY} onClick={deleteMyVote}>
|
|
Retirer mon vote
|
|
</Button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<Confirm
|
|
isOpen={isSuperAdminModalOpened}
|
|
onClose={closeSuperAdminModal}
|
|
onAccept={handleSuperAdminModalAccepted}
|
|
closeBtn
|
|
header={`Souhaitez-vous attribuer un vote à ${
|
|
userSelected?.contact?.first_name + " " + userSelected?.contact?.last_name
|
|
} pour ${superAdminModalType === "add" ? "devenir" : "retirer son rôle de"} Super Administrateur ?`}
|
|
confirmText={"Attribuer un vote"}
|
|
cancelText={"Annuler"}>
|
|
<div className={classes["modal-content"]}>
|
|
<Typography typo={ETypo.TEXT_MD_REGULAR} className={classes["text"]}>
|
|
{superAdminModalType === "add" ? "Nommer" : "Retirer"} une personne Super Administrateur nécessite 3 votes
|
|
de super administrateurs existants. Souhaitez-vous attribuer un vote ?
|
|
</Typography>
|
|
</div>
|
|
</Confirm>
|
|
<Confirm
|
|
isOpen={isAdminModalOpened}
|
|
onClose={closeAdminModal}
|
|
onAccept={handleAdminModalAccepted}
|
|
closeBtn
|
|
header={
|
|
adminModalType === "add"
|
|
? `Souhaitez-vous nommer ${
|
|
userSelected?.contact?.first_name + " " + userSelected?.contact?.last_name
|
|
} administrateur de son office ?`
|
|
: `Souhaitez-vous retirer le rôle administrateur de son office à ${
|
|
userSelected?.contact?.first_name + " " + userSelected?.contact?.last_name
|
|
} ?`
|
|
}
|
|
confirmText={adminModalType === "add" ? "Ajouter" : "Retirer"}
|
|
cancelText={"Annuler"}>
|
|
<div className={classes["modal-content"]}></div>
|
|
</Confirm>
|
|
</div>
|
|
)}
|
|
{isLoading && (
|
|
<div className={classes["loader-container"]}>
|
|
<div className={classes["loader"]}>
|
|
<Loader />
|
|
</div>
|
|
</div>
|
|
)}
|
|
</DefaultUserDashboard>
|
|
);
|
|
}
|