285 lines
8.0 KiB
JavaScript
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>
|
|
);
|
|
}
|