2022-05-18 10:15:54 +02:00
|
|
|
import axios from "axios";
|
|
|
|
import Layout from "../../components/Layout.js";
|
2022-06-11 23:39:03 +02:00
|
|
|
import { useState, useEffect, useCallback, useRef } from "react";
|
2022-05-18 10:15:54 +02:00
|
|
|
import { Card } from "../../components/exos/Card.jsx";
|
2022-06-11 23:39:03 +02:00
|
|
|
import {
|
|
|
|
getExos,
|
|
|
|
getPublicExos,
|
|
|
|
getTags,
|
|
|
|
getUserExos,
|
|
|
|
} from "../../requests/requests.exos.js";
|
|
|
|
import { useQuery, useQueryClient } from "react-query";
|
2022-05-18 10:15:54 +02:00
|
|
|
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";
|
2022-06-11 23:39:03 +02:00
|
|
|
import { isBrowser, parseClassName } from "../../utils/utils.js";
|
2022-05-18 10:15:54 +02:00
|
|
|
import useFilter from "../../hooks/useFilter.hook.jsx";
|
|
|
|
import { Pagination } from "../../components/exos/Pagination.jsx";
|
2022-06-24 13:42:16 +02:00
|
|
|
import { useSessionContext } from "../../context/session.context.js";
|
|
|
|
import { isEmpty } from "../../utils/utils.js";
|
|
|
|
import { notificationService } from "../../services/notification.service.js";
|
2022-05-18 10:15:54 +02:00
|
|
|
|
2022-06-11 23:39:03 +02:00
|
|
|
export default function ExercicesPage() {
|
2022-06-24 13:42:16 +02:00
|
|
|
const { authData } = useSessionContext();
|
2022-06-11 23:39:03 +02:00
|
|
|
|
|
|
|
const router = useRouter();
|
|
|
|
const { exo } = router.query;
|
|
|
|
const [page, setPage] = useState(1); //correspond à l'index
|
|
|
|
|
2022-06-24 13:42:16 +02:00
|
|
|
const [selectFilter, setSelectFilter] = useState(null);
|
|
|
|
const queryClient = useQueryClient();
|
2022-06-11 23:39:03 +02:00
|
|
|
|
|
|
|
const [search, setSearch] = useState("");
|
|
|
|
const [tmpSearch, setTmpSearch] = useState("");
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
const timeOutId = setTimeout(() => setSearch(tmpSearch), 500);
|
|
|
|
return () => {
|
|
|
|
clearInterval(timeOutId);
|
|
|
|
};
|
|
|
|
}, [tmpSearch]);
|
|
|
|
|
|
|
|
const [selectedOption, setSelectedOption] = useState([]);
|
|
|
|
|
|
|
|
const {
|
|
|
|
isLoading,
|
|
|
|
isError,
|
|
|
|
data: publicData,
|
|
|
|
isFetching,
|
|
|
|
} = useQuery(
|
2022-06-24 13:42:16 +02:00
|
|
|
[
|
|
|
|
"public-data",
|
|
|
|
parseInt(page),
|
|
|
|
{ search, tags: selectedOption.map((t) => t.value) },
|
|
|
|
],
|
2022-06-11 23:39:03 +02:00
|
|
|
async () =>
|
|
|
|
await getPublicExos("all", page, {
|
|
|
|
search,
|
|
|
|
tags: selectedOption.map((t) => t.value),
|
|
|
|
}),
|
|
|
|
|
2022-05-18 10:15:54 +02:00
|
|
|
{
|
|
|
|
refetchOnWindowFocus: false,
|
2022-06-11 23:39:03 +02:00
|
|
|
enabled: selectFilter == "all",
|
|
|
|
staleTime: 60000,
|
2022-05-18 10:15:54 +02:00
|
|
|
keepPreviousData: true,
|
|
|
|
}
|
|
|
|
);
|
2022-06-11 23:39:03 +02:00
|
|
|
|
|
|
|
const {
|
|
|
|
isLoading: userLoading,
|
|
|
|
isError: userError,
|
|
|
|
data: userExosData,
|
|
|
|
isFetching: userFetching,
|
|
|
|
} = useQuery(
|
2022-06-24 13:42:16 +02:00
|
|
|
[
|
|
|
|
"user-data",
|
|
|
|
parseInt(page),
|
|
|
|
{ search, tags: selectedOption.map((t) => t.value) },
|
|
|
|
],
|
2022-06-11 23:39:03 +02:00
|
|
|
async () =>
|
|
|
|
await getUserExos("all", page, {
|
|
|
|
search,
|
|
|
|
tags: selectedOption.map((t) => t.value),
|
|
|
|
}),
|
|
|
|
{
|
|
|
|
refetchOnWindowFocus: false,
|
2022-06-24 13:42:16 +02:00
|
|
|
enabled: selectFilter == "user" && !isEmpty(authData),
|
2022-06-11 23:39:03 +02:00
|
|
|
staleTime: 60000,
|
|
|
|
keepPreviousData: true,
|
|
|
|
}
|
|
|
|
);
|
2022-05-18 10:15:54 +02:00
|
|
|
const { data: tagsData } = useQuery(
|
|
|
|
["tags"],
|
|
|
|
async () => {
|
|
|
|
return await getTags();
|
|
|
|
},
|
|
|
|
{
|
2022-06-24 13:42:16 +02:00
|
|
|
enabled: !isEmpty(authData),
|
2022-06-11 23:39:03 +02:00
|
|
|
initialData: [],
|
|
|
|
staleTime: 2 * 60 * 1000,
|
|
|
|
initialDataUpdatedAt: 10 * 1000 * 60,
|
2022-05-18 10:15:54 +02:00
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
const [activeData, setActiveData] = useState({
|
2022-06-11 23:39:03 +02:00
|
|
|
active: false,
|
2022-06-24 13:42:16 +02:00
|
|
|
data: null,
|
2022-05-18 10:15:54 +02:00
|
|
|
});
|
2022-06-11 23:39:03 +02:00
|
|
|
|
2022-05-18 10:15:54 +02:00
|
|
|
const [create, setCreate] = useState(false);
|
2022-06-11 23:39:03 +02:00
|
|
|
|
2022-06-24 13:42:16 +02:00
|
|
|
const isLoad = useRef(false);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
console.log(
|
|
|
|
"AUTH DATA",
|
|
|
|
authData,
|
|
|
|
isLoad,
|
|
|
|
isLoad.current || authData !== undefined
|
|
|
|
);
|
|
|
|
if (exo !== undefined && (/* isLoad.current || */authData !== undefined)) {
|
|
|
|
if (exo[0] == "public") {
|
|
|
|
setSelectFilter("all");
|
|
|
|
} else if (exo[0] == "user") {
|
|
|
|
if (!isEmpty(authData)) {
|
|
|
|
setSelectFilter("user");
|
|
|
|
} else {
|
|
|
|
router.push({ pathname: "/exercices/public", query: { page: 1 } });
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (selectFilter === null) {
|
|
|
|
setSelectFilter(!isEmpty(authData) ? "user" : "public");
|
|
|
|
}
|
|
|
|
getExos(exo[0])
|
|
|
|
.then((res) => {
|
|
|
|
setActiveData({ active: true, data: { ...res } });
|
|
|
|
})
|
|
|
|
.catch(() => {
|
|
|
|
router.push({
|
|
|
|
pathname:
|
|
|
|
"/exercices/" + (!isEmpty(authData) ? "user" : "public"),
|
|
|
|
query: { page: 1 },
|
|
|
|
});
|
|
|
|
notificationService.error("Erreur", "Exercice introuvable", {
|
|
|
|
keepAfterRouteChange: true,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
} else if (exo === undefined && (/* isLoad.current || */ authData !== undefined)) {
|
|
|
|
if (selectFilter === null) {
|
|
|
|
router.push({
|
|
|
|
pathname: "/exercices/" + (!isEmpty(authData) ? "user" : "public"),
|
|
|
|
query: { page: 1 },
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isLoad.current) {
|
|
|
|
isLoad.current = true;
|
|
|
|
}
|
|
|
|
return () => {
|
|
|
|
setActiveData({ active: false, data: null });
|
|
|
|
};
|
|
|
|
}, [router.asPath, authData, isLoad, selectFilter]);
|
|
|
|
|
2022-05-18 10:15:54 +02:00
|
|
|
useEffect(() => {
|
2022-06-11 23:39:03 +02:00
|
|
|
if (publicData && router.query.page && selectFilter == "all") {
|
|
|
|
if (publicData.pages && parseInt(router.query.page) <= publicData.pages) {
|
|
|
|
setPage(parseInt(router.query.page));
|
|
|
|
} else if (
|
|
|
|
publicData.pages &&
|
|
|
|
parseInt(router.query.page) > publicData.pages
|
|
|
|
) {
|
|
|
|
var exo = router.query.exo || [];
|
|
|
|
router.push(
|
|
|
|
{
|
|
|
|
pathname: "/exercices/" + exo.join("/"),
|
|
|
|
query: { page: publicData.pages },
|
|
|
|
},
|
|
|
|
undefined,
|
|
|
|
{ shallow: true }
|
|
|
|
);
|
|
|
|
} else if (parseInt(router.query.page) == 0) {
|
|
|
|
var exo = router.query.exo || [];
|
|
|
|
router.push(
|
|
|
|
{
|
|
|
|
pathname: "/exercices/" + exo.join("/"),
|
|
|
|
query: { page: 1 },
|
|
|
|
},
|
|
|
|
undefined,
|
|
|
|
{ shallow: true }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (userExosData && router.query.page && selectFilter == "user") {
|
|
|
|
if (
|
|
|
|
userExosData.pages &&
|
|
|
|
parseInt(router.query.page) <= userExosData.pages
|
|
|
|
) {
|
|
|
|
setPage(parseInt(router.query.page));
|
|
|
|
} else if (
|
|
|
|
userExosData.pages &&
|
|
|
|
parseInt(router.query.page) > userExosData.pages
|
|
|
|
) {
|
|
|
|
var exo = router.query.exo || [];
|
|
|
|
router.push(
|
|
|
|
{
|
|
|
|
pathname: "/exercices/" + exo.join("/"),
|
|
|
|
query: { page: userExosData.pages },
|
|
|
|
},
|
|
|
|
undefined,
|
|
|
|
{ shallow: true }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2022-06-24 13:42:16 +02:00
|
|
|
}, [router.asPath, publicData, userExosData, selectFilter]);
|
2022-05-18 10:15:54 +02:00
|
|
|
|
2022-06-11 23:39:03 +02:00
|
|
|
const [deleted, setDeleted] = useState([]);
|
2022-05-18 10:15:54 +02:00
|
|
|
|
2022-06-11 23:39:03 +02:00
|
|
|
const onClose = () => {
|
|
|
|
if (activeData.active == true) {
|
|
|
|
setActiveData({ active: false, data: { ...activeData.data } });
|
|
|
|
queryClient.invalidateQueries(
|
|
|
|
selectFilter == "all" ? "public-data" : "user-data"
|
|
|
|
);
|
|
|
|
router.push(
|
|
|
|
{
|
|
|
|
pathname: "/exercices/" + (selectFilter == "all" ? "public" : "user"),
|
|
|
|
query: { page: page },
|
|
|
|
},
|
|
|
|
undefined,
|
|
|
|
{ shallow: true }
|
|
|
|
);
|
|
|
|
setTimeout(() => {
|
|
|
|
setActiveData({ active: false, data: null });
|
|
|
|
}, 300); // le temps de la transition
|
|
|
|
} else if (create == true) {
|
|
|
|
setCreate(false);
|
|
|
|
}
|
|
|
|
};
|
2022-05-18 10:15:54 +02:00
|
|
|
return (
|
|
|
|
<Layout page="Tous les exercices">
|
2022-06-24 13:42:16 +02:00
|
|
|
<div className={parseClassName([styles["all_exos--full_container"]])}>
|
2022-06-11 23:39:03 +02:00
|
|
|
{isLoading ||
|
|
|
|
isFetching ||
|
2022-06-24 13:42:16 +02:00
|
|
|
userLoading ||
|
|
|
|
(userFetching && (
|
2022-06-11 23:39:03 +02:00
|
|
|
<p
|
|
|
|
style={{
|
|
|
|
textAlign: "center",
|
|
|
|
position: "absolute",
|
|
|
|
width: "100%",
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<span className="loader"></span>
|
|
|
|
</p>
|
|
|
|
))}
|
2022-06-24 13:42:16 +02:00
|
|
|
|
2022-05-18 10:15:54 +02:00
|
|
|
<div className={styles["all_exos--head"]}>
|
|
|
|
<div className={styles["new-container"]}>
|
2022-06-24 13:42:16 +02:00
|
|
|
{!isEmpty(authData) && (
|
|
|
|
<button
|
|
|
|
onClick={() => {
|
|
|
|
setCreate(true);
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
Nouveau +
|
|
|
|
</button>
|
|
|
|
)}
|
2022-05-18 10:15:54 +02:00
|
|
|
</div>
|
2022-06-24 13:42:16 +02:00
|
|
|
|
2022-05-18 10:15:54 +02:00
|
|
|
<div className={styles["search-full-container"]}>
|
|
|
|
<input
|
|
|
|
placeholder="Rechercher..."
|
|
|
|
type="text"
|
|
|
|
className="exo-input"
|
2022-06-11 23:39:03 +02:00
|
|
|
value={tmpSearch}
|
2022-05-18 10:15:54 +02:00
|
|
|
onChange={(e) => {
|
2022-06-11 23:39:03 +02:00
|
|
|
setTmpSearch(e.target.value);
|
|
|
|
setPage(1);
|
2022-05-18 10:15:54 +02:00
|
|
|
}}
|
|
|
|
/>
|
2022-06-24 13:42:16 +02:00
|
|
|
<div style={{ display: "flex", width: '100%' }}>
|
|
|
|
{!isEmpty(authData) && (
|
|
|
|
<TagSelect
|
|
|
|
tags={tagsData ? tagsData: []}
|
|
|
|
onChange={(e) => {
|
|
|
|
setSelectedOption(e);
|
|
|
|
setPage(1);
|
|
|
|
}}
|
|
|
|
select={selectedOption}
|
|
|
|
/>
|
|
|
|
)}
|
2022-05-18 10:15:54 +02:00
|
|
|
</div>
|
2022-06-24 13:42:16 +02:00
|
|
|
{!isEmpty(authData) && (
|
2022-06-11 23:39:03 +02:00
|
|
|
<select
|
|
|
|
onChange={(e) => {
|
|
|
|
router.push(
|
|
|
|
{
|
|
|
|
pathname:
|
|
|
|
"/exercices/" +
|
|
|
|
(e.target.value == "user" ? "user" : "public"),
|
|
|
|
query: { page: 1 },
|
|
|
|
},
|
|
|
|
undefined,
|
|
|
|
{ shallow: true }
|
|
|
|
);
|
|
|
|
setSelectFilter(e.target.value);
|
|
|
|
|
|
|
|
setPage(1);
|
|
|
|
}}
|
|
|
|
value={selectFilter}
|
2022-06-24 13:42:16 +02:00
|
|
|
className={styles.select}
|
2022-06-11 23:39:03 +02:00
|
|
|
>
|
2022-06-24 13:42:16 +02:00
|
|
|
<option value="user">Vos exercices</option>
|
|
|
|
<option value="all">Tous les exercices</option>
|
2022-06-11 23:39:03 +02:00
|
|
|
</select>
|
|
|
|
)}
|
2022-05-18 10:15:54 +02:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className={styles["all_exos--container"]}>
|
|
|
|
<div className={styles["all_exos--title"]}>
|
2022-06-11 23:39:03 +02:00
|
|
|
{selectFilter == "all" && (
|
|
|
|
<h1>
|
|
|
|
Tous les <span className="primary">exercices</span>
|
|
|
|
</h1>
|
|
|
|
)}
|
|
|
|
|
|
|
|
{selectFilter == "user" && (
|
|
|
|
<h1>
|
|
|
|
Tous vos <span className="primary">exercices</span>
|
|
|
|
</h1>
|
|
|
|
)}
|
|
|
|
{selectFilter == "user" && (
|
|
|
|
<p>
|
|
|
|
Vous retrouverez ici tous les exercices que vous avez créé ou
|
|
|
|
copié depuis les exercices publics
|
|
|
|
</p>
|
|
|
|
)}
|
|
|
|
{selectFilter == "all" && (
|
|
|
|
<p>
|
|
|
|
Vous retrouverez ici tous les exercices crées par les autres
|
|
|
|
utilisateurs
|
|
|
|
</p>
|
|
|
|
)}
|
2022-05-18 10:15:54 +02:00
|
|
|
</div>
|
|
|
|
|
2022-06-11 23:39:03 +02:00
|
|
|
{selectFilter == "all" &&
|
|
|
|
publicData &&
|
|
|
|
publicData.results
|
|
|
|
//.sort((a, b) => a.id - b.id)
|
|
|
|
//.slice(page * inPage, (page + 1) * inPage)
|
|
|
|
.map((step) => {
|
|
|
|
return (
|
|
|
|
<Card
|
|
|
|
queryKey={[
|
|
|
|
"public-data",
|
|
|
|
parseInt(page),
|
|
|
|
{
|
|
|
|
search,
|
|
|
|
tags: selectedOption.map((e) => e.value),
|
|
|
|
},
|
|
|
|
]}
|
|
|
|
key={step.id}
|
|
|
|
step={step}
|
|
|
|
setActive={setActiveData}
|
|
|
|
deleted={deleted.includes(step.id_code)}
|
|
|
|
tags={tagsData}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
|
|
|
|
{selectFilter == "user" &&
|
|
|
|
userExosData &&
|
|
|
|
userExosData.results.map((step) => {
|
|
|
|
return (
|
|
|
|
<Card
|
|
|
|
queryKey={[
|
|
|
|
"user-data",
|
|
|
|
parseInt(page),
|
|
|
|
{
|
|
|
|
search,
|
|
|
|
tags: selectedOption.map((e) => e.value),
|
|
|
|
},
|
|
|
|
]}
|
|
|
|
key={step.id}
|
|
|
|
step={step}
|
|
|
|
setActive={setActiveData}
|
|
|
|
deleted={deleted.includes(step.id_code)}
|
|
|
|
tags={tagsData}
|
|
|
|
setRegistered={(reg) => {}}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
|
|
|
|
{publicData &&
|
|
|
|
publicData.results.length == 0 &&
|
|
|
|
selectFilter == "all" && <p>Aucun résultat</p>}
|
|
|
|
{userExosData &&
|
|
|
|
userExosData.results.length == 0 &&
|
|
|
|
selectFilter == "user" && <p>Aucun résultat</p>}
|
2022-05-18 10:15:54 +02:00
|
|
|
</div>
|
2022-06-11 23:39:03 +02:00
|
|
|
|
|
|
|
{selectFilter == "all" && publicData && publicData.pages != 1 && (
|
|
|
|
<Pagination setPage={setPage} page={page} pages={publicData.pages} />
|
|
|
|
)}
|
|
|
|
|
|
|
|
{selectFilter == "user" && userExosData && userExosData.pages != 1 && (
|
2022-05-18 10:15:54 +02:00
|
|
|
<Pagination
|
|
|
|
setPage={setPage}
|
2022-06-11 23:39:03 +02:00
|
|
|
page={page}
|
|
|
|
pages={userExosData.pages}
|
2022-05-18 10:15:54 +02:00
|
|
|
/>
|
|
|
|
)}
|
2022-06-24 13:42:16 +02:00
|
|
|
</div>
|
2022-06-11 23:39:03 +02:00
|
|
|
<Modal active={activeData.active || create} onClose={onClose}>
|
2022-05-18 10:15:54 +02:00
|
|
|
{activeData.data != null && create == false && (
|
|
|
|
<ModalCard
|
2022-06-11 23:39:03 +02:00
|
|
|
queryKey={[
|
2022-06-24 13:42:16 +02:00
|
|
|
selectFilter == "all" ? "public-data" : "user-data",
|
2022-06-11 23:39:03 +02:00
|
|
|
parseInt(page),
|
|
|
|
{
|
|
|
|
search,
|
|
|
|
tags: selectedOption.map((e) => e.value),
|
|
|
|
},
|
|
|
|
]}
|
2022-05-18 10:15:54 +02:00
|
|
|
step={activeData.data}
|
|
|
|
setActive={setActiveData}
|
|
|
|
modal={true}
|
2022-06-11 23:39:03 +02:00
|
|
|
onClose={onClose}
|
2022-05-18 10:15:54 +02:00
|
|
|
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);
|
|
|
|
}}
|
2022-06-24 13:42:16 +02:00
|
|
|
resetFilter={() => {
|
|
|
|
setSelectedOption([])
|
|
|
|
setSearch('')
|
|
|
|
}}
|
2022-06-11 23:39:03 +02:00
|
|
|
addExo={(newExo) => {
|
|
|
|
setUserExosData((s) => [...s, newExo]);
|
|
|
|
}}
|
2022-05-18 10:15:54 +02:00
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</Modal>
|
|
|
|
</Layout>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-06-11 23:39:03 +02:00
|
|
|
/* export async function getStaticProps() {
|
2022-05-18 10:15:54 +02:00
|
|
|
const exos = await getExos();
|
|
|
|
const tags = await getTags();
|
|
|
|
return {
|
|
|
|
props: {
|
|
|
|
exos: exos,
|
|
|
|
tags: tags,
|
|
|
|
},
|
|
|
|
revalidate: 60,
|
|
|
|
};
|
2022-06-11 23:39:03 +02:00
|
|
|
} */
|
2022-05-18 10:15:54 +02:00
|
|
|
|
2022-06-11 23:39:03 +02:00
|
|
|
/* export const getStaticPaths = async () => {
|
2022-05-18 10:15:54 +02:00
|
|
|
return {
|
|
|
|
paths: [], //indicates that no page needs be created at build time
|
|
|
|
fallback: "blocking", //indicates the type of fallback
|
|
|
|
};
|
2022-06-11 23:39:03 +02:00
|
|
|
}; */
|