Skip to content

Commit

Permalink
Merge pull request #125 from codersforcauses/issue-121-Create_Practic…
Browse files Browse the repository at this point in the history
…e_Test_Management_-_ADMIN

Issue 121 Functionality Dashboard - ADMIN
  • Loading branch information
loklokyx authored Feb 12, 2025
2 parents d31fd81 + 3c85378 commit a5786be
Show file tree
Hide file tree
Showing 52 changed files with 3,622 additions and 1,949 deletions.
5 changes: 4 additions & 1 deletion client/src/components/sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Cookies from "js-cookie";
import { useRouter } from "next/router";
import React from "react";

Expand Down Expand Up @@ -60,9 +61,11 @@ export default function Sidebar({ children, role }: LayoutProps) {
return { title, url };
});

// ref https://ui.shadcn.com/docs/components/sidebar#persisted-state
const defaultOpen = Cookies.get("sidebar:state") === "true";
return (
<div>
<SidebarProvider>
<SidebarProvider defaultOpen={defaultOpen}>
<AppSidebar className="z-50" Role={role} />
<SidebarInset>
<header className="sticky top-0 z-40 flex h-16 shrink-0 items-center gap-2 border-b bg-background px-4">
Expand Down
195 changes: 75 additions & 120 deletions client/src/components/ui/Question/category-data-grid.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { useRouter } from "next/router";
import React, { useEffect, useState } from "react";
import { toast } from "sonner";
import * as React from "react";

import { Button } from "@/components/ui/button";
import DeleteModal from "@/components/ui/delete-modal";
import { SortIcon } from "@/components/ui/icon";
import { Pagination } from "@/components/ui/pagination";
import {
Table,
TableBody,
Expand All @@ -13,135 +12,91 @@ import {
TableHeader,
TableRow,
} from "@/components/ui/table";
import { useDynamicDeleteMutation } from "@/hooks/use-delete-data";
import { cn } from "@/lib/utils";
import { DatagridProps, sortData } from "@/types/data-grid";
import { DatagridProps } from "@/types/data-grid";
import { Category } from "@/types/question";

export function CategoryDataGrid({
datacontext,
onDataChange,
changePage,
onOrderingChange = () => {},
}: DatagridProps<Category>) {
const router = useRouter();
const [isAscending, setIsAscending] = useState(true);
const [currentPage, setCurrentPage] = useState(1);
const [paddedData, setPaddedData] = useState<Category[]>([]);
const itemsPerPage = 5;
const totalPages = Math.ceil(datacontext.length / itemsPerPage);

const sortByColumn = (column: keyof Category) => {
const sortedData = sortData(datacontext, column, isAscending);
setCurrentPage(1);
onDataChange(sortedData);
setIsAscending(!isAscending);
};

const { mutate: deleteCategory, isPending } = useDynamicDeleteMutation({
baseUrl: "/questions/categories",
mutationKey: ["category_delete"],
onSuccess: () => {
router.reload();
toast.success("Category has been deleted.");
},
});

const onDelete = (id: number) => {
if (!window.confirm("Are you sure you want to delete this category?")) {
return;
}
deleteCategory(id);
};

const handlePageChange = (page: number) => {
if (page >= 1 && page <= totalPages) {
setCurrentPage(page);
}
};

useEffect(() => {
const indexOfLastItem = currentPage * itemsPerPage;
const indexOfFirstItem = indexOfLastItem - itemsPerPage;
const currentData = datacontext.slice(indexOfFirstItem, indexOfLastItem);

const updatedPaddedData = [...currentData];
while (updatedPaddedData.length < itemsPerPage) {
updatedPaddedData.push({} as Category);
}

setPaddedData(updatedPaddedData);
}, [datacontext, currentPage]);

useEffect(() => {
setCurrentPage(changePage);
}, [datacontext]);

const commonTableHeadClasses = "w-auto text-white text-nowrap";
return (
<div>
<Table className="w-full border-collapse text-left shadow-md">
<TableHeader className="bg-black text-lg font-semibold">
<TableRow className="hover:bg-muted/0">
<TableHead className={cn(commonTableHeadClasses, "rounded-tl-lg")}>
Category Id
</TableHead>
<TableHead className={commonTableHeadClasses}>
<div className="flex items-center text-white">
<span>Genre</span>
<span
className="ml-2 cursor-pointer"
onClick={() => sortByColumn("genre")}
<div className="grid">
<div className="overflow-hidden rounded-lg border">
<Table className="w-full border-collapse text-left shadow-md">
<TableHeader className="bg-black text-lg font-semibold">
<TableRow className="hover:bg-muted/0">
<TableHead className={commonTableHeadClasses}>
Category Id
</TableHead>
<TableHead
className={commonTableHeadClasses}
onClick={() => onOrderingChange("genre")}
>
<SortIcon title="Genre" />
</TableHead>
<TableHead className={commonTableHeadClasses}>Info</TableHead>
<TableHead
className={cn(
commonTableHeadClasses,
"sticky right-0 bg-black",
)}
>
Actions
</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{datacontext.length > 0 ? (
datacontext.map((item, index) => (
<TableRow
key={item.id}
className={
"divide-gray-200 border-gray-50 text-sm text-black"
}
>
<SortIcon />
</span>
</div>
</TableHead>
<TableHead className={commonTableHeadClasses}>Info</TableHead>
<TableHead className={cn(commonTableHeadClasses, "rounded-tr-lg")}>
Actions
</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{paddedData.map((item, index) => (
<TableRow
key={index}
className={"divide-gray-200 border-gray-50 text-sm text-black"}
>
<TableCell className="w-1/3">{item.id}</TableCell>
<TableCell className="w-1/3">{item.genre}</TableCell>
<TableCell className="w-1/3">{item.info}</TableCell>
<TableCell className="flex py-4">
<div
className={cn("flex w-full justify-between", {
invisible: !item.id,
})}
<TableCell className="w-0">{item.id}</TableCell>
<TableCell className="w-1/4">{item.genre}</TableCell>
<TableCell className="w-3/4 max-w-80 truncate">
{item.info}
</TableCell>
<TableCell className="sticky right-0 flex bg-white">
<div className="flex w-full justify-between">
<Button
className="me-2"
onClick={() =>
router.push(`/question/category/${item.id}`)
}
>
View
</Button>
<DeleteModal
baseUrl="/questions/categories"
entity="category"
id={item.id}
>
<Button variant={"destructive"}>Delete</Button>
</DeleteModal>
</div>
</TableCell>
</TableRow>
))
) : (
<TableRow>
<TableCell
colSpan={4}
className="py-4 text-center text-gray-500"
>
<Button
className="me-2"
onClick={() => router.push(`/question/category/${item.id}`)}
>
View
</Button>
<Button
variant={"destructive"}
onClick={() => onDelete(item.id)}
>
{isPending ? "Deleting..." : "Delete"}
</Button>
</div>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>

<Pagination
totalPages={totalPages}
currentPage={currentPage}
onPageChange={(page: number) => handlePageChange(page)}
className="mr-20 mt-5 flex justify-end"
/>
No Results Found
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export function CategoryDataTableForm() {
mutationKey: ["categories"],
endpoint: "/questions/categories/",
onSuccess: () => {
toast.success("Teams created successfully!");
toast.success("Categories created successfully!");
router.push("/question/category/");
},
});
Expand Down
Loading

0 comments on commit a5786be

Please sign in to comment.