feat: add gender
This commit is contained in:
parent
b739246129
commit
4e2e0dd2a5
@ -1,6 +1,7 @@
|
||||
from datetime import datetime, timezone
|
||||
from sqlmodel import (
|
||||
ARRAY,
|
||||
CHAR,
|
||||
Column,
|
||||
Integer,
|
||||
Relationship,
|
||||
@ -48,6 +49,7 @@ class Player(SQLModel, table=True):
|
||||
display_name: str
|
||||
email: str | None = None
|
||||
full_name: str | None = None
|
||||
gender: str | None = Field(default=None, sa_column=Column(CHAR(3)))
|
||||
disabled: bool | None = None
|
||||
hashed_password: str | None = None
|
||||
number: str | None = None
|
||||
|
@ -21,8 +21,9 @@ player_router = APIRouter(prefix="/player", tags=["player"])
|
||||
class PlayerRequest(BaseModel):
|
||||
display_name: str
|
||||
username: str
|
||||
gender: str | None
|
||||
number: str
|
||||
email: str
|
||||
email: str | None
|
||||
|
||||
|
||||
class AddPlayerRequest(PlayerRequest): ...
|
||||
@ -54,6 +55,7 @@ def add_player(
|
||||
new_player = Player(
|
||||
username=r.username,
|
||||
display_name=r.display_name,
|
||||
gender=r.gender if r.gender else None,
|
||||
email=r.email if r.email else None,
|
||||
number=r.number,
|
||||
disabled=False,
|
||||
@ -80,9 +82,11 @@ def modify_player(
|
||||
.where(Team.id == request.team_id, P.id == r.id, P.username == r.username)
|
||||
).one_or_none()
|
||||
if player:
|
||||
print(r)
|
||||
player.display_name = r.display_name.strip()
|
||||
player.number = r.number.strip()
|
||||
player.email = r.email.strip()
|
||||
player.gender = r.gender.strip() if r.gender else None
|
||||
player.email = r.email.strip() if r.email else None
|
||||
session.add(player)
|
||||
session.commit()
|
||||
return PlainTextResponse("modification successful")
|
||||
@ -170,7 +174,14 @@ async def list_players(
|
||||
if players:
|
||||
return [
|
||||
player.model_dump(
|
||||
include={"id", "display_name", "username", "number", "email"}
|
||||
include={
|
||||
"id",
|
||||
"display_name",
|
||||
"username",
|
||||
"gender",
|
||||
"number",
|
||||
"email",
|
||||
}
|
||||
)
|
||||
for player in players
|
||||
if not player.disabled
|
||||
|
60
src/App.css
60
src/App.css
@ -29,7 +29,6 @@ dialog {
|
||||
border-radius: 1em;
|
||||
}
|
||||
|
||||
|
||||
/*=========Network Controls=========*/
|
||||
|
||||
.infobutton {
|
||||
@ -61,7 +60,7 @@ dialog {
|
||||
flex-wrap: wrap;
|
||||
max-width: 240px;
|
||||
margin: 0px;
|
||||
background-color: #F0F8FFdd;
|
||||
background-color: #f0f8ffdd;
|
||||
|
||||
.slider,
|
||||
span {
|
||||
@ -103,8 +102,8 @@ dialog {
|
||||
bottom: 0;
|
||||
background-color: #ccc;
|
||||
border-radius: 34px;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
-webkit-transition: 0.4s;
|
||||
transition: 0.4s;
|
||||
}
|
||||
|
||||
.slider:before {
|
||||
@ -116,19 +115,19 @@ dialog {
|
||||
bottom: 3px;
|
||||
background-color: white;
|
||||
border-radius: 50%;
|
||||
-webkit-transition: .4s;
|
||||
transition: .4s;
|
||||
-webkit-transition: 0.4s;
|
||||
transition: 0.4s;
|
||||
}
|
||||
|
||||
input:checked+.slider {
|
||||
background-color: #2196F3;
|
||||
input:checked + .slider {
|
||||
background-color: #2196f3;
|
||||
}
|
||||
|
||||
input:focus+.slider {
|
||||
box-shadow: 0 0 1px #2196F3;
|
||||
input:focus + .slider {
|
||||
box-shadow: 0 0 1px #2196f3;
|
||||
}
|
||||
|
||||
input:checked+.slider:before {
|
||||
input:checked + .slider:before {
|
||||
-webkit-transform: translateX(24px);
|
||||
-ms-transform: translateX(24px);
|
||||
transform: translateX(24px);
|
||||
@ -138,8 +137,6 @@ input:checked+.slider:before {
|
||||
opacity: 66%;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.hint {
|
||||
position: absolute;
|
||||
font-size: 80%;
|
||||
@ -151,7 +148,8 @@ input:checked+.slider:before {
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
input {
|
||||
input,
|
||||
select {
|
||||
padding: 0.2em 16px;
|
||||
margin-top: 0.25em;
|
||||
margin-bottom: 0.25em;
|
||||
@ -180,7 +178,6 @@ h3 {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
@ -281,10 +278,8 @@ button {
|
||||
font-size: 80%;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@media only screen and (max-width: 768px) {
|
||||
#control-panel {
|
||||
grid-template-columns: 1fr;
|
||||
@ -308,7 +303,6 @@ button {
|
||||
font-size: xx-large;
|
||||
margin-bottom: 16px;
|
||||
margin-right: 16px;
|
||||
|
||||
}
|
||||
|
||||
.wavering {
|
||||
@ -317,11 +311,13 @@ button {
|
||||
}
|
||||
|
||||
::backdrop {
|
||||
background-image: linear-gradient(45deg,
|
||||
magenta,
|
||||
rebeccapurple,
|
||||
dodgerblue,
|
||||
green);
|
||||
background-image: linear-gradient(
|
||||
45deg,
|
||||
magenta,
|
||||
rebeccapurple,
|
||||
dodgerblue,
|
||||
green
|
||||
);
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
@ -488,7 +484,10 @@ button {
|
||||
|
||||
input {
|
||||
max-width: 300px;
|
||||
margin: 0.2em auto;
|
||||
}
|
||||
select {
|
||||
max-width: 335px;
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
|
||||
@ -511,6 +510,12 @@ button {
|
||||
&.disable-player {
|
||||
background-color: #e338;
|
||||
}
|
||||
&.mmp {
|
||||
background-color: lightskyblue;
|
||||
}
|
||||
&.fmp {
|
||||
background-color: salmon;
|
||||
}
|
||||
}
|
||||
|
||||
.new-player-inputs {
|
||||
@ -533,21 +538,19 @@ button {
|
||||
margin: auto 1em;
|
||||
}
|
||||
|
||||
input {
|
||||
input,
|
||||
select {
|
||||
width: 90%;
|
||||
margin: 4px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@keyframes blink {
|
||||
|
||||
0% {
|
||||
background-color: #8888;
|
||||
}
|
||||
|
||||
|
||||
13% {
|
||||
background-color: #8888;
|
||||
}
|
||||
@ -560,7 +563,6 @@ button {
|
||||
background-color: #8888;
|
||||
}
|
||||
|
||||
|
||||
38% {
|
||||
background-color: #8888;
|
||||
}
|
||||
|
@ -22,6 +22,10 @@ const UserInfo = (user: User, teams: TeamState | undefined) => {
|
||||
<b>display name: </b>
|
||||
</div>
|
||||
<div>{user?.display_name}</div>
|
||||
<div>
|
||||
<b>gender: </b>
|
||||
</div>
|
||||
<div>{user?.gender?.toUpperCase() || "-"}</div>
|
||||
<div>
|
||||
<b>number: </b>
|
||||
</div>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { FormEvent, useEffect, useState } from "react";
|
||||
import { apiAuth, loadPlayers, User } from "./api";
|
||||
import { apiAuth, Gender, loadPlayers, User } from "./api";
|
||||
import { useSession } from "./Session";
|
||||
import { ErrorState } from "./types";
|
||||
import { useNavigate } from "react-router";
|
||||
@ -15,6 +15,7 @@ const TeamPanel = () => {
|
||||
id: 0,
|
||||
username: "",
|
||||
display_name: "",
|
||||
gender: undefined,
|
||||
number: "",
|
||||
email: "",
|
||||
} as User;
|
||||
@ -95,7 +96,7 @@ const TeamPanel = () => {
|
||||
{players &&
|
||||
players.map((p) => (
|
||||
<button
|
||||
className="team-player"
|
||||
className={"team-player " + p.gender}
|
||||
key={p.id}
|
||||
onClick={() => {
|
||||
setPlayer(p);
|
||||
@ -151,6 +152,22 @@ const TeamPanel = () => {
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label>gender</label>
|
||||
<select
|
||||
name="gender"
|
||||
required
|
||||
value={player.gender}
|
||||
onChange={(e) => {
|
||||
setPlayer({ ...player, gender: e.target.value as Gender });
|
||||
setError({ ok: true, message: "" });
|
||||
}}
|
||||
>
|
||||
<option value={undefined}></option>
|
||||
<option value="fmp">FMP</option>
|
||||
<option value="mmp">MMP</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label>number (optional)</label>
|
||||
<input
|
||||
|
@ -43,12 +43,15 @@ export async function apiAuth(
|
||||
}
|
||||
}
|
||||
|
||||
export type Gender = "fmp" | "mmp" | undefined;
|
||||
|
||||
export type User = {
|
||||
id: number;
|
||||
username: string;
|
||||
display_name: string;
|
||||
email: string;
|
||||
number: string;
|
||||
gender: Gender;
|
||||
scopes: string;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user