feat(student): 完成 student 模块 v4 剩余修复
- P1-4.2: 新增班级详情页 courses/[classId],展示教师/学校/教室信息与课表 - P2-2.5: 今日课表卡片高亮当前/下一节课(useMemo 实时计算) - P2-3.9: 作业作答进度网格支持点击跳转题目(scrollIntoView) - P2-3.10: 作业复习视图显示正确答案(选择/判断/文本题) - P2-4.4: 课程列表支持按班级名/教师/学校搜索 - P2-5.2: 成绩页新增趋势折线图组件 GradeTrendCard - P2-9.2/9.3: 诊断报告新增历史记录卡片与弱点练习入口 - P2-10.2: 选课列表支持搜索与选课模式筛选 - P2-11.3: 修复教材阅读页全屏溢出 - P3-1.5: 面包屑保留首个角色段作为根上下文 - P3-7.3: 课表项支持点击跳转至班级详情页(ScheduleList href)
This commit is contained in:
@@ -2,6 +2,7 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/shared/components/ui
|
||||
import { EmptyState } from "@/shared/components/ui/empty-state"
|
||||
import { CalendarX } from "lucide-react"
|
||||
import { ScheduleList } from "@/shared/components/schedule/schedule-list"
|
||||
import { cn } from "@/shared/lib/utils"
|
||||
|
||||
import type { StudentScheduleItem } from "@/modules/classes/types"
|
||||
|
||||
@@ -15,6 +16,16 @@ const WEEKDAYS: Array<{ key: 1 | 2 | 3 | 4 | 5 | 6 | 7; label: string }> = [
|
||||
{ key: 7, label: "Sun" },
|
||||
]
|
||||
|
||||
const getTodayWeekday = (): 1 | 2 | 3 | 4 | 5 | 6 | 7 => {
|
||||
// getDay() returns 0 (Sun) - 6 (Sat); convert to 1 (Mon) - 7 (Sun)
|
||||
const WEEKDAY_MAP = [7, 1, 2, 3, 4, 5, 6] as const
|
||||
const day = new Date().getDay()
|
||||
if (day < 0 || day > 6) {
|
||||
throw new Error(`Invalid day from getDay(): ${day}`)
|
||||
}
|
||||
return WEEKDAY_MAP[day]
|
||||
}
|
||||
|
||||
export function StudentScheduleView({ items }: { items: StudentScheduleItem[] }) {
|
||||
if (items.length === 0) {
|
||||
return (
|
||||
@@ -27,6 +38,8 @@ export function StudentScheduleView({ items }: { items: StudentScheduleItem[] })
|
||||
)
|
||||
}
|
||||
|
||||
const todayKey = getTodayWeekday()
|
||||
|
||||
const itemsByDay = new Map<number, StudentScheduleItem[]>()
|
||||
for (const item of items) {
|
||||
const list = itemsByDay.get(item.weekday) ?? []
|
||||
@@ -41,17 +54,33 @@ export function StudentScheduleView({ items }: { items: StudentScheduleItem[] })
|
||||
<div className="grid gap-4 lg:grid-cols-2">
|
||||
{WEEKDAYS.map((d) => {
|
||||
const dayItems = itemsByDay.get(d.key) ?? []
|
||||
const isToday = d.key === todayKey
|
||||
return (
|
||||
<Card key={d.key}>
|
||||
<Card
|
||||
key={d.key}
|
||||
className={cn(
|
||||
isToday && "border-primary ring-1 ring-primary/30 shadow-sm"
|
||||
)}
|
||||
>
|
||||
<CardHeader className="pb-3">
|
||||
<CardTitle className="text-sm font-medium">{d.label}</CardTitle>
|
||||
<CardTitle className="flex items-center gap-2 text-sm font-medium">
|
||||
<span>{d.label}</span>
|
||||
{isToday && (
|
||||
<span className="rounded-full bg-primary px-2 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-primary-foreground">
|
||||
Today
|
||||
</span>
|
||||
)}
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{dayItems.length === 0 ? (
|
||||
<div className="text-sm text-muted-foreground">No classes.</div>
|
||||
) : (
|
||||
<ScheduleList
|
||||
items={dayItems}
|
||||
items={dayItems.map((item) => ({
|
||||
...item,
|
||||
href: `/student/learning/courses/${encodeURIComponent(item.classId)}`,
|
||||
}))}
|
||||
variant="card"
|
||||
spacingClassName="space-y-3"
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user