Skip to content

Commit

Permalink
Merge pull request #216 from Venkat-737/Dashboard-Frontend
Browse files Browse the repository at this point in the history
Added Dashboard frontend
  • Loading branch information
dinxsh authored Jan 5, 2025
2 parents 167b8a6 + 51bc6ce commit ceea671
Show file tree
Hide file tree
Showing 3 changed files with 345 additions and 7 deletions.
25 changes: 18 additions & 7 deletions app/(auth)/sign-in/page.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { signIn } from "next-auth/react";
import * as z from "zod";
import { signIn, useSession } from "next-auth/react";
import {
Form,
FormField,
Expand All @@ -15,7 +16,7 @@ import { Input } from "../../../@/components/ui/input";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { signInSchema } from "../../../model/Schema/signInSchema";
import React, { useState } from "react";
import React, { useState, useEffect } from "react";
import {
Card,
CardContent,
Expand Down Expand Up @@ -52,9 +53,12 @@ export default function SignInForm() {
redirect: false,
});
console.log(response);
if (!response.ok) throw new Error();
window.location.href = response?.url || "/tournaments";
toast.success("Successfull Signup");
if (response?.error) {
toast.error(response.error);
} else {
router.push("/dashboard");
toast.success("Successfull Signup");
}
} catch (error) {
toast.error("Username / Password mismatched");
} finally {
Expand All @@ -63,12 +67,19 @@ export default function SignInForm() {
};

const handleGoogleSignIn = async () => {
await signIn("google", { callbackUrl: "/" });
await signIn("google", { callbackUrl: "/dashboard" });
};

const handleDiscordSignIn = async () => {
await signIn("discord", { callbackUrl: "/" });
await signIn("discord", { callbackUrl: "/dashboard" });
};
const { data: session, status } = useSession();

useEffect(() => {
if (status === "authenticated") {
router.push("/dashboard");
}
}, [status, router]);

return (
<div>
Expand Down
112 changes: 112 additions & 0 deletions app/api/dashboard/route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { getServerSession } from "next-auth/next";
import { authOptions } from "../auth/[...nextauth]/route";
import { NextResponse } from "next/server";
import dbConnect from "../../../lib/dbConnect";
import Tournament from "../../../model/Tournament";
import Team from "../../../model/Team";
import Bracket from "../../../model/Bracket";

export async function GET(request) {
try {
const session = await getServerSession(authOptions);

if (!session) {
return NextResponse.json({
participatedTournaments: [],
upcomingTournaments: [],
userTeams: [],
userBrackets: [],
});
}

await dbConnect();

const testData = {
participatedTournaments: [
{
_id: "T1",
tournamentName: "Tournament 1",
game: "BGMI",
startDate: new Date(),
status: "ongoing",
},
{
_id: "T2",
tournamentName: "Valo Tournament",
game: "Valorent",
startDate: new Date(),
status: "completed",
},
],
upcomingTournaments: [
{
_id: "UT1",
tournamentName: "Tournament 3",
game: "Valorent",
registrationEndDate: new Date(Date.now()),
},
{
_id: "UT2",
tournamentName: "Tournament 4",
game: "Apex Legends",
registrationEndDate: new Date(Date.now() + 7 * 1000 * 86400),
},
],
userTeams: [
{
_id: "team 1",
teamName: "Team 1",
members: ["pro", "exp", "a32"],
},
{
_id: "team 2",
teamName: "Team 2",
members: ["dragon", "vince", "strange"],
},
],
userBrackets: [
{
_id: "B1",
name: "bgmi bracket",
rounds: 3,
teams: 9,
},
{
_id: "B2",
name: "valorent bracket",
rounds: 4,
teams: 15,
},
],
};
return NextResponse.json(testData);

/*
const [participatedTournaments, upcomingTournaments, userTeams, userBrackets] = await Promise.all([
Tournament.find({ "teamsRegistered.members": session.user.email }).lean(),
Tournament.find({ registrationEndDate: { $gt: new Date() } }).limit(5).lean(),
Team.find({ members: session.user.email }).lean(),
Bracket.find({ createdBy: session.user.email }).lean()
]);
return NextResponse.json({
participatedTournaments,
upcomingTournaments,
userTeams,
userBrackets
});
*/
} catch (error) {
console.log("API Error:", error);
return NextResponse.json(
/*{
participatedTournaments: [],
upcomingTournaments: [],
userTeams: [],
userBrackets: []
}*/
{ error: "Internal Server Error" },
{ status: 500 },
);
}
}
215 changes: 215 additions & 0 deletions app/dashboard/page.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
"use client";
import { useState, useEffect } from "react";
import { useSession } from "next-auth/react";
import { useRouter } from "next/navigation";
import { PacmanLoader } from "react-spinners";
import {
Card,
CardContent,
CardHeader,
CardTitle,
} from "../../@/components/ui/card";
import Link from "next/link";
import { CalendarDays, Users, Trophy, Brackets } from "lucide-react";

export default function Dashboard() {
const { data: session, status } = useSession();
const router = useRouter();
const [isLoading, setIsLoading] = useState(true);
const [userData, setUserData] = useState({
participatedTournaments: [],
upcomingTournaments: [],
userTeams: [],
userBrackets: [],
});

useEffect(() => {
//console.log("Session:", session);
if (status === "unauthenticated") {
router.push("/sign-in");
}

if (status === "authenticated" && session?.user) {
fetchDashboardData();
}
}, [status, session, router]);

const fetchDashboardData = async () => {
try {
const response = await fetch("/api/dashboard", {
method: "GET",
headers: {
"Content-Type": "application/json",
},
credentials: "same-origin",
});

const data = await response.json();

if (data.error) {
console.log("API Error:", data.error);
setUserData({
participatedTournaments: [],
upcomingTournaments: [],
userTeams: [],
userBrackets: [],
});
return;
}

setUserData(data);
} catch (error) {
console.log("Fetch Error:", error);
setUserData({
participatedTournaments: [],
upcomingTournaments: [],
userTeams: [],
userBrackets: [],
});
} finally {
setIsLoading(false);
}
};

if (status === "loading" || isLoading) {
return (
<div className="flex w-full h-screen justify-center items-center ">
<PacmanLoader color="white" />
</div>
);
}

if (!session) {
return null;
}

return (
<div className="min-h-screen bg-gradient-to-b from-gray-900 to-gray-950">
<div className="container mx-auto px-4 py-8">
<h1 className="text-4xl font-bold mb-8 text-white/90">
Welcome back, {session.user.username}
</h1>

<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{/* Participated Tournaments */}
<Card className="border-0 bg-gray-800/50 backdrop-blur-sm hover:bg-gray-800/60 transition-all">
<CardHeader className="flex flex-row items-center gap-2">
<Trophy className="w-6 h-6 " />
<CardTitle className="text-xl text-white/90">
Participated Tournaments
</CardTitle>
</CardHeader>
<CardContent className="grid gap-4">
{userData?.participatedTournaments.map((tournament) => (
<div
key={tournament._id}
className="group relative bg-gray-700/50 p-4 rounded-lg hover:bg-gray-700/70 transition-all"
>
<h3 className="font-medium text-white/90">
{tournament.tournamentName}
</h3>
<p className="text-sm text-gray-300 mt-2 mb-3">
Game: {tournament.game}
</p>
<Link
href={`/tournaments/${tournament._id}`}
className="inline-flex items-center text-sm hover:text-gray-400 transition-colors"
>
View Details
</Link>
</div>
))}
</CardContent>
</Card>

{/* Upcoming Tournaments */}
<Card className="border-0 bg-gray-800/50 backdrop-blur-sm hover:bg-gray-800/60 transition-all">
<CardHeader className="flex flex-row items-center gap-2">
<CalendarDays className="w-6 h-6 " />
<CardTitle className="text-xl text-white/90">
Upcoming Tournaments
</CardTitle>
</CardHeader>
<CardContent className="grid gap-4">
{userData?.upcomingTournaments.map((tournament) => (
<div
key={tournament._id}
className="group relative bg-gray-700/50 p-4 rounded-lg hover:bg-gray-700/70 transition-all"
>
<h3 className="font-medium text-white/90">
{tournament.tournamentName}
</h3>
<p className="text-sm text-gray-300 mt-2 mb-3">
Registration Ends:{" "}
{new Date(
tournament.registrationEndDate,
).toLocaleDateString()}
</p>
<Link
href={`/tournaments/${tournament._id}`}
className="inline-flex items-center text-sm hover:text-gray-400 transition-colors"
>
Register Now
</Link>
</div>
))}
</CardContent>
</Card>

{/* User Teams */}
<Card className="border-0 bg-gray-800/50 backdrop-blur-sm hover:bg-gray-800/60 transition-all">
<CardHeader className="flex flex-row items-center gap-2">
<Users className="w-6 h-6 " />
<CardTitle className="text-xl text-white/90">My Teams</CardTitle>
</CardHeader>
<CardContent className="grid gap-4">
{userData?.userTeams.map((team) => (
<div
key={team._id}
className="group relative bg-gray-700/50 p-4 rounded-lg hover:bg-gray-700/70 transition-all"
>
<h3 className="font-medium text-white/90">{team.teamName}</h3>
<p className="text-sm text-gray-300 mt-2 mb-3">
Members: {team.members.length}
</p>
<Link
href={`/teams/${team._id}`}
className="inline-flex items-center text-sm hover:text-gray-400 transition-colors"
>
View Team
</Link>
</div>
))}
</CardContent>
</Card>

{/* Brackets */}
<Card className="border-0 bg-gray-800/50 backdrop-blur-sm hover:bg-gray-800/60 transition-all">
<CardHeader className="flex flex-row items-center gap-2">
<Brackets className="w-6 h-6 " />
<CardTitle className="text-xl text-white/90">
My Brackets
</CardTitle>
</CardHeader>
<CardContent className="grid gap-4">
{userData?.userBrackets.map((bracket) => (
<div
key={bracket._id}
className="group relative bg-gray-700/50 p-4 rounded-lg hover:bg-gray-700/70 transition-all"
>
<h3 className="font-medium text-white/90">{bracket.name}</h3>
<Link
href={`/brackets/${bracket._id}`}
className="inline-flex items-center text-sm hover:text-gray-400 transition-colors mt-3"
>
View Bracket
</Link>
</div>
))}
</CardContent>
</Card>
</div>
</div>
</div>
);
}

1 comment on commit ceea671

@vercel
Copy link

@vercel vercel bot commented on ceea671 Jan 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.