initial commit

This commit is contained in:
shafin-r
2025-07-03 01:50:10 +06:00
commit 913ec11bc7
49 changed files with 6784 additions and 0 deletions

View File

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

View File

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

246
app/(tabs)/home/page.tsx Normal file
View File

@ -0,0 +1,246 @@
"use client";
import React, { useState, useEffect } from "react";
import { useRouter } from "next/navigation";
import Image from "next/image";
import Link from "next/link";
import Header from "@/components/Header";
import SlidingGallery from "@/components/SlidingGallery";
import BackgroundWrapper from "@/components/BackgroundWrapper";
import DestructibleAlert from "@/components/DestructibleAlert";
import { ChevronRight } from "lucide-react"; // Using Lucide React for icons
import styles from "@/css/Home.module.css";
const API_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:3000/api";
const page = () => {
const profileImg = "/images/static/avatar.jpg";
const router = useRouter();
const [boardData, setBoardData] = useState([]);
const [boardError, setBoardError] = useState(null);
const performanceData = [
{ label: "Mock Test", progress: 20 },
{ label: "Topic Test", progress: 70 },
{ label: "Subject Test", progress: 50 },
];
const progressData = [
{ label: "Physics", progress: 25 },
{ label: "Chemistry", progress: 57 },
];
// Fetch function for leaderboard data
useEffect(() => {
let isMounted = true;
async function fetchBoardData() {
try {
const response = await fetch(`${API_URL}/leaderboard`);
if (!response.ok) {
throw new Error("Failed to fetch leaderboard data");
}
const data = await response.json();
if (isMounted) setBoardData(data);
} catch (error) {
if (isMounted) setBoardError(error.message || "An error occurred");
}
}
fetchBoardData();
return () => {
isMounted = false;
};
}, []);
const getTopThree = (boardData) => {
if (!boardData || boardData.length === 0) return [];
return boardData
.slice()
.sort((a, b) => b.points - a.points)
.slice(0, 3)
.map((player, index) => ({
...player,
rank: index + 1,
height: index === 0 ? 250 : index === 1 ? 200 : 170,
}));
};
return (
<BackgroundWrapper>
<div className={styles.container}>
<Header displayTabTitle={null} displayUser image={profileImg} />
<div className={styles.scrollContainer}>
<div className={styles.contentWrapper}>
<SlidingGallery />
<div className={styles.mainContent}>
{/* Categories Section */}
<div>
<div className={styles.sectionHeader}>
<h2 className={styles.sectionTitle}>Categories</h2>
<button
onClick={() => router.push("/categories")}
className={styles.arrowButton}
>
<ChevronRight size={24} color="#113768" />
</button>
</div>
<div className={styles.categoriesContainer}>
<div className={styles.categoryRow}>
<button
disabled
className={`${styles.categoryButton} ${styles.disabled}`}
>
<Image
src="/images/icons/topic-test.png"
alt="Topic Test"
width={70}
height={70}
/>
<span className={styles.categoryButtonText}>
Topic Test
</span>
</button>
<button
onClick={() => router.push("/unit")}
className={styles.categoryButton}
>
<Image
src="/images/icons/mock-test.png"
alt="Mock Test"
width={70}
height={70}
/>
<span className={styles.categoryButtonText}>
Mock Test
</span>
</button>
</div>
<div className={styles.categoryRow}>
<button
disabled
className={`${styles.categoryButton} ${styles.disabled}`}
>
<Image
src="/images/icons/past-paper.png"
alt="Past Papers"
width={62}
height={62}
/>
<span className={styles.categoryButtonText}>
Past Papers
</span>
</button>
<button
disabled
className={`${styles.categoryButton} ${styles.disabled}`}
>
<Image
src="/images/icons/subject-test.png"
alt="Subject Test"
width={70}
height={70}
/>
<span className={styles.categoryButtonText}>
Subject Test
</span>
</button>
</div>
</div>
</div>
{/* Leaderboard Section */}
<div className={styles.leaderboardWrapper}>
<h2 className={styles.sectionTitle}>Leaderboard</h2>
<div className={styles.leaderboardContainer}>
<div className={styles.topThreeHeader}>
<span className={styles.topThreeTitle}>Top 3</span>
<button
onClick={() => router.push("/leaderboard")}
className={styles.arrowButton}
>
<ChevronRight size={24} color="#113768" />
</button>
</div>
<div className={styles.divider}></div>
<div className={styles.topThreeList}>
{getTopThree(boardData).map((student, idx) => (
<div key={idx} className={styles.topThreeItem}>
<div className={styles.studentInfo}>
<span className={styles.rank}>{student.rank}</span>
<Image
src="/images/static/avatar.jpg"
alt="Avatar"
width={20}
height={20}
className={styles.avatar}
/>
<span className={styles.studentName}>
{student.name}
</span>
</div>
<span className={styles.points}>
{student.points}pt
</span>
</div>
))}
</div>
</div>
</div>
{/* Performance Summary Section */}
<div className={styles.section}>
<div className={styles.sectionHeader}>
<h2 className={styles.sectionTitle}>Performance Summary</h2>
<button
disabled
onClick={() => router.push("/performance")}
className={styles.arrowButton}
>
<ChevronRight size={24} color="#113768" />
</button>
</div>
<div className={styles.comingSoonCard}>
<p className={styles.comingSoonText}>Coming soon.</p>
</div>
</div>
{/* Progress Tracker Section */}
<div className={styles.section}>
<div className={styles.sectionHeader}>
<h2 className={styles.sectionTitle}>Progress Tracker</h2>
<button
disabled
onClick={() => router.push("/progress")}
className={styles.arrowButton}
>
<ChevronRight size={24} color="#113768" />
</button>
</div>
<div className={styles.comingSoonCard}>
<p className={styles.comingSoonText}>Coming soon.</p>
</div>
</div>
{/* Daily Quiz Section */}
<div className={styles.section}>
<h2 className={styles.sectionTitle}>Daily Quiz</h2>
<div className={styles.comingSoonCard}>
<p className={styles.comingSoonText}>Coming soon.</p>
</div>
</div>
{/* Live Exams Section */}
<div className={`${styles.section} ${styles.lastSection}`}>
<h2 className={styles.sectionTitle}>Live Exams</h2>
<div className={styles.comingSoonCard}>
<p className={styles.comingSoonText}>Coming soon.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</BackgroundWrapper>
);
};
export default page;

