feat: show teams

This commit is contained in:
julius 2025-03-17 19:26:09 +01:00
parent 3441e405a6
commit 054508cf6a
Signed by: julius
GPG Key ID: C80A63E6A5FD7092
7 changed files with 60 additions and 11 deletions

13
main.py
View File

@ -59,7 +59,7 @@ def add_players(players: list[Player]):
session.commit()
def list_players():
async def list_players():
with Session(engine) as session:
statement = select(Player).order_by(Player.display_name)
players = session.exec(statement).fetchall()
@ -69,6 +69,11 @@ def list_players():
]
async def read_teams_me(user: Annotated[Player, Depends(get_current_active_user)]):
with Session(engine) as session:
return [p.teams for p in session.exec(select(P).where(P.id == user.id))][0]
def list_teams():
with Session(engine) as session:
statement = select(Team)
@ -79,12 +84,16 @@ player_router = APIRouter(prefix="/player")
player_router.add_api_route("/list", endpoint=list_players, methods=["GET"])
player_router.add_api_route("/add", endpoint=add_player, methods=["POST"])
player_router.add_api_route("/me", endpoint=read_player_me, methods=["GET"])
player_router.add_api_route("/me/teams", endpoint=read_teams_me, methods=["GET"])
player_router.add_api_route("/me/items", endpoint=read_own_items, methods=["GET"])
player_router.add_api_route(
"/change_password", endpoint=change_password, methods=["POST"]
)
team_router = APIRouter(prefix="/team")
team_router = APIRouter(
prefix="/team",
dependencies=[Security(get_current_active_user, scopes=["admin"])],
)
team_router.add_api_route("/list", endpoint=list_teams, methods=["GET"])
team_router.add_api_route("/add", endpoint=add_team, methods=["POST"])

View File

@ -60,6 +60,7 @@ oauth2_scheme = CookieOAuth2(
tokenUrl="api/token",
scopes={
"analysis": "Access the results.",
"admin": "Maintain DB etc.",
},
)

View File

@ -421,7 +421,7 @@ button {
.user-info {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-columns: 8em 12em;
gap: 2px 16px;
div {

View File

@ -4,13 +4,14 @@ import { User } from "./api";
import { useTheme } from "./ThemeProvider";
import { colourTheme, darkTheme, normalTheme, rainbowTheme } from "./themes";
import { useNavigate } from "react-router";
import { Team } from "./types";
interface ContextMenuItem {
label: string;
onClick: () => void;
}
const UserInfo = (user: User) => {
const UserInfo = (user: User, teams: Team[] | undefined) => {
return (
<div className="user-info">
<div>
@ -24,17 +25,38 @@ const UserInfo = (user: User) => {
<div>
<b>number: </b>
</div>
<div>{user?.number ? user?.number : "-"}</div>
<div>{user?.number || "-"}</div>
<div>
<b>email: </b>
</div>
<div>{user?.email ? user?.email : "-"}</div>
<div>{user?.email || "-"}</div>
{teams && (
<>
<div>
<b>teams: </b>
</div>
<ul
style={{
margin: 0,
padding: 0,
textAlign: "left",
}}
>
{teams.map((team) => (
<li>
{team.name} (
{team.location || team.country || "location unknown"})
</li>
))}
</ul>
</>
)}
</div>
);
};
export default function Avatar() {
const { user, onLogout } = useSession();
const { user, teams, onLogout } = useSession();
const { theme, setTheme } = useTheme();
const navigate = useNavigate();
const [contextMenu, setContextMenu] = useState<{
@ -118,9 +140,9 @@ export default function Avatar() {
const dialogRef = createRef<HTMLDialogElement>();
function handleViewProfile() {
if (user) {
if (user && teams) {
dialogRef.current?.showModal();
setDialog(UserInfo(user));
setDialog(UserInfo(user, teams));
}
}

View File

@ -5,9 +5,10 @@ import {
useEffect,
useState,
} from "react";
import { currentUser, logout, User } from "./api";
import { apiAuth, currentUser, logout, User } from "./api";
import { Login } from "./Login";
import Header from "./Header";
import { Team } from "./types";
export interface SessionProviderProps {
children: ReactNode;
@ -15,11 +16,13 @@ export interface SessionProviderProps {
export interface Session {
user: User | null;
teams: Team[] | null;
onLogout: () => void;
}
const sessionContext = createContext<Session>({
user: null,
teams: null,
onLogout: () => {},
});
@ -27,6 +30,7 @@ export function SessionProvider(props: SessionProviderProps) {
const { children } = props;
const [user, setUser] = useState<User | null>(null);
const [teams, setTeams] = useState<Team[]>();
const [err, setErr] = useState<unknown>(null);
const [loading, setLoading] = useState(false);
@ -44,8 +48,14 @@ export function SessionProvider(props: SessionProviderProps) {
.finally(() => setLoading(false));
}
async function loadTeam() {
const teams: Team[] = await apiAuth("player/me/teams", null, "GET");
if (teams) setTeams(teams);
}
useEffect(() => {
loadUser();
setTimeout(() => loadTeam(), 1500);
}, []);
function onLogin(user: User) {
@ -77,7 +87,7 @@ export function SessionProvider(props: SessionProviderProps) {
content = <Login onLogin={onLogin} />;
} else
content = (
<sessionContext.Provider value={{ user, onLogout }}>
<sessionContext.Provider value={{ user, teams, onLogout }}>
{children}
</sessionContext.Provider>
);

View File

@ -1,4 +1,5 @@
import { useSession } from "./Session";
import { Team } from "./types";
export const baseUrl = import.meta.env.VITE_BASE_URL as string;

View File

@ -32,3 +32,9 @@ export interface MVPRanking {
user: number;
mvps: number[];
}
export interface Team {
name: string;
location: string;
country: string;
}