2024-07-18 18:40:12 +02:00

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>
);
}