SarahXia0405 commited on
Commit
d26c264
·
verified ·
1 Parent(s): de779be

Update web/src/components/sidebar/LeftSidebar.tsx

Browse files
web/src/components/sidebar/LeftSidebar.tsx CHANGED
@@ -1,5 +1,5 @@
1
  // web/src/components/sidebar/LeftSidebar.tsx
2
- import React, { useEffect, useMemo, useState } from "react";
3
  import { Button } from "../ui/button";
4
  import { Input } from "../ui/input";
5
  import { Badge } from "../ui/badge";
@@ -7,7 +7,6 @@ import { Badge } from "../ui/badge";
7
  import { SavedChatSection } from "./SavedChatSection";
8
 
9
  import { MailPlus, Users, GraduationCap } from "lucide-react";
10
-
11
  import { toast } from "sonner";
12
 
13
  import {
@@ -106,9 +105,27 @@ function toIntOrFallback(v: any, fb: number) {
106
  return fb;
107
  }
108
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  export function LeftSidebar(props: Props) {
110
  const {
111
- user,
112
  isLoggedIn,
113
  spaceType,
114
  groupMembers,
@@ -120,8 +137,6 @@ export function LeftSidebar(props: Props) {
120
  workspaces,
121
  selectedCourse,
122
  availableCourses,
123
- onRenameGroupName,
124
- onRenameGroupNo,
125
  } = props;
126
 
127
  const currentWorkspace = useMemo(
@@ -178,7 +193,7 @@ export function LeftSidebar(props: Props) {
178
  }, [availableCourses, currentWorkspace, selectedCourse]);
179
 
180
  const courseName = useMemo(() => {
181
- return (courseInfo as any)?.name ?? (selectedCourse || "Course");
182
  }, [courseInfo, selectedCourse]);
183
 
184
  // --------- Group fields ---------
@@ -189,7 +204,8 @@ export function LeftSidebar(props: Props) {
189
 
190
  const wsGroupName = useMemo(() => {
191
  const ws: any = currentWorkspace as any;
192
- return pickAny(ws, ["groupName", "name", "title"]) || "My Group";
 
193
  }, [currentWorkspace]);
194
 
195
  // --------- Demo group mapping (My Space only) ---------
@@ -213,11 +229,9 @@ export function LeftSidebar(props: Props) {
213
 
214
  const memberCount = (groupMembers || []).length;
215
 
216
- // ✅ YYYYYYYYYYYY Name and Number
217
- const groupName = useMemo(() => wsGroupName || "YYY", [wsGroupName]);
218
  const groupNo = useMemo(() => toIntOrFallback(wsGroupNo, 1), [wsGroupNo]);
219
 
220
-
221
  // Invite dialog state
222
  const [inviteOpen, setInviteOpen] = useState(false);
223
  const [inviteEmail, setInviteEmail] = useState("");
@@ -232,27 +246,24 @@ export function LeftSidebar(props: Props) {
232
  setInviteOpen(false);
233
  };
234
 
235
-
236
  // --------- Contacts ---------
237
- const instructorName = (courseInfo as any)?.instructor?.name ?? "N/A";
238
  const instructorEmail = String((courseInfo as any)?.instructor?.email ?? "").trim();
239
 
240
- const taName = (courseInfo as any)?.teachingAssistant?.name ?? "N/A";
241
  const taEmail = String((courseInfo as any)?.teachingAssistant?.email ?? "").trim();
242
 
243
  return (
244
  <div className="h-full w-full flex flex-col min-h-0 bg-background text-foreground">
245
  {/* ================= TOP (non-scroll) ================= */}
246
  <div className="flex-shrink-0">
247
- {/* removed Welcome section entirely */}
248
-
249
  <div className="mt-2 mb-4">
250
  <Divider />
251
  </div>
252
 
253
  {/* Course + Group */}
254
  <div className="px-4 pt-5 pb-6 space-y-4">
255
- {/* Course row with icon (single-color, no container/background) */}
256
  <div className="flex items-start gap-3">
257
  <div className="w-6 flex items-start justify-center flex-shrink-0 pt-[2px]">
258
  <GraduationCap className="w-5 h-5 text-muted-foreground" />
@@ -260,12 +271,14 @@ export function LeftSidebar(props: Props) {
260
  <div className="text-[22px] leading-snug font-semibold truncate">{courseName}</div>
261
  </div>
262
 
263
- {/* ===== My Space (beautified) ===== */}
264
  {!isTeamSpace ? (
265
  <div className="space-y-2">
266
  <div className="flex items-center justify-between text-[15px]">
267
  <span className="text-muted-foreground">Group Name:</span>
268
- <span className="font-semibold truncate max-w-[60%] text-right">{demoGroup.name}</span>
 
 
269
  </div>
270
  <div className="flex items-center justify-between text-[15px]">
271
  <span className="text-muted-foreground">Group Number:</span>
@@ -273,19 +286,18 @@ export function LeftSidebar(props: Props) {
273
  </div>
274
  </div>
275
  ) : (
276
- /* ===== Team/Group (editable card) ===== */
277
  <div className="rounded-2xl border bg-background overflow-hidden">
278
  <div className="px-4 pt-4 pb-3 space-y-3">
279
- {/* Line 1: group name (read-only) */}
280
  <div className="flex items-center gap-2">
281
  <div className="text-[18px] font-semibold truncate">{groupName}</div>
282
  </div>
283
 
284
- {/* Line 2: Group {no}(✏️) ({count}) + Invite */}
285
  <div className="flex items-center justify-between gap-3">
286
  <div className="flex items-center gap-2">
287
  <Users className="w-4 h-4 text-muted-foreground" />
288
-
289
  <div className="text-[16px] font-medium">
290
  Group <span className="font-semibold">{groupNo}</span> ({memberCount})
291
  </div>
@@ -306,7 +318,7 @@ export function LeftSidebar(props: Props) {
306
  <div className="px-3 pb-3 space-y-2">
307
  {(groupMembers || []).map((member) => {
308
  const isAI = !!(member as any).isAI;
309
- const name = String((member as any).name || "");
310
  const email = String((member as any).email || "");
311
  const initials = name
312
  ? name
 
1
  // web/src/components/sidebar/LeftSidebar.tsx
2
+ import React, { useMemo, useState } from "react";
3
  import { Button } from "../ui/button";
4
  import { Input } from "../ui/input";
5
  import { Badge } from "../ui/badge";
 
7
  import { SavedChatSection } from "./SavedChatSection";
8
 
9
  import { MailPlus, Users, GraduationCap } from "lucide-react";
 
10
  import { toast } from "sonner";
11
 
12
  import {
 
105
  return fb;
106
  }
107
 
108
+ /**
109
+ * Important:
110
+ * - The "pencil" you see near Group Name can be coming from DATA (workspace/group name string),
111
+ * not from lucide icons. This sanitizes display text only.
112
+ */
113
+ function sanitizeGroupDisplayName(v: any) {
114
+ const s = String(v ?? "");
115
+ // Remove common pencil/pen emoji variants (safe no-op if none)
116
+ return s
117
+ .replaceAll("✏️", "")
118
+ .replaceAll("✏", "")
119
+ .replaceAll("🖊️", "")
120
+ .replaceAll("🖊", "")
121
+ .replaceAll("🖋️", "")
122
+ .replaceAll("🖋", "")
123
+ .replace(/\(\s*✏️?\s*\)/g, "")
124
+ .trim();
125
+ }
126
+
127
  export function LeftSidebar(props: Props) {
128
  const {
 
129
  isLoggedIn,
130
  spaceType,
131
  groupMembers,
 
137
  workspaces,
138
  selectedCourse,
139
  availableCourses,
 
 
140
  } = props;
141
 
142
  const currentWorkspace = useMemo(
 
193
  }, [availableCourses, currentWorkspace, selectedCourse]);
194
 
195
  const courseName = useMemo(() => {
196
+ return sanitizeGroupDisplayName((courseInfo as any)?.name ?? (selectedCourse || "Course"));
197
  }, [courseInfo, selectedCourse]);
198
 
199
  // --------- Group fields ---------
 
204
 
205
  const wsGroupName = useMemo(() => {
206
  const ws: any = currentWorkspace as any;
207
+ const raw = pickAny(ws, ["groupName", "name", "title"]) || "My Group";
208
+ return sanitizeGroupDisplayName(raw);
209
  }, [currentWorkspace]);
210
 
211
  // --------- Demo group mapping (My Space only) ---------
 
229
 
230
  const memberCount = (groupMembers || []).length;
231
 
232
+ const groupName = useMemo(() => wsGroupName || "My Group", [wsGroupName]);
 
233
  const groupNo = useMemo(() => toIntOrFallback(wsGroupNo, 1), [wsGroupNo]);
234
 
 
235
  // Invite dialog state
236
  const [inviteOpen, setInviteOpen] = useState(false);
237
  const [inviteEmail, setInviteEmail] = useState("");
 
246
  setInviteOpen(false);
247
  };
248
 
 
249
  // --------- Contacts ---------
250
+ const instructorName = sanitizeGroupDisplayName((courseInfo as any)?.instructor?.name ?? "N/A");
251
  const instructorEmail = String((courseInfo as any)?.instructor?.email ?? "").trim();
252
 
253
+ const taName = sanitizeGroupDisplayName((courseInfo as any)?.teachingAssistant?.name ?? "N/A");
254
  const taEmail = String((courseInfo as any)?.teachingAssistant?.email ?? "").trim();
255
 
256
  return (
257
  <div className="h-full w-full flex flex-col min-h-0 bg-background text-foreground">
258
  {/* ================= TOP (non-scroll) ================= */}
259
  <div className="flex-shrink-0">
 
 
260
  <div className="mt-2 mb-4">
261
  <Divider />
262
  </div>
263
 
264
  {/* Course + Group */}
265
  <div className="px-4 pt-5 pb-6 space-y-4">
266
+ {/* Course row with icon */}
267
  <div className="flex items-start gap-3">
268
  <div className="w-6 flex items-start justify-center flex-shrink-0 pt-[2px]">
269
  <GraduationCap className="w-5 h-5 text-muted-foreground" />
 
271
  <div className="text-[22px] leading-snug font-semibold truncate">{courseName}</div>
272
  </div>
273
 
274
+ {/* ===== My Space ===== */}
275
  {!isTeamSpace ? (
276
  <div className="space-y-2">
277
  <div className="flex items-center justify-between text-[15px]">
278
  <span className="text-muted-foreground">Group Name:</span>
279
+ <span className="font-semibold truncate max-w-[60%] text-right">
280
+ {sanitizeGroupDisplayName(demoGroup.name)}
281
+ </span>
282
  </div>
283
  <div className="flex items-center justify-between text-[15px]">
284
  <span className="text-muted-foreground">Group Number:</span>
 
286
  </div>
287
  </div>
288
  ) : (
289
+ /* ===== Team/Group ===== */
290
  <div className="rounded-2xl border bg-background overflow-hidden">
291
  <div className="px-4 pt-4 pb-3 space-y-3">
292
+ {/* Line 1: group name (read-only, NO pencil) */}
293
  <div className="flex items-center gap-2">
294
  <div className="text-[18px] font-semibold truncate">{groupName}</div>
295
  </div>
296
 
297
+ {/* Line 2: Group {no} ({count}) + Invite */}
298
  <div className="flex items-center justify-between gap-3">
299
  <div className="flex items-center gap-2">
300
  <Users className="w-4 h-4 text-muted-foreground" />
 
301
  <div className="text-[16px] font-medium">
302
  Group <span className="font-semibold">{groupNo}</span> ({memberCount})
303
  </div>
 
318
  <div className="px-3 pb-3 space-y-2">
319
  {(groupMembers || []).map((member) => {
320
  const isAI = !!(member as any).isAI;
321
+ const name = sanitizeGroupDisplayName(String((member as any).name || ""));
322
  const email = String((member as any).email || "");
323
  const initials = name
324
  ? name