From 443669330b21cbe059a641026b30bdbb119ac517 Mon Sep 17 00:00:00 2001 From: akshat Date: Thu, 14 Mar 2024 22:17:57 +0530 Subject: [PATCH] feat(app): allowing subjects to be choosen --- src/components/SubjectList.tsx | 127 +++++++++++++++++++++++++++++---- src/hooks/use-subject-list.ts | 60 ++++++++++++++++ 2 files changed, 174 insertions(+), 13 deletions(-) diff --git a/src/components/SubjectList.tsx b/src/components/SubjectList.tsx index 6c5db26..b8b88c3 100644 --- a/src/components/SubjectList.tsx +++ b/src/components/SubjectList.tsx @@ -1,14 +1,17 @@ "use client"; import { Courses } from "@/config"; -import { useSubjectList } from "@/hooks/use-subject-list"; +import { + useActiveSubjectsStore, + useSubjectList, +} from "@/hooks/use-subject-list"; import { getSubjectList } from "@/lib/server"; import { cn } from "@/lib/utils"; import { QueryKey, useQuery } from "@tanstack/react-query"; import _ from "lodash"; -import { Expand, Maximize2, Minimize2 } from "lucide-react"; +import { Check, Expand, ListChecks, Maximize2, Minimize2 } from "lucide-react"; import { usePathname, useRouter, useSearchParams } from "next/navigation"; -import { useCallback, useState } from "react"; +import { useCallback, useMemo, useRef, useState } from "react"; import { Button } from "./ui/button"; import { Card, @@ -17,6 +20,8 @@ import { CardHeader, CardTitle, } from "./ui/card"; +import { Command, CommandGroup, CommandInput, CommandItem } from "./ui/command"; +import { Popover, PopoverContent, PopoverTrigger } from "./ui/popover"; import { ScrollArea } from "./ui/scroll-area"; import { Skeleton } from "./ui/skeleton"; @@ -29,6 +34,8 @@ const SubjectList = ({ course }: SubjectListProps) => { const searchParams = useSearchParams()!; + const { activeSubjects } = useActiveSubjectsStore(); + const semester = searchParams.get("semester"); const branch = searchParams.get("branch"); @@ -49,6 +56,18 @@ const SubjectList = ({ course }: SubjectListProps) => { queryFn: async () => await getSubjectList({ course, branch, semester }), }); + const generateSubjectList = useMemo(() => { + const subjects = activeSubjects.find( + (active) => active.branch === branch && active.semester === semester + ); + + if (subjects && subjects.subjects.length > 0) { + return subjects.subjects; + } else { + if (list) return list.slice(0, 9); + } + }, [list, semester, branch, activeSubjects]); + if (isLoading) { return ; } @@ -69,19 +88,24 @@ const SubjectList = ({ course }: SubjectListProps) => { Spoiler alert: courage required - +
+ {list.length > 9 && ( + + )} + +
- + @@ -185,4 +209,81 @@ SubjectList.Data = function SubjectListData({ list }: { list: string[] }) { ); }; +SubjectList.ActiveSubjects = function SubjectListActiveSubjects({ + list, +}: { + list: string[]; +}) { + const inputRef = useRef(null); + const [open, setOpen] = useState(false); + + const searchParams = useSearchParams()!; + + const semester = searchParams.get("semester"); + const branch = searchParams.get("branch"); + + const { activeSubjects, toggleSubject } = useActiveSubjectsStore(); + + const onOpenChange = (value: boolean) => { + inputRef.current?.blur(); + setOpen(value); + }; + + const toggle = (subject: string) => { + if (semester && branch) { + toggleSubject(semester, branch, subject); + } + }; + + return ( + + + + + + + + + {list.map((subject) => { + const isActive = activeSubjects.some( + (active) => + active.branch === branch && + active.semester === semester && + active.subjects.includes(subject) + ); + return ( + toggle(subject)} + > + +
{subject}
+
+ ); + })} +
+
+
+
+ ); +}; + export default SubjectList; diff --git a/src/hooks/use-subject-list.ts b/src/hooks/use-subject-list.ts index e30c8ea..99136db 100644 --- a/src/hooks/use-subject-list.ts +++ b/src/hooks/use-subject-list.ts @@ -1,4 +1,5 @@ import { create } from "zustand"; +import { persist } from "zustand/middleware"; type SubjectListStore = { isOpen: boolean; @@ -13,3 +14,62 @@ export const useSubjectList = create((set, get) => ({ onClose: () => set({ isOpen: false, subjectList: [] }), subjectList: [], })); + +type ActiveSubjectList = { + semester: string; + branch: string; + subjects: string[]; +}; + +type ActiveSubjectsState = { + activeSubjects: ActiveSubjectList[]; + toggleSubject: (semester: string, branch: string, subject: string) => void; +}; + +export const useActiveSubjectsStore = create()( + persist( + (set, get) => ({ + activeSubjects: [], + toggleSubject: (semester, branch, subject) => { + const activeSubjects = [...get().activeSubjects]; + const existingSubjectIndex = activeSubjects.findIndex( + (active) => + active.branch === branch && active.semester === semester + ); + + if (existingSubjectIndex !== -1) { + const existingSubject = + activeSubjects[existingSubjectIndex]; + const updatedSubjects = existingSubject.subjects.includes( + subject + ) + ? existingSubject.subjects.filter((s) => s !== subject) + : [...existingSubject.subjects, subject]; + const updatedActiveSubjects = [ + ...activeSubjects.slice(0, existingSubjectIndex), + { ...existingSubject, subjects: updatedSubjects }, + ...activeSubjects.slice(existingSubjectIndex + 1), + ]; + set({ activeSubjects: updatedActiveSubjects }); + } else { + const newActiveSubject = { + semester, + branch, + subjects: [subject], + }; + const updatedActiveSubjects = [ + ...activeSubjects, + newActiveSubject, + ]; + set({ activeSubjects: updatedActiveSubjects }); + } + }, + }), + { + name: "active-subjects", + partialize: (state) => ({ + activeSubjects: state.activeSubjects, + }), + } + ) +);