Files
CICD/src/modules/dashboard/components/teacher-dashboard/recent-submissions.tsx
SpecialX ade8d4346c feat(dashboard): optimize teacher dashboard ui and layout
- Refactor layout: move Needs Grading to main column, Homework to sidebar
- Enhance TeacherStats: replace static counts with actionable metrics (Needs Grading, Active Assignments, Avg Score, Submission Rate)
- Update RecentSubmissions: table view with quick grade actions and late status
- Update TeacherSchedule: vertical timeline view with scroll hints
- Update TeacherHomeworkCard: compact list view
- Integrate Recharts: add TeacherGradeTrends chart and shared chart component
- Update documentation
2026-01-12 11:38:27 +08:00

118 lines
4.7 KiB
TypeScript

import Link from "next/link";
import { Inbox, ArrowRight } from "lucide-react";
import { Card, CardContent, CardHeader, CardTitle } from "@/shared/components/ui/card";
import { Avatar, AvatarFallback, AvatarImage } from "@/shared/components/ui/avatar";
import { Badge } from "@/shared/components/ui/badge";
import { Button } from "@/shared/components/ui/button";
import { EmptyState } from "@/shared/components/ui/empty-state";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/shared/components/ui/table";
import { formatDate } from "@/shared/lib/utils";
import type { HomeworkSubmissionListItem } from "@/modules/homework/types";
export function RecentSubmissions({
submissions,
title = "Recent Submissions",
emptyTitle = "No New Submissions",
emptyDescription = "All caught up! There are no new submissions to review."
}: {
submissions: HomeworkSubmissionListItem[],
title?: string,
emptyTitle?: string,
emptyDescription?: string
}) {
const hasSubmissions = submissions.length > 0;
return (
<Card className="h-full flex flex-col">
<CardHeader className="flex flex-row items-center justify-between pb-2">
<CardTitle className="flex items-center gap-2 text-lg">
<Inbox className="h-5 w-5 text-primary" />
{title}
</CardTitle>
<Button variant="ghost" size="sm" className="text-muted-foreground hover:text-primary" asChild>
<Link href="/teacher/homework/submissions" className="flex items-center gap-1">
View All <ArrowRight className="h-3 w-3" />
</Link>
</Button>
</CardHeader>
<CardContent className="flex-1">
{!hasSubmissions ? (
<EmptyState
icon={Inbox}
title={emptyTitle}
description={emptyDescription}
action={{ label: "View submissions", href: "/teacher/homework/submissions" }}
className="border-none h-full min-h-[200px]"
/>
) : (
<div className="rounded-md border">
<Table>
<TableHeader>
<TableRow className="bg-muted/50">
<TableHead className="w-[200px]">Student</TableHead>
<TableHead>Assignment</TableHead>
<TableHead className="w-[140px]">Submitted</TableHead>
<TableHead className="w-[100px] text-right">Action</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{submissions.map((item) => (
<TableRow key={item.id} className="hover:bg-muted/50">
<TableCell>
<div className="flex items-center gap-3">
<Avatar className="h-8 w-8 border">
<AvatarImage src={undefined} alt={item.studentName} />
<AvatarFallback className="bg-primary/10 text-primary text-xs">
{item.studentName.charAt(0)}
</AvatarFallback>
</Avatar>
<span className="font-medium text-sm">{item.studentName}</span>
</div>
</TableCell>
<TableCell>
<Link
href={`/teacher/homework/submissions/${item.id}`}
className="font-medium hover:text-primary hover:underline transition-colors block truncate max-w-[240px]"
title={item.assignmentTitle}
>
{item.assignmentTitle}
</Link>
</TableCell>
<TableCell>
<div className="flex flex-col gap-1">
<span className="text-xs text-muted-foreground">
{item.submittedAt ? formatDate(item.submittedAt) : "-"}
</span>
{item.isLate && (
<Badge variant="destructive" className="w-fit text-[10px] h-4 px-1.5 font-normal">
Late
</Badge>
)}
</div>
</TableCell>
<TableCell className="text-right">
<Button size="sm" variant="secondary" className="h-8 px-3" asChild>
<Link href={`/teacher/homework/submissions/${item.id}`}>
Grade
</Link>
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
)}
</CardContent>
</Card>
);
}