Generateurv2/frontend/components/exos/ModalCard.jsx
2022-05-18 10:15:54 +02:00

285 lines
8.0 KiB
JavaScript

import { useEffect, useRef, useState } from "react";
import styles from "../../styles/exos/ModalCard.module.scss";
import { parseClassName } from "../../utils/utils.js";
import ExoPrinterForm from "./ExoPrinterForm.jsx";
import Tag from "../Tag.jsx";
import { HiOutlineTrash } from "react-icons/hi";
import { TiEdit } from "react-icons/ti";
import { AiOutlineClose } from "react-icons/ai";
import { notificationService } from "../../services/notification.service.js";
import { AlertType, useAlert } from "../../context/alert.context.js";
import { ExoEditForm } from "./ExoEditForm.jsx";
import {
delExo,
delTag,
getExos,
getModelFile,
setTags,
} from "../../requests/requests.exos.js";
import { useMutation, useQuery, useQueryClient } from "react-query";
import { TagCreatable } from "./TagCreate.jsx";
export default function ModalCard({ step, onClose, onDelete, tags }) {
const [tagMode, setTagMode] = useState(false);
const alert = useAlert();
const [edit, setEdit] = useState(false);
const queryClient = useQueryClient();
const {
isLoading: isUpdating,
isFetching,
data: step_data,
} = useQuery(
["exo-data", step.id_code],
async () => await getExos(step.id_code),
{ initialData: step, refetchOnWindowFocus: !edit }
);
const [selected, setSelected] = useState([]);
console.log(step_data);
const [tagOptions, setTagOptions] = useState(
tags.map((tag) => {
return {
...tag,
isDisabled: step_data.tags.map((t) => t.id_code).includes(tag.id_code),
};
})
);
useEffect(() => {
setTagOptions(
tags.map((tag) => {
return {
...tag,
isDisabled: step_data.tags
.map((t) => t.id_code)
.includes(tag.id_code),
};
})
);
return () => {
setTagOptions([]);
};
}, [step_data.tags, tags]);
const { mutate: setTagMutate } = useMutation(
async () => await setTags({ step: step.id_code, tags: [...selected] }),
{
onSuccess: () => {
queryClient.invalidateQueries("exo-data");
queryClient.invalidateQueries(step.id_code);
queryClient.invalidateQueries("tags");
setSelected([]);
notificationService.success("Tags", `Tags de ${step.name} modifiés !`, {
autoClose: true,
});
setTagMode(false);
},
onError: () => {
notificationService.error(
"Erreur",
`Les tags de ${step.name} n'ont pu être modifiés !`
);
},
}
);
const { mutate: delTagMutate } = useMutation(
async (tag) => {
return await delTag({ tag: tag, step: step.id_code });
},
{
onSuccess: (data) => {
queryClient.invalidateQueries("exo-data");
queryClient.invalidateQueries("tags");
notificationService.success(
"Tags",
`Tag ${data.name} retiré à ${step.name} !`,
{
autoClose: true,
}
);
setTagMode(false);
},
onError: () => {
notificationService.error(
"Erreur",
`Le tag n'a pu être retiré de ${step.name} !`
);
},
}
);
const { mutate, isLoading } = useMutation(
async () => {
onDelete(step_data.id_code);
await delExo(step_data.id_code);
},
{
onMutate: () => {
onClose();
},
onSuccess: (data, variables, context) => {
onDelete(step_data.id_code);
queryClient.invalidateQueries("exo-data");
notificationService.success(
"Suppression",
`Exercice ${step_data.name} supprimé !`,
{ autoClose: true, keepAfterRouteChange: true }
);
},
onError: (err) => {
notificationService.error(
"Erreur",
"La suppression n'a pu être effectuée ! Réessayez plus tard !",
{ autoClose: true, keepAfterRouteChange: true }
);
},
}
);
const [full, setFull] = useState({ state: false, fade: false });
const fadeFull = (state) => {
setFull({ state: !state, fade: state });
setTimeout(() => {
setFull({ state: state, fade: false });
}, 300);
};
return (
<div
className={styles["ex_card--full"]}
onKeyDown={(e) => {
if (e.code == "Escape") {
onClose();
}
}}
//id={"card-" + step_data.id_code}
>
<div
className={parseClassName([
styles["ex_card--body"],
edit ? "marginb-p0" : undefined,
full.fade ? styles["ex_card-fade"] : undefined,
full.fade || full.state ? styles["ex_card--big"] : undefined,
full.state ? "vh-100" : undefined,
edit ? styles["edit-card"] : undefined,
])}
>
{isFetching && (
<div className={styles["updating"]}>
<span className="loader"></span>
</div>
)}
{!(isFetching || isUpdating) && (
<>
{!edit && full.state == false && (
<div className={styles["ex_card--title"]}>{step_data.name}</div>
)}
{!edit && full.state == false && <ExoPrinterForm step={step} />}
{edit && (
<ExoEditForm
step={step}
cancel={() => {
setEdit(false);
}}
setFull={fadeFull}
full={full.state}
/>
)}
</>
)}
</div>
{!(isFetching || isUpdating) && full.state == false && (
<div
className={parseClassName([
styles["ex_card--footer"],
tagMode == true
? styles["tag_card"]
: styles["ex_card--footer-not-tag"],
])}
>
{tagMode == false && !edit && full.state == false && (
<>
<div className={styles["tag--container"]}>
{step_data.tags.map((t, i) => {
return <Tag key={i} tag={t} onDelete={delTagMutate} />;
})}
</div>
<div
onClick={() => {
setTagMode(true);
}}
className={styles["ex_card--add-tag"]}
>
{" "}
<hr /> <p> +</p>
</div>
</>
)}
{tagMode && !edit && full.state == false && (
<>
<TagCreatable
options={tagOptions}
selectOption={setSelected}
select={selected}
onCreate={setTagOptions}
/>
<div className="margint-p3 flex-column">
<button onClick={setTagMutate} className="exo-btn">
Valider
</button>
<button
onClick={() => {
setTagMode(false);
setSelected([]);
}}
className="cancel-btn"
>
Annuler
</button>
</div>
</>
)}
</div>
)}
{!edit && !(isFetching || isUpdating) && full.state == false && (
<div className={styles["icon-container"]}>
{/* <Delete className={styles['icon']}/> */}
<AiOutlineClose
className={parseClassName([styles["icon"]])}
onClick={onClose}
/>
<div>
<HiOutlineTrash
className={parseClassName([styles["icon"], styles["delete"]])}
onClick={() => {
alert.alert({
title: "Êtes-vous sûr ?",
active: true,
message: `Vous allez supprimer l'exercice ${step_data.name} ! Cette action est irréversible !`,
type: AlertType.Warning,
validate: mutate,
});
}}
/>
<TiEdit
className={parseClassName([styles["icon"], styles["edit"]])}
onClick={() => {
setEdit(true);
}}
/>
</div>
</div>
)}
</div>
);
}