Module Update
This commit is contained in:
25
src/modules/dashboard/components/admin-view.tsx
Normal file
25
src/modules/dashboard/components/admin-view.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
"use client"
|
||||
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/shared/components/ui/card"
|
||||
|
||||
export function AdminDashboard() {
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<h1 className="text-3xl font-bold tracking-tight">Admin Dashboard</h1>
|
||||
<div className="grid gap-4 md:grid-cols-3">
|
||||
<Card>
|
||||
<CardHeader><CardTitle>System Status</CardTitle></CardHeader>
|
||||
<CardContent className="text-green-600 font-bold">Operational</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader><CardTitle>Total Users</CardTitle></CardHeader>
|
||||
<CardContent>2,450</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader><CardTitle>Active Sessions</CardTitle></CardHeader>
|
||||
<CardContent>142</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
105
src/modules/dashboard/components/recent-submissions.tsx
Normal file
105
src/modules/dashboard/components/recent-submissions.tsx
Normal file
@@ -0,0 +1,105 @@
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/shared/components/ui/card";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/shared/components/ui/avatar";
|
||||
import { EmptyState } from "@/shared/components/ui/empty-state";
|
||||
import { Inbox } from "lucide-react";
|
||||
|
||||
interface SubmissionItem {
|
||||
id: string;
|
||||
studentName: string;
|
||||
studentAvatar?: string;
|
||||
assignment: string;
|
||||
submittedAt: string;
|
||||
status: "submitted" | "late";
|
||||
}
|
||||
|
||||
const MOCK_SUBMISSIONS: SubmissionItem[] = [
|
||||
{
|
||||
id: "1",
|
||||
studentName: "Alice Johnson",
|
||||
assignment: "React Component Composition",
|
||||
submittedAt: "10 minutes ago",
|
||||
status: "submitted",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
studentName: "Bob Smith",
|
||||
assignment: "Design System Analysis",
|
||||
submittedAt: "1 hour ago",
|
||||
status: "submitted",
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
studentName: "Charlie Brown",
|
||||
assignment: "React Component Composition",
|
||||
submittedAt: "2 hours ago",
|
||||
status: "late",
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
studentName: "Diana Prince",
|
||||
assignment: "CSS Grid Layout",
|
||||
submittedAt: "Yesterday",
|
||||
status: "submitted",
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
studentName: "Evan Wright",
|
||||
assignment: "Design System Analysis",
|
||||
submittedAt: "Yesterday",
|
||||
status: "submitted",
|
||||
},
|
||||
];
|
||||
|
||||
export function RecentSubmissions() {
|
||||
const hasSubmissions = MOCK_SUBMISSIONS.length > 0;
|
||||
|
||||
return (
|
||||
<Card className="col-span-4 lg:col-span-4">
|
||||
<CardHeader>
|
||||
<CardTitle>Recent Submissions</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{!hasSubmissions ? (
|
||||
<EmptyState
|
||||
icon={Inbox}
|
||||
title="No New Submissions"
|
||||
description="All caught up! There are no new submissions to review."
|
||||
className="border-none h-[300px]"
|
||||
/>
|
||||
) : (
|
||||
<div className="space-y-6">
|
||||
{MOCK_SUBMISSIONS.map((item) => (
|
||||
<div key={item.id} className="flex items-center justify-between group">
|
||||
<div className="flex items-center space-x-4">
|
||||
<Avatar className="h-9 w-9">
|
||||
<AvatarImage src={item.studentAvatar} alt={item.studentName} />
|
||||
<AvatarFallback>{item.studentName.charAt(0)}</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="space-y-1">
|
||||
<p className="text-sm font-medium leading-none">
|
||||
{item.studentName}
|
||||
</p>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Submitted <span className="font-medium text-foreground">{item.assignment}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="text-sm text-muted-foreground">
|
||||
{/* Using static date for demo to prevent hydration mismatch */}
|
||||
{item.submittedAt}
|
||||
</div>
|
||||
{item.status === "late" && (
|
||||
<span className="inline-flex items-center rounded-full border border-destructive px-2 py-0.5 text-xs font-semibold text-destructive transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2">
|
||||
Late
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
21
src/modules/dashboard/components/student-view.tsx
Normal file
21
src/modules/dashboard/components/student-view.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
"use client"
|
||||
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/shared/components/ui/card"
|
||||
|
||||
export function StudentDashboard() {
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<h1 className="text-3xl font-bold tracking-tight">Student Dashboard</h1>
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||
<Card>
|
||||
<CardHeader><CardTitle>My Courses</CardTitle></CardHeader>
|
||||
<CardContent>Enrolled in 5 courses</CardContent>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardHeader><CardTitle>Assignments</CardTitle></CardHeader>
|
||||
<CardContent>2 due this week</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
21
src/modules/dashboard/components/teacher-quick-actions.tsx
Normal file
21
src/modules/dashboard/components/teacher-quick-actions.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { Button } from "@/shared/components/ui/button";
|
||||
import { PlusCircle, CheckSquare, MessageSquare } from "lucide-react";
|
||||
|
||||
export function TeacherQuickActions() {
|
||||
return (
|
||||
<div className="flex items-center space-x-2">
|
||||
<Button size="sm">
|
||||
<PlusCircle className="mr-2 h-4 w-4" />
|
||||
Create Assignment
|
||||
</Button>
|
||||
<Button variant="outline" size="sm">
|
||||
<CheckSquare className="mr-2 h-4 w-4" />
|
||||
Grade All
|
||||
</Button>
|
||||
<Button variant="outline" size="sm">
|
||||
<MessageSquare className="mr-2 h-4 w-4" />
|
||||
Message Class
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
81
src/modules/dashboard/components/teacher-schedule.tsx
Normal file
81
src/modules/dashboard/components/teacher-schedule.tsx
Normal file
@@ -0,0 +1,81 @@
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/shared/components/ui/card";
|
||||
import { Badge } from "@/shared/components/ui/badge";
|
||||
import { Clock, MapPin, CalendarX } from "lucide-react";
|
||||
import { EmptyState } from "@/shared/components/ui/empty-state";
|
||||
|
||||
interface ScheduleItem {
|
||||
id: string;
|
||||
course: string;
|
||||
time: string;
|
||||
location: string;
|
||||
type: "Lecture" | "Workshop" | "Lab";
|
||||
}
|
||||
|
||||
// MOCK_SCHEDULE can be empty to test empty state
|
||||
const MOCK_SCHEDULE: ScheduleItem[] = [
|
||||
{
|
||||
id: "1",
|
||||
course: "Advanced Web Development",
|
||||
time: "09:00 AM - 10:30 AM",
|
||||
location: "Room 304",
|
||||
type: "Lecture",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
course: "UI/UX Design Principles",
|
||||
time: "11:00 AM - 12:30 PM",
|
||||
location: "Design Studio A",
|
||||
type: "Workshop",
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
course: "Frontend Frameworks",
|
||||
time: "02:00 PM - 03:30 PM",
|
||||
location: "Online (Zoom)",
|
||||
type: "Lecture",
|
||||
},
|
||||
];
|
||||
|
||||
export function TeacherSchedule() {
|
||||
const hasSchedule = MOCK_SCHEDULE.length > 0;
|
||||
|
||||
return (
|
||||
<Card className="col-span-3">
|
||||
<CardHeader>
|
||||
<CardTitle>Today's Schedule</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{!hasSchedule ? (
|
||||
<EmptyState
|
||||
icon={CalendarX}
|
||||
title="No Classes Today"
|
||||
description="You have no classes scheduled for today. Enjoy your free time!"
|
||||
className="border-none h-[300px]"
|
||||
/>
|
||||
) : (
|
||||
<div className="space-y-4">
|
||||
{MOCK_SCHEDULE.map((item) => (
|
||||
<div
|
||||
key={item.id}
|
||||
className="flex items-center justify-between border-b pb-4 last:border-0 last:pb-0"
|
||||
>
|
||||
<div className="space-y-1">
|
||||
<p className="font-medium leading-none">{item.course}</p>
|
||||
<div className="flex items-center text-sm text-muted-foreground">
|
||||
<Clock className="mr-1 h-3 w-3" />
|
||||
<span className="mr-3">{item.time}</span>
|
||||
<MapPin className="mr-1 h-3 w-3" />
|
||||
<span>{item.location}</span>
|
||||
</div>
|
||||
</div>
|
||||
<Badge variant={item.type === "Lecture" ? "default" : "secondary"}>
|
||||
{item.type}
|
||||
</Badge>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
83
src/modules/dashboard/components/teacher-stats.tsx
Normal file
83
src/modules/dashboard/components/teacher-stats.tsx
Normal file
@@ -0,0 +1,83 @@
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/shared/components/ui/card";
|
||||
import { Users, BookOpen, FileCheck, Calendar } from "lucide-react";
|
||||
import { Skeleton } from "@/shared/components/ui/skeleton";
|
||||
|
||||
interface StatItem {
|
||||
title: string;
|
||||
value: string;
|
||||
description: string;
|
||||
icon: React.ElementType;
|
||||
}
|
||||
|
||||
const MOCK_STATS: StatItem[] = [
|
||||
{
|
||||
title: "Total Students",
|
||||
value: "1,248",
|
||||
description: "+12% from last semester",
|
||||
icon: Users,
|
||||
},
|
||||
{
|
||||
title: "Active Courses",
|
||||
value: "4",
|
||||
description: "2 lectures, 2 workshops",
|
||||
icon: BookOpen,
|
||||
},
|
||||
{
|
||||
title: "To Grade",
|
||||
value: "28",
|
||||
description: "5 submissions pending review",
|
||||
icon: FileCheck,
|
||||
},
|
||||
{
|
||||
title: "Upcoming Classes",
|
||||
value: "3",
|
||||
description: "Today's schedule",
|
||||
icon: Calendar,
|
||||
},
|
||||
];
|
||||
|
||||
interface TeacherStatsProps {
|
||||
isLoading?: boolean;
|
||||
}
|
||||
|
||||
export function TeacherStats({ isLoading = false }: TeacherStatsProps) {
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||
{Array.from({ length: 4 }).map((_, i) => (
|
||||
<Card key={i}>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<Skeleton className="h-4 w-[100px]" />
|
||||
<Skeleton className="h-4 w-4 rounded-full" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Skeleton className="h-8 w-[60px] mb-2" />
|
||||
<Skeleton className="h-3 w-[140px]" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||
{MOCK_STATS.map((stat, i) => (
|
||||
<Card key={i}>
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
||||
<CardTitle className="text-sm font-medium">
|
||||
{stat.title}
|
||||
</CardTitle>
|
||||
<stat.icon className="h-4 w-4 text-muted-foreground" />
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="text-2xl font-bold">{stat.value}</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{stat.description}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
25
src/modules/dashboard/components/teacher-view.tsx
Normal file
25
src/modules/dashboard/components/teacher-view.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
"use client"
|
||||
|
||||
import { TeacherQuickActions } from "@/modules/dashboard/components/teacher-quick-actions";
|
||||
import { TeacherStats } from "@/modules/dashboard/components/teacher-stats";
|
||||
import { TeacherSchedule } from "@/modules/dashboard/components/teacher-schedule";
|
||||
import { RecentSubmissions } from "@/modules/dashboard/components/recent-submissions";
|
||||
|
||||
// This component is now exclusively for the Teacher Role View
|
||||
export function TeacherDashboard() {
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="flex items-center justify-between">
|
||||
<h1 className="text-3xl font-bold tracking-tight">Teacher Dashboard</h1>
|
||||
<TeacherQuickActions />
|
||||
</div>
|
||||
|
||||
<TeacherStats />
|
||||
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-7">
|
||||
<TeacherSchedule />
|
||||
<RecentSubmissions />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user