diff --git a/app/(auth)/login/page.js b/app/(auth)/login/page.js index 4e0448f..c3c936c 100644 --- a/app/(auth)/login/page.js +++ b/app/(auth)/login/page.js @@ -1,107 +1,175 @@ -'use client'; // Mark as a Client Component -import { useState } from 'react'; -import { signIn } from 'next-auth/react'; -import { useRouter } from 'next/navigation'; -import Link from 'next/link'; +"use client"; // Mark as a Client Component +import { useState } from "react"; +import { signIn } from "next-auth/react"; +import { useRouter } from "next/navigation"; +import Link from "next/link"; export default function Login() { - const [username, setUsername] = useState(''); - const [password, setPassword] = useState(''); - const [error, setError] = useState(''); - const [isLoading, setIsLoading] = useState(false); - const router = useRouter(); + const [username, setUsername] = useState(""); + const [password, setPassword] = useState(""); + const [error, setError] = useState(""); + const [isLoading, setIsLoading] = useState(false); + const router = useRouter(); - const handleLogin = async (e) => { - e.preventDefault(); - setIsLoading(true); - setError(''); + const handleLogin = async (e) => { + e.preventDefault(); + setIsLoading(true); + setError(""); - try { - const result = await signIn('credentials', { - redirect: false, - username, - password, - }); + try { + const result = await signIn("credentials", { + redirect: false, + username, + password, + }); - if (result?.error) { - setError('Invalid username or password'); - setIsLoading(false); - } else { - // Fetch the user role to redirect appropriately - const response = await fetch('/api/user'); - const userData = await response.json(); + if (result?.error) { + setError("Invalid username or password"); + setIsLoading(false); + } else { + // Fetch the user role to redirect appropriately + const response = await fetch("/api/user"); + const userData = await response.json(); - if (userData.role === 'admin') { - router.push('/admin'); - } else { - router.push('/team-selection'); - } - } - } catch (err) { - setError('An unexpected error occurred'); - console.error(err); - setIsLoading(false); + if (userData.role === "admin") { + router.push("/admin"); + } else { + router.push("/team-selection"); } - }; + } + } catch (err) { + setError("An unexpected error occurred"); + console.error(err); + setIsLoading(false); + } + }; - return ( -
-
-
←
-
Login
-
-
+ return ( +
+
+
←
+
Login
+
+
-
-
-
- setUsername(e.target.value)} - required - className="auth-input" - /> -
-
- setPassword(e.target.value)} - required - className="auth-input" - /> -
- {error &&
{error}
} - -
- Don't have an account? Register -
-
-
- -
-
-
🏠
-
-
-
📊
-
-
-
🏆
-
-
-
👤
-
-
+
+
+
+ setUsername(e.target.value)} + required + className="auth-input" + /> +
+
+ setPassword(e.target.value)} + required + className="auth-input" + /> +
+ {error &&
{error}
} + + + +
- ); -} \ No newline at end of file +
+ +
+
+
🏠
+
+
+
📊
+
+
+
🏆
+
+
+
👤
+
+
+ + +
+ ); +} diff --git a/app/(auth)/register/page.js b/app/(auth)/register/page.js index a65a909..74b5dc8 100644 --- a/app/(auth)/register/page.js +++ b/app/(auth)/register/page.js @@ -1,99 +1,181 @@ -'use client'; // Mark as a Client Component -import { useState } from 'react'; -import { useRouter } from 'next/navigation'; -import { registerUser } from '../../actions/auth'; -import Link from 'next/link'; +"use client"; // Mark as a Client Component +import { useState } from "react"; +import { signIn } from "next-auth/react"; +import { useRouter } from "next/navigation"; +import Link from "next/link"; export default function Register() { - const [username, setUsername] = useState(''); - const [password, setPassword] = useState(''); - const [error, setError] = useState(''); - const [isLoading, setIsLoading] = useState(false); - const router = useRouter(); + const [username, setUsername] = useState(""); + const [password, setPassword] = useState(""); + const [error, setError] = useState(""); + const [isLoading, setIsLoading] = useState(false); + const router = useRouter(); - async function handleSubmit(e) { - e.preventDefault(); - setIsLoading(true); - setError(''); + const handleRegister = async (e) => { + e.preventDefault(); + setIsLoading(true); + setError(""); - try { - const formData = new FormData(); - formData.append('username', username); - formData.append('password', password); + try { + const response = await fetch("/api/register", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ username, password }), + }); - const result = await registerUser(formData); + const result = await response.json(); - if (result.success) { - router.push('/login'); - } else { - setError(result.error || 'Registration failed'); - } - } catch (err) { - setError('An unexpected error occurred'); - console.error(err); - } finally { - setIsLoading(false); + if (result.error) { + setError(result.error); + setIsLoading(false); + } else { + // Automatically log in the user after successful registration + const signInResult = await signIn("credentials", { + redirect: false, + username, + password, + }); + + if (signInResult?.error) { + setError("Registration successful, but failed to log in"); + setIsLoading(false); + } else { + router.push("/team-selection"); } + } + } catch (err) { + setError("An unexpected error occurred"); + console.error(err); + setIsLoading(false); } + }; - return ( -
-
- ← -
Register
-
-
+ return ( +
+
+
←
+
Register
+
+
-
-
-
- setUsername(e.target.value)} - required - className="auth-input" - /> -
-
- setPassword(e.target.value)} - required - className="auth-input" - /> -
- {error &&
{error}
} - -
- Already have an account? Login -
-
-
- -
-
-
🏠
-
-
-
📊
-
-
-
🏆
-
-
-
👤
-
-
+
+
+
+ setUsername(e.target.value)} + required + className="auth-input" + /> +
+
+ setPassword(e.target.value)} + required + className="auth-input" + /> +
+ {error &&
{error}
} + + + +
- ); -} \ No newline at end of file +
+ +
+
+
🏠
+
+
+
📊
+
+
+
🏆
+
+
+
👤
+
+
+ + +
+ ); +} diff --git a/app/(main)/create-team/page.js b/app/(main)/create-team/page.js index 3a20730..99df990 100644 --- a/app/(main)/create-team/page.js +++ b/app/(main)/create-team/page.js @@ -1,118 +1,197 @@ -'use client'; // Mark as a Client Component -import { useState, useEffect } from 'react'; -import { useSession } from 'next-auth/react'; -import { useRouter } from 'next/navigation'; -import Link from 'next/link'; +"use client"; +import { useState } from "react"; +import { useSession } from "next-auth/react"; +import { useRouter } from "next/navigation"; +import Link from "next/link"; + +const styles = { + navbar: { + position: "fixed", + bottom: 0, + width: "100%", + backgroundColor: "#fff", + borderTop: "1px solid #ccc", + padding: "10px 0", + textAlign: "center", + }, +}; export default function CreateTeam() { - const { data: session, status } = useSession(); - const [teamName, setTeamName] = useState(''); - const [error, setError] = useState(''); - const [isLoading, setIsLoading] = useState(false); - const router = useRouter(); + const { data: session, status } = useSession(); + const [teamName, setTeamName] = useState(""); + const [error, setError] = useState(""); + const [isLoading, setIsLoading] = useState(false); + const router = useRouter(); - // Use useEffect for navigation instead of doing it in render - useEffect(() => { - // Redirect if not authenticated - if (status === 'unauthenticated') { - router.push('/login'); - } + if (status === "loading") { + return
Loading...
; + } - // Redirect if user is admin - if (status === 'authenticated' && session?.user?.role === 'admin') { - router.push('/admin'); - } - }, [status, session, router]); + if (!session || status === "unauthenticated") { + router.replace("/login"); + return null; + } - const handleCreateTeam = async (e) => { - e.preventDefault(); - setIsLoading(true); - setError(''); + if (session?.user?.role === "admin") { + router.replace("/admin"); + return null; + } - try { - const response = await fetch('/api/teams/create', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - name: teamName, - userId: session.user.id - }), - }); + const handleCreateTeam = async (e) => { + e.preventDefault(); + if (isLoading || !teamName.trim()) return; - const result = await response.json(); + setIsLoading(true); + try { + const response = await fetch("/api/teams/create", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + name: teamName, + userId: session.user.id, + }), + }); - if (result.success) { - router.push(`/team/${result.teamId}`); - } else { - setError(result.error || 'Failed to create team'); - } - } catch (err) { - setError('An unexpected error occurred'); - console.error(err); - } finally { - setIsLoading(false); - } - }; + const result = await response.json(); + if (result.success) { + // Update the user's session with the new teamId + await fetch("/api/auth/session", { + method: "PATCH", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + teamId: result.teamId, + }), + }); - if (status === 'loading') { - return
Loading...
; + router.push(`/team/${result.teamId}`); + } else { + setError(result.error || "Failed to create team"); + } + } catch (err) { + console.error("Team creation error:", err); + setError("An unexpected error occurred"); + } finally { + setIsLoading(false); } + }; - // Don't render anything if redirecting - if (status === 'unauthenticated' || (status === 'authenticated' && session?.user?.role === 'admin')) { - return null; - } + return ( +
+
+
+
Create Team
+
+
- return ( -
-
-
Create Team
-
-
- -
-

Create a New Team

-
-
- setTeamName(e.target.value)} - required - className="team-input" - /> -
- -
- {error &&

{error}

} -
- Back to Team Selection -
-
- -
-
-
🏠
-
-
-
📊
-
-
-
🏆
-
-
-
👤
-
+
+
+

