完整性更新
现在已经实现了大部分基础功能
This commit is contained in:
@@ -1,20 +1,53 @@
|
||||
import { Search, Filter } from "lucide-react";
|
||||
import { Button } from "@/shared/components/ui/button";
|
||||
import { Input } from "@/shared/components/ui/input";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/shared/components/ui/select";
|
||||
import { Suspense } from "react"
|
||||
import { BookOpen } from "lucide-react"
|
||||
import { TextbookCard } from "@/modules/textbooks/components/textbook-card";
|
||||
import { TextbookFormDialog } from "@/modules/textbooks/components/textbook-form-dialog";
|
||||
import { getTextbooks } from "@/modules/textbooks/data-access";
|
||||
import { TextbookFilters } from "@/modules/textbooks/components/textbook-filters"
|
||||
import { EmptyState } from "@/shared/components/ui/empty-state"
|
||||
|
||||
export default async function TextbooksPage() {
|
||||
// In a real app, we would parse searchParams here
|
||||
const textbooks = await getTextbooks();
|
||||
export const dynamic = "force-dynamic"
|
||||
|
||||
type SearchParams = { [key: string]: string | string[] | undefined }
|
||||
|
||||
const getParam = (params: SearchParams, key: string) => {
|
||||
const v = params[key]
|
||||
return Array.isArray(v) ? v[0] : v
|
||||
}
|
||||
|
||||
async function TextbooksResults({ searchParams }: { searchParams: Promise<SearchParams> }) {
|
||||
const params = await searchParams
|
||||
|
||||
const q = getParam(params, "q") || undefined
|
||||
const subject = getParam(params, "subject")
|
||||
const grade = getParam(params, "grade")
|
||||
|
||||
const textbooks = await getTextbooks(q, subject || undefined, grade || undefined)
|
||||
|
||||
const hasFilters = Boolean(q || (subject && subject !== "all") || (grade && grade !== "all"))
|
||||
|
||||
if (textbooks.length === 0) {
|
||||
return (
|
||||
<EmptyState
|
||||
icon={BookOpen}
|
||||
title={hasFilters ? "No textbooks match your filters" : "No textbooks yet"}
|
||||
description={hasFilters ? "Try clearing filters or adjusting keywords." : "Create your first textbook to start organizing chapters."}
|
||||
action={hasFilters ? { label: "Clear filters", href: "/teacher/textbooks" } : undefined}
|
||||
className="bg-card"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
|
||||
{textbooks.map((textbook) => (
|
||||
<TextbookCard key={textbook.id} textbook={textbook} />
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default async function TextbooksPage({ searchParams }: { searchParams: Promise<SearchParams> }) {
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
@@ -29,50 +62,13 @@ export default async function TextbooksPage() {
|
||||
<TextbookFormDialog />
|
||||
</div>
|
||||
|
||||
{/* Toolbar */}
|
||||
<div className="flex flex-col gap-4 md:flex-row md:items-center justify-between bg-card p-4 rounded-lg border shadow-sm">
|
||||
<div className="relative w-full md:w-96">
|
||||
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
|
||||
<Input
|
||||
placeholder="Search textbooks..."
|
||||
className="pl-9 bg-background"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-2 w-full md:w-auto">
|
||||
<Select>
|
||||
<SelectTrigger className="w-[140px] bg-background">
|
||||
<Filter className="mr-2 h-4 w-4 text-muted-foreground" />
|
||||
<SelectValue placeholder="Subject" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">All Subjects</SelectItem>
|
||||
<SelectItem value="math">Mathematics</SelectItem>
|
||||
<SelectItem value="physics">Physics</SelectItem>
|
||||
<SelectItem value="history">History</SelectItem>
|
||||
<SelectItem value="english">English</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
<Select>
|
||||
<SelectTrigger className="w-[140px] bg-background">
|
||||
<SelectValue placeholder="Grade" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">All Grades</SelectItem>
|
||||
<SelectItem value="10">Grade 10</SelectItem>
|
||||
<SelectItem value="11">Grade 11</SelectItem>
|
||||
<SelectItem value="12">Grade 12</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
<Suspense fallback={<div className="h-14 w-full animate-pulse rounded-lg bg-muted" />}>
|
||||
<TextbookFilters />
|
||||
</Suspense>
|
||||
|
||||
{/* Grid Content */}
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
|
||||
{textbooks.map((textbook) => (
|
||||
<TextbookCard key={textbook.id} textbook={textbook} />
|
||||
))}
|
||||
</div>
|
||||
<Suspense fallback={<div className="h-[360px] w-full animate-pulse rounded-md bg-muted" />}>
|
||||
<TextbooksResults searchParams={searchParams} />
|
||||
</Suspense>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user