added access variable to exams soo we can distinguish private, public and confidential exams and also bugfixes and improvements

This commit is contained in:
José Lima
2025-02-09 04:28:34 +00:00
parent f95bce6fa2
commit b175d8797e
32 changed files with 1320 additions and 909 deletions

View File

@@ -1,60 +1,141 @@
import Button from "@/components/Low/Button";
import {useMemo, useState} from "react";
import {BiChevronLeft} from "react-icons/bi";
import {BsChevronDoubleLeft, BsChevronDoubleRight, BsChevronLeft, BsChevronRight} from "react-icons/bs";
import { useEffect, useMemo, useState } from "react";
import {
BsChevronDoubleLeft,
BsChevronDoubleRight,
BsChevronLeft,
BsChevronRight,
} from "react-icons/bs";
import Select from "../components/Low/Select";
export default function usePagination<T>(list: T[], size = 25) {
const [page, setPage] = useState(0);
const [page, setPage] = useState(0);
const [itemsPerPage, setItemsPerPage] = useState(size);
const items = useMemo(() => list.slice(page * size, (page + 1) * size), [page, size, list]);
const items = useMemo(
() => list.slice(page * itemsPerPage, (page + 1) * itemsPerPage),
[list, page, itemsPerPage]
);
useEffect(() => {
if (page * itemsPerPage >= list.length) setPage(0);
}, [items, itemsPerPage, list.length, page]);
const render = () => (
<div className="w-full flex gap-2 justify-between items-center">
<div className="flex items-center gap-4 w-fit">
<Button className="w-[200px] h-fit" disabled={page === 0} onClick={() => setPage((prev) => prev - 1)}>
Previous Page
</Button>
</div>
<div className="flex items-center gap-4 w-fit">
<span className="opacity-80">
{page * size + 1} - {(page + 1) * size > list.length ? list.length : (page + 1) * size} / {list.length}
</span>
<Button className="w-[200px]" disabled={(page + 1) * size >= list.length} onClick={() => setPage((prev) => prev + 1)}>
Next Page
</Button>
</div>
</div>
);
const itemsPerPageOptions = [25, 50, 100, 200];
const renderMinimal = () => (
<div className="flex gap-4 items-center">
<div className="flex gap-2 items-center">
<button disabled={page === 0} onClick={() => setPage(0)} className="disabled:opacity-60 disabled:cursor-not-allowed">
<BsChevronDoubleLeft />
</button>
<button disabled={page === 0} onClick={() => setPage((prev) => prev - 1)} className="disabled:opacity-60 disabled:cursor-not-allowed">
<BsChevronLeft />
</button>
</div>
<span className="opacity-80 w-32 text-center">
{page * size + 1} - {(page + 1) * size > list.length ? list.length : (page + 1) * size} / {list.length}
</span>
<div className="flex gap-2 items-center">
<button
disabled={(page + 1) * size >= list.length}
onClick={() => setPage((prev) => prev + 1)}
className="disabled:opacity-60 disabled:cursor-not-allowed">
<BsChevronRight />
</button>
<button
disabled={(page + 1) * size >= list.length}
onClick={() => setPage(Math.floor(list.length / size))}
className="disabled:opacity-60 disabled:cursor-not-allowed">
<BsChevronDoubleRight />
</button>
</div>
</div>
);
const render = () => (
<div className="w-full flex gap-2 justify-between items-center">
<div className="flex items-center gap-4 w-fit">
<Button
className="w-[200px] h-fit"
disabled={page === 0}
onClick={() => setPage((prev) => prev - 1)}
>
Previous Page
</Button>
</div>
<div className="flex items-center gap-4 w-fit">
<div className="flex flex-row items-center gap-1 w-56">
<Select
value={{
value: itemsPerPage.toString(),
label: (itemsPerPage * page > items.length
? items.length
: itemsPerPage * page
).toString(),
}}
onChange={(value) =>
setItemsPerPage(parseInt(value!.value ?? "25"))
}
options={itemsPerPageOptions.map((size) => ({
label: size.toString(),
value: size.toString(),
}))}
isClearable={false}
styles={{
control: (styles) => ({ ...styles, width: "100px" }),
container: (styles) => ({ ...styles, width: "100px" }),
}}
/>
<span className="opacity-80 w-32 text-center">
{page * itemsPerPage + 1} -{" "}
{itemsPerPage * (page + 1) > list.length
? list.length
: itemsPerPage * (page + 1)}
{list.length}
</span>
</div>
<Button
className="w-[200px]"
disabled={(page + 1) * itemsPerPage >= list.length}
onClick={() => setPage((prev) => prev + 1)}
>
Next Page
</Button>
</div>
</div>
);
return {page, items, setPage, render, renderMinimal};
const renderMinimal = () => (
<div className="flex gap-4 items-center">
<div className="flex gap-2 items-center">
<button
disabled={page === 0}
onClick={() => setPage(0)}
className="disabled:opacity-60 disabled:cursor-not-allowed"
>
<BsChevronDoubleLeft />
</button>
<button
disabled={page === 0}
onClick={() => setPage((prev) => prev - 1)}
className="disabled:opacity-60 disabled:cursor-not-allowed"
>
<BsChevronLeft />
</button>
</div>
<div className="flex flex-row items-center gap-1 w-56">
<Select
value={{
value: itemsPerPage.toString(),
label: itemsPerPage.toString(),
}}
onChange={(value) => setItemsPerPage(parseInt(value!.value ?? "25"))}
options={itemsPerPageOptions.map((size) => ({
label: size.toString(),
value: size.toString(),
}))}
isClearable={false}
styles={{
control: (styles) => ({ ...styles, width: "100px" }),
container: (styles) => ({ ...styles, width: "100px" }),
}}
/>
<span className="opacity-80 w-32 text-center">
{page * itemsPerPage + 1} -{" "}
{itemsPerPage * (page + 1) > list.length
? list.length
: itemsPerPage * (page + 1)}
/ {list.length}
</span>
</div>
<div className="flex gap-2 items-center">
<button
disabled={(page + 1) * itemsPerPage >= list.length}
onClick={() => setPage((prev) => prev + 1)}
className="disabled:opacity-60 disabled:cursor-not-allowed"
>
<BsChevronRight />
</button>
<button
disabled={(page + 1) * itemsPerPage >= list.length}
onClick={() => setPage(Math.floor(list.length / itemsPerPage))}
className="disabled:opacity-60 disabled:cursor-not-allowed"
>
<BsChevronDoubleRight />
</button>
</div>
</div>
);
return { page, items, setPage, render, renderMinimal };
}