+ {/* Mobile Tabs */}
+
{tabs.map((t) => {
const meta = TAB_META[t];
const isActive = tab === t;
+
return (
navigate(`/course/${id}/${t}`)}
- className={`flex items-center gap-1.5 px-3 py-2 rounded-xl whitespace-nowrap
- text-xs font-bold transition-all duration-200 cursor-pointer shrink-0
- ${
- isActive
- ? "bg-[var(--accent)]/15 text-[var(--accent)] border border-[var(--accent)]/20"
- : "glass border border-[var(--border)]/20 text-[var(--muted)] hover:text-[var(--text)]"
- }`}
+ className={`flex items-center gap-1.5 px-3 py-2 rounded-2xl text-xs font-semibold whitespace-nowrap transition-all duration-200
+ ${
+ isActive
+ ? "bg-[var(--accent)]/15 text-[var(--accent)] border border-[var(--accent)]/20"
+ : "text-[var(--muted)] border border-[var(--border)]/20 hover:bg-[var(--border)]/10"
+ }`}
>
- {meta.icon}
- {meta.label}
-
+ {meta.icon}
+ {meta.label}
+
{tabCount[t]}
@@ -774,9 +828,15 @@ ${
})}
+<<<<<<< HEAD
+ {/* Content */}
+
+
+=======
{/* Tab content */}
+>>>>>>> 42795c9a6a2ed72e942e6619110abc54bb76c281
{tab === "materials" && (
setModal("material")}
/>
)}
+
{tab === "assignments" && (
setModal("assignment")}
/>
)}
+
{tab === "quizzes" && (
setModal("quiz")}
/>
)}
+
{tab === "live-classes" && (
setModal("live-class")}
/>
)}
+
{tab === "students" && isTeacher && (
)}
@@ -836,6 +900,7 @@ ${
+ {/* Modals untouched */}
>>>>>> 42795c9a6a2ed72e942e6619110abc54bb76c281
const chatEndRef = useRef(null);
// ββ presence state ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
@@ -353,7 +357,7 @@ export default function LiveClassRoom() {
} catch {
/* user cancelled */
}
- }, [id, socket]);
+ }, [id, socket, stopScreenShare]);
const stopScreenShare = useCallback(() => {
screenStreamRef.current?.getTracks().forEach((t) => t.stop());
@@ -547,6 +551,9 @@ export default function LiveClassRoom() {
[id, user.id, commentText, replyTo],
);
+<<<<<<< HEAD
+ // Mount pending screen stream once remoteScreenRef is available
+=======
const postQuestion = useCallback(
async (e) => {
e.preventDefault();
@@ -576,6 +583,7 @@ export default function LiveClassRoom() {
);
// Mount pending screen stream once ref is available
+>>>>>>> 42795c9a6a2ed72e942e6619110abc54bb76c281
useEffect(() => {
if (
teacherHasScreen &&
@@ -839,7 +847,22 @@ export default function LiveClassRoom() {
["recording-available", onRecordingAvailable],
].forEach(([ev, fn]) => socket.off(ev, fn));
};
+<<<<<<< HEAD
+ }, [
+ id,
+ isTeacher,
+ loadClass,
+ loadComments,
+ loadQuestions,
+ makePeerForViewer,
+ navigate,
+ showReaction,
+ socket,
+ user.id,
+ ]);
+=======
}, [id, isTeacher]); // eslint-disable-line react-hooks/exhaustive-deps
+>>>>>>> 42795c9a6a2ed72e942e6619110abc54bb76c281
// βββ derived ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
const topLevel = comments.filter((c) => !c.parentComment);
@@ -1363,6 +1386,140 @@ export default function LiveClassRoom() {
+<<<<<<< HEAD
+ {/* βββ SIDEBAR PANEL ββββββββββββββββββββββββββββββββββββββββββββββββββββ */}
+
+ {/* Tabs */}
+
+
+ {[
+ { key: "chat", label: "π¬ Chat", badge: comments.length },
+ {
+ key: "qa",
+ label: "β Q&A",
+ badge: questions.filter((q) => !q.isAnswered).length,
+ },
+ { key: "people", label: "π₯", badge: handCount || null },
+ ].map(({ key, label, badge }) => (
+ setPanelTab(key)}
+ className={`flex-1 flex items-center justify-center gap-1 py-2 rounded-lg text-[11px] font-medium transition-all
+ ${
+ panelTab === key
+ ? "bg-[var(--surface)] shadow-sm text-[var(--text)]"
+ : "text-[var(--muted)] hover:text-[var(--text)]"
+ }`}
+ >
+ {label}
+ {badge > 0 && (
+
+ {badge}
+
+ )}
+
+ ))}
+
+
+
+ {/* ββ CHAT ββ */}
+ {panelTab === "chat" && (
+ <>
+
+ {topLevel.length === 0 && (
+
+
π¬
+
+ No messages yet
+
+
+ )}
+
+ {topLevel.map((c) => {
+ const replies = getReplies(c.id);
+
+ return (
+
+
+
+
+
+ {/* Header */}
+
+
+ {c.user?.name}
+
+
+ {c.isTeacherReply && (
+
+ Teacher
+
+ )}
+
+
+ {timeAgo(c.createdAt)}
+
+
+
+ {/* Message bubble */}
+
+ {c.text}
+
+
+
+ setReplyTo(
+ replyTo?.id === c.id
+ ? null
+ : { id: c.id, userName: c.user?.name },
+ )
+ }
+ className="mt-1 text-[10px] text-[var(--muted)] hover:text-[var(--accent)]"
+ >
+ Reply
+
+
+
+
+ {/* Replies */}
+ {replies.length > 0 && (
+
+ {replies.map((r) => (
+
+
+
+
+ {r.user?.name}
+
+
+ {r.text}
+
+
+
+ ))}
+
+ )}
+
+ );
+ })}
+
+
+ {/* Input */}
+
+<<<<<<< HEAD
+ {/* ββ Q&A ββ */}
+ {panelTab === "qa" && (
+
+ {questions.map((q) => (
+
+
{q.question}
+
+ {q.isAnswered && (
+
+ Answered
+
+ )}
+
+ ))}
+
+ )}
+
+ {/* ββ PEOPLE ββ */}
+ {panelTab === "people" && (
+
+ {/* Host */}
+
+
+ Host
+
+
+
+
+
+ {liveClass.teacher?.name}
+
+=======
{/* β Chat βββββββββββββββββββββββββββββββββββββββββββββββββββββββ */}
{panelTab === "chat" && (
<>
@@ -1654,8 +1852,20 @@ export default function LiveClassRoom() {
+>>>>>>> 42795c9a6a2ed72e942e6619110abc54bb76c281
+<<<<<<< HEAD
+ {/* Participants */}
+
+
+ Participants Β· {participantCount}
+
+
+
+ {participantCount} people joined
+
+=======
{/* Raised hands */}
{handCount > 0 && (
@@ -1751,6 +1961,7 @@ export default function LiveClassRoom() {
)}
+>>>>>>> 42795c9a6a2ed72e942e6619110abc54bb76c281
)}
diff --git a/client/src/pages/StudentDashboard.jsx b/client/src/pages/StudentDashboard.jsx
index 84d2a16..06b73a4 100644
--- a/client/src/pages/StudentDashboard.jsx
+++ b/client/src/pages/StudentDashboard.jsx
@@ -1,4 +1,4 @@
-import { useState, useEffect, useRef } from "react";
+import { useState, useEffect, useRef, useCallback } from "react";
import { useNavigate } from "react-router-dom";
import { useAuth } from "../context/AuthContext";
import { apiFetch } from "../utils/api.js";
@@ -7,6 +7,9 @@ import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import Navbar from "../components/Navbar";
import Footer from "../components/Footer";
+import { GraduationCap } from "lucide-react";
+import { Brain, ClipboardList, Clock, Calendar, FileText } from "lucide-react";
+import { BookOpen, Video } from "lucide-react";
import {
LineChart,
Line,
@@ -22,6 +25,14 @@ import {
Legend,
ResponsiveContainer,
} from "recharts";
+import {
+ MessageCircle,
+ CalendarDays,
+ Lightbulb,
+ BarChart3,
+ BrainCircuit,
+ Sparkles,
+} from "lucide-react";
function SdAiMarkdown({ text }) {
return (
@@ -203,10 +214,37 @@ function StudentDashboard() {
const [perfContext, setPerfContext] = useState(null); // real performance data from DB
const openAiModal = (type) => {
+ if (!user?.id) return;
+
setAiModal(type);
setAiResult(null);
setAiError("");
setPlanSaved(false);
+
+ if (type === "chat") {
+ setChatInput("");
+ setAiError("");
+ }
+
+ if (type === "explain") {
+ setExplainForm((f) => ({
+ ...f,
+ concept: f.concept || "",
+ difficulty_level: f.difficulty_level || "intermediate",
+ course_context: f.course_context || "",
+ }));
+ }
+
+ if (type === "performance") {
+ setPerfForm((f) => ({
+ ...f,
+ subject: f.subject || "",
+ quiz_scores: f.quiz_scores || "",
+ assignment_grades: f.assignment_grades || "",
+ course_progress: f.course_progress || 0,
+ }));
+ }
+
if (type === "plan") {
setPlanForm((f) => ({
...f,
@@ -243,6 +281,17 @@ function StudentDashboard() {
setPlanSaved(false);
};
+ useEffect(() => {
+ if (aiModal) {
+ document.body.style.overflow = "hidden";
+ } else {
+ document.body.style.overflow = "";
+ }
+ return () => {
+ document.body.style.overflow = "";
+ };
+ }, [aiModal]);
+
async function aiPost(path, body, method = "POST") {
const res = await apiFetch(`/api/ai${path}`, {
method,
@@ -542,7 +591,7 @@ function StudentDashboard() {
}
};
- const load = async () => {
+ const load = useCallback(async () => {
try {
setLoading(true);
const dashResponse = await apiFetch(`/api/students/${user.id}/dashboard`);
@@ -565,7 +614,7 @@ function StudentDashboard() {
} finally {
setLoading(false);
}
- };
+ }, [user?.id]);
useEffect(() => {
if (user?.id) {
@@ -580,7 +629,7 @@ function StudentDashboard() {
socket.off("dashboard-update");
};
}
- }, [user?.id]);
+ }, [load]);
const enroll = async (courseId) => {
setEnrollingId(courseId);
@@ -629,36 +678,28 @@ function StudentDashboard() {
const stats = [
{
- icon: "π",
+ icon: BookOpen,
val: dashData.totalEnrolled ?? enrolled.length,
label: "Enrolled",
- color: "from-blue-500 to-blue-600",
- bg: "from-blue-500/15 to-blue-600/5",
},
{
- icon: "π",
+ icon: ClipboardList,
val: dashData.pendingAssignments ?? 0,
label: "Pending",
- color: "from-amber-500 to-amber-600",
- bg: "from-amber-500/15 to-amber-600/5",
},
{
- icon: "π§ ",
+ icon: Brain,
val: dashData.completedQuizzes ?? 0,
label: "Quizzes Done",
- color: "from-purple-500 to-purple-600",
- bg: "from-purple-500/15 to-purple-600/5",
},
{
- icon: "πΉ",
+ icon: Video,
val: dashData.upcomingClasses?.length ?? 0,
label: "Upcoming",
- color: "from-emerald-500 to-emerald-600",
- bg: "from-emerald-500/15 to-emerald-600/5",
},
];
- const chartColors = ["#818cf8", "#a78bfa", "#f472b6", "#fbbf24", "#34d399"];
+ const chartColors = ["#7cff6b", "#a78bfa", "#f472b6", "#fbbf24", "#34d399"];
const tooltipStyle = {
backgroundColor: "var(--surface)",
@@ -671,15 +712,17 @@ function StudentDashboard() {
return (
+
{/* Header */}
-
- π
-
+
Welcome back,{" "}
@@ -697,33 +740,56 @@ function StudentDashboard() {
{/* Stats Grid */}
-
- {stats.map((s, i) => (
-
-
- {s.icon}
-
-
- {s.val}
-
-
- {s.label}
-
-
- ))}
+
+ {/* Top Divider */}
+
+
+ {/* Stats Cards */}
+
+ {stats.map((s) => {
+ const Icon = s.icon;
+
+ return (
+
+ {/* Soft Hover Glow */}
+
+
+ {/* Content */}
+
+ {/* Icon */}
+
+
+
+
+ {/* Value */}
+
{s.val}
+
+ {/* Label */}
+
+ {s.label}
+
+
+
+ {/* Bottom Accent Line */}
+
+
+ );
+ })}
+
{/* AI Assistant Section */}
@@ -732,117 +798,158 @@ function StudentDashboard() {
style={{ animationDelay: "120ms" }}
>
-
- π€
-
+
+
+
AI Assistant
-
- {[
- {
- icon: "π¬",
- label: "AI Chat",
- desc: "Ask anything educational",
- type: "chat",
- color: "from-blue-500/15 to-blue-600/5",
- },
- {
- icon: "π
",
- label: "Study Plan",
- desc: "Personalized weekly schedule",
- type: "plan",
- color: "from-emerald-500/15 to-emerald-600/5",
- },
- {
- icon: "π‘",
- label: "Explain",
- desc: "Understand any concept",
- type: "explain",
- color: "from-amber-500/15 to-amber-600/5",
- },
- {
- icon: "π",
- label: "Performance",
- desc: "Analyze your scores",
- type: "performance",
- color: "from-purple-500/15 to-purple-600/5",
- },
- ].map((tool) => (
-
openAiModal(tool.type)}
- className={`group sc-card-premium glass rounded-2xl p-4 text-left bg-gradient-to-br ${tool.color} hover-lift active:scale-95 transition-all duration-300 border border-[var(--border)]/30 hover:border-[var(--accent)]/30`}
- >
- {tool.icon}
-
- {tool.label}
-
-
- {tool.desc}
-
-
- ))}
+
+ {/* Top Divider */}
+
+
+ {/* AI Tools */}
+
+ {[
+ {
+ icon: MessageCircle,
+ label: "AI Chat",
+ desc: "Ask anything instantly",
+ type: "chat",
+ },
+ {
+ icon: CalendarDays,
+ label: "Study Plan",
+ desc: "Smart weekly planner",
+ type: "plan",
+ },
+ {
+ icon: Lightbulb,
+ label: "Explain",
+ desc: "Break down concepts",
+ type: "explain",
+ },
+ {
+ icon: BarChart3,
+ label: "Performance",
+ desc: "Analyze progress",
+ type: "performance",
+ },
+ ].map((tool) => {
+ const Icon = tool.icon;
+
+ return (
+
openAiModal(tool.type)}
+ className="
+ group relative w-[240px] h-[160px]
+ rounded-2xl
+ bg-white
+ border border-green-100
+ shadow-md
+ hover:shadow-xl
+ transition-all duration-300
+ hover:-translate-y-1
+ "
+ >
+ {/* Soft Hover Glow */}
+
+
+ {/* Content */}
+
+ {/* Icon */}
+
+
+
+
+ {/* Title */}
+
+ {tool.label}
+
+
+ {/* Description */}
+
{tool.desc}
+
+
+ {/* Bottom Accent Line */}
+
+
+ );
+ })}
+
{/* ββ Active Quizzes ββ */}
-
-
-
- π§
-
- Active Quizzes
-
+
+ {/* Header */}
+
+
+
+
+
+ Active Quizzes
+
+
+
{quizzesLoading ? (
-
+
Loading quizzesβ¦
) : activeQuizzes.length === 0 ? (
-
-
π―
-
- No active quizzes right now. Check back later!
+
+
+
+ No active quizzes right now
) : (
-
+
{activeQuizzes.map((q) => (
-
-
-
- {q.title}
-
-
- π {q.courseTitle}
-
-
-
- {q.questionCount ?? q.questions?.length ?? 0}Q
-
-
-
-
- {q.timeLimit ? `β± ${q.timeLimit} min` : "No time limit"}
-
- {q.dueDate && (
-
- Due: {new Date(q.dueDate).toLocaleDateString()}
+ {/* Top */}
+
+
+ {q.title}
+
+
+
+ {q.courseTitle}
+
+
+ {/* Meta */}
+
+
+
+ {q.questionCount ?? q.questions?.length ?? 0} Q
- )}
+
+
+
+ {q.timeLimit ? `${q.timeLimit} min` : "No limit"}
+
+
+ {q.dueDate && (
+
+
+ {new Date(q.dueDate).toLocaleDateString()}
+
+ )}
+
+
+ {/* Button */}
startQuiz(q)}
- className="w-full py-2.5 sc-btn-glow rounded-xl text-sm font-bold cursor-pointer active:scale-95"
+ className="mt-6 py-3 rounded-xl bg-green-500 text-white text-sm font-semibold hover:bg-green-600 transition active:scale-95"
>
- Take Quiz β
+ Start Quiz β
))}
@@ -851,74 +958,78 @@ function StudentDashboard() {
{/* ββ My Assignments ββ */}
-
-
-
- π
-
- My Assignments
-
+
+ {/* Header */}
+
+
+
+
+
+ My Assignments
+
+
+
{assignmentsLoading ? (
-
+
Loading assignmentsβ¦
) : myAssignments.length === 0 ? (
-
-
π
-
- No assignments yet.
-
+
) : (
-
+
{myAssignments.map((a) => {
const isOverdue = a.dueDate && new Date(a.dueDate) < new Date();
+
return (
-
-
-
- {a.title}
-
-
- π {a.courseTitle}
-
-
-
- {a.maxScore}pts
-
-
- {a.description && (
-
- {a.description}
+ {/* Top */}
+
+
+ {a.title}
- )}
-
- {a.dueDate ? (
-
- {isOverdue ? "β Overdue" : "Due"}:{" "}
- {new Date(a.dueDate).toLocaleDateString()}
-
- ) : (
-
No due date
+
+
+ {a.courseTitle}
+
+
+ {a.description && (
+
+ {a.description}
+
)}
+
+ {/* Meta */}
+
+ {a.maxScore} pts
+
+ {a.dueDate ? (
+
+ {isOverdue ? "Overdue" : "Due"}:{" "}
+ {new Date(a.dueDate).toLocaleDateString()}
+
+ ) : (
+ No due date
+ )}
+
+
+ {/* Button */}
openSubmitModal(a)}
- className="w-full py-2.5 sc-btn-glow rounded-xl text-sm font-bold cursor-pointer active:scale-95"
+ className="mt-6 py-3 rounded-xl border border-green-500 text-green-600 font-semibold text-sm hover:bg-green-50 transition active:scale-95"
>
Submit / View β
@@ -940,7 +1051,7 @@ function StudentDashboard() {
style={{ animationDelay: "100ms" }}
>
-
+
π
Performance Trend
@@ -1093,7 +1204,7 @@ function StudentDashboard() {
className={`px-3 py-1 rounded-full text-[10px] font-bold uppercase tracking-wider whitespace-nowrap ${
lc.status === "live"
? "bg-red-500/15 text-red-500 animate-pulse border border-red-500/30 shadow-[0_0_12px_rgba(239,68,68,0.2)]"
- : "bg-blue-500/15 text-blue-500 border border-blue-500/30"
+ : "bg-green-500/15 text-green-500 border border-green-500/30"
}`}
>
{lc.status === "live" ? "π΄ LIVE" : "ποΈ Scheduled"}
@@ -1195,7 +1306,7 @@ function StudentDashboard() {
{
val: c.materialCount || 0,
label: "Materials",
- color: "blue",
+ color: "green",
},
{
val: c.assignmentCount || 0,
@@ -1254,98 +1365,96 @@ function StudentDashboard() {
className="animate-[slide-up_0.6s_cubic-bezier(0.16,1,0.3,1)_both]"
style={{ animationDelay: "400ms" }}
>
-
+ {/* Header */}
+
-
-
+
+
π
Explore More
-
+
Expand your skills with new courses
-
+
+
{available.length} available
+ {/* Cards */}
{available.map((c, i) => (
-
-
-
-
- {c.title}
-
- {c.subject && (
-
- {c.subject}
-
- )}
-
+ {/* Title + Subject */}
+
+
+ {c.title}
+
+
+ {c.subject && (
+
+ {c.subject}
+
+ )}
+
-
- π¨βπ« {c.teacher?.name || "Unknown"}
-
+ {/* Teacher */}
+
+ π¨βπ« {c.teacher?.name || "Unknown"}
+
-
- {c.description ||
- "Explore this amazing course and expand your knowledge"}
-
+ {/* Description */}
+
+ {c.description ||
+ "Explore this amazing course and expand your knowledge"}
+
-
-
-
- {c.enrollmentCount || 0}
-
-
- Enrolled
-
-
-
-
- {c.materialCount || 0}
-
-
- Materials
-
-
+ {/* Stats */}
+
+
+
+ {c.enrollmentCount || 0}
+
+
+ Enrolled
+
-
enroll(c.id)}
- disabled={enrollingId === c.id}
- className="w-full py-3 rounded-xl text-sm font-bold border-2 cursor-pointer disabled:cursor-not-allowed transition-all duration-300
- bg-emerald-500/10 hover:bg-emerald-500/20 disabled:opacity-60 text-emerald-500 border-emerald-500/30
- hover:shadow-[0_8px_24px_-8px_rgba(16,185,129,0.4)] hover:-translate-y-1 active:scale-95"
- >
- {enrollingId === c.id ? (
-
-
- Enrolling...
-
- ) : (
- "+ Enroll Now"
- )}
-
+
+
+ {c.materialCount || 0}
+
+
+ Materials
+
+
+
+ {/* Button */}
+
enroll(c.id)}
+ disabled={enrollingId === c.id}
+ className="w-full py-3 rounded-xl text-sm font-bold cursor-pointer transition-all duration-300
+ bg-emerald-500 text-white hover:bg-emerald-600
+ disabled:opacity-60 disabled:cursor-not-allowed
+ hover:shadow-md active:scale-95"
+ >
+ {enrollingId === c.id ? (
+
+
+ Enrolling...
+
+ ) : (
+ "+ Enroll Now"
+ )}
+
))}
@@ -1650,12 +1759,15 @@ function StudentDashboard() {
- π€ AI Feedback
+
+
+
{" "}
+ AI Feedback
{aiFeedbackLoading ? (
<>
@@ -1669,7 +1781,7 @@ function StudentDashboard() {
{mySubmission.feedback && !aiFeedback && (
-
+
Saved Feedback
@@ -1678,9 +1790,9 @@ function StudentDashboard() {
)}
{aiFeedback && (
-
-
-
+
+
+
AI Analysis
@@ -1707,7 +1819,7 @@ function StudentDashboard() {
{/* Header */}
-
+
{aiModal === "chat"
? "π¬"
: aiModal === "plan"
@@ -1732,20 +1844,32 @@ function StudentDashboard() {
{/* ββ CHAT ββ */}
{aiModal === "chat" && (
-
-
+
+ {/* Chat Box */}
+
+ {/* Empty State */}
{chatHistory.length === 0 && (
-
+
+
π¬
Ask me anything about your coursesβ¦
-
+
)}
+
+ {/* Messages */}
{chatHistory.map((m, i) => (
{m.role === "assistant" ? (
@@ -1755,49 +1879,62 @@ function StudentDashboard() {
))}
+
+ {/* Typing Loader */}
{aiLoading && (
-
-
+
+
{[0, 1, 2].map((i) => (
))}
-
+
)}
+
+ {/* Error */}
{aiError && (
{aiError}
)}
+
-
+
+ {/* Clear Button */}
{
setChatHistory([]);
setAiError("");
}}
- className="text-xs text-[var(--muted)] hover:text-red-400 transition-colors text-right"
+ className="text-xs text-gray-400 hover:text-red-500 transition mt-2 text-right"
>
Clear conversation
@@ -2156,28 +2293,28 @@ function StudentDashboard() {
{/* ββ PERFORMANCE ββ */}
{aiModal === "performance" && (
-
- {/* Load real data from DB */}
- {perfContext &&
- perfContext.courses &&
- perfContext.courses.length > 0 && (
-
-
- Load Real Data From DB
-
-
- {perfContext.courses.map((c) => (
- loadRealPerformanceData(c)}
- className="px-3 py-1.5 rounded-lg border border-[var(--accent)]/30 text-xs font-semibold text-[var(--accent)] hover:bg-[var(--accent)]/10 transition-all cursor-pointer"
- >
- {c.title}
-
- ))}
-
+
+ {/* REAL DATA */}
+ {perfContext?.courses?.length > 0 && (
+
+
+ Load Real Data
+
+
+ {perfContext.courses.map((c) => (
+ loadRealPerformanceData(c)}
+ className="px-3 py-1.5 rounded-lg text-xs font-semibold bg-emerald-50 text-emerald-600 border border-emerald-200 hover:bg-emerald-100 transition"
+ >
+ {c.title}
+
+ ))}
- )}
+
+ )}
+
+ {/* FORM */}
diff --git a/client/src/pages/TeacherDashboard.jsx b/client/src/pages/TeacherDashboard.jsx
index e711cab..81862b7 100644
--- a/client/src/pages/TeacherDashboard.jsx
+++ b/client/src/pages/TeacherDashboard.jsx
@@ -1,4 +1,4 @@
-import { useState, useEffect, useRef } from "react";
+import { useState, useEffect, useRef, useCallback } from "react";
import { useNavigate } from "react-router-dom";
import { useAuth } from "../context/AuthContext";
import { apiFetch } from "../utils/api.js";
@@ -597,14 +597,17 @@ function TeacherDashboard() {
);
};
- const load = () =>
- apiFetch(`/api/teachers/${user.id}/dashboard`)
- .then((r) => r.json())
- .then((d) => !d.error && setData(d));
+ const load = useCallback(
+ () =>
+ apiFetch(`/api/teachers/${user.id}/dashboard`)
+ .then((r) => r.json())
+ .then((d) => !d.error && setData(d)),
+ [user.id],
+ );
useEffect(() => {
load();
- }, [user.id]);
+ }, [load]);
const openCreate = () => {
setEditCourse(null);
diff --git a/client/src/theme/ThemeApplier.jsx b/client/src/theme/ThemeApplier.jsx
index d426f67..5702e9e 100644
--- a/client/src/theme/ThemeApplier.jsx
+++ b/client/src/theme/ThemeApplier.jsx
@@ -23,6 +23,21 @@ const themeStyles = {
className: "light",
},
dark: {
+<<<<<<< HEAD
+ "--bg": "#0a0a0a",
+ "--surface": "#111827",
+ "--surface-elevated": "#1f2937",
+ "--text": "#ffffff",
+ "--text-secondary": "#f1f5f9",
+ "--muted": "#9ca3af",
+ "--accent": "#7cff6b",
+ "--accent-light": "#9cff8a",
+ "--accent-contrast": "#0a0a0a",
+ "--border": "#374151",
+ "--border-light": "#4b5563",
+ "--shadow-color": "0 0% 0%",
+ "--glow-color": "120 100% 50%",
+=======
"--bg": "#0f172a",
"--surface": "#1e293b",
"--surface-elevated": "#273549",
@@ -41,6 +56,7 @@ const themeStyles = {
"--warning": "#f59e0b",
"--danger": "#f87171",
"--info": "#38bdf8",
+>>>>>>> 42795c9a6a2ed72e942e6619110abc54bb76c281
className: "dark",
},
};