395 lines
13 KiB
JavaScript
395 lines
13 KiB
JavaScript
import { createRef, useEffect, useRef } from "react";
|
|
import { useState } from "react";
|
|
import { FiLink } from "react-icons/fi";
|
|
import useFilter from "../../hooks/useFilter.hook.jsx";
|
|
import styles from "../../styles/pdf_gen/selectExo.module.scss";
|
|
import { isBrowser, isEmpty, parseClassName } from "../../utils/utils.js";
|
|
import TagSelect from "../exos/TagSelect.jsx";
|
|
import Modal from "../Modal.jsx";
|
|
import Tag from "../Tag.jsx";
|
|
import ParamItem from "./ParamItem.jsx";
|
|
import TagContainer from "./tagContainer.jsx";
|
|
import { AiOutlineClose } from "react-icons/ai";
|
|
import { useInfiniteQuery, useQuery } from "react-query";
|
|
import {
|
|
getExos,
|
|
getPublicExos,
|
|
getTags,
|
|
getUserExos,
|
|
} from "../../requests/requests.exos.js";
|
|
import { useInView } from "react-intersection-observer";
|
|
import { useSessionContext } from "../../context/session.context.js";
|
|
|
|
export default function SelectExo({
|
|
exos,
|
|
setExos,
|
|
emptyError,
|
|
onlyNumber = false,
|
|
}) {
|
|
const { ref, inView } = useInView();
|
|
const [active, setActive] = useState(false);
|
|
|
|
const { data: tagsData } = useQuery(
|
|
["tags"],
|
|
async () => {
|
|
return await getTags();
|
|
},
|
|
{ enabled: active, staleTime: 60 * 1000 }
|
|
);
|
|
const [selectedOption, setSelectedOption] = useState([]);
|
|
const [selectFilter, setSelectFilter] = useState(
|
|
isBrowser && localStorage.getItem("token") != null ? "user" : "all"
|
|
);
|
|
const [search, setSearch] = useState("");
|
|
|
|
|
|
const {
|
|
isLoading,
|
|
isError,
|
|
data,
|
|
fetchNextPage,
|
|
hasNextPage,
|
|
isFetching,
|
|
isFetchingNextPage,
|
|
} = useInfiniteQuery(
|
|
["userExo-data", { search, tags: selectedOption.map((t) => t.value) }],
|
|
({ pageParam = 0 }) => {
|
|
return getUserExos("pdf", pageParam == 0 ? 1 : pageParam, {
|
|
search,
|
|
tags: selectedOption.map((t) => t.value),
|
|
}).then((res) => {
|
|
return {
|
|
...res,
|
|
results: [
|
|
...res.results.map((r) => {
|
|
return { ...r, numberInExo: 10, numberOfExo: 1 };
|
|
}),
|
|
],
|
|
};
|
|
});
|
|
},
|
|
{
|
|
enabled: (active && selectFilter == "user") /* || exos.length != 0 */,
|
|
staleTime: 60 * 1000,
|
|
refetchOnWindowFocus: false,
|
|
keepPreviousData: true,
|
|
getPreviousPageParam: (firstPage) =>
|
|
firstPage.links.previous ? firstPage.page_number - 1 : undefined,
|
|
getNextPageParam: (lastPage) =>
|
|
lastPage.links.next ? lastPage.page_number + 1 : undefined,
|
|
}
|
|
);
|
|
const {
|
|
isLoading: publicLoading,
|
|
isError: publicError,
|
|
data: publicData,
|
|
fetchNextPage: publicFetchNextPage,
|
|
hasNextPage: publicHasNextPage,
|
|
isFetching: publicFetching,
|
|
isFetchingNextPage: publicIsFetchingNextPage,
|
|
} = useInfiniteQuery(
|
|
["publicExo-data", { search, tags: selectedOption.map((t) => t.value) }],
|
|
({ pageParam = 0 }) => {
|
|
return getPublicExos("pdf", pageParam == 0 ? 1 : pageParam, {
|
|
search,
|
|
tags: selectedOption.map((t) => t.value),
|
|
}).then((res) => {
|
|
return {
|
|
...res,
|
|
results: [
|
|
...res.results.map((r) => {
|
|
return { ...r, numberInExo: 10, numberOfExo: 1 };
|
|
}),
|
|
],
|
|
};
|
|
});
|
|
},
|
|
{
|
|
enabled: (active && selectFilter == "all") /* || exos.length != 0 */,
|
|
staleTime: 60 * 1000,
|
|
refetchOnWindowFocus: false,
|
|
keepPreviousData: true,
|
|
getPreviousPageParam: (firstPage) =>
|
|
firstPage.links.previous ? firstPage.page_number - 1 : undefined,
|
|
getNextPageParam: (lastPage) =>
|
|
lastPage.links.next ? lastPage.page_number + 1 : undefined,
|
|
}
|
|
);
|
|
|
|
useEffect(() => {
|
|
if (inView) {
|
|
selectFilter == "user" ? fetchNextPage() : publicFetchNextPage();
|
|
}
|
|
}, [inView]);
|
|
|
|
const {authData} = useSessionContext()
|
|
|
|
return (
|
|
<>
|
|
<div className={styles["exo-select"]}>
|
|
<div className={styles["head"]}>
|
|
<p>Ajouter exercices</p>
|
|
<p className={styles.add} onClick={() => setActive(true)}>
|
|
+
|
|
</p>
|
|
</div>
|
|
<div className={styles["exos-selected"]}>
|
|
{exos.length === 0 && (
|
|
<>
|
|
<p
|
|
className={parseClassName([
|
|
styles["no-select"],
|
|
emptyError ? styles["error-empty"] : undefined,
|
|
])}
|
|
>
|
|
Aucun exercice selectionné
|
|
</p>
|
|
{emptyError == true && (
|
|
<p className={parseClassName(["error-msg", styles.error])}>
|
|
Veuillez selectionner un exercice au minimum
|
|
</p>
|
|
)}
|
|
</>
|
|
)}
|
|
|
|
{exos.map((s, i) => {
|
|
return (
|
|
<ParamItem
|
|
exo={{
|
|
name: s.name,
|
|
...exos.filter((ex) => ex.id_code == s.id_code)[0],
|
|
}}
|
|
unSelect={() => {
|
|
setExos((o) => [
|
|
...o.filter((ex) => {
|
|
return ex.id_code != s.id_code;
|
|
}),
|
|
]);
|
|
}}
|
|
setExo={(nbIn, nbOf) => {
|
|
setExos((o) => [
|
|
...o.map((ex) => {
|
|
if (ex.id_code == s.id_code) {
|
|
return {
|
|
...ex,
|
|
numberInExo: nbIn,
|
|
numberOfExo: nbOf,
|
|
};
|
|
}
|
|
return ex;
|
|
}),
|
|
]);
|
|
}}
|
|
key={i}
|
|
onlyNumber={onlyNumber}
|
|
/>
|
|
);
|
|
})}
|
|
{/* {[
|
|
...(data || { pages: [] }).pages,
|
|
...(publicData || { pages: [] }).pages,
|
|
]
|
|
.map((p) => p.results)
|
|
.flat()
|
|
.filter((e) => {
|
|
return exos.map((ex) => ex.id_code).includes(e.id_code);
|
|
})
|
|
.sort((a, b) => {
|
|
return (
|
|
exos.map((ex) => ex.id_code).indexOf(a.id_code) -
|
|
exos.map((ex) => ex.id_code).indexOf(b.id_code)
|
|
);
|
|
})
|
|
.map((s, i) => {
|
|
return (
|
|
<ParamItem
|
|
exo={{
|
|
name: s.name,
|
|
...exos.filter((ex) => ex.id_code == s.id_code)[0],
|
|
}}
|
|
unSelect={() => {
|
|
setExos((o) => [
|
|
...o.filter((ex) => {
|
|
return ex.id_code != s.id_code;
|
|
}),
|
|
]);
|
|
}}
|
|
setExo={(nbIn, nbOf) => {
|
|
setExos((o) => [
|
|
...o.map((ex) => {
|
|
if (ex.id_code == s.id_code) {
|
|
return {
|
|
...ex,
|
|
numberInExo: nbIn,
|
|
numberOfExo: nbOf,
|
|
};
|
|
}
|
|
return ex;
|
|
}),
|
|
]);
|
|
}}
|
|
key={i}
|
|
onlyNumber={onlyNumber}
|
|
/>
|
|
);
|
|
})} */}
|
|
</div>
|
|
</div>
|
|
<Modal active={active} onClose={() => setActive(false)}>
|
|
<div className={styles["modal-list-container"]}>
|
|
<div className={styles["search-container"]}>
|
|
<input
|
|
type="text"
|
|
className="exo-input"
|
|
placeholder="Rechercher..."
|
|
value={search}
|
|
onChange={(e) => {
|
|
setSearch(e.target.value);
|
|
}}
|
|
/>
|
|
|
|
<div style={{ display: "flex" }}>
|
|
{tagsData && !isEmpty(authData) && (
|
|
<TagSelect
|
|
tags={tagsData}
|
|
onChange={setSelectedOption}
|
|
select={selectedOption}
|
|
/>
|
|
)}
|
|
{!isEmpty(authData) && (
|
|
<select
|
|
className={styles.select}
|
|
value={selectFilter}
|
|
onChange={(e) => {
|
|
setSelectFilter(e.target.value);
|
|
}}
|
|
>
|
|
<option value="all">Tous</option>
|
|
<option value="user">User</option>
|
|
</select>
|
|
)}
|
|
</div>
|
|
</div>
|
|
<div>
|
|
{selectFilter == "user" &&
|
|
data &&
|
|
data.pages.map((p) => p.results).flat().length == 0 && (
|
|
<p className={styles["no-select"]}>Aucun résultat</p>
|
|
)}
|
|
{selectFilter == "all" &&
|
|
publicData &&
|
|
publicData.pages.map((p) => p.results).flat().length == 0 && (
|
|
<p className={styles["no-select"]}>Aucun résultat</p>
|
|
)}
|
|
|
|
{selectFilter == "user" &&
|
|
data &&
|
|
data.pages.map((page) => {
|
|
return page.results.map((d, i) => {
|
|
return (
|
|
<div
|
|
key={i}
|
|
onClick={() => {
|
|
if (!exos.map((ex) => ex.id_code).includes(d.id_code)) {
|
|
setExos((o) => [
|
|
...o,
|
|
{
|
|
id_code: d.id_code,
|
|
numberInExo: d.numberInExo,
|
|
numberOfExo: d.numberOfExo,
|
|
name: d.name,
|
|
},
|
|
]);
|
|
} else {
|
|
setExos((o) => [
|
|
...o.filter((ex) => {
|
|
return ex.id_code != d.id_code;
|
|
}),
|
|
]);
|
|
}
|
|
}}
|
|
className={parseClassName([
|
|
exos.map((ex) => ex.id_code).includes(d.id_code)
|
|
? styles["selected"]
|
|
: undefined,
|
|
styles["item-in-modal"],
|
|
"pointer",
|
|
])}
|
|
>
|
|
<div className={styles["modal-name"]}>{d.name}</div>
|
|
|
|
{d.tags.length !== 0 && <TagContainer tags={d.tags} />}
|
|
</div>
|
|
);
|
|
});
|
|
})}
|
|
|
|
{selectFilter == "all" &&
|
|
publicData &&
|
|
publicData.pages.map((page) => {
|
|
return page.results.map((d, i) => {
|
|
return (
|
|
<div
|
|
key={i}
|
|
onClick={() => {
|
|
if (!exos.map((ex) => ex.id_code).includes(d.id_code)) {
|
|
setExos((o) => [
|
|
...o,
|
|
{
|
|
id_code: d.id_code,
|
|
numberInExo: d.numberInExo,
|
|
numberOfExo: d.numberOfExo,
|
|
name: d.name,
|
|
},
|
|
]);
|
|
} else {
|
|
setExos((o) => [
|
|
...o.filter((ex) => {
|
|
return ex.id_code != d.id_code;
|
|
}),
|
|
]);
|
|
}
|
|
}}
|
|
className={parseClassName([
|
|
exos.map((ex) => ex.id_code).includes(d.id_code)
|
|
? styles["selected"]
|
|
: undefined,
|
|
styles["item-in-modal"],
|
|
"pointer",
|
|
])}
|
|
>
|
|
<div className={styles["modal-name"]}>{d.name}</div>
|
|
|
|
{d.tags.length !== 0 && <TagContainer tags={d.tags} />}
|
|
</div>
|
|
);
|
|
});
|
|
})}
|
|
<span ref={ref}></span>
|
|
{isFetchingNextPage ||
|
|
(isFetching && (
|
|
<div className={styles["loader-container"]}>
|
|
<span className="loader"></span>
|
|
</div>
|
|
))}
|
|
{publicIsFetchingNextPage ||
|
|
(publicFetching && (
|
|
<div className={styles["loader-container"]}>
|
|
<span className="loader"></span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
<div className={styles["icon-container"]}>
|
|
<AiOutlineClose
|
|
className={styles["icon"]}
|
|
onClick={() => {
|
|
setActive(false);
|
|
}}
|
|
/>
|
|
</div>
|
|
</Modal>
|
|
</>
|
|
);
|
|
}
|