Create a New Team

+
+
+ setTeamName(e.target.value)} + required + className="auth-input" + />
+ +
+ {error &&

{error}

} +
+ + + +
- ); -} \ No newline at end of file +
+ +
+
+
🏠
+
+
+
📊
+
+
+
🏆
+
+
+
👤
+
+
+ + +
+ ); +} diff --git a/app/(main)/team-selection/page.js b/app/(main)/team-selection/page.js index ceaae2e..e46043e 100644 --- a/app/(main)/team-selection/page.js +++ b/app/(main)/team-selection/page.js @@ -1,109 +1,193 @@ -'use client'; // Mark as a Client Component -import { useState, useEffect } from 'react'; -import { useSession } from 'next-auth/react'; -import { useRouter } from 'next/navigation'; -import Link from 'next/link'; -import { joinTeam } from '../../actions/auth'; +"use client"; // Mark as a Client Component +import { useState, useEffect } from "react"; +import { useSession } from "next-auth/react"; +import { useRouter } from "next/navigation"; +import Link from "next/link"; +import { joinTeam } from "../../actions/auth"; + +// Add CSS to fix the navbar at the bottom +const styles = { + navbar: { + position: "fixed", + bottom: 0, + width: "100%", + backgroundColor: "#fff", + borderTop: "1px solid #ccc", + padding: "10px 0", + textAlign: "center", + }, +}; export default function TeamSelection() { - const { data: session, status } = useSession(); - const [teamCode, setTeamCode] = useState(''); - const [error, setError] = useState(''); - const [isLoading, setIsLoading] = useState(false); - const router = useRouter(); + const { data: session, status } = useSession(); + const [teamCode, setTeamCode] = useState(""); + const [error, setError] = useState(""); + const [isLoading, setIsLoading] = useState(false); + const router = useRouter(); - // Use useEffect for navigation instead of doing it in render - useEffect(() => { - // Redirect if not authenticated - if (status === 'unauthenticated') { - router.push('/login'); - } - - // Redirect if user is admin - if (status === 'authenticated' && session?.user?.role === 'admin') { - router.push('/admin'); - } - }, [status, session, router]); - - const handleJoinTeam = async (e) => { - e.preventDefault(); - setIsLoading(true); - setError(''); - - try { - const result = await joinTeam(session.user.id, teamCode); - - if (result.success) { - router.push(`/team/${result.teamId}`); - } else { - setError(result.error || 'Team not found'); - } - } catch (err) { - setError('An unexpected error occurred'); - console.error(err); - } finally { - setIsLoading(false); - } - }; - - if (status === 'loading') { - return
Loading...
; + // Use useEffect for navigation instead of doing it in render + useEffect(() => { + // Redirect if not authenticated + if (status === "unauthenticated") { + router.push("/login"); } - // Don't render anything if redirecting - if (status === 'unauthenticated' || (status === 'authenticated' && session?.user?.role === 'admin')) { - return null; + // Redirect if user is admin + if (status === "authenticated" && session?.user?.role === "admin") { + router.push("/admin"); } + }, [status, session, router]); - return ( -
-
-
-
Team Selection
-
-
+ const handleJoinTeam = async (e) => { + e.preventDefault(); + setIsLoading(true); + setError(""); -
-

Team Selection

-
-
- setTeamCode(e.target.value)} - required - className="team-input" - /> -
- -
- {error &&

{error}

} -
- Create a new team -
-
+ try { + const result = await joinTeam(session.user.id, teamCode); -
-
-
🏠
-
-
-
📊
-
-
-
🏆
-
-
-
👤
-
+ if (result.success) { + router.push(`/team/${result.teamId}`); + } else { + setError(result.error || "Team not found"); + } + } catch (err) { + setError("An unexpected error occurred"); + console.error(err); + } finally { + setIsLoading(false); + } + }; + + if (status === "loading") { + return
Loading...
; + } + + // Don't render anything if redirecting + if ( + status === "unauthenticated" || + (status === "authenticated" && session?.user?.role === "admin") + ) { + return null; + } + + return ( +
+
+
+
Team Selection
+
+
+ +
+
+

