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
110 changes: 55 additions & 55 deletions app/bookmarks/page.tsx
Original file line number Diff line number Diff line change
@@ -1,56 +1,56 @@
"use client";
import { useBookmarks } from "../hooks/useBookmarks";
import Navbar from "@/app/components/navbar";
import Link from "next/link";
import { useEffect, useState } from "react";
import { Road_Rage } from "next/font/google";

const roadRage = Road_Rage({
variable: "--font-road-rage",
subsets: ["latin"],
weight: "400",
});

export default function BookmarksPage() {
const { bookmarks, toggleBookmark } = useBookmarks();
const [mounted, setMounted] = useState(false);

useEffect(() => setMounted(true), []);
if (!mounted) return null;

return (
<div className="p-8 pt-24 min-h-screen bg-[#1B0D00] text-[#FAE8D7]">
<Navbar />
<Link
href="/"
className="inline-flex items-center gap-2 mb-6 px-4 py-2 bg-[#e2d1c1] text-[#1b0d00] rounded hover:bg-[#ac9e91] transition font-bold"
style={{ fontFamily: "Rockwell, Serif, serif" }}
>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M15 18l-6-6 6-6"/></svg>
Back to Home
</Link>
<h1 className={`text-5xl font-bold mb-8 ${roadRage.className}`}>My Bookmarks</h1>
{bookmarks.length === 0 ? (
<p className="text-xl" style={{ fontFamily: "Rockwell, Serif, serif" }}>
No bookmarks saved yet. Go explore some subjects!
</p>
) : (
<ul className="space-y-4 max-w-3xl">
{bookmarks.map((b) => (
<li key={b.url} className="flex items-center justify-between p-4 border border-[#FAE8D7] rounded hover:bg-[#2a1809] transition">
<Link href={b.url} className="text-2xl font-bold hover:underline" style={{ fontFamily: "Rockwell, Serif, serif" }}>
{b.title}
</Link>
<button
onClick={() => toggleBookmark(b)}
className="text-red-400 hover:text-red-300 font-bold px-4 py-2 border border-red-400 rounded"
>
Remove
</button>
</li>
))}
</ul>
)}
</div>
);
"use client";
import { useBookmarks } from "../hooks/useBookmarks";
import Navbar from "@/app/components/navbar";
import Link from "next/link";
import { useEffect, useState } from "react";
import { Road_Rage } from "next/font/google";
const roadRage = Road_Rage({
variable: "--font-road-rage",
subsets: ["latin"],
weight: "400",
});
export default function BookmarksPage() {
const { bookmarks, toggleBookmark } = useBookmarks();
const [mounted, setMounted] = useState(false);
useEffect(() => setMounted(true), []);
if (!mounted) return null;
return (
<div className="p-8 pt-24 min-h-screen bg-[#1B0D00] text-[#FAE8D7]">
<Navbar />
<Link
href="/"
className="inline-flex items-center gap-2 mb-6 px-4 py-2 bg-[#e2d1c1] text-[#1b0d00] rounded hover:bg-[#ac9e91] transition font-bold"
style={{ fontFamily: "Rockwell, Serif, serif" }}
>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M15 18l-6-6 6-6"/></svg>
Back to Home
</Link>
<h1 className={`text-5xl font-bold mb-8 ${roadRage.className}`}>My Bookmarks</h1>
{bookmarks.length === 0 ? (
<p className="text-xl" style={{ fontFamily: "Rockwell, Serif, serif" }}>
No bookmarks saved yet. Go explore some subjects!
</p>
) : (
<ul className="space-y-4 max-w-3xl">
{bookmarks.map((b) => (
<li key={b.url} className="flex items-center justify-between p-4 border border-[#FAE8D7] rounded hover:bg-[#2a1809] transition">
<Link href={b.url} className="text-2xl font-bold hover:underline" style={{ fontFamily: "Rockwell, Serif, serif" }}>
{b.title}
</Link>
<button
onClick={() => toggleBookmark(b)}
className="text-red-400 hover:text-red-300 font-bold px-4 py-2 border border-red-400 rounded"
>
Remove
</button>
</li>
))}
</ul>
)}
</div>
);
}
31 changes: 31 additions & 0 deletions app/flashcards/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { flashcardDecks } from "@/lib/flashcardData";
import { notFound } from "next/navigation";
import FlashcardClient from "./FlashcardClient";
import { Metadata } from "next";

export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }): Promise<Metadata> {
const { slug } = await params;
const deck = flashcardDecks.find((d) => d.slug === slug);
if (!deck) return {};

return {
title: `${deck.subject} Flashcards - openCSE`,
description: deck.description,
};
}

export function generateStaticParams() {
return flashcardDecks.map((deck) => ({
slug: deck.slug,
}));
}

export default function FlashcardDeckPage({ params }: { params: { slug: string } }) {
const deck = flashcardDecks.find((d) => d.slug === slug);

if (!deck) {
notFound();
}

return <FlashcardClient deck={deck} />;
}
87 changes: 87 additions & 0 deletions app/flashcards/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"use client";

import Link from "next/link";
import Navbar from "@/app/components/navbar";
import { flashcardDecks } from "@/lib/flashcardData";
import { Road_Rage } from "next/font/google";

const roadRage = Road_Rage({
variable: "--font-road-rage",
subsets: ["latin"],
weight: "400",
});

