diff --git a/backend/app/api/endpoints/group.py b/backend/app/api/endpoints/group.py index 9736c259..9f786715 100644 --- a/backend/app/api/endpoints/group.py +++ b/backend/app/api/endpoints/group.py @@ -1,6 +1,7 @@ """ Group endpoints """ + import time from functools import partial @@ -10,7 +11,14 @@ from app.api import APIRoute, Request, oidc from app.config import INDEXED_ROLES from app.exceptions import DatabaseIntegrityException, NotFound, PunishmentTypeNotExists -from app.models.group import Group, GroupPublic, GroupCreate, GroupCreateMinified, GroupSearchResult, InviteCodePatch +from app.models.group import ( + Group, + GroupPublic, + GroupCreate, + GroupCreateMinified, + GroupSearchResult, + InviteCodePatch, +) from app.models.group_event import GroupEvent, GroupEventCreate from app.models.group_join_requests import GroupJoinRequest from app.models.group_member import GroupMemberCreate @@ -253,10 +261,11 @@ async def get_public_group(request: Request, group_name_short: str) -> GroupPubl else: user_id = None - async with app.db.pool.acquire() as conn: try: - return await app.db.groups.get_public_group_profile(group_name_short, user_id, conn=conn) + return await app.db.groups.get_public_group_profile( + group_name_short, user_id, conn=conn + ) except NotFound as exc: raise HTTPException( status_code=404, detail="Gruppen ble ikke funnet" @@ -352,6 +361,7 @@ async def patch_group( return {"id": data["id"]} + @router.patch( "/{group_id}/inviteCode", dependencies=[Depends(oidc)], @@ -388,12 +398,12 @@ async def patch_invite_code( if invite_code == "" or invite_code is not None and invite_code.isspace(): raise HTTPException( - status_code=400, - detail="Invitasjonskoden kan ikke være tom" + status_code=400, detail="Invitasjonskoden kan ikke være tom" ) await app.db.groups.update_invite_code(group_id, invite_code, conn=conn) + @router.delete( "/{group_id}", dependencies=[Depends(oidc)], @@ -895,8 +905,7 @@ async def add_punishment( ) if punishment.punishment_type_id not in group_punishment_types: raise HTTPException( - status_code=400, - detail="Ugyldig straff, last inn siden på nytt" + status_code=400, detail="Ugyldig straff, last inn siden på nytt" ) try: @@ -1461,7 +1470,9 @@ async def join_group( requester_user_id, _ = await app.ow_sync.sync_for_access_token(access_token) async with app.db.pool.acquire() as conn: - group = await app.db.groups.get(group_id, invite_code=invite_code, include_members=False, conn=conn) + group = await app.db.groups.get( + group_id, invite_code=invite_code, include_members=False, conn=conn + ) if not group: raise HTTPException( @@ -1477,7 +1488,9 @@ async def join_group( await app.db.groups.insert_member( group_id, - GroupMemberCreate(user_id=requester_user_id, ow_group_user_id=None, active=True), + GroupMemberCreate( + user_id=requester_user_id, ow_group_user_id=None, active=True + ), conn=conn, ) @@ -1490,6 +1503,7 @@ async def join_group( except NotFound: pass + @router.post( "/{group_id}/joinRequests/{user_id}/deny", dependencies=[Depends(oidc)], diff --git a/backend/app/api/endpoints/user.py b/backend/app/api/endpoints/user.py index 7d3812b5..0decbaee 100644 --- a/backend/app/api/endpoints/user.py +++ b/backend/app/api/endpoints/user.py @@ -2,6 +2,7 @@ User endpoints """ +from functools import partial from app.models.punishment import LeaderboardPunishmentRead from fastapi import APIRouter, Depends, HTTPException, Query @@ -70,6 +71,7 @@ async def get_leadeboard( request: Request, page: int = Query(title="Page number", default=0, ge=0), page_size: int = Query(title="Page size", default=30, ge=1, le=50), + this_year: bool = Query(title="Only show users from this year", default=False), ) -> Page[MinifiedLeaderboardUser]: access_token = request.raise_if_missing_authorization() @@ -87,12 +89,13 @@ async def get_leadeboard( request=request, total_coro=app.db.users.get_leaderboard_count, # results_coro=app.db.users.get_leaderboard, - results_coro=app.db.users.get_minified_leaderboard, + results_coro=partial(app.db.users.get_minified_leaderboard, this_year), page=page, page_size=page_size, ) return await pagination.paginate(conn=conn) - + + @router.get( "/leaderboard/punishments/{user_id}", response_model=list[LeaderboardPunishmentRead], @@ -108,4 +111,6 @@ async def get_user_punishments( _, _ = await app.ow_sync.sync_for_access_token(access_token) async with app.db.pool.acquire() as conn: - return await app.db.users.get_punishments_for_leaderboard_user(user_id, conn=conn) + return await app.db.users.get_punishments_for_leaderboard_user( + user_id, conn=conn + ) diff --git a/backend/app/db/group_events.py b/backend/app/db/group_events.py index 9aad1a18..1b92dcdf 100644 --- a/backend/app/db/group_events.py +++ b/backend/app/db/group_events.py @@ -1,5 +1,5 @@ import datetime -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING, Any, Optional from asyncpg import Pool from asyncpg.exceptions import ForeignKeyViolationError, UniqueViolationError diff --git a/backend/app/db/users.py b/backend/app/db/users.py index 47026741..d0bed16a 100644 --- a/backend/app/db/users.py +++ b/backend/app/db/users.py @@ -354,6 +354,7 @@ async def get_groups( async def get_minified_leaderboard( self, + this_year: bool, offset: int, limit: int, conn: Optional[Pool] = None, @@ -399,10 +400,14 @@ async def get_minified_leaderboard( LEFT JOIN groups g ON g.group_id = gm.group_id WHERE g.ow_group_id IS NOT NULL OR g.special - ORDER BY total_value DESC, u.first_name ASC - OFFSET $1 - LIMIT $2 """ + + if this_year: + query += "ORDER BY total_value_this_year DESC, u.first_name ASC " + else: + query += "ORDER BY total_value DESC, u.first_name ASC " + query += "OFFSET $1 LIMIT $2" + res = await conn.fetch( query, offset, diff --git a/frontend/src/helpers/api.ts b/frontend/src/helpers/api.ts index 577ab1bc..920b7a0b 100644 --- a/frontend/src/helpers/api.ts +++ b/frontend/src/helpers/api.ts @@ -33,12 +33,10 @@ const BASE_URL = import.meta.env.VITE_API_URL ?? "http://localhost:8000" const LEADERBOARD_URL = BASE_URL + "/users/leaderboard" -const getLeaderboardUrl = (page: number) => `${LEADERBOARD_URL}?page=${page}` +const getLeaderboardUrl = (page: number, this_year: boolean) => `${LEADERBOARD_URL}?page=${page}&this_year=${this_year}` export const getLeaderboardUserPunishmentsUrl = (userId: string) => `${LEADERBOARD_URL}/punishments/${userId}` -const GROUPS_URL = BASE_URL + "/groups/me" - const ME_URL = BASE_URL + "/users/me" const getGroupUrl = (groupId: string) => BASE_URL + `/groups/${groupId}` @@ -661,18 +659,14 @@ export const committeesQuery = () => ({ staletime: 1000 * 60, }) -const getLeaderboard = async ({ pageParam = 0 }) => - LeaderboardSchema.parse(await axios.get(getLeaderboardUrl(pageParam)).then((res) => res.data)) +const getLeaderboard = async ({ pageParam = 0, this_year = true }) => + LeaderboardSchema.parse(await axios.get(getLeaderboardUrl(pageParam, this_year)).then((res) => res.data)) -export const leaderboardQuery = (): UseInfiniteQueryOptions< - Leaderboard, - unknown, - Leaderboard, - Leaderboard, - string[] -> => ({ +export const leaderboardQuery = ( + this_year: boolean = true +): UseInfiniteQueryOptions => ({ queryKey: ["leaderboard"], - queryFn: getLeaderboard, + queryFn: ({ pageParam = 0 }) => getLeaderboard({ pageParam, this_year }), getNextPageParam: (lastPage: Leaderboard) => { const nextPage = lastPage.next ? new URL(lastPage.next).searchParams.get("page") : undefined return nextPage ? Number(nextPage) : undefined diff --git a/frontend/src/pages/wallOfShame/WallOfShame.tsx b/frontend/src/pages/wallOfShame/WallOfShame.tsx index fa23727d..1152540c 100644 --- a/frontend/src/pages/wallOfShame/WallOfShame.tsx +++ b/frontend/src/pages/wallOfShame/WallOfShame.tsx @@ -3,7 +3,7 @@ import { useInfiniteQuery, useQuery } from "@tanstack/react-query" import { leaderboardQuery, userQuery } from "../../helpers/api" import { Button } from "../../components/button/Button" import { useCurrentUser } from "../../helpers/context/currentUserContext" -import { useState } from "react" +import { useEffect, useState } from "react" export const WallOfShame = () => { const { setCurrentUser } = useCurrentUser() @@ -18,7 +18,11 @@ export const WallOfShame = () => { }, }) - const { isFetching, data, refetch, fetchNextPage } = useInfiniteQuery(leaderboardQuery()) + const { isFetching, data, refetch, fetchNextPage } = useInfiniteQuery(leaderboardQuery(filter === "year")) + + useEffect(() => { + refetch() + }, [filter, refetch]) const leaderboardUsers = data?.pages.flatMap((page) => page.results)