From 10f666955c8eab75d4079eb052f3e0a7188d3144 Mon Sep 17 00:00:00 2001 From: ABHISHEKUPAI Date: Sun, 5 Jul 2026 13:42:37 +0530 Subject: [PATCH 1/2] feat:Revise page UI --- app/components/ui/CalenderStat.tsx | 124 +++++++++++++++++++ app/components/ui/Revisionlist.tsx | 188 +++++++++++++++++++++++++++++ app/revise/page.tsx | 22 ++++ 3 files changed, 334 insertions(+) create mode 100644 app/components/ui/CalenderStat.tsx create mode 100644 app/components/ui/Revisionlist.tsx diff --git a/app/components/ui/CalenderStat.tsx b/app/components/ui/CalenderStat.tsx new file mode 100644 index 0000000..fe50944 --- /dev/null +++ b/app/components/ui/CalenderStat.tsx @@ -0,0 +1,124 @@ +"use client"; + +import { ChevronLeft, ChevronRight, Flame } from "lucide-react"; + +const revisionData = { + completedDays: [2, 3, 5, 7, 8, 10, 12, 15, 18, 20, 24, 25], + currentStreak: 2, + longestStreak: 12, +}; + +export default function CalendarStats() { + const today = new Date(); + + const month = today.toLocaleString("default", { month: "long" }); + const year = today.getFullYear(); + const currentDay = today.getDate(); + + const totalDays = new Date(year, today.getMonth() + 1, 0).getDate(); + const firstDay = new Date(year, today.getMonth(), 1).getDay(); + + const calendarCells: (number | null)[] = [ + ...Array(firstDay).fill(null), + ...Array.from({ length: totalDays }, (_, i) => i + 1), + ]; + + return ( + + ); +} \ No newline at end of file diff --git a/app/components/ui/Revisionlist.tsx b/app/components/ui/Revisionlist.tsx new file mode 100644 index 0000000..ea6ca47 --- /dev/null +++ b/app/components/ui/Revisionlist.tsx @@ -0,0 +1,188 @@ +"use client"; + +import { useState } from "react"; +import ChapterCard from "./ChapterCard"; +import type { Chapter, Topic } from "@/app/types"; + +type SelectedConcepts = Record>; + +const topics: Topic[] = [ + { + name: "Mathematics", + chapters: [ + { + name: "Calculus I", + concepts: [ + { name: "Limits and Continuity" }, + { name: "Derivatives" }, + { name: "Chain Rule" }, + { name: "Mean Value Theorem" }, + ], + }, + { + name: "Calculus II", + concepts: [ + { name: "Integration" }, + { name: "Definite Integrals" }, + { name: "Area Under Curve" }, + ], + }, + { + name: "Probability", + concepts: [ + { name: "Basic Probability" }, + { name: "Conditional Probability" }, + { name: "Bayes Theorem" }, + ], + }, + ], + }, + { + name: "Physics", + chapters: [ + { + name: "Mechanics", + concepts: [ + { name: "Kinematics" }, + { name: "Newton's Laws of Motion" }, + { name: "Work, Energy and Power" }, + ], + }, + { + name: "Thermodynamics", + concepts: [ + { name: "Heat Transfer" }, + { name: "Laws of Thermodynamics" }, + { name: "Entropy" }, + ], + }, + { + name: "Optics", + concepts: [ + { name: "Reflection" }, + { name: "Refraction" }, + { name: "Lens Formula" }, + ], + }, + ], + }, + { + name: "Chemistry", + chapters: [ + { + name: "Organic Chemistry", + concepts: [ + { name: "Hydrocarbons" }, + { name: "Functional Groups" }, + { name: "Reaction Mechanisms" }, + ], + }, + { + name: "Chemical Bonding", + concepts: [ + { name: "Ionic Bonding" }, + { name: "Covalent Bonding" }, + { name: "Hybridization" }, + ], + }, + { + name: "Equilibrium", + concepts: [ + { name: "Chemical Equilibrium" }, + { name: "Le Chatelier's Principle" }, + { name: "Ionic Equilibrium" }, + ], + }, + ], + }, +]; + +export default function RevisionList() { + const [expanded, setExpanded] = useState>({}); + const [selected, setSelected] = useState({}); + + function isChapterSelected(chapter: Chapter) { + const chapterData = selected[chapter.name] || {}; + + return chapter.concepts.every((concept) => chapterData[concept.name]); + } + + function updateSelectedConcepts(updatedSelected: SelectedConcepts) { + const selectedList: string[] = []; + + for (const chapterName in updatedSelected) { + const concepts = updatedSelected[chapterName]; + + for (const conceptName in concepts) { + if (concepts[conceptName]) { + selectedList.push(conceptName); + } + } + } + + console.log(selectedList); + } + + function toggleChapter(chapter: Chapter) { + const shouldCheck = !isChapterSelected(chapter); + + const chapterConcepts: Record = {}; + + for (const concept of chapter.concepts) { + chapterConcepts[concept.name] = shouldCheck; + } + + const updatedSelected: SelectedConcepts = { + ...selected, + [chapter.name]: chapterConcepts, + }; + + setSelected(updatedSelected); + updateSelectedConcepts(updatedSelected); + } + + function toggleConcept(chapterName: string, concept: string) { + const updatedSelected: SelectedConcepts = { + ...selected, + [chapterName]: { + ...(selected[chapterName] || {}), + [concept]: !selected[chapterName]?.[concept], + }, + }; + + setSelected(updatedSelected); + updateSelectedConcepts(updatedSelected); + } + + return ( +
+ {topics.map((topic) => ( +
+
+

+ {topic.name} +

+
+ +
+ {topic.chapters.map((chapter) => ( + + ))} +
+
+ ))} +
+ ); +} \ No newline at end of file diff --git a/app/revise/page.tsx b/app/revise/page.tsx index e69de29..357df26 100644 --- a/app/revise/page.tsx +++ b/app/revise/page.tsx @@ -0,0 +1,22 @@ +"use client"; + +import Sidebar from "../components/Sidebar"; +import RevisionList from "../components/ui/Revisionlist"; +import CalendarStats from "../components/ui/CalenderStat"; +export default function Revise() { + return ( +
+
+ +
+
+ +
+ +
+
+
+
+
+ ); +} \ No newline at end of file From 0a8a0c69de2938684dd08ab9af1646dea8a479b0 Mon Sep 17 00:00:00 2001 From: ABHISHEKUPAI Date: Wed, 5 Aug 2026 21:28:43 +0530 Subject: [PATCH 2/2] Routing take-test page to test interface --- app/{Retentiaquiz.tsx => Retentiaquiz/page.tsx} | 10 +++++----- app/take-test/page.tsx | 5 ++++- 2 files changed, 9 insertions(+), 6 deletions(-) rename app/{Retentiaquiz.tsx => Retentiaquiz/page.tsx} (96%) diff --git a/app/Retentiaquiz.tsx b/app/Retentiaquiz/page.tsx similarity index 96% rename from app/Retentiaquiz.tsx rename to app/Retentiaquiz/page.tsx index 5aa031e..e0f7aba 100644 --- a/app/Retentiaquiz.tsx +++ b/app/Retentiaquiz/page.tsx @@ -2,11 +2,11 @@ import { ChevronRight, Flag } from "lucide-react"; import { useState } from "react"; -import Button from "./components/ui/Button"; -import Card from "./components/ui/Card"; -import ProgressBar from "./components/ui/Progressbar"; -import QuestionNavigation from "./components/ui/QuestionNavigation"; -import Timer from "./components/ui/Timer"; +import Button from "../components/ui/Button"; +import Card from "../components/ui/Card"; +import ProgressBar from "../components/ui/Progressbar"; +import QuestionNavigation from "../components/ui/QuestionNavigation"; +import Timer from "../components/ui/Timer"; export default function Retentiaquiz() { const totalQuestions = 50; diff --git a/app/take-test/page.tsx b/app/take-test/page.tsx index 4270ebf..f2408fa 100644 --- a/app/take-test/page.tsx +++ b/app/take-test/page.tsx @@ -7,6 +7,7 @@ import Button from "@/app/components/ui/Button"; import SelectChapterCard from "@/app/components/ui/SelectConcepts"; import { Subject } from "@/app/types" import { fetchSyllabus, subjectIconColors, subjectIcons } from "@/app/take-test/lib"; +import { useRouter } from "next/navigation"; export default function TakeTest() { const [search, setSearch] = useState(""); @@ -14,7 +15,7 @@ export default function TakeTest() { const [physicsSelected, setPhysicsSelected] = useState([]); const [chemSelected, setChemSelected] = useState([]); const [subjects, setSubjects] = useState([]); - + const router = useRouter(); const selectionHandlers: Record< string, React.Dispatch> @@ -29,7 +30,9 @@ export default function TakeTest() { Mathematics: mathSelected, Physics: physicsSelected, Chemistry: chemSelected, + }); + router.push("/Retentiaquiz") } useEffect(() => {