Team Selection

+
+
+ setTeamCode(e.target.value)} + required + className="auth-input" + />
+ +
+ {error &&

{error}

} +
+ + + +
- ); -} \ No newline at end of file +
+ +
+
+
🏠
+
+
+
📊
+
+
+
🏆
+
+
+
👤
+
+
+ + +
+ ); +} diff --git a/app/(main)/team/[teamId]/members/route.js b/app/(main)/team/[teamId]/members/route.js index eaae3c9..74675d9 100644 --- a/app/(main)/team/[teamId]/members/route.js +++ b/app/(main)/team/[teamId]/members/route.js @@ -1,35 +1,51 @@ -// app/api/teams/[teamId]/members/route.js -import { query } from '../../../../../lib/db'; -import { getServerSession } from 'next-auth/next'; -import { authOptions } from '../../../api/auth/[...nextauth]/route'; +import { query } from "../../../../lib/db"; +import { getServerSession } from "next-auth/next"; +import { authOptions } from "../../auth/[...nextauth]/route"; -export async function GET(request, { params }) { - const session = await getServerSession(authOptions); +export async function GET(request, context) { + const session = await getServerSession(authOptions); - if (!session) { - return Response.json({ error: 'Unauthorised' }, { status: 401 }); + if (!session) { + return Response.json({ error: "Unauthorised" }, { status: 401 }); + } + + try { + const { teamId } = context.params; + + // Convert teamId to number for proper comparison + const requestedTeamId = parseInt(teamId, 10); + const userTeamId = parseInt(session.user.teamId, 10); + + // Log for debugging + console.log("Requested team:", requestedTeamId); + console.log("User team:", userTeamId); + console.log("User role:", session.user.role); + + // Ensure the user is requesting their own team or is an admin + if (userTeamId !== requestedTeamId && session.user.role !== "admin") { + return Response.json( + { error: "Not authorized to view this team" }, + { status: 403 } + ); } - try { - const { teamId } = params; + const teamMembers = await query("SELECT * FROM users WHERE team_id = ?", [ + requestedTeamId, + ]); - // Convert teamId to number for proper comparison - const requestedTeamId = parseInt(teamId, 10); - const userTeamId = parseInt(session.user.teamId, 10); - - // Ensure the user is requesting their own team or is an admin - if (userTeamId !== requestedTeamId && session.user.role !== 'admin') { - return Response.json({ error: 'Not authorized to view this team' }, { status: 403 }); - } - - const members = await query( - 'SELECT id, username FROM users WHERE team_id = ?', - [requestedTeamId] - ); - - return Response.json(members); - } catch (error) { - console.error('Team members fetch error:', error); - return Response.json({ error: 'Failed to fetch team members' }, { status: 500 }); + if (!teamMembers) { + return Response.json( + { error: "Team members not found" }, + { status: 404 } + ); } -} \ No newline at end of file + + return Response.json(teamMembers); + } catch (error) { + console.error("Team members fetch error:", error); + return Response.json( + { error: "Failed to fetch team members" }, + { status: 500 } + ); + } +} diff --git a/app/(main)/team/[teamId]/page.js b/app/(main)/team/[teamId]/page.js index 44a2bfd..2580a1f 100644 --- a/app/(main)/team/[teamId]/page.js +++ b/app/(main)/team/[teamId]/page.js @@ -1,129 +1,139 @@ -'use client'; // Mark as a Client Component -import { useState, useEffect } from 'react'; -import { useSession } from 'next-auth/react'; -import { useRouter } from 'next/navigation'; -import Link from 'next/link'; +"use client"; // Mark as a Client Component +import { useState, useEffect } from "react"; +import { useSession } from "next-auth/react"; +import { useRouter } from "next/navigation"; +import Link from "next/link"; export default function TeamPage({ params }) { - const { data: session, status } = useSession(); - const [team, setTeam] = useState(null); - const [teamMembers, setTeamMembers] = useState([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(''); - const router = useRouter(); - const { teamId } = params; + const { data: session, status } = 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(); + const { teamId } = params; - // Fetch team data - useEffect(() => { - async function fetchTeamData() { - try { - if (!teamId) { - throw new Error('No team ID provided'); - } - - // Fetch team details - const teamResponse = await fetch(`/api/teams/${teamId}`); - if (!teamResponse.ok) { - const errorData = await teamResponse.json(); - throw new Error(errorData.error || 'Failed to fetch team data'); - } - const teamData = await teamResponse.json(); - setTeam(teamData); - - // Fetch team members - const membersResponse = await fetch(`/api/teams/${teamId}/members`); - if (!membersResponse.ok) { - // Don't throw here, just log the error - console.error('Failed to fetch team members'); - } else { - const membersData = await membersResponse.json(); - setTeamMembers(membersData); - } - } catch (err) { - console.error('Team page error:', err); - setError(err.message); - } finally { - setLoading(false); - } + // Fetch team data + useEffect(() => { + async function fetchTeamData() { + try { + if (!teamId) { + throw new Error("No team ID provided"); } - if (status === 'authenticated' && teamId) { - fetchTeamData(); + // Fetch team details + const teamResponse = await fetch(`/api/teams/${teamId}`); + if (!teamResponse.ok) { + const errorData = await teamResponse.json(); + throw new Error(errorData.error || "Failed to fetch team data"); } - }, [teamId, status]); + const teamData = await teamResponse.json(); + setTeam(teamData); - // Handle authentication - useEffect(() => { - if (status === 'unauthenticated') { - router.push('/login'); + // Fetch team members + const membersResponse = await fetch(`/api/teams/${teamId}/members`); + if (!membersResponse.ok) { + // Don't throw here, just log the error + console.error("Failed to fetch team members"); + } else { + const membersData = await membersResponse.json(); + setTeamMembers(membersData); } - }, [status, router]); - if (status === 'loading' || loading) { - return
Loading...
; + // Fetch hunt status + const huntStatusResponse = await fetch("/api/hunt-status"); + if (huntStatusResponse.ok) { + const huntStatusData = await huntStatusResponse.json(); + setHuntActive(huntStatusData.active); + } + } catch (err) { + console.error("Team page error:", err); + setError(err.message); + } finally { + setLoading(false); + } } - if (error) { - return
Error: {error}
; + if (status === "authenticated" && teamId) { + fetchTeamData(); } + }, [teamId, status]); - if (!team) { - return
Team not found
; + // Handle authentication + useEffect(() => { + if (status === "unauthenticated") { + router.push("/login"); } + }, [status, router]); - return ( -
-
- ← -
Team Details
-
-
+ if (status === "loading" || loading) { + return
Loading...
; + } -
-

{team.name}

+ if (error) { + return
Error: {error}
; + } -
-

Team Code

-
{team.code}
-

Share this code with others to join your team

-
+ if (!team) { + return
Team not found
; + } -
-

Team Members

- {teamMembers.length === 0 ? ( -

No members have joined yet

- ) : ( -
    - {teamMembers.map(member => ( -
  • - {member.username} -
  • - ))} -
- )} -
+ return ( +
+
+ + ← + +
Team Details
+
+
-
- - Start Hunt - -
-
+
+

{team.name}

-
-
-
🏠
-
-
-
📊
-
-
-
🏆
-
-
-
👤
-
-
+
+

Team Code

+
{team.code}
+

Share this code with others to join your team

- ); -} \ No newline at end of file + +
+

