diff --git a/app/(main)/[teamId]/page.js b/app/(main)/[teamId]/page.js
new file mode 100644
index 0000000..52d018e
--- /dev/null
+++ b/app/(main)/[teamId]/page.js
@@ -0,0 +1,489 @@
+"use client";
+import { useState, useEffect, useCallback } from "react";
+import { useSession } from "next-auth/react";
+import { useRouter } from "next/navigation";
+import Link from "next/link";
+import { use } from "react"; // Add this import for React.use()
+
+export default function TeamPage({ params }) {
+ const { status, data: session } = useSession();
+ const [team, setTeam] = useState(null);
+ const [teamMembers, setTeamMembers] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState("");
+ const [huntActive, setHuntActive] = useState(false);
+ const router = useRouter();
+
+ // Unwrap the params Promise using React.use()
+ const unwrappedParams = use(params);
+ const teamId = unwrappedParams.teamId;
+
+ // Add a function to check if the hunt has been activated by admin
+ const checkHuntStatus = useCallback(async () => {
+ try {
+ const response = await fetch("/api/hunt-status", {
+ method: "GET",
+ headers: { "Content-Type": "application/json" },
+ credentials: "include",
+ });
+
+ if (response.ok) {
+ const data = await response.json();
+ setHuntActive(data.active || false);
+ }
+ } catch (err) {
+ console.error("Failed to check hunt status:", err);
+ }
+ }, []);
+
+ const fetchTeamData = useCallback(async () => {
+ try {
+ if (!teamId || isNaN(parseInt(teamId, 10))) {
+ throw new Error("Invalid team ID");
+ }
+
+ console.log("Fetching team data for team ID:", teamId);
+
+ const response = await fetch(`/api/teams/${teamId}`, {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ credentials: "include",
+ // Add cache: 'no-store' to prevent caching of team data
+ cache: "no-store",
+ });
+
+ if (!response.ok) {
+ const text = await response.text();
+ let errorMessage;
+ try {
+ const errorData = JSON.parse(text);
+ errorMessage = errorData.error || "Failed to fetch team data";
+ } catch (unused) {
+ errorMessage = `Failed to fetch team data: ${
+ response.status
+ } ${text.slice(0, 100)}`;
+ }
+ throw new Error(errorMessage);
+ }
+
+ const data = await response.json();
+ console.log("Team data received:", data);
+
+ if (!data.team) {
+ throw new Error("Team not found");
+ }
+
+ setTeam(data.team);
+ setTeamMembers(data.members || []);
+ setError("");
+
+ // Check hunt status whenever we fetch team data
+ await checkHuntStatus();
+ } catch (err) {
+ console.error("Team page error:", err);
+ setError(err.message);
+ // If we get a 401 error, redirect to login
+ if (err.message.includes("401")) {
+ router.push("/login");
+ }
+ } finally {
+ setLoading(false);
+ }
+ }, [teamId, router, checkHuntStatus]);
+
+ useEffect(() => {
+ // Only attempt to fetch data when session is ready and we have a teamId
+ if (status === "authenticated" && teamId) {
+ console.log("Session authenticated, fetching team data");
+ fetchTeamData();
+
+ // Set up an interval to refresh team data every 10 seconds
+ const refreshInterval = setInterval(fetchTeamData, 10000);
+
+ // Clean up the interval when component unmounts
+ return () => clearInterval(refreshInterval);
+ } else if (status === "unauthenticated") {
+ console.log("User not authenticated, redirecting to login");
+ router.push("/login");
+ }
+ }, [teamId, status, fetchTeamData, router]);
+
+ if (status === "loading" || loading) {
+ return (
+
+
+
Loading team data...
+
+ );
+ }
+
+ if (error) {
+ return (
+
+
⚠️
+
Error: {error}
+
+
+
+
+ );
+ }
+
+ if (!team) {
+ return (
+
+
🔍
+
Team not found
+
+
+
+
+ );
+ }
+
+ return (
+
+
+
+
Team Name: {team.name}
+
{team.code}
+
+
+
+
+
Team Members
+
+ {teamMembers.length > 0 ? (
+
+ {teamMembers.map((member) => (
+
+
👤
+
+
+ {member.username}
+ {member.id === session?.user?.id && " (You)"}
+
+
+
+ ))}
+
+ ) : (
+
No team members found
+ )}
+
+ {/* Remove the add member button - it was here before */}
+
+
+
+
+
+ {/* New Start Hunt button with conditional behavior */}
+ {session?.user?.role !== "admin" && (
+
+ )}
+
+ {/* Keep the admin start button which directly starts the hunt */}
+ {session?.user?.role === "admin" && (
+
+ )}
+
+
+
+ {/* Update the Home link to point to the current team page */}
+
+
🏠
+
Home
+
+
+
📊
+
Stats
+
+
+
👥
+
Team
+
+
+
👤
+
Profile
+
+
+
+
+
+ );
+}
diff --git a/app/(main)/hunt-not-started/page.js b/app/(main)/hunt-not-started/page.js
new file mode 100644
index 0000000..0726e09
--- /dev/null
+++ b/app/(main)/hunt-not-started/page.js
@@ -0,0 +1,102 @@
+"use client";
+import { useState, useEffect } from "react";
+import { useRouter, useSearchParams } from "next/navigation";
+import Link from "next/link";
+
+export default function HuntNotStarted() {
+ const [countdown, setCountdown] = useState(10);
+ const router = useRouter();
+ const searchParams = useSearchParams();
+ const teamId = searchParams.get("teamId");
+
+ useEffect(() => {
+ // Countdown timer
+ if (countdown > 0) {
+ const timer = setTimeout(() => {
+ setCountdown(countdown - 1);
+ }, 1000);
+ return () => clearTimeout(timer);
+ } else {
+ // Redirect back to team page when countdown reaches 0
+ if (teamId) {
+ router.push(`/${teamId}`);
+ } else {
+ router.push("/team-selection");
+ }
+ }
+ }, [countdown, router, teamId]);
+
+ return (
+
+
+
⏳
+
Hunt Not Started Yet
+
+ The treasure hunt has not been activated by an administrator yet.
+ Please check back later or contact an admin to start the hunt.
+
+
Redirecting back in {countdown} seconds...
+
+
+
+
+
+
+
+ );
+}
diff --git a/app/(main)/team/[teamId]/page.js b/app/(main)/team/[teamId]/page.js
index a20d048..ae30ddf 100644
--- a/app/(main)/team/[teamId]/page.js
+++ b/app/(main)/team/[teamId]/page.js
@@ -132,12 +132,9 @@ export default function TeamPage({ params }) {
return (
-
- ←
-
-
{team.name}
-
Team Code: {team.code}
+
Team Name: {team.name}
+
{team.code}
@@ -299,17 +296,11 @@ export default function TeamPage({ params }) {
align-items: center;
}
- .back-button {
- text-decoration: none;
- color: white;
- font-size: 24px;
- margin-right: 15px;
- display: flex;
- align-items: center;
- }
-
.team-info {
flex: 1;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
}
.team-name {
@@ -319,9 +310,9 @@ export default function TeamPage({ params }) {
}
.team-code {
- margin-top: 5px;
- font-size: 14px;
- opacity: 0.8;
+ font-size: 24px;
+ font-weight: bold;
+ margin-left: auto;
}
.members-container {