SarahXia0405 commited on
Commit
25ab7de
·
verified ·
1 Parent(s): 2f8db1b

Update web/src/App.tsx

Browse files
Files changed (1) hide show
  1. web/src/App.tsx +63 -12
web/src/App.tsx CHANGED
@@ -120,6 +120,33 @@ function mapLanguagePref(lang: Language): string {
120
  return "Auto";
121
  }
122
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  function App() {
124
  const [isDarkMode, setIsDarkMode] = useState(() => {
125
  const saved = localStorage.getItem("theme");
@@ -281,6 +308,32 @@ function App() {
281
 
282
  const [savedChats, setSavedChats] = useState<SavedChat[]>([]);
283
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
284
  const [groupMembers] = useState<GroupMember[]>([
285
  { id: "clare", name: "Clare AI", email: "clare@ai.assistant", isAI: true },
286
  { id: "1", name: "Sarah Johnson", email: "sarah.j@university.edu" },
@@ -388,7 +441,6 @@ function App() {
388
 
389
  // =========================
390
  // ✅ Review Star (按天) state
391
- // scope:默认按 workspace 统计(你也可以改成 currentCourseId)
392
  // =========================
393
  const reviewStarKey = useMemo(() => {
394
  if (!user) return "";
@@ -397,7 +449,6 @@ function App() {
397
 
398
  const [reviewStarState, setReviewStarState] = useState<ReviewStarState | null>(null);
399
 
400
- // 进入 Review tab 或 workspace 切换时:normalize(跨天归零 todayCount -> 星星自动变暗)
401
  useEffect(() => {
402
  if (!user || !reviewStarKey) return;
403
  if (chatMode !== "review") return;
@@ -667,6 +718,16 @@ function App() {
667
  );
668
  };
669
 
 
 
 
 
 
 
 
 
 
 
670
  const handleSaveChat = () => {
671
  if (messages.length <= 1) {
672
  toast.info("No conversation to save");
@@ -707,16 +768,6 @@ function App() {
707
  toast.success("Chat loaded!");
708
  };
709
 
710
- const handleDeleteSavedChat = (id: string) => {
711
- setSavedChats((prev) => prev.filter((chat) => chat.id !== id));
712
- toast.success("Chat deleted");
713
- };
714
-
715
- const handleRenameSavedChat = (id: string, newTitle: string) => {
716
- setSavedChats((prev) => prev.map((chat) => (chat.id === id ? { ...chat, title: newTitle } : chat)));
717
- toast.success("Chat renamed");
718
- };
719
-
720
  const handleClearConversation = (shouldSave: boolean = false) => {
721
  if (shouldSave) handleSaveChat();
722
 
 
120
  return "Auto";
121
  }
122
 
123
+ // ✅ NEW: localStorage helpers for saved chats
124
+ function savedChatsStorageKey(email: string) {
125
+ return `saved_chats::${email}`;
126
+ }
127
+
128
+ function hydrateSavedChats(raw: any): SavedChat[] {
129
+ if (!Array.isArray(raw)) return [];
130
+ return raw
131
+ .map((c: any) => {
132
+ try {
133
+ return {
134
+ ...c,
135
+ timestamp: c?.timestamp ? new Date(c.timestamp) : new Date(),
136
+ messages: Array.isArray(c?.messages)
137
+ ? c.messages.map((m: any) => ({
138
+ ...m,
139
+ timestamp: m?.timestamp ? new Date(m.timestamp) : new Date(),
140
+ }))
141
+ : [],
142
+ } as SavedChat;
143
+ } catch {
144
+ return null;
145
+ }
146
+ })
147
+ .filter(Boolean) as SavedChat[];
148
+ }
149
+
150
  function App() {
151
  const [isDarkMode, setIsDarkMode] = useState(() => {
152
  const saved = localStorage.getItem("theme");
 
308
 
309
  const [savedChats, setSavedChats] = useState<SavedChat[]>([]);
310
 
311
+ // ✅ NEW: load saved chats after login
312
+ useEffect(() => {
313
+ if (!user?.email) return;
314
+ try {
315
+ const raw = localStorage.getItem(savedChatsStorageKey(user.email));
316
+ if (!raw) {
317
+ setSavedChats([]);
318
+ return;
319
+ }
320
+ const parsed = JSON.parse(raw);
321
+ setSavedChats(hydrateSavedChats(parsed));
322
+ } catch {
323
+ setSavedChats([]);
324
+ }
325
+ }, [user?.email]);
326
+
327
+ // ✅ NEW: persist saved chats whenever changed
328
+ useEffect(() => {
329
+ if (!user?.email) return;
330
+ try {
331
+ localStorage.setItem(savedChatsStorageKey(user.email), JSON.stringify(savedChats));
332
+ } catch {
333
+ // ignore
334
+ }
335
+ }, [savedChats, user?.email]);
336
+
337
  const [groupMembers] = useState<GroupMember[]>([
338
  { id: "clare", name: "Clare AI", email: "clare@ai.assistant", isAI: true },
339
  { id: "1", name: "Sarah Johnson", email: "sarah.j@university.edu" },
 
441
 
442
  // =========================
443
  // ✅ Review Star (按天) state
 
444
  // =========================
445
  const reviewStarKey = useMemo(() => {
446
  if (!user) return "";
 
449
 
450
  const [reviewStarState, setReviewStarState] = useState<ReviewStarState | null>(null);
451
 
 
452
  useEffect(() => {
453
  if (!user || !reviewStarKey) return;
454
  if (chatMode !== "review") return;
 
718
  );
719
  };
720
 
721
+ const handleDeleteSavedChat = (id: string) => {
722
+ setSavedChats((prev) => prev.filter((chat) => chat.id !== id));
723
+ toast.success("Chat deleted");
724
+ };
725
+
726
+ const handleRenameSavedChat = (id: string, newTitle: string) => {
727
+ setSavedChats((prev) => prev.map((chat) => (chat.id === id ? { ...chat, title: newTitle } : chat)));
728
+ toast.success("Chat renamed");
729
+ };
730
+
731
  const handleSaveChat = () => {
732
  if (messages.length <= 1) {
733
  toast.info("No conversation to save");
 
768
  toast.success("Chat loaded!");
769
  };
770
 
 
 
 
 
 
 
 
 
 
 
771
  const handleClearConversation = (shouldSave: boolean = false) => {
772
  if (shouldSave) handleSaveChat();
773