export default function FlashcardsIndex() {
return (
<div className="min-h-screen bg-[#1B0D00] text-[#e2d1c1] pt-14">
<Navbar />

<section
className="relative overflow-hidden w-full py-16 sm:py-24 px-4 sm:px-6 md:px-10 lg:px-16 text-center shadow-lg"
style={{
backgroundImage: "url('/HeroBG.png')",
backgroundSize: "cover",
backgroundPosition: "center",
backgroundRepeat: "no-repeat",
backgroundColor: "#cbb89d",
}}
>
<div
className="absolute inset-0 backdrop-blur-[2px]"
style={{ WebkitBackdropFilter: "blur(2px)", zIndex: 0 }}
/>

<div className="relative z-10 max-w-4xl mx-auto flex flex-col items-center">
<h1
className={`font-bold ${roadRage.variable} text-black text-center text-5xl sm:text-6xl md:text-7xl leading-snug`}
style={{
fontFamily: "var(--font-road-rage), 'Road Rage', cursive",
fontWeight: 400,
}}
>
Smart Flashcards
</h1>
<p
className="sm:text-xl md:text-2xl text-[#3a2a14] mt-2 font-bold max-w-2xl text-center mx-auto"
style={{ fontFamily: "Rockwell, serif" }}
>
Master core engineering concepts with an algorithmic Spaced Repetition System.
</p>
</div>
</section>

<div className="max-w-5xl mx-auto px-4 py-16">
<h2 className="text-3xl font-bold mb-8 text-[#f0d7a8] text-center" style={{ fontFamily: "Rockwell, serif" }}>
Select a Subject
</h2>

<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{flashcardDecks.map((deck) => (
<div
key={deck.slug}
className="rounded-2xl border border-[#c7a669] bg-[#2a1b0f] p-8 shadow-xl flex flex-col transition hover:scale-[1.02]"
>
<h3 className="text-2xl font-bold text-[#f0d7a8] mb-3" style={{ fontFamily: "Rockwell, serif" }}>
{deck.subject}
</h3>
<p className="text-[#dcd2b8] mb-6 flex-grow">{deck.description}</p>

<div className="flex items-center justify-between mt-auto">
<span className="text-sm font-semibold text-[#a07840]">
{deck.cards.length} Core Concepts
</span>
<Link
href={`/flashcards/${deck.slug}`}
className="px-6 py-2 rounded-lg text-lg font-bold bg-[#d2b48c] text-[#2b1b0e] hover:bg-[#c7a669] transition shadow-md"
style={{ fontFamily: "Rockwell, serif" }}
>
Review
</Link>
</div>
</div>
))}
</div>
</div>
</div>
);
}
56 changes: 28 additions & 28 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
import ContributionsSection from "./components/contribute";
import HeroSection from "./components/hero";
import Navbar from "./components/navbar";
import SponsorSection from "./components/sponsor";
import SubjectsSection from "./components/subjects";
import RequestCourse from "./components/request-course";
export default function Home() {
return (
<div
style={{
scrollbarColor: "yellow transparent",
scrollbarWidth: "thin",
}}
className="scrollbar-yellow pt-14"
>
<Navbar />
<HeroSection />
<hr className="mx-70 mb-6 mt-18 border-t-4" />
<SubjectsSection />
<RequestCourse />
<hr className="mx-70 mb-6 mt-10 border-t-4" />
<ContributionsSection />
<hr className="mx-70 mb-6 mt-10 border-t-4" />
<SponsorSection />

</div>
);
}
import ContributionsSection from "./components/contribute";
import HeroSection from "./components/hero";
import Navbar from "./components/navbar";
import SponsorSection from "./components/sponsor";
import SubjectsSection from "./components/subjects";
import RequestCourse from "./components/request-course";
export default function Home() {
return (
<div
style={{
scrollbarColor: "yellow transparent",
scrollbarWidth: "thin",
}}
className="scrollbar-yellow pt-14"
>
<Navbar />
<HeroSection />
<hr className="mx-70 mb-6 mt-18 border-t-4" />
<SubjectsSection />
<RequestCourse />
<hr className="mx-70 mb-6 mt-10 border-t-4" />
<ContributionsSection />
<hr className="mx-70 mb-6 mt-10 border-t-4" />
<SponsorSection />
</div>
);
}
52 changes: 26 additions & 26 deletions app/quiz/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
// app/quiz/[slug]/page.tsx
import { getQuizBySlug, moduleQuizzes, quizzes } from "@/lib/quizData";
import { notFound } from "next/navigation";
import QuizClient from "./QuizClient";

// Pre-generate all quiz pages at build time
export function generateStaticParams() {
return [...quizzes, ...moduleQuizzes].map((q) => ({ slug: q.slug }));
}

export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
const quiz = getQuizBySlug(slug);
if (!quiz) return {};
return {
title: `${quiz.subject} Quiz | openCSE`,
description: quiz.description,
};
}

export default async function QuizPage({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
const quiz = getQuizBySlug(slug);
if (!quiz) notFound();

return <QuizClient quiz={quiz} />;
// app/quiz/[slug]/page.tsx
import { getQuizBySlug, moduleQuizzes, quizzes } from "@/lib/quizData";
import { notFound } from "next/navigation";
import QuizClient from "./QuizClient";
// Pre-generate all quiz pages at build time
export function generateStaticParams() {
return [...quizzes, ...moduleQuizzes].map((q) => ({ slug: q.slug }));
}
export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
const quiz = getQuizBySlug(slug);
if (!quiz) return {};
return {
title: `${quiz.subject} Quiz | openCSE`,
description: quiz.description,
};
}
export default async function QuizPage({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
const quiz = getQuizBySlug(slug);
if (!quiz) notFound();
return <QuizClient quiz={quiz} />;
}
Loading