From 3cb963452409770d9fa157e8d583e8adf01ed14c Mon Sep 17 00:00:00 2001 From: Elijah Date: Fri, 10 Jul 2026 16:15:51 -0700 Subject: [PATCH] Add minimize group feature with local storage persistence --- .../[classSlug]/flashcards/page.tsx | 81 +++++++++++++------ .../(protected)/[classSlug]/quizzes/page.tsx | 81 +++++++++++++------ 2 files changed, 112 insertions(+), 50 deletions(-) diff --git a/src/app/(protected)/[classSlug]/flashcards/page.tsx b/src/app/(protected)/[classSlug]/flashcards/page.tsx index ce0f56a..665e003 100644 --- a/src/app/(protected)/[classSlug]/flashcards/page.tsx +++ b/src/app/(protected)/[classSlug]/flashcards/page.tsx @@ -174,6 +174,22 @@ export default function FlashcardsPage() { const [newGroupName, setNewGroupName] = useState(""); const [editingGroupId, setEditingGroupId] = useState(null); const [editGroupName, setEditGroupName] = useState(""); + const [collapsedGroups, setCollapsedGroups] = useState>({}); + + useEffect(() => { + const saved = localStorage.getItem('flashcards_collapsed_groups'); + if (saved) { + try { setCollapsedGroups(JSON.parse(saved)); } catch(e) {} + } + }, []); + + function toggleGroup(id: string) { + setCollapsedGroups(prev => { + const next = { ...prev, [id]: !prev[id] }; + localStorage.setItem('flashcards_collapsed_groups', JSON.stringify(next)); + return next; + }); + } const fetchAll = useCallback(async (cId: string) => { try { @@ -430,7 +446,7 @@ export default function FlashcardsPage() {
{groupedDecks.map(group => (
-
+
{editingGroupId === group.id ? (
setEditGroupName(e.target.value)} className="px-2 py-1 rounded border border-border bg-bg-surface text-text-heading focus:ring-1 focus:ring-primary" /> @@ -438,7 +454,12 @@ export default function FlashcardsPage() {
) : ( -

{group.name}

+
+ +

{group.name}

+
)}
@@ -448,34 +469,44 @@ export default function FlashcardsPage() {
- d.id)} strategy={verticalListSortingStrategy}> - - {group.decks.length === 0 ? ( -
Drop decks here
- ) : ( - group.decks.map(deck => ( - { setEditingId(d.id); setEditName(d.name); setEditDescription(d.description || ""); }} onDelete={handleDeleteDeck} classSlug={classSlug} /> - )) - )} -
-
+
+ d.id)} strategy={verticalListSortingStrategy}> + + {group.decks.length === 0 ? ( +
Drop decks here
+ ) : ( + group.decks.map(deck => ( + { setEditingId(d.id); setEditName(d.name); setEditDescription(d.description || ""); }} onDelete={handleDeleteDeck} classSlug={classSlug} /> + )) + )} +
+
+
))} {/* Uncategorized */}
-

Uncategorized

- d.id)} strategy={verticalListSortingStrategy}> - - {uncategorizedDecks.length === 0 ? ( -
No uncategorized decks
- ) : ( - uncategorizedDecks.map(deck => ( - { setEditingId(d.id); setEditName(d.name); setEditDescription(d.description || ""); }} onDelete={handleDeleteDeck} classSlug={classSlug} /> - )) - )} -
-
+
+ +

Uncategorized

+
+ +
+ d.id)} strategy={verticalListSortingStrategy}> + + {uncategorizedDecks.length === 0 ? ( +
No uncategorized decks
+ ) : ( + uncategorizedDecks.map(deck => ( + { setEditingId(d.id); setEditName(d.name); setEditDescription(d.description || ""); }} onDelete={handleDeleteDeck} classSlug={classSlug} /> + )) + )} +
+
+
diff --git a/src/app/(protected)/[classSlug]/quizzes/page.tsx b/src/app/(protected)/[classSlug]/quizzes/page.tsx index 72df87e..e44cf78 100644 --- a/src/app/(protected)/[classSlug]/quizzes/page.tsx +++ b/src/app/(protected)/[classSlug]/quizzes/page.tsx @@ -130,6 +130,22 @@ export default function QuizzesPage() { const [newGroupName, setNewGroupName] = useState(""); const [editingGroupId, setEditingGroupId] = useState(null); const [editGroupName, setEditGroupName] = useState(""); + const [collapsedGroups, setCollapsedGroups] = useState>({}); + + useEffect(() => { + const saved = localStorage.getItem('quizzes_collapsed_groups'); + if (saved) { + try { setCollapsedGroups(JSON.parse(saved)); } catch(e) {} + } + }, []); + + function toggleGroup(id: string) { + setCollapsedGroups(prev => { + const next = { ...prev, [id]: !prev[id] }; + localStorage.setItem('quizzes_collapsed_groups', JSON.stringify(next)); + return next; + }); + } const fetchAll = useCallback(async (cId: string) => { try { @@ -403,7 +419,7 @@ export default function QuizzesPage() {
{groupedQuizzes.map(group => (
-
+
{editingGroupId === group.id ? (
setEditGroupName(e.target.value)} className="px-2 py-1 rounded border border-border bg-bg-surface text-text-heading focus:ring-1 focus:ring-primary" /> @@ -411,7 +427,12 @@ export default function QuizzesPage() {
) : ( -

{group.name}

+
+ +

{group.name}

+
)}
@@ -421,34 +442,44 @@ export default function QuizzesPage() {
- q.id)} strategy={verticalListSortingStrategy}> - - {group.quizzes.length === 0 ? ( -
Drop quizzes here
- ) : ( - group.quizzes.map(quiz => ( - { setEditingId(q.id); setEditName(q.name); setEditDescription(q.description || ""); }} onDelete={handleDeleteQuiz} classSlug={classSlug} /> - )) - )} -
-
+
+ q.id)} strategy={verticalListSortingStrategy}> + + {group.quizzes.length === 0 ? ( +
Drop quizzes here
+ ) : ( + group.quizzes.map(quiz => ( + { setEditingId(q.id); setEditName(q.name); setEditDescription(q.description || ""); }} onDelete={handleDeleteQuiz} classSlug={classSlug} /> + )) + )} +
+
+
))} {/* Uncategorized */}
-

Uncategorized

- q.id)} strategy={verticalListSortingStrategy}> - - {uncategorizedQuizzes.length === 0 ? ( -
No uncategorized quizzes
- ) : ( - uncategorizedQuizzes.map(quiz => ( - { setEditingId(q.id); setEditName(q.name); setEditDescription(q.description || ""); }} onDelete={handleDeleteQuiz} classSlug={classSlug} /> - )) - )} -
-
+
+ +

Uncategorized

+
+ +
+ q.id)} strategy={verticalListSortingStrategy}> + + {uncategorizedQuizzes.length === 0 ? ( +
No uncategorized quizzes
+ ) : ( + uncategorizedQuizzes.map(quiz => ( + { setEditingId(q.id); setEditName(q.name); setEditDescription(q.description || ""); }} onDelete={handleDeleteQuiz} classSlug={classSlug} /> + )) + )} +
+
+