feat(app): add error/loading boundaries and update dashboard routes
- Add error.tsx and loading.tsx boundaries for admin, parent, student, teacher routes - Add dashboard-error-fallback and dashboard-loading-skeleton components - Add student/learning page, parent/leave routes, teacher textbook components - Update existing app routes across auth, dashboard, and API endpoints - Update proxy middleware and next-auth type declarations
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import Link from "next/link"
|
||||
import Link from "next/link"
|
||||
import type { Metadata } from "next"
|
||||
import type { JSX } from "react"
|
||||
import { BarChart3 } from "lucide-react"
|
||||
@@ -7,13 +7,16 @@ import { requirePermission } from "@/shared/lib/auth-guard"
|
||||
import { Permissions } from "@/shared/types/permissions"
|
||||
import { getGrades } from "@/modules/school/data-access"
|
||||
import { getGradeHomeworkInsights } from "@/modules/classes/data-access"
|
||||
import { getSchoolWideGradeSummary } from "@/modules/grades/data-access-analytics"
|
||||
import { SchoolWideSummaryCard } from "@/modules/grades/components/school-wide-summary-card"
|
||||
import { EmptyState } from "@/shared/components/ui/empty-state"
|
||||
import { StatCard } from "@/shared/components/ui/stat-card"
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/shared/components/ui/card"
|
||||
import { Badge } from "@/shared/components/ui/badge"
|
||||
import { Button } from "@/shared/components/ui/button"
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/shared/components/ui/table"
|
||||
import { formatDate, formatNumber, getSearchParam, type SearchParams } from "@/shared/lib/utils"
|
||||
import { formatDate, formatNumber } from "@/shared/lib/utils"
|
||||
import { getParam, type SearchParams } from "@/shared/lib/search-params"
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "年级作业洞察 - Next_Edu",
|
||||
@@ -27,15 +30,17 @@ export default async function AdminGradeInsightsPage({
|
||||
}: {
|
||||
searchParams: Promise<SearchParams>
|
||||
}): Promise<JSX.Element> {
|
||||
await requirePermission(Permissions.SCHOOL_MANAGE)
|
||||
const ctx = await requirePermission(Permissions.SCHOOL_MANAGE)
|
||||
const params = await searchParams
|
||||
const gradeId = getSearchParam(params, "gradeId")
|
||||
const gradeId = getParam(params, "gradeId")
|
||||
const selected = gradeId && gradeId !== "all" ? gradeId : ""
|
||||
|
||||
// grades 与 insights 无数据依赖,并行查询
|
||||
const [grades, insights] = await Promise.all([
|
||||
// grades、insights、全校汇总无数据依赖,并行查询
|
||||
const [grades, insights, schoolWideSummary] = await Promise.all([
|
||||
getGrades(),
|
||||
selected ? getGradeHomeworkInsights({ gradeId: selected, limit: 50 }) : Promise.resolve(null),
|
||||
// v3-P2-9:管理员全校成绩汇总视图
|
||||
getSchoolWideGradeSummary(ctx.dataScope),
|
||||
])
|
||||
|
||||
return (
|
||||
@@ -50,6 +55,11 @@ export default async function AdminGradeInsightsPage({
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* v3-P2-9: 全校成绩汇总视图 */}
|
||||
{schoolWideSummary.grades.length > 0 && (
|
||||
<SchoolWideSummaryCard summary={schoolWideSummary} />
|
||||
)}
|
||||
|
||||
<Card className="shadow-none">
|
||||
<CardHeader className="flex flex-row items-center justify-between space-y-0">
|
||||
<CardTitle className="text-base">筛选</CardTitle>
|
||||
|
||||
Reference in New Issue
Block a user