Generateurv2/frontend/components/exos/Card.jsx

290 lines
8.6 KiB
JavaScript

import Link from "next/link";
import { useRouter } from "next/router";
import React, { useEffect, useState } from "react";
import { useMutation, useQueryClient } from "react-query";
import { delTag, favExo, setTags } from "../../requests/requests.exos.js";
import { notificationService } from "../../services/notification.service.js";
import styles from "../../styles/exos/Card.module.scss";
import { isBrowser, isEmpty, parseClassName } from "../../utils/utils.js";
import Delete from "../icon_component/delete.jsx";
import Tag from "../Tag.jsx";
import { TagCreatable } from "./TagCreate.jsx";
import { BsBookmark, BsBookmarkFill } from "react-icons/bs";
import { HiOutlineDuplicate } from "react-icons/hi";
import { useSessionContext } from "../../context/session.context.js";
function CardComp({ step, setActive, deleted, tags, queryKey }) {
const [tagMode, setTagMode] = useState(false);
const router = useRouter();
const [selected, setSelected] = useState([]);
const queryClient = useQueryClient();
const { mutate } = useMutation(
async () => await setTags({ step: step.id_code, tags: [...selected] }),
{
onSuccess: (data, variables, context) => {
queryClient.setQueryData(queryKey, (old) => {
return {
...old,
results: [
...old.results.map((r) => {
if (r.id_code === data.data.id_code) {
return { ...r, tags: data.data.tags };
}
return r;
}),
],
};
});
queryClient.invalidateQueries(queryKey[0], { active: false });
queryClient.invalidateQueries("tags");
setSelected([]);
notificationService.success("Tags", `Tags de ${step.name} modifiés !`, {
autoClose: true,
});
setTagMode(false);
},
onError: (data) => {
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) => {
var tagsSelected = queryKey[2].tags || null;
if (tagsSelected && tagsSelected.includes(data.data.tagId)) {
queryClient.invalidateQueries(queryKey);
}
queryClient.setQueriesData(queryKey, (old) => {
return {
...old,
results: [
...old.results.map((r) => {
if (r.id_code === data.data.id_code) {
return { ...r, tags: data.data.tags };
}
return r;
}),
],
};
});
queryClient.invalidateQueries(queryKey[0], { active: false });
notificationService.success(
"Tags",
`Tag ${data.data.name} retiré à ${step.name} !`,
{
autoClose: true,
}
);
setTagMode(false);
},
onError: (e) => {
notificationService.error(
"Erreur",
`Le tag n'a pu être retiré de ${step.name} !`
);
},
}
);
const [tagOptions, setTagOptions] = useState(
tags.map((tag) => {
return {
...tag,
isDisabled: step.tags.map((t) => t.id_code).includes(tag.id_code),
};
})
);
useEffect(() => {
setTagOptions(
tags.map((tag) => {
return {
...tag,
isDisabled: step.tags.map((t) => t.id_code).includes(tag.id_code),
};
})
);
return () => {
setTagOptions([]);
};
}, [step.tags, tags]);
const {authData} = useSessionContext()
return (
<div
className={
parseClassName([
styles["ex_card--full"],
tagMode == true ? styles["no_hover"] : "",
deleted ? styles["card-deleted"] : "",
]) //(fade == true ? " editor-card" : "")
}
//id={"card-" + step.id_code}
>
{/* <div className={styles["card-content"]} hidden={model} > */}
<div
className={parseClassName([
styles["card-hover"],
deleted ? styles["no_hover"] : undefined,
])}
onClick={() => {
setActive({ active: true, data: { ...step } });
router.push(`/exercices/${step.id_code}`, undefined, {
shallow: true,
});
//onClick && onClick();
}}
>
{deleted && <span className="loader"></span>}
</div>
<div className={styles["ex_card--body"]}>
<div
onClick={() => {
setActive({ active: true, data: { ...step } });
router.push(`/exercices/${step.id_code}`, undefined, {
shallow: true,
});
}}
className={parseClassName([
styles["ex_card--title"],
deleted ? styles["no_hover"] : undefined,
])}
>
<a className={deleted ? styles["no_hover"] : undefined}>
{step.name}
</a>
{/* <ColorField>
<p className="small-text">{step.parent.name}</p>
</ColorField> */}
</div>
<div
className={parseClassName([
styles["ex_card--content"],
deleted ? styles["no_hover"] : undefined,
])}
>
{step.exemple.data && (
<p className="margint-p0 fontw-800">
Exemples ({step.exemple.type && step.exemple.type})
</p>
)}
{step.exemple.data &&
step.exemple.data.slice(0, 3).map((ex, i) => {
return (
<p
key={i}
className={"marginl-p5" + " small-text " + styles.exemple}
title={ex.calcul}
>
{ex.calcul}
</p>
);
})}
{step.exemple.data && <p className="marginl-p5 margint-p2">...</p>}
{!step.exemple.data && <p>Exemples indisponibles</p>}
</div>
{/* {modal == false && <div className={styles["card-hover"]}> </div>} */}
{!isEmpty(authData) && !step.isUser && (
<div
title="Dupliquer l'exercice pour pouvoir le modifier"
className={parseClassName([
styles["icon-container"],
step.isRegistered ? styles["registered"] : undefined,
])}
onClick={() => {
favExo(step.id_code)
}}
>
<HiOutlineDuplicate />
</div>
)}
</div>
<div className={styles["card-progress"]}>
<span></span>
</div>
<div
className={parseClassName([
styles["ex_card--footer"],
tagMode == true
? styles["tag_card"]
: styles["ex_card--footer-not-tag"],
])}
>
{tagMode == false && localStorage.getItem("token") != null && (
<>
<div className={styles["tag--container"]}>
{step.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 && (
<>
<TagCreatable
options={tagOptions}
selectOption={setSelected}
select={selected}
onCreate={setTagOptions}
/>
<div className="margint-p3 flex-column">
<button onClick={mutate} className="exo-btn">
Valider
</button>
<button
onClick={() => {
setTagMode(false);
setSelected([]);
}}
className="cancel-btn"
>
Annuler
</button>
</div>
</>
)}
</div>
{/* </div> */}
</div>
);
}
const StepsCardCompar = (prv, nxt) => {
return (
prv.step.tags.length == nxt.step.tags.length &&
prv.tags.length == nxt.tags.length &&
prv.step.name == nxt.step.name &&
prv.step.exo_model == nxt.step.exo_model &&
prv.step.model_type == nxt.step.model_type &&
prv.step.isRegistered == nxt.step.isRegistered &&
prv.step.consigne == nxt.step.consigne &&
prv.queryKey == nxt.queryKey
);
};
export const Card = React.memo(CardComp, StepsCardCompar);