2025-08-20 16:29:11 +08:00
|
|
|
import { useState, useEffect } from "react";
|
2025-08-15 16:16:41 +08:00
|
|
|
import StartClass from "./components/StartClass";
|
|
|
|
|
import QuickAccess from "./components/QuickAccess";
|
|
|
|
|
import CalendarTaskModule from "./components/CalendarTaskModule";
|
|
|
|
|
import StudyStatus from "./components/StudyStatus";
|
|
|
|
|
import Rank from "@/components/Rank";
|
|
|
|
|
import StageProgress from "@/components/StageProgress";
|
|
|
|
|
import TaskList from "./components/TaskList";
|
2025-08-25 20:56:56 +08:00
|
|
|
import { getDashboardStatistics } from "@/services";
|
2025-08-15 16:16:41 +08:00
|
|
|
import "./index.css";
|
|
|
|
|
|
|
|
|
|
const Dashboard = () => {
|
2025-08-25 20:56:56 +08:00
|
|
|
const [dashboardData, setDashboardData] = useState(null);
|
|
|
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
|
const [selectedDate, setSelectedDate] = useState(new Date());
|
2025-08-25 14:26:42 +08:00
|
|
|
|
|
|
|
|
useEffect(() => {
|
2025-08-25 20:56:56 +08:00
|
|
|
fetchDashboardData();
|
2025-08-25 14:26:42 +08:00
|
|
|
}, []);
|
|
|
|
|
|
2025-08-25 20:56:56 +08:00
|
|
|
// 获取仪表板完整数据
|
|
|
|
|
const fetchDashboardData = async () => {
|
2025-08-25 14:26:42 +08:00
|
|
|
try {
|
2025-08-25 20:56:56 +08:00
|
|
|
setLoading(true);
|
|
|
|
|
const response = await getDashboardStatistics();
|
2025-08-25 14:32:11 +08:00
|
|
|
if (response && response.success) {
|
2025-08-25 20:56:56 +08:00
|
|
|
setDashboardData(response.data);
|
2025-08-25 14:32:11 +08:00
|
|
|
} else if (response) {
|
|
|
|
|
// 兼容直接返回数据的情况
|
2025-08-25 20:56:56 +08:00
|
|
|
setDashboardData(response);
|
2025-08-25 14:26:42 +08:00
|
|
|
}
|
|
|
|
|
} catch (error) {
|
2025-08-26 10:54:12 +08:00
|
|
|
console.error("Failed to fetch dashboard data:", error);
|
2025-08-25 14:26:42 +08:00
|
|
|
} finally {
|
2025-08-25 20:56:56 +08:00
|
|
|
setLoading(false);
|
2025-08-25 14:26:42 +08:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2025-08-25 20:56:56 +08:00
|
|
|
// 根据选中日期筛选任务
|
|
|
|
|
const getTasksForDate = (date) => {
|
|
|
|
|
if (!dashboardData?.tasks?.allTasks) return [];
|
|
|
|
|
// Check if date is valid before calling toISOString
|
|
|
|
|
if (!date || isNaN(date.getTime())) {
|
2025-08-26 10:54:12 +08:00
|
|
|
console.warn("Invalid date provided to getTasksForDate:", date);
|
2025-08-25 20:56:56 +08:00
|
|
|
return [];
|
2025-08-25 14:32:11 +08:00
|
|
|
}
|
2025-08-26 10:54:12 +08:00
|
|
|
const dateStr = date.toISOString().split("T")[0];
|
|
|
|
|
return dashboardData.tasks.allTasks.filter((task) => task.date === dateStr);
|
2025-08-25 14:32:11 +08:00
|
|
|
};
|
2025-08-22 10:32:57 +08:00
|
|
|
|
2025-08-15 16:16:41 +08:00
|
|
|
return (
|
|
|
|
|
<div className="dashboard">
|
|
|
|
|
<StageProgress showBlockageAlert={true} />
|
|
|
|
|
|
|
|
|
|
<div className="dashboard-grid">
|
2025-08-26 10:54:12 +08:00
|
|
|
<StartClass
|
2025-08-25 20:56:56 +08:00
|
|
|
courses={dashboardData?.courses}
|
|
|
|
|
tasks={dashboardData?.tasks}
|
|
|
|
|
loading={loading}
|
|
|
|
|
/>
|
2025-08-15 16:16:41 +08:00
|
|
|
<QuickAccess />
|
2025-08-26 10:54:12 +08:00
|
|
|
<CalendarTaskModule
|
2025-08-25 20:56:56 +08:00
|
|
|
tasks={dashboardData?.tasks?.allTasks}
|
|
|
|
|
selectedDate={selectedDate}
|
|
|
|
|
onDateChange={setSelectedDate}
|
|
|
|
|
loading={loading}
|
|
|
|
|
/>
|
2025-08-26 10:54:12 +08:00
|
|
|
<StudyStatus
|
2025-08-25 20:56:56 +08:00
|
|
|
progress={dashboardData?.overview?.overallProgress}
|
|
|
|
|
loading={loading}
|
|
|
|
|
/>
|
2025-08-26 10:54:12 +08:00
|
|
|
<Rank
|
|
|
|
|
data={
|
|
|
|
|
dashboardData?.ranking
|
|
|
|
|
? {
|
|
|
|
|
rankings: dashboardData.ranking.topStudents,
|
|
|
|
|
}
|
|
|
|
|
: null
|
|
|
|
|
}
|
2025-08-25 20:56:56 +08:00
|
|
|
loading={loading}
|
|
|
|
|
/>
|
2025-08-26 10:54:12 +08:00
|
|
|
<TaskList
|
2025-08-25 20:56:56 +08:00
|
|
|
tasks={getTasksForDate(selectedDate)}
|
|
|
|
|
selectedDate={selectedDate}
|
|
|
|
|
loading={loading}
|
|
|
|
|
/>
|
2025-08-15 16:16:41 +08:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default Dashboard;
|