feat(screens): implement bookmark and profile screens

This commit is contained in:
shafin-r
2025-07-15 21:20:26 +06:00
parent 71eeafdaee
commit aa7bc67dc9
6 changed files with 323 additions and 26 deletions

View File

@ -1,7 +1,87 @@
import React from "react"; "use client";
const page = () => { import React, { useState, useEffect } from "react";
return <div>page</div>; import BackgroundWrapper from "@/components/BackgroundWrapper";
import { Bookmark, BookmarkCheck, ListFilter, MoveLeft } from "lucide-react";
import { useRouter } from "next/navigation";
interface Question {
id: number;
question: string;
options: Record<string, string>;
}
interface QuestionItemProps {
question: Question;
}
const QuestionItem = ({ question }: QuestionItemProps) => {
const [bookmark, setBookmark] = useState(true);
return (
<div className="border border-[#8abdff]/50 rounded-2xl p-4 flex flex-col gap-7">
<h3 className="text-xl font-medium">
{question.id + 1}. {question.question}
</h3>
<div className="flex justify-between items-center">
<div></div>
<button onClick={() => setBookmark(!bookmark)}>
{bookmark ? (
<BookmarkCheck size={25} color="#113768" />
) : (
<Bookmark size={25} color="#113768" />
)}
</button>
</div>
<div className="flex flex-col gap-4 items-start">
{Object.entries(question.options).map(([key, value]) => {
return (
<div key={key} className="flex items-center gap-3">
<span className="px-2 py-1 flex items-center rounded-full border font-medium text-sm">
{key.toUpperCase()}
</span>
<span className="option-description">{value}</span>
</div>
);
})}
</div>
</div>
);
}; };
export default page; const BookmarkPage = () => {
const router = useRouter();
const [questions, setQuestions] = useState();
useEffect(() => {
fetch("/data/bookmark.json")
.then((res) => res.json())
.then((data) => setQuestions(data))
.catch((err) => console.error("Error loading questions: ", err));
}, []);
return (
<BackgroundWrapper>
<section className="min-h-screen flex flex-col justify-between">
<div className="flex-1 mb-20">
<div className="mx-8 mt-10 pb-6 space-y-6">
<button onClick={() => router.push("/home")}>
<MoveLeft size={30} color="#113768" />
</button>
<h1 className="text-4xl font-semibold text-[#113768]">Bookmark</h1>
<div className="flex justify-between">
<h3 className="text-xl font-semibold text-[#113768]">Recent</h3>
<button>
<ListFilter size={24} color="#113768" />
</button>
</div>
{questions?.map((question) => (
<QuestionItem key={question.id} question={question} />
))}
</div>
</div>
</section>
</BackgroundWrapper>
);
};
export default BookmarkPage;

View File

