Skip to content

Commit

Permalink
Implement Admin Dashboard Instructors Page Active Instructor Table
Browse files Browse the repository at this point in the history
  • Loading branch information
prominhaj committed Aug 4, 2024
1 parent fe55db2 commit f744227
Show file tree
Hide file tree
Showing 6 changed files with 255 additions and 20 deletions.
34 changes: 34 additions & 0 deletions app/(admin)/admin/instructors/_components/ActiveInstructor.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { DataTable } from "@/app/dashboard/courses/_components/data-table";
import { getAdminInstructors } from "@/queries/admin";
import { columns } from "./columns";
import { getCourseDetailsByInstructor } from "@/queries/courses";

const ActiveInstructor = async () => {
const activeInstructors = await getAdminInstructors("Teacher");

const modifiedInstructors = await Promise.all(activeInstructors.map(async instructor => {
const { courses, enrollments, ratings } = await getCourseDetailsByInstructor(instructor?.id);

return {
id: instructor.id,
role: instructor.role,
image: instructor?.profilePicture?.url,
name: instructor?.firstName + " " + instructor?.lastName,
email: instructor.email,
status: "Active",
courses,
enrollments,
ratings
}
}))

console.log(modifiedInstructors);

return (
<div>
<DataTable columns={columns} data={modifiedInstructors} />
</div>
);
};

export default ActiveInstructor;
10 changes: 10 additions & 0 deletions app/(admin)/admin/instructors/_components/PendingInstructor.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

const PendingInstructor = () => {
return (
<div>

</div>
);
};

export default PendingInstructor;
181 changes: 181 additions & 0 deletions app/(admin)/admin/instructors/_components/columns.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
"use client";

import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { cn } from "@/lib/utils";
import { GraduationCap, Trash } from "lucide-react";
import { Star } from "lucide-react";
import { ArrowUpDown, MoreHorizontal, Pencil } from "lucide-react";
import Link from "next/link";

export const columns = [
{
accessorKey: "image",
header: ({ column }) => {
return (
<Button
variant="ghost"
>
Photo
</Button>
);
},
cell: ({ row }) => {
const photo = row?.original?.image;
const name = row?.original?.name;

return <div className="ml-3">
<Avatar>
<AvatarImage className="object-cover" src={photo} alt={name} />
<AvatarFallback>{name.slice(0, 2)}</AvatarFallback>
</Avatar>
</div>;
},
},
{
accessorKey: "name",
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Name <ArrowUpDown className="w-4 h-4 ml-2" />
</Button>
);
}
},
{
accessorKey: "email",
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Email <ArrowUpDown className="w-4 h-4 ml-2" />
</Button>
);
}
},
{
accessorKey: "courses",
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Course <ArrowUpDown className="w-4 h-4 ml-2" />
</Button>
);
},
cell: ({ row }) => {
const courses = row.original.courses;

return (
<div className="ml-4">
{courses}
</div>
);
},
},
{
accessorKey: "enrollments",
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Enrollment <ArrowUpDown className="w-4 h-4 ml-2" />
</Button>
);
},
cell: ({ row }) => {
const enrollments = row.original.enrollments;

return (
<div className="ml-4">
{enrollments}
</div>
);
},
},
{
accessorKey: "ratings",
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Rating <ArrowUpDown className="w-4 h-4 ml-2" />
</Button>
);
},
cell: ({ row }) => {
const ratings = row.original.ratings;

return (
<div className="ml-4">
{ratings}
</div>
);
},
},
{
accessorKey: "status",
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Status <ArrowUpDown className="w-4 h-4 ml-2" />
</Button>
);
},
cell: ({ row }) => {
const status = row.original.status;

return (
<Badge className={cn("bg-gray-500 ml-4", status === "Active" && "bg-success")}>
{status === "Active" && "Active"}
</Badge>
);
},
},
{
id: "actions",
cell: ({ row }) => {
const { id } = row.original;

return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="w-8 h-4 p-0">
<span className="sr-only">Open Menu</span>
<MoreHorizontal className="w-4 h-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<button className="w-full">
<DropdownMenuItem className="flex items-center w-full gap-2 cursor-pointer">
<Trash className="w-4 h-4" />
Delete
</DropdownMenuItem>
</button>
</DropdownMenuContent>
</DropdownMenu>
);
},
},
];
14 changes: 10 additions & 4 deletions app/(admin)/admin/instructors/page.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import BreadcrumbSection from '@/components/globals/Breadcrumb/BreadcrumbSection';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { cookies } from 'next/headers';
import ActiveInstructor from './_components/ActiveInstructor';
import PendingInstructor from './_components/PendingInstructor';

// items
const items = [
Expand All @@ -20,13 +22,17 @@ const AdminDashboardInstructorPage = () => {
<>
<BreadcrumbSection items={items} />
<div className='px-6 py-3'>
<Tabs defaultValue='active' className='max-w-sm mx-auto'>
<TabsList className='grid w-full grid-cols-2'>
<Tabs defaultValue='active' className='w-full'>
<TabsList className='grid max-w-sm grid-cols-2 mx-auto'>
<TabsTrigger value='active'>Active</TabsTrigger>
<TabsTrigger value='pending'>Pending</TabsTrigger>
</TabsList>
<TabsContent value='active'></TabsContent>
<TabsContent value='pending'></TabsContent>
<TabsContent value='active'>
<ActiveInstructor />
</TabsContent>
<TabsContent value='pending'>
<PendingInstructor />
</TabsContent>
</Tabs>
</div>
</>
Expand Down
20 changes: 4 additions & 16 deletions app/dashboard/courses/_components/data-table.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,9 @@ import {
} from "@/components/ui/table";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import Link from "next/link";
import { PlusCircle } from "lucide-react";
import { useState } from "react";

export function DataTable({ columns, data, isAdmin }) {
export function DataTable({ columns, data }) {
const [sorting, setSorting] = useState([]);
const [columnFilters, setColumnFilters] = useState([]);

Expand All @@ -45,23 +43,13 @@ export function DataTable({ columns, data, isAdmin }) {
<div>
<div className="flex items-center justify-between py-4">
<Input
placeholder="Filter courses..."
value={table.getColumn("title")?.getFilterValue() ?? ""}
placeholder="Filter names..."
value={table.getColumn("name")?.getFilterValue() ?? ""}
onChange={(event) =>
table.getColumn("title")?.setFilterValue(event.target.value)
table.getColumn("name")?.setFilterValue(event.target.value)
}
className="max-w-sm"
/>
{
!isAdmin && (
<Link href="/dashboard/courses/add">
<Button>
<PlusCircle className="w-4 h-4 mr-2" />
New Course
</Button>
</Link>
)
}
</div>
<div className="border rounded-md">
<Table>
Expand Down
16 changes: 16 additions & 0 deletions queries/admin.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { replaceMongoIdInArray } from '@/lib/convertData';
import Enrollment from '@/modals/enrollment-model';
import User from '@/modals/users-modal';

export const calculateSales = async () => {
const now = new Date();
Expand Down Expand Up @@ -95,3 +97,17 @@ export const calculateSales = async () => {
percentChange: parseFloat(percentChange.toFixed(2))
};
};

export const getAdminInstructors = async (type) => {
try {
const adminInstructors = await User.find({
role: type
})
.select('-password')
.lean();

return replaceMongoIdInArray(adminInstructors);
} catch (error) {
throw new Error(error);
}
};

0 comments on commit f744227

Please sign in to comment.