2023-10-04 19:30:06 +02:00

386 lines
14 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 SelectField, { IOption } from "@Front/Components/DesignSystem/Form/SelectField";
import Confirm from "@Front/Components/DesignSystem/Modal/Confirm";
import Switch from "@Front/Components/DesignSystem/Switch";
import Typography, { ITypo, ITypoColor } 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, OfficeRole, 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";
type IProps = {};
export default function UserInformations(props: IProps) {
const router = useRouter();
let { userUid } = router.query;
const [userSelected, setUserSelected] = useState<User | null>(null);
const [availableRoles, setAvailableRoles] = useState<IOption[]>([]);
const [roleModalOpened, setRoleModalOpened] = useState<boolean>(false);
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 [selectedOption, setSelectedOption] = useState<IOption | null>(null);
const [currentAppointment, setCurrentAppointment] = useState<Appointment | null>(null);
const handleRoleChange = useCallback((option: IOption) => {
setSelectedOption(option);
setRoleModalOpened(true);
}, []);
/** When page change, get the user of the page */
const getUser = useCallback(async () => {
if (!userUid) return;
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 Roles.getInstance().get({
where: {NOT: {OR:[{name: "super-admin"}, {name: "admin"}]}},
});
if (!roles) return
setAvailableRoles(roles.map((role) => ({ value: role.uid, label: role.label })));
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,
}),
);
}
setIsAdminModalOpened(false);
}, [userSelected, adminModalType]);
/** 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) {
Toasts.getInstance().open({
title: `Le titre de super-administrateur a été attribué à ${userSelected.contact?.first_name} ${userSelected.contact?.last_name} `,
});
}
await getUser();
setIsSuperAdminModalOpened(false);
}, [userSelected, currentAppointment, superAdminModalType, getUser]);
const closeRoleModal = useCallback(() => {
setRoleModalOpened(false);
setSelectedOption({
value: userSelected?.office_role ? userSelected?.office_role?.uid : userSelected?.role?.uid,
label: userSelected?.office_role ? userSelected?.office_role?.name : userSelected?.role?.label!,
});
}, [userSelected?.office_role, userSelected?.role?.label, userSelected?.role?.uid]);
const changeRole = useCallback(async () => {
await Users.getInstance().put(
userSelected?.uid as string,
User.hydrate<User>({
uid: userSelected?.uid as string,
office_role: OfficeRole.hydrate<OfficeRole>({
uid: selectedOption?.value as string,
}),
}),
);
setRoleModalOpened(false);
getUser();
}, [getUser, selectedOption?.value, userSelected?.uid]);
/** 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"}>
<div className={classes["root"]}>
<div className={classes["header"]}>
<Typography typo={ITypo.H1Bis}>{userSelected?.contact?.first_name + " " + userSelected?.contact?.last_name}</Typography>
<Typography typo={ITypo.H3} color={ITypoColor.GREY}>
Office {userSelected?.office_membership?.name.toLocaleUpperCase()}
</Typography>
</div>
<div className={classes["user-infos"]}>
<div className={classes["user-infos-row"]}>
<Typography typo={ITypo.NAV_INPUT_16} color={ITypoColor.GREY}>
Nom
</Typography>
<Typography typo={ITypo.P_18}>{userSelected?.contact?.first_name}</Typography>
</div>
<div className={classes["user-infos-row"]}>
<Typography typo={ITypo.NAV_INPUT_16} color={ITypoColor.GREY}>
Prénom
</Typography>
<Typography typo={ITypo.P_18}>{userSelected?.contact?.last_name}</Typography>
</div>
<div className={classes["user-infos-row"]}>
<Typography typo={ITypo.NAV_INPUT_16} color={ITypoColor.GREY}>
Numéro de téléphone
</Typography>
<Typography typo={ITypo.P_18}>{userSelected?.contact?.phone_number}</Typography>
</div>
<div className={classes["user-infos-row"]}>
<Typography typo={ITypo.NAV_INPUT_16} color={ITypoColor.GREY}>
Email
</Typography>
<Typography typo={ITypo.P_18}>{userSelected?.contact?.email}</Typography>
</div>
</div>
<div className={classes["role-container"]}>
<div className={classes["part"]}>
<div className={classes["first-line"]}>
<Typography typo={ITypo.P_SB_18}>Rôle au sein de son office</Typography>
</div>
<div className={classes["second-line"]}>
<SelectField
placeholder="Rôle"
name="role"
options={availableRoles.filter((role) => role.label !== "admin")}
onChange={handleRoleChange}
selectedOption={{
value: userSelected?.office_role ? userSelected?.office_role?.uid : userSelected?.role?.uid,
label: userSelected?.office_role ? userSelected?.office_role?.name : "Utilisateur restreint",
}}
/>
</div>
</div>
<div className={classes["part"]}>
<div className={classes["first-line"]}>
<Typography typo={ITypo.P_SB_18}>Attribuer un titre</Typography>
</div>
<div className={classes["second-line"]}>
{!isSuperAdminChecked && (
<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={ITypo.P_SB_18}>{currentAppointment.votes?.length}/3</Typography>
</div>
<div>
<Typography typo={ITypo.CAPTION_14}>
{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={roleModalOpened}
onClose={closeRoleModal}
onAccept={changeRole}
closeBtn
header={"Changement de rôle"}
confirmText={"Valider"}
cancelText={"Annuler"}>
<div className={classes["modal-content"]}>
<Typography typo={ITypo.P_16} className={classes["text"]}>
Attribuer le rôle de <span className={classes["role-name"]}>{selectedOption?.label}</span> à{" "}
{userSelected?.contact?.first_name} {userSelected?.contact?.last_name} ?
</Typography>
</div>
</Confirm>
<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={ITypo.P_16} 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>
</DefaultUserDashboard>
);
}