diff --git a/app/(tabs)/home/page.tsx b/app/(tabs)/home/page.tsx index 6435c36..5d3e223 100644 --- a/app/(tabs)/home/page.tsx +++ b/app/(tabs)/home/page.tsx @@ -1,24 +1,29 @@ "use client"; -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect, ReactNode } 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"; -import facebookStyles from "@/css/SlidingGallery.module.css"; import { API_URL } from "@/lib/auth"; -import { Avatar, AvatarFallback } from "@radix-ui/react-avatar"; +import { Avatar } from "@/components/ui/avatar"; +import { getLinkedViews } from "@/lib/gallery-views"; +import { getTopThree } from "@/lib/leaderboard"; + +interface LinkedView { + id: string; + content: ReactNode; +} const page = () => { - const profileImg = "/images/static/avatar.jpg"; const router = useRouter(); const [boardData, setBoardData] = useState([]); const [boardError, setBoardError] = useState(null); + const [linkedViews, setLinkedViews] = useState(); const performanceData = [ { label: "Mock Test", progress: 20 }, @@ -31,38 +36,6 @@ const page = () => { { label: "Chemistry", progress: 57 }, ]; - const facebookViews = [ - { - id: "1", - content: ( - -
-
-

- Meet, Share, and Learn! -

-

- Join Facebook Community -

