diff --git a/api/index.py b/api/index.py index 1ef889e..e4b57f4 100644 --- a/api/index.py +++ b/api/index.py @@ -96,3 +96,149 @@ def get(self, url_tag): api.add_resource(Game, "/api/g/") + + +class Scoreboard(Resource): + """Scoreboard""" + + def get(self, url_tag): + """Get the scoreboard for an existing game.""" + + # TODO get game id from url_tag then filter scoreboard, don't filter by foreign key + + try: + res = ( + supabase.table("scoreboard_games_profiles") + .select("*, games!inner(url_tag), profiles!inner(username)") + .eq("games.url_tag", url_tag) + .execute() + ) + return {"success": True, "data": res.data, "count": len(res.data)} + except APIError as e: + return {"success": False, "message": e.message, "count": 0}, 500 + + def post(self, url_tag): + """Add or update a user to the scoreboard for an existing game.""" + req = request.get_json() + check_auth(req, req["user_id"]) + + try: + game_id, user_id, details = ( + req["game_id"], + req["user_id"], + req["details"], + ) + + # see if user has previous scoreboard submission + res = ( + supabase.table("scoreboard_games_profiles") + .select("*") + .eq("game_id", game_id) + .eq("user_id", user_id) + .execute() + ) + + if len(res.data) > 0: + # TODO if user has previous submission, update it + return {"success": True, "data": res.data, "count": len(res.data)} + else: + # if user has no previous submission, insert new row + res = ( + supabase.table("scoreboard_games_profiles") + .insert( + { + "game_id": game_id, + "user_id": user_id, + "details": details, + } + ) + .execute() + ) + + return {"success": True, "data": res.data, "count": len(res.data)} + + except APIError as e: + return { + "success": False, + "message": e.message, + }, 500 + + +api.add_resource(Scoreboard, "/api/g//scoreboard") + + +class Rating(Resource): + """Ratings & Comments""" + + def get(self, url_tag): + """Get the ratings and comments for an existing game.""" + + # TODO get game id from url_tag then filter ratings, don't filter by foreign key + # TODO do this for both get and post, update apiService.js to query by game id not url_tag + + try: + res = ( + supabase.table("ratings") + .select("*, games!inner(url_tag), profiles!inner(id, username)") + .eq("games.url_tag", url_tag) + .execute() + ) + return {"success": True, "data": res.data, "count": len(res.data)} + except APIError as e: + return {"success": False, "message": e.message, "count": 0}, 500 + + def post(self, url_tag): + """Create a new rating/comment for an existing game.""" + req = request.get_json() + check_auth(req, req["user_id"]) + + try: + game_id, user_id, rating, comment = ( + req["game_id"], + req["user_id"], + req["rating"], + req["comment"], + ) + + # see if user has previously left a rating/comment + res = ( + supabase.table("ratings") + .select("*") + .eq("game_id", game_id) + .eq("user_id", user_id) + .execute() + ) + + if len(res.data) > 0: + # user has already left a rating/comment + return { + "success": False, + "message": "You have already left a rating/comment for this game.", + } + else: + # if user has no previous rating/comment, insert new row + res = ( + supabase.table("ratings") + .insert( + { + "game_id": game_id, + "user_id": user_id, + "rating": rating, + "comment": comment, + } + ) + .execute() + ) + + return {"success": True, "data": res.data, "count": len(res.data)} + + except APIError as e: + return { + "success": False, + "message": e.message, + }, 500 + + # TODO put method to update rating/comment + + +api.add_resource(Rating, "/api/g//rating") diff --git a/src/app/auth/signout/route.js b/src/app/auth/signout/route.js index 4332298..74bd5ab 100644 --- a/src/app/auth/signout/route.js +++ b/src/app/auth/signout/route.js @@ -17,7 +17,7 @@ export async function POST(req) { } revalidatePath("/", "layout"); - return NextResponse.redirect(new URL("/login", req.url), { + return NextResponse.redirect(new URL("/", req.url), { status: 302, }); } diff --git a/src/app/g/[slug]/details/page.jsx b/src/app/g/[slug]/details/page.jsx new file mode 100644 index 0000000..753975a --- /dev/null +++ b/src/app/g/[slug]/details/page.jsx @@ -0,0 +1,320 @@ +"use client"; + +import { useCallback, useEffect, useState } from "react"; +import Link from "next/link"; +import { useRouter } from "next/navigation"; +import { + Box, + Button, + Container, + Heading, + Input, + Table, + Textarea, +} from "@chakra-ui/react"; +import createClient from "@/utils/supabase/client"; +import { + createRating, + getGame, + getRatings, + getScoreboard, +} from "@/services/apiService"; + +// Scoreboard React component +function Scoreboard({ scores }) { + // TODO sorting by some metric (e.g. score) before displaying + // TODO style table + return ( + + + Scoreboard + + + + + + + + + + + {scores + .sort() // TODO sort by score + .map((score, index) => ( + + + + + + ))} + +
RankNameScore
{index + 1}{score.profiles.username}{score.details ? score.details.score : ""}
+
+ ); +} + +function Ratings({ ratings }) { + return ( + + + Ratings + + + + + + + + + + + {ratings + .sort() // TODO sort by rating + .map((rating) => ( + + + + + + ))} + +
NameRatingComment
{rating.profiles.username}{rating.rating}{rating.comment}
+
+ ); +} + +// Component to create a new rating +function CreateRating({ + user, + callCreateRating, + rating, + setRating, + comment, + setComment, + ratingCreated, +}) { + if (!user) { + return ( + + + + {" "} + to rate this game. + + ); + } + + if (ratingCreated) { + return Rating created successfully!; + } + + return ( + + + Rate This Game + + {/* Textbox */} +