generated from muhtadeetaron/nextjs-template
initial commit
This commit is contained in:
7
app/(tabs)/bookmark/page.tsx
Normal file
7
app/(tabs)/bookmark/page.tsx
Normal file
@ -0,0 +1,7 @@
|
||||
import React from "react";
|
||||
|
||||
const page = () => {
|
||||
return <div>page</div>;
|
||||
};
|
||||
|
||||
export default page;
|
||||
7
app/(tabs)/categories/page.tsx
Normal file
7
app/(tabs)/categories/page.tsx
Normal 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
246
app/(tabs)/home/page.tsx
Normal 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
38
app/(tabs)/layout.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
0
app/(tabs)/leaderboard/page.tsx
Normal file
0
app/(tabs)/leaderboard/page.tsx
Normal file
0
app/(tabs)/live/page.tsx
Normal file
0
app/(tabs)/live/page.tsx
Normal file
7
app/(tabs)/performance/page.tsx
Normal file
7
app/(tabs)/performance/page.tsx
Normal file
@ -0,0 +1,7 @@
|
||||
import React from "react";
|
||||
|
||||
const page = () => {
|
||||
return <div>page</div>;
|
||||
};
|
||||
|
||||
export default page;
|
||||
7
app/(tabs)/profile/page.tsx
Normal file
7
app/(tabs)/profile/page.tsx
Normal file
@ -0,0 +1,7 @@
|
||||
import React from "react";
|
||||
|
||||
const page = () => {
|
||||
return <div>page</div>;
|
||||
};
|
||||
|
||||
export default page;
|
||||
7
app/(tabs)/progress/page.tsx
Normal file
7
app/(tabs)/progress/page.tsx
Normal 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
63
app/(tabs)/unit/page.tsx
Normal 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;
|
||||
Reference in New Issue
Block a user