@ -5,13 +5,19 @@ import Link from "next/link";
import { ReactNode } from "react"; import { ReactNode } from "react";
import { usePathname } from "next/navigation"; import { usePathname } from "next/navigation";
import clsx from "clsx"; import clsx from "clsx";
import { House, LayoutGrid, Bookmark, CircleUser } from "lucide-react"; import {
House,
LayoutGrid,
Bookmark,
CircleUser,
Settings,
} from "lucide-react";
const tabs = [ const tabs = [
{ name: "Home", href: "/home", component: <House size={30} /> }, { name: "Home", href: "/home", component: <House size={30} /> },
{ name: "Unit", href: "/unit", component: <LayoutGrid size={30} /> }, { name: "Unit", href: "/unit", component: <LayoutGrid size={30} /> },
{ name: "Bookmark", href: "/bookmark", component: <Bookmark size={30} /> }, { name: "Bookmark", href: "/bookmark", component: <Bookmark size={30} /> },
{ name: "Profile", href: "/profile", component: <CircleUser size={30} /> }, { name: "Settings", href: "/settings", component: <Settings size={30} /> },
]; ];
export default function TabsLayout({ children }: { children: ReactNode }) { export default function TabsLayout({ children }: { children: ReactNode }) {

View File

@ -1,7 +0,0 @@
import React from "react";
const page = () => {
return <div>page</div>;
};
export default page;

View File

@ -0,0 +1,79 @@
"use client";
import BackgroundWrapper from "@/components/BackgroundWrapper";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import { API_URL, getToken } from "@/lib/auth";
import { MoveLeft, UserCircle2 } from "lucide-react";
import Image from "next/image";
import { useRouter } from "next/navigation";
import React, { useEffect, useState } from "react";
const SettingsPage = () => {
const router = useRouter();
const [userData, setUserData] = useState(null);
useEffect(() => {
async function fetchUser() {
try {
const token = await getToken();
if (!token) return;
const response = await fetch(`${API_URL}/me`, {
method: "GET",
headers: {
Authorization: `Bearer ${token}`,
},
});
if (response.ok) {
const fetchedUserData = await response.json();
setUserData(fetchedUserData);
console.log(fetchedUserData);
}
} catch (error) {
console.error("Error fetching user data: ", error);
}
}
fetchUser();
}, []);
return (
<BackgroundWrapper>
<section className="min-h-screen flex flex-col justify-between">
<div className="flex-1 mb-20">
<div className="mx-8 mt-10 pb-6 space-y-6">
<section className="flex justify-between">
<button onClick={() => router.push("/home")}>
<MoveLeft size={30} color="#113768" />
</button>
<h3 className="text-2xl font-semibold text-[#113768]">
Settings
</h3>
<button onClick={() => router.push("/profile")}>
<UserCircle2 size={30} color="#113768" />
</button>
</section>
<section className="flex flex-col gap-4">
<div className="flex gap-4 items-center">
<Avatar className="bg-[#113768] w-20 h-20">
<AvatarFallback className="text-3xl text-white">
{userData?.name
? userData.name.charAt(0).toUpperCase()
: ""}
</AvatarFallback>
</Avatar>
<div className="flex flex-col ">
<h1 className="font-semibold text-2xl">{userData?.name}</h1>
<h3 className=" text-md">{userData?.email}</h3>
</div>
</div>
</section>
</div>
</div>
</section>
</BackgroundWrapper>
);
};
export default SettingsPage;

View File

@ -79,21 +79,8 @@ export default function PretestPage() {
</BackgroundWrapper> </BackgroundWrapper>
); );
} }
const { isHydrated, isInitialized, currentExam } = useExam();
useEffect(() => {
console.log(
"hydrated:",
isHydrated,
"initialized:",
isInitialized,
"exam:",
currentExam
);
}, [isHydrated, isInitialized, currentExam]);
function handleStartExam() { function handleStartExam() {
console.log(id);
setCurrentExam(examData); setCurrentExam(examData);
startExam(); startExam();
router.push(`/exam/${id}?time=${metadata?.metadata.duration}`); router.push(`/exam/${id}?time=${metadata?.metadata.duration}`);

152
public/data/bookmark.json Normal file
View File

@ -0,0 +1,152 @@
[
{
"id": 0,
"question": "What is the gravitational acceleration on Earth's surface?",
"options": {
"a": "8.9 m/s²",
"b": "9.8 m/s²",
"c": "10.5 m/s²",
"d": "11.2 m/s²"
}
},
{
"id": 1,
"question": "Which planet is known as the Red Planet?",
"options": {
"a": "Venus",
"b": "Jupiter",
"c": "Mars",
"d": "Saturn"
}
},
{
"id": 2,
"question": "What is the chemical symbol for gold?",
"options": {
"a": "Go",
"b": "Gd",
"c": "Au",
"d": "Ag"
}
},
{
"id": 3,
"question": "How many chambers does a human heart have?",
"options": {
"a": "2",
"b": "3",
"c": "4",
"d": "5"
}
},
{
"id": 4,
"question": "What is the speed of light in a vacuum?",
"options": {
"a": "299,792,458 m/s",
"b": "300,000,000 m/s",
"c": "298,000,000 m/s",
"d": "301,000,000 m/s"
}
},
{
"id": 5,
"question": "Which gas makes up approximately 78% of Earth's atmosphere?",
"options": {
"a": "Oxygen",
"b": "Carbon dioxide",
"c": "Nitrogen",
"d": "Argon"
}
},
{
"id": 6,
"question": "What is the hardest natural substance on Earth?",
"options": {
"a": "Quartz",
"b": "Diamond",
"c": "Graphite",
"d": "Titanium"
}
},
{
"id": 7,
"question": "How many bones are in an adult human body?",
"options": {
"a": "196",
"b": "206",
"c": "216",
"d": "226"
}
},
{
"id": 8,
"question": "What is the pH of pure water?",
"options": {
"a": "6",
"b": "7",
"c": "8",
"d": "9"
}
},
{
"id": 9,
"question": "Which organelle is known as the powerhouse of the cell?",
"options": {
"a": "Nucleus",
"b": "Ribosome",
"c": "Mitochondria",
"d": "Golgi apparatus"
}
},
{
"id": 10,
"question": "What is the most abundant element in the universe?",
"options": {
"a": "Helium",
"b": "Hydrogen",
"c": "Oxygen",
"d": "Carbon"
}
},
{
"id": 11,
"question": "At what temperature does water boil at sea level?",
"options": {
"a": "90°C",
"b": "95°C",
"c": "100°C",
"d": "105°C"
}
},
{
"id": 12,
"question": "How many chromosomes do humans have?",
"options": {
"a": "44",
"b": "46",
"c": "48",
"d": "50"
}
},
{
"id": 13,
"question": "What is the smallest unit of matter?",
"options": {
"a": "Molecule",
"b": "Atom",
"c": "Electron",
"d": "Proton"
}
},
{
"id": 14,
"question": "Which type of electromagnetic radiation has the longest wavelength?",
"options": {
"a": "X-rays",
"b": "Visible light",
"c": "Radio waves",
"d": "Gamma rays"
}
}
]