Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions app/Retentiaquiz.tsx → app/Retentiaquiz/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
124 changes: 124 additions & 0 deletions app/components/ui/CalenderStat.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<aside className="w-full max-w-full rounded-3xl bg-[#2f2f2f] p-4 text-white shadow-xl sm:p-5">
<div>
<h1 className="text-xl font-bold leading-tight sm:text-2xl">
Revision Schedule
</h1>
<p className="mt-1 text-xs leading-relaxed text-white/80 sm:text-sm">
Manage your spaced repetition and mastery goals.
</p>
</div>

<div className="mt-5 rounded-[22px] bg-black p-3 sm:p-4">
<div className="mb-4 flex items-center justify-between gap-3">
<button
type="button"
className="flex h-8 w-8 items-center justify-center rounded-full hover:bg-white/10"
aria-label="Previous month"
>
<ChevronLeft size={18} />
</button>

<p className="text-center text-sm font-medium sm:text-base">
{month} {year}
</p>

<button
type="button"
className="flex h-8 w-8 items-center justify-center rounded-full hover:bg-white/10"
aria-label="Next month"
>
<ChevronRight size={18} />
</button>
</div>

<div className="grid grid-cols-7 text-center text-xs font-medium text-white/80">
{["S", "M", "T", "W", "T", "F", "S"].map((day, index) => (
<span key={`${day}-${index}`}>{day}</span>
))}
</div>

<div className="mt-2 grid grid-cols-7 gap-1.5 sm:gap-2">
{calendarCells.map((day, index) => {
const isToday = day === currentDay;
const isRevisionDay =
day !== null && revisionData.completedDays.includes(day);

return (
<div
key={index}
className={`flex aspect-square min-h-7 items-center justify-center rounded-full text-[11px] sm:text-xs ${
day === null
? "invisible"
: isToday || isRevisionDay
? "bg-green-500 font-semibold text-black"
: "border border-white/40 text-white"
}`}>
{day}
</div>
);
})}
</div>
</div>

<div className="mt-5 space-y-3 sm:mt-6">
<div className="flex flex-col gap-1 rounded-2xl bg-blue-500 px-4 py-3 shadow-lg sm:flex-row sm:items-center sm:justify-between">
<span className="text-sm font-bold sm:text-base">
Current Streak
</span>

<span className="text-base font-bold sm:text-lg">
{revisionData.currentStreak} Days
</span>
</div>

<div className="flex flex-col gap-2 rounded-2xl bg-blue-500 px-4 py-3 shadow-lg sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-2">
<span className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-yellow-300">
<Flame size={18} className="text-orange-500" />
</span>

<span className="text-sm font-bold sm:text-base">
Longest Streak
</span>
</div>

<span className="text-base font-bold sm:text-lg">
{revisionData.longestStreak} Days
</span>
</div>
</div>

<button
type="button"
className="mt-6 w-full rounded-full bg-green-600 py-3 text-sm font-bold text-black shadow-lg transition hover:bg-green-700 sm:text-base">
Proceed for Revision →
</button>
</aside>
);
}
188 changes: 188 additions & 0 deletions app/components/ui/Revisionlist.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
"use client";

import { useState } from "react";
import ChapterCard from "./ChapterCard";
import type { Chapter, Topic } from "@/app/types";

type SelectedConcepts = Record<string, Record<string, boolean>>;

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<Record<string, boolean>>({});
const [selected, setSelected] = useState<SelectedConcepts>({});

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<string, boolean> = {};

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 (
<div className="flex min-w-0 flex-col gap-4">
{topics.map((topic) => (
<div
key={topic.name}
className="w-full rounded-2xl bg-foreground p-4 shadow-xl sm:p-5"
>
<div className="mb-3 flex items-center gap-2">
<h2 className="text-sm font-semibold text-white sm:text-base">
{topic.name}
</h2>
</div>

<div className="flex flex-col gap-2">
{topic.chapters.map((chapter) => (
<ChapterCard
key={chapter.name}
chapter={chapter}
isExpanded={!!expanded[chapter.name]}
isChapterSelected={isChapterSelected}
toggleChapter={toggleChapter}
toggleConcept={toggleConcept}
setExpanded={setExpanded}
selected={selected}
/>
))}
</div>
</div>
))}
</div>
);
}
22 changes: 22 additions & 0 deletions app/revise/page.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<main className="min-h-screen bg-background text-white">
<div className="flex min-h-screen">
<Sidebar />
<section className="min-w-0 flex-1 px-4 py-5 sm:px-6 lg:px-8">
<div className="grid grid-cols-1 gap-6 xl:grid-cols-[minmax(0,1fr)_340px] 2xl:grid-cols-[minmax(0,1fr)_360px]">
<RevisionList />
<div className="xl:sticky xl:top-6 xl:self-start">
<CalendarStats />
</div>
</div>
</section>
</div>
</main>
);
}
5 changes: 4 additions & 1 deletion app/take-test/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ 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("");
const [mathSelected, setMathSelected] = useState<string[]>([]);
const [physicsSelected, setPhysicsSelected] = useState<string[]>([]);
const [chemSelected, setChemSelected] = useState<string[]>([]);
const [subjects, setSubjects] = useState<Subject[]>([]);

const router = useRouter();
const selectionHandlers: Record<
string,
React.Dispatch<React.SetStateAction<string[]>>
Expand All @@ -29,7 +30,9 @@ export default function TakeTest() {
Mathematics: mathSelected,
Physics: physicsSelected,
Chemistry: chemSelected,

});
router.push("/Retentiaquiz")
}

useEffect(() => {
Expand Down
Loading