38
app/(tabs)/layout.tsx Normal file
View File

@ -0,0 +1,38 @@
// app/tabs/layout.tsx
"use client";
import Link from "next/link";
import { ReactNode } from "react";
import { usePathname } from "next/navigation";
import clsx from "clsx";
const tabs = [
{ name: "Home", href: "/tabs/home" },
{ name: "Profile", href: "/tabs/profile" },
{ name: "Leaderboard", href: "/tabs/leaderboard" },
];
export default function TabsLayout({ children }: { children: ReactNode }) {
const pathname = usePathname();
return (
<div className="min-h-screen flex flex-col">
<main className="flex-1">{children}</main>
<nav className="flex justify-around border-t p-4 bg-white">
{tabs.map((tab) => (
<Link
key={tab.name}
href={tab.href}
className={clsx(
"text-center text-sm font-medium",
pathname === tab.href ? "text-blue-600" : "text-gray-500"
)}
>
{tab.name}
</Link>
))}
</nav>
</div>
);
}

View File

0
app/(tabs)/live/page.tsx Normal file
View File

View File

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

View File

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

View File

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

63
app/(tabs)/unit/page.tsx Normal file
View File

@ -0,0 +1,63 @@
"use client";
import React from "react";
import { useRouter } from "next/navigation";
import Header from "@/components/Header";
import BackgroundWrapper from "@/components/BackgroundWrapper";
const units = [
{
id: 3,
name: "C Unit (Business Studies)",
rating: 9,
},
];
const Unit = () => {
const router = useRouter();
const handleUnitPress = (unit) => {
router.push(`/paper?name=${encodeURIComponent(unit.name)}`);
};
return (
<BackgroundWrapper>
<div className="flex flex-col min-h-screen">
<Header
displayExamInfo={null}
displayTabTitle={"Units"}
displaySubject={null}
displayUser={false}
title=""
image={""}
/>
<div className="flex-1">
<div className="overflow-y-auto">
<div className="border border-blue-200 gap-4 rounded-3xl p-6 mx-10 mt-10">
{units ? (
units.map((unit) => (
<button
key={unit.id}
onClick={() => handleUnitPress(unit)}
className="border-2 border-blue-300 py-4 rounded-xl px-6 gap-2 block w-full text-left hover:bg-blue-50 transition-colors duration-200"
>
<p className="text-lg font-medium">{unit.name}</p>
<p className="text-sm">Rating: {unit.rating} / 10</p>
</button>
))
) : (
<div className="flex flex-col items-center py-8">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500 mb-4"></div>
<p className="font-bold text-2xl text-center">Loading...</p>
</div>
)}
</div>
</div>
</div>
</div>
{/* <CustomBackHandler fallbackRoute="home" useCustomHandler={false} /> */}
</BackgroundWrapper>
);
};
export default Unit;