290 lines
8.6 KiB
JavaScript
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);
|