Team Members

+ {teamMembers.length === 0 ? ( +

No members have joined yet

+ ) : ( +
    + {teamMembers.map((member) => ( +
  • + {member.username} +
  • + ))} +
+ )} +
+ +
+ +
+
+ +
+
+
🏠
+
+
+
📊
+
+
+
🏆
+
+
+
👤
+
+
+
+ ); +} diff --git a/app/(main)/team/[teamId]/route.js b/app/(main)/team/[teamId]/route.js index 59ac8b2..ff4e36a 100644 --- a/app/(main)/team/[teamId]/route.js +++ b/app/(main)/team/[teamId]/route.js @@ -1,41 +1,101 @@ // app/api/teams/[teamId]/route.js -import { queryOne } from '../../../../lib/db'; -import { getServerSession } from 'next-auth/next'; -import { authOptions } from '../../../api/auth/[...nextauth]/route'; +import { queryOne } from "../../../../lib/db"; +import { getServerSession } from "next-auth/next"; +import { authOptions } from "../../../api/auth/[...nextauth]/route"; -export async function GET(request, { params }) { - const session = await getServerSession(authOptions); +export async function GET(request, context) { + const session = await getServerSession(authOptions); - if (!session) { - return Response.json({ error: 'Unauthorised' }, { status: 401 }); + if (!session) { + return new Response(JSON.stringify({ error: "Unauthorised" }), { + status: 401, + }); + } + + try { + const { teamId } = await context.params; // Await the params + + // Convert teamId to number for proper comparison + const requestedTeamId = parseInt(teamId, 10); + const userTeamId = parseInt(session.user.teamId, 10); + + // Log for debugging + console.log("Requested team:", requestedTeamId); + console.log("User team:", userTeamId); + console.log("User role:", session.user.role); + + // Ensure the user is requesting their own team or is an admin + if (userTeamId !== requestedTeamId && session.user.role !== "admin") { + return new Response( + JSON.stringify({ error: "Not authorized to view this team" }), + { status: 403 } + ); } - try { - const { teamId } = params; + const team = await queryOne("SELECT * FROM teams WHERE id = ?", [ + requestedTeamId, + ]); - // Convert teamId to number for proper comparison - const requestedTeamId = parseInt(teamId, 10); - const userTeamId = parseInt(session.user.teamId, 10); - - // Log for debugging - console.log('Requested team:', requestedTeamId); - console.log('User team:', userTeamId); - console.log('User role:', session.user.role); - - // Ensure the user is requesting their own team or is an admin - if (userTeamId !== requestedTeamId && session.user.role !== 'admin') { - return Response.json({ error: 'Not authorized to view this team' }, { status: 403 }); - } - - const team = await queryOne('SELECT * FROM teams WHERE id = ?', [requestedTeamId]); - - if (!team) { - return Response.json({ error: 'Team not found' }, { status: 404 }); - } - - return Response.json(team); - } catch (error) { - console.error('Team fetch error:', error); - return Response.json({ error: 'Failed to fetch team details' }, { status: 500 }); + if (!team) { + return new Response(JSON.stringify({ error: "Team not found" }), { + status: 404, + }); } -} \ No newline at end of file + + return new Response(JSON.stringify(team), { status: 200 }); + } catch (error) { + console.error("Team fetch error:", error); + return new Response( + JSON.stringify({ error: "Failed to fetch team details" }), + { status: 500 } + ); + } +} + +export async function PATCH(request, context) { + const session = await getServerSession(authOptions); + + if (!session) { + return new Response(JSON.stringify({ error: "Unauthorised" }), { + status: 401, + }); + } + + try { + const { teamId } = await context.params; // Await the params + const requestedTeamId = parseInt(teamId, 10); + const { userId } = await request.json(); // Parse the request body + + // Log for debugging + console.log("Requested team:", requestedTeamId); + console.log("User role:", session.user.role); + + // Ensure the user is an admin or the user themselves + if (session.user.role !== "admin" && session.user.id !== userId) { + return new Response( + JSON.stringify({ error: "Not authorized to change this team" }), + { status: 403 } + ); + } + + // Update the user's team + await queryOne("UPDATE users SET teamId = ? WHERE id = ?", [ + requestedTeamId, + userId, + ]); + + // Update the session with the new teamId + session.user.teamId = requestedTeamId; + + return new Response( + JSON.stringify({ success: "Team updated successfully" }), + { status: 200 } + ); + } catch (error) { + console.error("Team update error:", error); + return new Response( + JSON.stringify({ error: "Failed to update team" }), + { status: 500 } + ); + } +} diff --git a/app/api/teams/[teamId]/route.js b/app/api/teams/[teamId]/route.js index eb7bbf4..e768564 100644 --- a/app/api/teams/[teamId]/route.js +++ b/app/api/teams/[teamId]/route.js @@ -1,31 +1,38 @@ -import { queryOne } from '../../../../lib/db'; -import { getServerSession } from 'next-auth/next'; -import { authOptions } from '../../auth/[...nextauth]/route'; +import { queryOne } from "../../../../lib/db"; +import { getServerSession } from "next-auth/next"; +import { authOptions } from "../../auth/[...nextauth]/route"; export async function GET(request, { params }) { - const session = await getServerSession(authOptions); + const session = await getServerSession(authOptions); - if (!session) { - return Response.json({ error: 'Unauthorised' }, { status: 401 }); + if (!session) { + return Response.json({ error: "Unauthorised" }, { status: 401 }); + } + + try { + const { teamId } = params; + + // Single query to get team data with authorization check + const team = await queryOne( + `SELECT t.* FROM teams t + LEFT JOIN users u ON u.id = ? + WHERE t.id = ? AND (u.team_id = t.id OR ? = 'admin')`, + [session.user.id, teamId, session.user.role] + ); + + if (!team) { + return Response.json( + { error: "Team not found or unauthorized" }, + { status: 404 } + ); } - try { - const { teamId } = params; - - // Ensure the user is requesting their own team or is an admin - if (session.user.teamId != teamId && session.user.role !== 'admin') { - return Response.json({ error: 'Not authorized to view this team' }, { status: 403 }); - } - - const team = await queryOne('SELECT * FROM teams WHERE id = ?', [teamId]); - - if (!team) { - return Response.json({ error: 'Team not found' }, { status: 404 }); - } - - return Response.json(team); - } catch (error) { - console.error('Team fetch error:', error); - return Response.json({ error: 'Failed to fetch team details' }, { status: 500 }); - } -} \ No newline at end of file + return Response.json(team); + } catch (error) { + console.error("Team fetch error:", error); + return Response.json( + { error: "Failed to fetch team details" }, + { status: 500 } + ); + } +}