2026-03-07 17:32:08 +00:00

153 lines
5.4 KiB
TypeScript

import FormContainer from "@/components/FormContainer";
import Pagination from "@/components/Pagination";
import Table from "@/components/Table";
import TableSearch from "@/components/TableSearch";
import { getSupabaseClient } from "@/lib/supabase";
import { ITEM_PER_PAGE } from "@/lib/settings";
import { Tables } from "@/types/supabase";
import Image from "next/image";
import { auth } from "@clerk/nextjs/server";
import GenerateTimetableForm from "@/components/forms/GenerateTimetableForm";
type TermList = Tables<"Term"> & { academicYear: Tables<"AcademicYear"> | null };
const TermListPage = async ({
searchParams,
}: {
searchParams: { [key: string]: string | undefined };
}) => {
const { sessionClaims } = auth();
const role = (sessionClaims?.metadata as { role?: string })?.role;
const teacherType = (sessionClaims?.metadata as { teacherType?: string })?.teacherType;
const schoolId = (sessionClaims?.metadata as { schoolId?: string })?.schoolId;
const canManageSchool =
role === "admin" ||
(role === "teacher" &&
(teacherType === "INDEPENDENT" || teacherType === "AGENCY"));
const columns = [
{ header: "Term Name", accessor: "name" },
{
header: "Academic Year",
accessor: "academicYear",
className: "hidden md:table-cell",
},
{
header: "Start Date",
accessor: "startDate",
className: "hidden md:table-cell",
},
{
header: "End Date",
accessor: "endDate",
className: "hidden md:table-cell",
},
...(canManageSchool
? [
{
header: "Actions",
accessor: "action",
},
]
: []),
];
const renderRow = (item: TermList) => (
<tr
key={item.id}
className="border-b border-gray-200 even:bg-slate-50 text-sm hover:bg-lamaPurpleLight"
>
<td className="flex items-center gap-4 p-4">{item.name}</td>
<td className="hidden md:table-cell text-gray-600">
{item.academicYear ? item.academicYear.name : "—"}
</td>
<td className="hidden md:table-cell">
{new Date(item.startDate).toLocaleDateString()}
</td>
<td className="hidden md:table-cell">
{new Date(item.endDate).toLocaleDateString()}
</td>
<td>
<div className="flex items-center gap-2">
{canManageSchool && schoolId && (
<GenerateTimetableForm termId={item.id} schoolId={schoolId} />
)}
{canManageSchool && (
<>
<FormContainer table="term" type="update" data={item} />
<FormContainer table="term" type="delete" id={item.id} />
</>
)}
</div>
</td>
</tr>
);
const { page, ...queryParams } = searchParams;
const p = page ? parseInt(page) : 1;
const supabase = await getSupabaseClient();
let query = supabase
.from("Term")
.select("*, academicYear:AcademicYear(name)", { count: "exact" });
// ONLY show terms for the current school
if (schoolId) {
query = query.eq("schoolId", schoolId);
}
if (queryParams) {
for (const [key, value] of Object.entries(queryParams)) {
if (value !== undefined) {
switch (key) {
case "search":
query = query.ilike("name", `%${value}%`);
break;
default:
break;
}
}
}
}
// PAGINATION
query = query.range(ITEM_PER_PAGE * (p - 1), ITEM_PER_PAGE * p - 1);
const { data: rawData, count, error } = await query;
if (error) {
console.error("Error fetching terms from Supabase:", error);
}
const data = (rawData || []) as unknown as TermList[];
return (
<div className="bg-white p-4 rounded-md flex-1 m-4 mt-0">
{/* TOP */}
<div className="flex items-center justify-between">
<h1 className="hidden md:block text-lg font-semibold">School Terms</h1>
<div className="flex flex-col md:flex-row items-center gap-4 w-full md:w-auto">
<TableSearch />
<div className="flex items-center gap-4 self-end">
<button className="w-8 h-8 flex items-center justify-center rounded-full bg-lamaYellow">
<Image src="/filter.png" alt="" width={14} height={14} />
</button>
<button className="w-8 h-8 flex items-center justify-center rounded-full bg-lamaYellow">
<Image src="/sort.png" alt="" width={14} height={14} />
</button>
{role === "admin" && <FormContainer table="term" type="create" />}
</div>
</div>
</div>
{/* LIST */}
<Table columns={columns} renderRow={renderRow} data={data} />
{/* PAGINATION */}
<Pagination page={p} count={count || 0} />
</div>
);
};
export default TermListPage;