SarahXia0405 commited on
Commit
8e67c57
·
verified ·
1 Parent(s): 2863b71

Create CourseInfoSection.tsx

Browse files
web/src/components/sidebar/CourseInfoSection.tsx ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useMemo } from "react";
2
+ import { Separator } from "../ui/separator";
3
+
4
+ import type { Workspace } from "../../App";
5
+ import type { CourseDirectoryItem } from "../../lib/courseDirectory";
6
+
7
+ function gmailComposeLink(email: string, subject?: string, body?: string) {
8
+ const to = `to=${encodeURIComponent(email)}`;
9
+ const su = subject ? `&su=${encodeURIComponent(subject)}` : "";
10
+ const bd = body ? `&body=${encodeURIComponent(body)}` : "";
11
+ return `https://mail.google.com/mail/?view=cm&fs=1&${to}${su}${bd}`;
12
+ }
13
+
14
+ export function CourseInfoSection({
15
+ currentWorkspaceId,
16
+ workspaces,
17
+ selectedCourse,
18
+ availableCourses,
19
+ }: {
20
+ currentWorkspaceId: string;
21
+ workspaces: Workspace[];
22
+ selectedCourse: string;
23
+ availableCourses: CourseDirectoryItem[];
24
+ }) {
25
+ const currentWorkspace = useMemo(
26
+ () => workspaces.find((w) => w.id === currentWorkspaceId),
27
+ [workspaces, currentWorkspaceId]
28
+ );
29
+
30
+ const courseInfo: CourseDirectoryItem | null = useMemo(() => {
31
+ const sel = (selectedCourse || "").trim();
32
+ if (sel) {
33
+ const hitById = availableCourses.find((c) => c.id === sel);
34
+ if (hitById) return hitById;
35
+
36
+ const hitByName = availableCourses.find((c) => c.name === sel);
37
+ if (hitByName) return hitByName;
38
+ }
39
+
40
+ const wsCourse = (currentWorkspace as any)?.courseInfo as
41
+ | { id?: string; name?: string }
42
+ | undefined;
43
+
44
+ const wsId = wsCourse?.id?.trim();
45
+ if (wsId) return availableCourses.find((c) => c.id === wsId) ?? (wsCourse as any);
46
+
47
+ const wsName = wsCourse?.name?.trim();
48
+ if (wsName) return availableCourses.find((c) => c.name === wsName) ?? (wsCourse as any);
49
+
50
+ return null;
51
+ }, [availableCourses, currentWorkspace, selectedCourse]);
52
+
53
+ if (!courseInfo) return null;
54
+
55
+ const instructorName = courseInfo?.instructor?.name ?? "N/A";
56
+ const instructorEmail = courseInfo?.instructor?.email?.trim() || "";
57
+ const taName = courseInfo?.teachingAssistant?.name ?? "N/A";
58
+ const taEmail = courseInfo?.teachingAssistant?.email?.trim() || "";
59
+
60
+ return (
61
+ <div className="w-full">
62
+ <div className="px-4 pt-4 pb-3 space-y-2">
63
+ <div className="font-semibold text-base">{courseInfo.name}</div>
64
+
65
+ <div className="text-sm text-muted-foreground">
66
+ Instructor:&nbsp;
67
+ {instructorEmail ? (
68
+ <a
69
+ href={gmailComposeLink(
70
+ instructorEmail,
71
+ `[Clare] Question about ${courseInfo.name}`,
72
+ `Hi ${instructorName},\n\nI have a question about ${courseInfo.name}:\n\n(Write your question here)\n\nThanks,\n`
73
+ )}
74
+ target="_blank"
75
+ rel="noopener noreferrer"
76
+ className="text-primary hover:underline"
77
+ >
78
+ {instructorName}
79
+ </a>
80
+ ) : (
81
+ <span className="text-muted-foreground/60">{instructorName}</span>
82
+ )}
83
+ </div>
84
+
85
+ <div className="text-sm text-muted-foreground">
86
+ TA:&nbsp;
87
+ {taEmail ? (
88
+ <a
89
+ href={gmailComposeLink(
90
+ taEmail,
91
+ `[Clare] Help request for ${courseInfo.name}`,
92
+ `Hi ${taName},\n\nI need help with ${courseInfo.name}:\n\n(Write your question here)\n\nThanks,\n`
93
+ )}
94
+ target="_blank"
95
+ rel="noopener noreferrer"
96
+ className="text-primary hover:underline"
97
+ >
98
+ {taName}
99
+ </a>
100
+ ) : (
101
+ <span className="text-muted-foreground/60">{taName}</span>
102
+ )}
103
+ </div>
104
+ </div>
105
+
106
+ {/* 固定颜色分割线 */}
107
+ <Separator className="bg-[#ECECF1]" />
108
+ </div>
109
+ );
110
+ }