feat(portal-shell): wire dashboards to real data-ana queries (P1-2)
- add dashboard.graphql.ts with 6 real aggregate queries
(teacherDashboard / studentDashboard / parentDashboard /
adminDashboard / warnings / errorBookStats), snake_case aligned
- add dashboard.ts with 6 hooks + full domain model types
- add 4 role dashboard pages (teacher/student/parent/admin)
using DashboardShell + StatCard + DashboardSection with
loading / error / success tri-state
- update [[...route]]/page.tsx to redirect /shell -> /shell/{role}
- retire 6 fake contract queries and hooks (grades/homeworks/
schedule/attendance/exams/announcements) and mark widget
placeholders as migrated
- update universal.test.ts to drop retired hook tests
- mark ARCHITECTURE.md P1-2 as completed with acceptance evidence
This commit is contained in:
107
apps/portal-shell/src/app/shell/student/page.tsx
Normal file
107
apps/portal-shell/src/app/shell/student/page.tsx
Normal file
@@ -0,0 +1,107 @@
|
||||
"use client";
|
||||
|
||||
import { BookOpen, GraduationCap, TrendingUp } from "lucide-react";
|
||||
|
||||
import { useStudentDashboard } from "@/lib/api";
|
||||
import { DashboardShell } from "@/shared/components/dashboard/dashboard-shell";
|
||||
import { DashboardSection } from "@/shared/components/dashboard/dashboard-section";
|
||||
import { StatCard } from "@/shared/components/ui/stat-card";
|
||||
import { Card, CardContent } from "@/shared/components/ui/card";
|
||||
|
||||
/**
|
||||
* 学生仪表盘(ARCHITECTURE.md §7.1 / §10 P1-2)
|
||||
*
|
||||
* 改接 data-ana 的 studentDashboard 真实聚合查询,替换原
|
||||
* grades/homeworks/schedule/exams 假契约 widget 查询。
|
||||
*
|
||||
* 关联:ARCHITECTURE.md §5.5 / §10 P1-2
|
||||
*/
|
||||
export default function StudentDashboardPage(): React.ReactElement {
|
||||
const { data, loading, error } = useStudentDashboard();
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<DashboardShell title="学生仪表盘" description="学习概览">
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||
{Array.from({ length: 4 }).map((_, i) => (
|
||||
<StatCard key={i} title="" value="" isLoading />
|
||||
))}
|
||||
</div>
|
||||
</DashboardShell>
|
||||
);
|
||||
}
|
||||
|
||||
if (error || !data) {
|
||||
return (
|
||||
<DashboardShell title="学生仪表盘" description="学习概览">
|
||||
<Card>
|
||||
<CardContent className="py-8 text-center text-muted-foreground">
|
||||
仪表盘数据加载失败,请稍后重试。
|
||||
</CardContent>
|
||||
</Card>
|
||||
</DashboardShell>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<DashboardShell
|
||||
title="学生仪表盘"
|
||||
description="学习概览"
|
||||
stats={
|
||||
<>
|
||||
<StatCard
|
||||
title="平均分"
|
||||
value={data.avg_score?.toFixed(1) ?? "--"}
|
||||
icon={GraduationCap}
|
||||
/>
|
||||
<StatCard
|
||||
title="班级排名"
|
||||
value={`${data.class_rank ?? "--"} / ${data.total_students ?? "--"}`}
|
||||
icon={TrendingUp}
|
||||
/>
|
||||
<StatCard
|
||||
title="待交作业"
|
||||
value={data.pending_homework}
|
||||
icon={BookOpen}
|
||||
highlight={data.pending_homework > 0}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<DashboardSection title="薄弱知识点" variant="list">
|
||||
{data.weak_points ? (
|
||||
<div className="space-y-2 text-sm">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="font-medium">
|
||||
{data.weak_points.title ?? "--"}
|
||||
</span>
|
||||
<span className="text-muted-foreground">
|
||||
掌握度 {data.weak_points.mastery?.toFixed(1) ?? "--"}%
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
错误次数:{data.weak_points.error_count ?? 0}
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-sm text-muted-foreground">暂无薄弱知识点数据</p>
|
||||
)}
|
||||
</DashboardSection>
|
||||
|
||||
<DashboardSection title="近期成绩趋势" variant="chart">
|
||||
{data.recent_trends ? (
|
||||
<div className="text-sm">
|
||||
<span className="text-muted-foreground">
|
||||
{data.recent_trends.date ?? "--"}:
|
||||
</span>
|
||||
<span className="font-medium">
|
||||
{data.recent_trends.score?.toFixed(1) ?? "--"} 分
|
||||
</span>
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-sm text-muted-foreground">暂无趋势数据</p>
|
||||
)}
|
||||
</DashboardSection>
|
||||
</DashboardShell>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user