-
-
- Facebook Logo -
-
- - ), - }, - ]; - - // Fetch function for leaderboard data useEffect(() => { let isMounted = true; async function fetchBoardData() { @@ -77,32 +50,21 @@ const page = () => { if (isMounted) setBoardError(error.message || "An error occurred"); } } - fetchBoardData(); + const fetchedLinkedViews = getLinkedViews(); + setLinkedViews(fetchedLinkedViews); + 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 (
-
+
- +
{/* Categories Section */}
diff --git a/app/(tabs)/layout.tsx b/app/(tabs)/layout.tsx index 2fd6a8e..d9e2e39 100644 --- a/app/(tabs)/layout.tsx +++ b/app/(tabs)/layout.tsx @@ -5,13 +5,7 @@ import Link from "next/link"; import { ReactNode } from "react"; import { usePathname } from "next/navigation"; import clsx from "clsx"; -import { - House, - LayoutGrid, - Bookmark, - CircleUser, - Settings, -} from "lucide-react"; +import { House, LayoutGrid, Bookmark, Settings } from "lucide-react"; const tabs = [ { name: "Home", href: "/home", component: }, diff --git a/app/(tabs)/leaderboard/page.tsx b/app/(tabs)/leaderboard/page.tsx index ed7d7d3..ad06c8b 100644 --- a/app/(tabs)/leaderboard/page.tsx +++ b/app/(tabs)/leaderboard/page.tsx @@ -4,39 +4,17 @@ import BackgroundWrapper from "@/components/BackgroundWrapper"; import Header from "@/components/Header"; import { Avatar, AvatarFallback } from "@/components/ui/avatar"; import { API_URL, getToken } from "@/lib/auth"; +import { BoardData, getLeaderboard, getUserData } from "@/lib/leaderboard"; +import { UserData } from "@/types/auth"; import Image from "next/image"; import React, { useEffect, useState } from "react"; -const page = () => { +const LeaderboardPage = () => { const [boardError, setBoardError] = useState(null); - const [boardData, setBoardData] = useState([]); - const [userData, setUserData] = useState(null); + const [boardData, setBoardData] = useState([]); + const [userData, setUserData] = useState(); const [loading, setLoading] = useState(true); - async function fetchBoardData() { - try { - const boardResponse = await fetch(`${API_URL}/leaderboard`, { - method: "GET", - }); - - if (!boardResponse.ok) { - throw new Error("Failed to fetch leaderboard data"); - } - - const fetchedBoardData = await boardResponse.json(); - if (Array.isArray(fetchedBoardData) && fetchedBoardData.length > 0) { - setBoardData(fetchedBoardData); - } else { - setBoardError("No leaderboard data available."); - setBoardData([]); - } - } catch (error) { - console.error(error); - setBoardError("Something went wrong. Please try again."); - setBoardData([]); - } - } - useEffect(() => { async function fetchUser() { try { @@ -55,7 +33,31 @@ const page = () => { setUserData(fetchedUserData); } catch (error) { console.error(error); - setUserData(null); + setUserData(undefined); + } + } + + async function fetchBoardData() { + try { + const boardResponse = await fetch(`${API_URL}/leaderboard`, { + method: "GET", + }); + + if (!boardResponse.ok) { + throw new Error("Failed to fetch leaderboard data"); + } + + const fetchedBoardData = await boardResponse.json(); + if (Array.isArray(fetchedBoardData) && fetchedBoardData.length > 0) { + setBoardData(fetchedBoardData); + } else { + setBoardError("No leaderboard data available."); + setBoardData([]); + } + } catch (error) { + console.error(error); + setBoardError("Something went wrong. Please try again."); + setBoardData([]); } } @@ -63,7 +65,7 @@ const page = () => { fetchBoardData(); }, []); - const getTopThree = (boardData) => { + const getTopThree = (boardData: BoardData[]) => { if (!boardData || !Array.isArray(boardData)) return []; const sortedData = boardData .filter((player) => player?.points !== undefined) // Ensure `points` exists @@ -78,24 +80,10 @@ const page = () => { return [topThree[1], topThree[0], topThree[2]].filter(Boolean); // Handle missing players }; - const getLeaderboard = (boardData) => { - return boardData.slice().sort((a, b) => b.points - a.points); - }; - - const getUserData = (boardData, name) => { - if (!boardData || !Array.isArray(boardData)) return []; - const sortedData = boardData - .filter((player) => player?.name && player?.points !== undefined) - .sort((a, b) => b.points - a.points); - - const result = sortedData.find((player) => player.name === name); - return result ? [{ ...result, rank: sortedData.indexOf(result) + 1 }] : []; - }; - return (
-
+
{getTopThree(boardData).map((student, idx) => @@ -124,7 +112,7 @@ const page = () => {
- {getUserData(boardData, userData?.name).map((user, idx) => ( + {getUserData(boardData, userData!.name).map((user, idx) => (
{ ); }; -export default page; +export default LeaderboardPage; diff --git a/app/(tabs)/profile/page.tsx b/app/(tabs)/profile/page.tsx index 3006966..76b5b44 100644 --- a/app/(tabs)/profile/page.tsx +++ b/app/(tabs)/profile/page.tsx @@ -6,15 +6,7 @@ import { getToken, API_URL } from "@/lib/auth"; import { ChevronLeft, Edit2, Lock, Save } from "lucide-react"; import { useRouter } from "next/navigation"; import React, { useEffect, useState } from "react"; - -interface UserData { - name: string; - institution: string; - sscRoll: string; - hscRoll: string; - email: string; - phone: string; -} +import { UserData } from "@/types/auth"; const ProfilePage = () => { const router = useRouter(); diff --git a/app/layout.tsx b/app/layout.tsx index bc4ac14..034753d 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,9 +1,7 @@ import type { Metadata } from "next"; import { Montserrat } from "next/font/google"; import "./globals.css"; -import { AuthProvider } from "@/context/AuthContext"; -import { TimerProvider } from "@/context/TimerContext"; -import { ExamProvider } from "@/context/ExamContext"; + import { Providers } from "./providers"; const montserrat = Montserrat({ diff --git a/app/page.tsx b/app/page.tsx index 85b4521..805acb6 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -3,30 +3,10 @@ import Link from "next/link"; import { useRouter } from "next/navigation"; import Image from "next/image"; -import { useState, useEffect } from "react"; import BackgroundWrapper from "@/components/BackgroundWrapper"; export default function Home() { const router = useRouter(); - const [windowDimensions, setWindowDimensions] = useState({ - width: 0, - height: 0, - }); - - useEffect(() => { - function handleResize() { - setWindowDimensions({ - width: window.innerWidth, - height: window.innerHeight, - }); - } - - // Set initial dimensions - handleResize(); - - window.addEventListener("resize", handleResize); - return () => window.removeEventListener("resize", handleResize); - }, []); return ( diff --git a/components/Header.tsx b/components/Header.tsx index 6b30fed..d6a4ab9 100644 --- a/components/Header.tsx +++ b/components/Header.tsx @@ -1,33 +1,27 @@ import React, { useState, useEffect } from "react"; import { useRouter } from "next/navigation"; -import Image from "next/image"; import { ChevronLeft, Layers } from "lucide-react"; import { useTimer } from "@/context/TimerContext"; import styles from "@/css/Header.module.css"; import { useExam } from "@/context/ExamContext"; import { Avatar, AvatarFallback } from "@/components/ui/avatar"; import { useModal } from "@/context/ModalContext"; +import { API_URL, getToken } from "@/lib/auth"; +import { UserData } from "@/types/auth"; -const API_URL = "https://examjam-api.pptx704.com"; - -// You'll need to implement getToken for Next.js - could use cookies, localStorage, etc. -const getToken = async () => { - if (typeof window === "undefined") { - return null; - } - - // Extract authToken from cookies - const match = document.cookie.match(/(?:^|;\s*)authToken=([^;]*)/); - return match ? decodeURIComponent(match[1]) : null; -}; +interface HeaderProps { + displayUser?: boolean; + displaySubject?: string; + displayTabTitle: string; + examDuration?: string; +} const Header = ({ - image, displayUser, displaySubject, displayTabTitle, examDuration, -}) => { +}: HeaderProps) => { const router = useRouter(); const { open } = useModal(); const { clearExam } = useExam(); @@ -35,7 +29,7 @@ const Header = ({ examDuration ? parseInt(examDuration) * 60 : 0 ); const { timeRemaining, stopTimer } = useTimer(); - const [userData, setUserData] = useState(null); + const [userData, setUserData] = useState(); useEffect(() => { if (!examDuration) return; diff --git a/lib/resultViews.tsx b/lib/gallery-views.tsx similarity index 74% rename from lib/resultViews.tsx rename to lib/gallery-views.tsx index 893e222..2b3d79d 100644 --- a/lib/resultViews.tsx +++ b/lib/gallery-views.tsx @@ -1,4 +1,5 @@ -// lib/resultViews.tsx +// lib/gallery-views.tsx +import { Link } from "lucide-react"; import Image from "next/image"; interface ExamResults { @@ -97,3 +98,34 @@ export const getResultViews = (examResults: ExamResults | null) => [ ), }, ]; + +export const getLinkedViews = () => [ + { + id: "1", + content: ( + +
+
+

+ Meet, Share, and Learn! +

+

+ Join Facebook Community +

+
+
+ Facebook Logo +
+
+ + ), + }, +]; diff --git a/lib/leaderboard.ts b/lib/leaderboard.ts new file mode 100644 index 0000000..dcac5fd --- /dev/null +++ b/lib/leaderboard.ts @@ -0,0 +1,32 @@ +export interface BoardData { + id: string; + name: string; + points: number; +} + +export const getTopThree = (boardData: 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, + })); +}; + +export const getLeaderboard = (boardData: BoardData[]) => { + return boardData.slice().sort((a, b) => b.points - a.points); +}; + +export const getUserData = (boardData: BoardData[], name: string) => { + if (!boardData || !Array.isArray(boardData)) return []; + const sortedData = boardData + .filter((player) => player?.name && player?.points !== undefined) + .sort((a, b) => b.points - a.points); + + const result = sortedData.find((player) => player.name === name); + return result ? [{ ...result, rank: sortedData.indexOf(result) + 1 }] : []; +}; diff --git a/types/auth.d.ts b/types/auth.d.ts new file mode 100644 index 0000000..84cab28 --- /dev/null +++ b/types/auth.d.ts @@ -0,0 +1,8 @@ +export interface UserData { + name: string; + institution: string; + sscRoll: string; + hscRoll: string; + email: string; + phone: string; +}