Generateurv2/frontend/pages/exercices/[[...exo]].jsx
2022-05-18 10:15:54 +02:00

244 lines
7.3 KiB
JavaScript

import axios from "axios";
import Layout from "../../components/Layout.js";
import { useState, useEffect, useCallback } from "react";
import { Card } from "../../components/exos/Card.jsx";
import { getExos, getTags } from "../../requests/requests.exos.js";
import { useQuery } from "react-query";
import styles from "../../styles/exos/ExercicesPage.module.scss";
import Modal from "../../components/Modal.jsx";
import ModalCard from "../../components/exos/ModalCard.jsx";
import { useRouter } from "next/router";
import ExoCreateForm from "../../components/exos/ExoCreateForm.jsx";
import TagSelect from "../../components/exos/TagSelect.jsx";
import { FiLink } from "react-icons/fi";
import { parseClassName } from "../../utils/utils.js";
import useFilter from "../../hooks/useFilter.hook.jsx";
import { Pagination } from "../../components/exos/Pagination.jsx";
export default function ExercicesPage({ exos, tags }) {
//console.log("render");
const [page, setPage] = useState(0); //correspond à l'index
const { isLoading, isError, data, isFetching } = useQuery(
["exo-data"],
async () => await getExos(),
{
initialData: exos,
refetchOnWindowFocus: false,
keepPreviousData: true,
}
);
const { data: tagsData } = useQuery(
["tags"],
async () => {
return await getTags();
},
{
initialData: tags,
}
);
const router = useRouter();
const { exo } = router.query;
const [activeData, setActiveData] = useState({
active: exo != undefined,
data: exo == undefined ? null : data.filter((e) => e.id_code == exo)[0],
});
const [search, setSearch] = useState("");
const [create, setCreate] = useState(false);
useEffect(() => {
setActiveData({
active: exo != undefined,
data: exo == undefined ? null : data.filter((e) => e.id_code == exo)[0],
});
return () => {
setActiveData({ active: false, data: {} });
};
}, [exo, data]);
const [deleted, setDeleted] = useState([]);
const [selectedOption, setSelectedOption] = useState(null);
const [sortMode, setSortMode] = useState(false); // false == au moins 1 / true = tous
const [exData, setExData] = useState([]);
useFilter(data, selectedOption, search, setExData, sortMode);
useEffect(() => {
if (exData.length != 0) {
setExData([
...exData.sort(function (a, b) {
if (a.tags.length == 0 || b.tags.length == 0) {
return 1;
}
return (
tagsData.map((t) => t.id_code).indexOf(a.tags[0].id_code) -
tagsData.map((t) => t.id_code).indexOf(b.tags[0].id_code)
);
}),
]);
}
return () => {
setExData([]);
};
}, [exData.length]);
const inPage = 22;
return (
<Layout page="Tous les exercices">
<main
className={parseClassName([
styles["all_exos--full_container"],
"container",
])}
>
{(isLoading || isFetching) && (
<p
style={{ textAlign: "center", position: "absolute", width: "100%" }}
>
<span className="loader"></span>
</p>
)}
<div className={styles["all_exos--head"]}>
<div className={styles["new-container"]}>
<button
onClick={() => {
setCreate(true);
}}
>
Nouveau +
</button>
</div>
<div className={styles["search-full-container"]}>
<input
placeholder="Rechercher..."
type="text"
className="exo-input"
value={search}
onChange={(e) => {
setSearch(e.target.value);
setPage(0);
}}
/>
<div style={{ display: "flex" }}>
<TagSelect
tags={tagsData}
onChange={(e) => {
setSelectedOption(e);
setPage(0);
}}
select={selectedOption}
/>
<div
onClick={() => {
setSortMode(!sortMode);
}}
title={
sortMode == true
? "Doit avoir au moins tous les tags"
: "Doit avoir au moins un tag"
}
className={parseClassName([
styles["toggler-sort"],
sortMode
? styles["toggler-active"]
: styles["toggler-inactive"],
])}
>
<FiLink />
</div>
</div>
</div>
</div>
<div className={styles["all_exos--container"]}>
<div className={styles["all_exos--title"]}>
<h1>
Tous les <span className="primary">exercices</span>
</h1>
</div>
{exData.slice(page * inPage, (page + 1) * inPage).map((step) => {
return (
<Card
key={step.id}
step={step}
setActive={setActiveData}
deleted={deleted.includes(step.id_code)}
tags={tagsData}
/>
);
})}
{exData.length == 0 && <p>Aucun résultat</p>}
</div>
{exData.length > inPage && (
<Pagination
pages={Math.ceil(exData.length / inPage)}
page={page}
setPage={setPage}
/>
)}
</main>
<Modal
active={activeData.active || create}
onClose={() => {
if (activeData.active == true) {
setActiveData({ active: false, data: { ...activeData.data } });
router.push("/exercices", undefined, { shallow: true });
setTimeout(() => {
setActiveData({ active: false, data: null });
}, 300); // le temps de la transition}
} else if (create == true) {
setCreate(false);
}
}}
>
{activeData.data != null && create == false && (
<ModalCard
step={activeData.data}
setActive={setActiveData}
modal={true}
onClose={() => {
setActiveData({ active: false, data: { ...activeData.data } });
router.push("/exercices", undefined, { shallow: true });
setTimeout(() => {
setActiveData({ active: false, data: null });
}, 300);
}}
onDelete={(id) => {
if (!deleted.includes(id)) {
setDeleted([...deleted, id]);
} else {
setDeleted([...deleted.filter((d) => d !== id)]);
}
}}
tags={tagsData}
/>
)}
{create == true && activeData.data == null && (
<ExoCreateForm
cancel={() => {
setCreate(false);
}}
/>
)}
</Modal>
</Layout>
);
}
export async function getStaticProps() {
const exos = await getExos();
const tags = await getTags();
return {
props: {
exos: exos,
tags: tags,
},
revalidate: 60,
};
}
export const getStaticPaths = async () => {
return {
paths: [], //indicates that no page needs be created at build time
fallback: "blocking", //indicates the type of fallback
};
};