244 lines
7.3 KiB
React
244 lines
7.3 KiB
React
|
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
|
||
|
};
|
||
|
};
|