Use hey api more (#1480)

This commit is contained in:
Erik Vroon
2025-12-20 20:19:17 +01:00
committed by GitHub
parent a548ff6d61
commit ffaeb87463
48 changed files with 134 additions and 186 deletions

View File

@@ -10,8 +10,8 @@
"start": "vite start",
"typecheck": "tsc",
"export": "vite build && vite export",
"prettier:check": "prettier --check \"**/*.{ts,tsx}\"",
"prettier:write": "prettier --write \"**/*.{ts,tsx}\"",
"prettier:check": "prettier --list-different --check \"**/*.{ts,tsx}\"",
"prettier:write": "prettier --list-different --write \"**/*.{ts,tsx}\"",
"test": "tsc && pnpm run prettier:write"
},
"dependencies": {

View File

@@ -18,15 +18,16 @@ import { MdOutlineAutoFixHigh } from 'react-icons/md';
import { SWRResponse } from 'swr';
import { BracketDisplaySettings } from '../../interfaces/brackets';
import { RoundInterface } from '../../interfaces/round';
import { Round } from '../../interfaces/round';
import { StageItemWithRounds } from '../../interfaces/stage_item';
import { Tournament, TournamentMinimal } from '../../interfaces/tournament';
import { TournamentMinimal } from '../../interfaces/tournament';
import { Tournament } from '../../openapi';
import { createRound } from '../../services/round';
import ActivateNextRoundModal from '../modals/activate_next_round_modal';
import { NoContent } from '../no_content/empty_table_info';
import { Translator } from '../utils/types';
import { responseIsValid } from '../utils/util';
import Round from './round';
import RoundComponent from './round';
function AddRoundButton({
t,
@@ -86,12 +87,9 @@ export function RoundsGridCols({
let result: React.JSX.Element[] | React.JSX.Element = stageItem.rounds
.sort((r1: any, r2: any) => (r1.name > r2.name ? 1 : -1))
.filter(
(round: RoundInterface) =>
round.matches.length > 0 || displaySettings.matchVisibility === 'all'
)
.map((round: RoundInterface) => (
<Round
.filter((round: Round) => round.matches.length > 0 || displaySettings.matchVisibility === 'all')
.map((round: Round) => (
<RoundComponent
key={round.id}
tournamentData={tournamentData}
round={round}

View File

@@ -2,14 +2,14 @@ import { Grid, Title } from '@mantine/core';
import React from 'react';
import { SWRResponse } from 'swr';
import { RoundInterface } from '../../interfaces/round';
import { Round } from '../../interfaces/round';
import { TournamentMinimal } from '../../interfaces/tournament';
import { getStages } from '../../services/adapter';
import Match from './match';
function getRoundsGridCols(
swrStagesResponse: SWRResponse,
activeRound: RoundInterface,
activeRound: Round,
tournamentData: TournamentMinimal
) {
return activeRound.matches
@@ -36,7 +36,7 @@ export default function Courts({
activeRound,
}: {
tournamentData: TournamentMinimal;
activeRound: RoundInterface;
activeRound: Round;
}) {
const swrStagesResponse = getStages(tournamentData.id);
return (

View File

@@ -10,7 +10,7 @@ import {
formatMatchInput2,
isMatchHappening,
} from '../../interfaces/match';
import { RoundInterface } from '../../interfaces/round';
import { Round } from '../../interfaces/round';
import { TournamentMinimal } from '../../interfaces/tournament';
import { getMatchLookup, getStageItemLookup } from '../../services/lookups';
import MatchModal from '../modals/match_modal';
@@ -56,7 +56,7 @@ export default function Match({
match: MatchInterface;
readOnly: boolean;
round: RoundInterface;
round: Round;
}) {
const { t } = useTranslation();
const theme = useMantineTheme();

View File

@@ -8,12 +8,12 @@ import {
isMatchHappening,
isMatchInTheFutureOrPresent,
} from '../../interfaces/match';
import { RoundInterface } from '../../interfaces/round';
import { Round } from '../../interfaces/round';
import { TournamentMinimal } from '../../interfaces/tournament';
import RoundModal from '../modals/round_modal';
import Match from './match';
export default function Round({
export default function RoundComponent({
tournamentData,
round,
swrStagesResponse,
@@ -22,7 +22,7 @@ export default function Round({
displaySettings,
}: {
tournamentData: TournamentMinimal;
round: RoundInterface;
round: Round;
swrStagesResponse: SWRResponse;
swrUpcomingMatchesResponse: SWRResponse | null;
readOnly: boolean;

View File

@@ -22,7 +22,6 @@ import { useTranslation } from 'react-i18next';
import { BiSolidWrench } from 'react-icons/bi';
import { SWRResponse } from 'swr';
import { Ranking } from '../../interfaces/ranking';
import { StageWithStageItems } from '../../interfaces/stage';
import { StageItemWithRounds } from '../../interfaces/stage_item';
import {
@@ -31,7 +30,7 @@ import {
StageItemInputOption,
formatStageItemInputTentative,
} from '../../interfaces/stage_item_input';
import { Tournament } from '../../interfaces/tournament';
import { Ranking, StageItemInputOptionsResponse, Tournament } from '../../openapi';
import { getStageItemLookup, getTeamsLookup } from '../../services/lookups';
import { deleteStage } from '../../services/stage';
import { deleteStageItem } from '../../services/stage_item';
@@ -469,7 +468,7 @@ export default function Builder({
}: {
tournament: Tournament;
swrStagesResponse: SWRResponse;
swrAvailableInputsResponse: SWRResponse;
swrAvailableInputsResponse: SWRResponse<StageItemInputOptionsResponse>;
swrRankingsPerStageItemResponse: SWRResponse;
rankings: Ranking[];
}) {

View File

@@ -4,7 +4,7 @@ import React from 'react';
import { useTranslation } from 'react-i18next';
import { SWRResponse } from 'swr';
import { Tournament } from '../../interfaces/tournament';
import { Tournament } from '../../openapi';
import { createStage } from '../../services/stage';
export default function CreateStageButton({

View File

@@ -3,7 +3,7 @@ import React from 'react';
import { useTranslation } from 'react-i18next';
import { SWRResponse } from 'swr';
import { Tournament } from '../../interfaces/tournament';
import { Tournament } from '../../openapi';
import { getBaseApiUrl } from '../../services/adapter';
import { EmptyTableInfo } from '../no_content/empty_table_info';
import { DateTime } from '../utils/datetime';

View File

@@ -12,7 +12,7 @@ import React from 'react';
import QRCode from 'react-qr-code';
import { useLocation, useNavigate } from 'react-router';
import { Tournament } from '../../interfaces/tournament';
import { Tournament } from '../../openapi';
import { getBaseApiUrl } from '../../services/adapter';
import PreloadLink from '../utils/link';
import { getBaseURL } from '../utils/util';
@@ -77,7 +77,7 @@ export function TournamentTitle({ tournamentDataFull }: { tournamentDataFull: To
export function DoubleHeader({ tournamentData }: { tournamentData: Tournament }) {
const navigate = useLocation();
const endpoint = tournamentData.dashboard_endpoint;
const endpoint = tournamentData.dashboard_endpoint || '';
const pathName = navigate.pathname.replace('[id]', endpoint).replace(/\/+$/, '');
const mainLinks = [

View File

@@ -5,12 +5,12 @@ import { IconHash, IconLogout, IconUser } from '@tabler/icons-react';
import React from 'react';
import { useNavigate } from 'react-router';
import { UserInterface } from '../../interfaces/user';
import { UserPublic } from '../../openapi';
import { performLogoutAndRedirect } from '../../services/local_storage';
import { updatePassword, updateUser } from '../../services/user';
import { PasswordStrength } from '../utils/password';
export default function UserForm({ user, t, i18n }: { user: UserInterface; t: any; i18n: any }) {
export default function UserForm({ user, t, i18n }: { user: UserPublic; t: any; i18n: any }) {
const navigate = useNavigate();
const details_form = useForm({
initialValues: {

View File

@@ -1,8 +1,8 @@
import { Text } from '@mantine/core';
import { TeamInterface } from '../../interfaces/team';
import { FullTeamWithPlayers } from '../../openapi';
export default function PlayerList({ team }: { team: TeamInterface }) {
export default function PlayerList({ team }: { team: FullTeamWithPlayers }) {
const getPlayerNames = () =>
team.players
.map((p) => p.name)

View File

@@ -8,13 +8,13 @@ import { SWRResponse } from 'swr';
import { StageItemWithRounds } from '../../interfaces/stage_item';
import { StageItemInput, formatStageItemInput } from '../../interfaces/stage_item_input';
import { TeamInterface } from '../../interfaces/team';
import { FullTeamWithPlayers } from '../../openapi';
import { getStageItemLookup } from '../../services/lookups';
import { activateNextStage } from '../../services/stage';
import RequestErrorAlert from '../utils/error_alert';
import { GenericSkeleton } from '../utils/skeletons';
type Update = { stage_item_input: StageItemInput; team: TeamInterface };
type Update = { stage_item_input: StageItemInput; team: FullTeamWithPlayers };
type StageItemUpdate = { updates: Update[]; stageItem: StageItemWithRounds };
function UpdatesToStageItemInputsTable({

View File

@@ -5,6 +5,7 @@ import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { SWRResponse } from 'swr';
import { StageRankingResponse } from '../../openapi';
import { activateNextStage } from '../../services/stage';
export default function ActivatePreviousStageModal({
@@ -14,7 +15,7 @@ export default function ActivatePreviousStageModal({
}: {
tournamentId: number;
swrStagesResponse: SWRResponse;
swrRankingsPerStageItemResponse: SWRResponse;
swrRankingsPerStageItemResponse: SWRResponse<StageRankingResponse>;
}) {
const { t } = useTranslation();
const [opened, setOpened] = useState(false);

View File

@@ -17,7 +17,7 @@ import { useTranslation } from 'react-i18next';
import { SWRResponse } from 'swr';
import { StageWithStageItems } from '../../interfaces/stage';
import { Tournament } from '../../interfaces/tournament';
import { Tournament } from '../../openapi';
import { getStageItemLookup, getTeamsLookup } from '../../services/lookups';
import { createStageItem } from '../../services/stage_item';
import { Translator } from '../utils/types';

View File

@@ -10,7 +10,7 @@ import {
formatMatchInput1,
formatMatchInput2,
} from '../../interfaces/match';
import { RoundInterface } from '../../interfaces/round';
import { Round } from '../../interfaces/round';
import { TournamentMinimal } from '../../interfaces/tournament';
import { getMatchLookup, getStageItemLookup } from '../../services/lookups';
import { deleteMatch, updateMatch } from '../../services/match';
@@ -56,7 +56,7 @@ function MatchModalForm({
swrStagesResponse: SWRResponse;
swrUpcomingMatchesResponse: SWRResponse | null;
setOpened: any;
round: RoundInterface | null;
round: Round | null;
}) {
if (match == null) {
return null;
@@ -211,7 +211,7 @@ export default function MatchModal({
swrUpcomingMatchesResponse: SWRResponse | null;
opened: boolean;
setOpened: any;
round: RoundInterface | null;
round: Round | null;
}) {
const { t } = useTranslation();

View File

@@ -5,7 +5,7 @@ import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { SWRResponse } from 'swr';
import { Player } from '../../interfaces/player';
import { Player } from '../../openapi';
import { updatePlayer } from '../../services/player';
export default function PlayerUpdateModal({

View File

@@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next';
import { LuConstruction } from 'react-icons/lu';
import { SWRResponse } from 'swr';
import { RoundInterface } from '../../interfaces/round';
import { Round } from '../../interfaces/round';
import { TournamentMinimal } from '../../interfaces/tournament';
import { deleteRound, updateRound } from '../../services/round';
import DeleteButton from '../buttons/delete';
@@ -18,7 +18,7 @@ function RoundDeleteButton({
swrUpcomingMatchesResponse,
}: {
tournamentData: TournamentMinimal;
round: RoundInterface;
round: Round;
swrStagesResponse: SWRResponse;
swrUpcomingMatchesResponse: SWRResponse | null;
}) {
@@ -45,7 +45,7 @@ export default function RoundModal({
swrUpcomingMatchesResponse,
}: {
tournamentData: TournamentMinimal;
round: RoundInterface;
round: Round;
swrStagesResponse: SWRResponse;
swrUpcomingMatchesResponse: SWRResponse | null;
}) {

View File

@@ -5,7 +5,7 @@ import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { SWRResponse } from 'swr';
import { Player } from '../../interfaces/player';
import { Player } from '../../openapi';
import { getPlayers } from '../../services/adapter';
import { createTeam, createTeams } from '../../services/team';
import SaveButton from '../buttons/save';

View File

@@ -14,8 +14,7 @@ import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { SWRResponse } from 'swr';
import { Player } from '../../interfaces/player';
import { TeamInterface } from '../../interfaces/team';
import { FullTeamWithPlayers, Player } from '../../openapi';
import {
getBaseApiUrl,
getPlayers,
@@ -25,7 +24,7 @@ import {
import { updateTeam } from '../../services/team';
import { DropzoneButton } from '../utils/file_upload';
function TeamLogo({ team }: { team: TeamInterface | null }) {
function TeamLogo({ team }: { team: FullTeamWithPlayers | null }) {
if (team == null || team.logo_path == null) return null;
return (
<Image
@@ -42,7 +41,7 @@ export default function TeamUpdateModal({
swrTeamsResponse,
}: {
tournament_id: number;
team: TeamInterface;
team: FullTeamWithPlayers;
swrTeamsResponse: SWRResponse;
}) {
const { t } = useTranslation();

View File

@@ -16,8 +16,7 @@ import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { SWRResponse } from 'swr';
import { Tournament } from '../../interfaces/tournament';
import { Club } from '../../openapi';
import { Club, Tournament } from '../../openapi';
import { getBaseApiUrl, getClubs } from '../../services/adapter';
import { createTournament } from '../../services/tournament';
import SaveButton from '../buttons/save';

View File

@@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next';
import { SWRResponse } from 'swr';
import { StageWithStageItems } from '../../interfaces/stage';
import { Tournament } from '../../interfaces/tournament';
import { Tournament } from '../../openapi';
import { updateStage } from '../../services/stage';
export function UpdateStageModal({

View File

@@ -4,9 +4,8 @@ import React from 'react';
import { useTranslation } from 'react-i18next';
import { SWRResponse } from 'swr';
import { Ranking } from '../../interfaces/ranking';
import { StageItemWithRounds } from '../../interfaces/stage_item';
import { Tournament } from '../../interfaces/tournament';
import { Ranking, Tournament } from '../../openapi';
import { updateStageItem } from '../../services/stage_item';
import { RankingSelect } from '../select/ranking_select';

View File

@@ -3,9 +3,9 @@ import React from 'react';
import { SWRResponse } from 'swr';
import { SchedulerSettings } from '../../interfaces/match';
import { RoundInterface } from '../../interfaces/round';
import { Round } from '../../interfaces/round';
import { StageWithStageItems } from '../../interfaces/stage';
import { Tournament } from '../../interfaces/tournament';
import { Tournament } from '../../openapi';
import UpcomingMatchesTable from '../tables/upcoming_matches';
import SwissSettings, { getSwissRoundSchedulingProgress } from './settings/ladder_fixed';
@@ -19,7 +19,7 @@ export default function Scheduler({
schedulerSettings,
}: {
activeStage: StageWithStageItems;
draftRound: RoundInterface;
draftRound: Round;
tournamentData: Tournament;
swrStagesResponse: SWRResponse;
swrUpcomingMatchesResponse: SWRResponse;

View File

@@ -5,14 +5,11 @@ import { useTranslation } from 'react-i18next';
import { SWRResponse } from 'swr';
import { SchedulerSettings } from '../../../interfaces/match';
import { RoundInterface } from '../../../interfaces/round';
import { Round } from '../../../interfaces/round';
export type SchedulingProgress = { courtsCount: number; scheduledMatchesCount: number };
export function getSwissRoundSchedulingProgress(
draftRound: RoundInterface,
swrCourtsResponse: SWRResponse
) {
export function getSwissRoundSchedulingProgress(draftRound: Round, swrCourtsResponse: SWRResponse) {
return {
courtsCount: swrCourtsResponse.data?.data?.length || 0,
scheduledMatchesCount: draftRound?.matches.length,

View File

@@ -2,7 +2,7 @@ import { Select } from '@mantine/core';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Ranking } from '../../interfaces/ranking';
import { Ranking } from '../../openapi';
export function RankingSelect({ form, rankings }: { form: any; rankings: Ranking[] }) {
const { t } = useTranslation();

View File

@@ -3,8 +3,8 @@ import React from 'react';
import { useTranslation } from 'react-i18next';
import { SWRResponse } from 'swr';
import { Player } from '../../interfaces/player';
import { TournamentMinimal } from '../../interfaces/tournament';
import { Player } from '../../openapi';
import { deletePlayer } from '../../services/player';
import DeleteButton from '../buttons/delete';
import PlayerUpdateModal from '../modals/player_update_modal';

View File

@@ -3,8 +3,8 @@ import React from 'react';
import { useTranslation } from 'react-i18next';
import { SWRResponse } from 'swr';
import { TeamInterface } from '../../interfaces/team';
import { TournamentMinimal } from '../../interfaces/tournament';
import { FullTeamWithPlayers } from '../../openapi';
import { deleteTeam } from '../../services/team';
import DeleteButton from '../buttons/delete';
import PlayerList from '../info/player_list';
@@ -24,7 +24,7 @@ export default function TeamsTable({
}: {
tournamentData: TournamentMinimal;
swrTeamsResponse: SWRResponse;
teams: TeamInterface[];
teams: FullTeamWithPlayers[];
tableState: TableState;
teamCount: number;
}) {
@@ -36,7 +36,9 @@ export default function TeamsTable({
}
const rows = teams
.sort((p1: TeamInterface, p2: TeamInterface) => sortTableEntries(p1, p2, tableState))
.sort((p1: FullTeamWithPlayers, p2: FullTeamWithPlayers) =>
sortTableEntries(p1, p2, tableState)
)
.map((team) => (
<Table.Tr key={team.id}>
<Table.Td>

View File

@@ -7,8 +7,8 @@ import { FaCheck } from 'react-icons/fa6';
import { SWRResponse } from 'swr';
import { MatchCreateBodyInterface, UpcomingMatchInterface } from '../../interfaces/match';
import { RoundInterface } from '../../interfaces/round';
import { Tournament } from '../../interfaces/tournament';
import { Round } from '../../interfaces/round';
import { Tournament } from '../../openapi';
import { createMatch } from '../../services/match';
import { updateRound } from '../../services/round';
import { NoContent } from '../no_content/empty_table_info';
@@ -21,7 +21,7 @@ export default function UpcomingMatchesTable({
swrStagesResponse,
swrUpcomingMatchesResponse,
}: {
draftRound: RoundInterface;
draftRound: Round;
tournamentData: Tournament;
swrStagesResponse: SWRResponse;
swrUpcomingMatchesResponse: SWRResponse;

View File

@@ -6,8 +6,7 @@ import { useMemo, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { SWRResponse } from 'swr';
import { TeamInterface } from '../../interfaces/team';
import { Tournament } from '../../interfaces/tournament';
import { FullTeamWithPlayers, Tournament } from '../../openapi';
import { handleRequestError, uploadTeamLogo, uploadTournamentLogo } from '../../services/adapter';
export function DropzoneButton({
@@ -19,7 +18,7 @@ export function DropzoneButton({
tournamentId: Tournament['id'];
swrResponse: SWRResponse;
variant: 'tournament' | 'team';
teamId?: TeamInterface['id'];
teamId?: FullTeamWithPlayers['id'];
}) {
// const { classes, theme } = useStyles();
const openRef = useRef<() => void>(null);

View File

@@ -1,12 +0,0 @@
export interface Player {
id: number;
name: string;
active: boolean;
created: string;
tournament_id: number;
elo_score: number;
swiss_score: number;
wins: number;
draws: number;
losses: number;
}

View File

@@ -1,10 +0,0 @@
export interface Ranking {
id: number;
tournament_id: number;
created: string;
win_points: number;
draw_points: number;
loss_points: number;
add_score_points: boolean;
position: number;
}

View File

@@ -1,6 +1,6 @@
import { MatchInterface } from './match';
export interface RoundInterface {
export interface Round {
id: number;
stage_item_id: number;
created: string;

View File

@@ -1,4 +1,4 @@
import { RoundInterface } from './round';
import { Round } from './round';
import { StageItemInput } from './stage_item_input';
export interface StageItemWithRounds {
@@ -8,7 +8,7 @@ export interface StageItemWithRounds {
name: string;
type_name: string;
team_count: number;
rounds: RoundInterface[];
rounds: Round[];
inputs: StageItemInput[];
stage_id: number;
}

View File

@@ -1,5 +1,5 @@
import { assert_not_none } from '../components/utils/assert';
import { TeamInterface } from './team';
import { FullTeamWithPlayers } from '../openapi';
export interface StageItemInput {
id: number;
@@ -11,7 +11,7 @@ export interface StageItemInput {
losses: number;
points: number;
team_id: number | null;
team: TeamInterface | null;
team: FullTeamWithPlayers | null;
winner_from_stage_item_id: number | null;
winner_position: number | null;
}
@@ -26,7 +26,7 @@ export interface StageItemInputFinal {
losses: number;
points: number;
team_id: number;
team: TeamInterface;
team: FullTeamWithPlayers;
winner_from_stage_item_id: number | null;
winner_position: number | null;
}

View File

@@ -1,15 +0,0 @@
import { Player } from './player';
export interface TeamInterface {
id: number;
name: string;
created: string;
active: boolean;
players: Player[];
elo_score: number;
swiss_score: number;
wins: number;
draws: number;
losses: number;
logo_path: string;
}

View File

@@ -2,21 +2,6 @@ export type TournamentStatus = 'OPEN' | 'ARCHIVED';
export type TournamentFilter = 'ALL' | TournamentStatus;
export interface Tournament {
id: number;
name: string;
created: string;
start_time: string;
club_id: number;
dashboard_public: boolean;
dashboard_endpoint: string;
players_can_be_in_multiple_teams: boolean;
auto_assign_courts: boolean;
logo_path: string;
duration_minutes: number;
margin_minutes: number;
status: TournamentStatus;
}
export interface TournamentMinimal {
id: number;
}

View File

@@ -1,17 +0,0 @@
export interface UserInterface {
id: number;
created: string;
name: string;
email: string;
}
export interface UserBodyInterface {
name: string;
email: string;
}
export interface UserToRegisterInterface {
name: string;
email: string;
password: string;
}

View File

@@ -10,8 +10,7 @@ import RequestErrorAlert from '../../../components/utils/error_alert';
import { TableSkeletonSingleColumn } from '../../../components/utils/skeletons';
import { Translator } from '../../../components/utils/types';
import { getTournamentIdFromRouter } from '../../../components/utils/util';
import { Ranking } from '../../../interfaces/ranking';
import { Tournament } from '../../../interfaces/tournament';
import { Ranking, Tournament } from '../../../openapi';
import { getRankings, getTournamentById } from '../../../services/adapter';
import { createRanking, deleteRanking, editRanking } from '../../../services/ranking';
import TournamentLayout from '../_tournament_layout';
@@ -172,10 +171,14 @@ export default function RankingsPage() {
const swrRankingsResponse = getRankings(tournamentData.id);
const swrTournamentResponse = getTournamentById(tournamentData.id);
const tournamentDataFull =
swrTournamentResponse.data != null ? swrTournamentResponse.data.data : null;
const tournamentDataFull = swrTournamentResponse.data?.data;
const { t } = useTranslation();
// TODO: show loading icon.
if (tournamentDataFull == null) {
return null;
}
return (
<TournamentLayout tournament_id={tournamentData.id}>
<Container maw="50rem">

View File

@@ -30,8 +30,7 @@ import { assert_not_none } from '../../../components/utils/assert';
import { DropzoneButton } from '../../../components/utils/file_upload';
import { GenericSkeletonThreeRows } from '../../../components/utils/skeletons';
import { capitalize, getBaseURL, getTournamentIdFromRouter } from '../../../components/utils/util';
import { Tournament } from '../../../interfaces/tournament';
import { Club } from '../../../openapi';
import { Club, Tournament, TournamentResponse } from '../../../openapi';
import {
getBaseApiUrl,
getClubs,
@@ -65,7 +64,7 @@ function ArchiveTournamentButton({
}: {
t: any;
tournament: Tournament;
swrTournamentResponse: SWRResponse;
swrTournamentResponse: SWRResponse<TournamentResponse>;
}) {
return (
<Button
@@ -93,7 +92,7 @@ function UnarchiveTournamentButton({
}: {
t: any;
tournament: Tournament;
swrTournamentResponse: SWRResponse;
swrTournamentResponse: SWRResponse<TournamentResponse>;
}) {
return (
<Button
@@ -120,7 +119,7 @@ function GeneralTournamentForm({
clubs,
}: {
tournament: Tournament;
swrTournamentResponse: SWRResponse;
swrTournamentResponse: SWRResponse<TournamentResponse>;
clubs: Club[];
}) {
const navigate = useNavigate();

View File

@@ -9,8 +9,8 @@ import ActivatePreviousStageModal from '../../../../components/modals/activate_p
import { NoContent } from '../../../../components/no_content/empty_table_info';
import { TableSkeletonTwoColumnsSmall } from '../../../../components/utils/skeletons';
import { getTournamentIdFromRouter } from '../../../../components/utils/util';
import { Ranking } from '../../../../interfaces/ranking';
import { StageWithStageItems } from '../../../../interfaces/stage';
import { Ranking } from '../../../../openapi';
import {
getAvailableStageItemInputs,
getRankings,
@@ -30,7 +30,7 @@ export default function StagesPage() {
const swrRankingsPerStageItemResponse = getRankingsPerStageItem(tournamentData.id);
const tournamentDataFull =
swrTournamentResponse.data != null ? swrTournamentResponse.data.data : null;
const rankings: Ranking[] = swrRankingsResponse.data != null ? swrRankingsResponse.data.data : [];
const rankings = swrRankingsResponse.data != null ? swrRankingsResponse.data.data : [];
const stages: StageWithStageItems[] =
swrStagesResponse.data != null ? swrStagesResponse.data.data : [];
@@ -43,6 +43,9 @@ export default function StagesPage() {
swrRankingsResponse.isLoading
) {
content = <TableSkeletonTwoColumnsSmall />;
} else if (tournamentDataFull == null) {
// TODO: show loading icon.
return null;
} else if (stages.length < 1) {
content = (
<Stack align="center">

View File

@@ -20,9 +20,9 @@ import {
} from '../../../../../components/utils/util';
import { BracketDisplaySettings } from '../../../../../interfaces/brackets';
import { SchedulerSettings } from '../../../../../interfaces/match';
import { RoundInterface } from '../../../../../interfaces/round';
import { Round } from '../../../../../interfaces/round';
import { getStageById } from '../../../../../interfaces/stage';
import { Tournament } from '../../../../../interfaces/tournament';
import { Tournament } from '../../../../../openapi';
import {
checkForAuthError,
getCourts,
@@ -107,8 +107,7 @@ export default function SwissTournamentPage() {
setIterations,
};
const tournamentDataFull =
swrTournamentResponse.data != null ? swrTournamentResponse.data.data : null;
const tournamentDataFull = swrTournamentResponse.data?.data;
let activeStage = null;
let draftRound = null;
@@ -120,7 +119,7 @@ export default function SwissTournamentPage() {
if (activeStage != null && activeStage.stage_items != null) {
const draftRounds = stageItem.rounds.filter(
(round: RoundInterface) => round.stage_item_id === stageItemId && round.is_draft
(round: Round) => round.stage_item_id === stageItemId && round.is_draft
);
if (draftRounds != null && draftRounds.length > 0) {
@@ -144,6 +143,9 @@ export default function SwissTournamentPage() {
if (!swrTournamentResponse.isLoading && tournamentDataFull == null) {
return <NotFoundTitle />;
} else if (tournamentDataFull == null) {
// TODO: show loading icon.
return null;
}
if (

View File

@@ -12,7 +12,7 @@ import {
} from '../../../components/utils/util';
import { StageItemWithRounds } from '../../../interfaces/stage_item';
import { StageItemInput } from '../../../interfaces/stage_item_input';
import { TeamInterface } from '../../../interfaces/team';
import { FullTeamWithPlayers } from '../../../openapi';
import { getStages, getTeamsPaginated } from '../../../services/adapter';
import { getStageItemList, getStageItemTeamIdsLookup } from '../../../services/lookups';
import TournamentLayout from '../_tournament_layout';
@@ -56,7 +56,7 @@ export default function TeamsPage() {
? getStageItemTeamIdsLookup(swrStagesResponse)
: {};
let teams: TeamInterface[] =
let teams: FullTeamWithPlayers[] =
swrTeamsResponse.data != null ? swrTeamsResponse.data.data.teams : [];
const teamCount = swrTeamsResponse.data != null ? swrTeamsResponse.data.data.count : 1;

View File

@@ -21,7 +21,7 @@ export default function TournamentLayout({ children, tournament_id }: any) {
/
</Title>
<Title order={2} maw="20rem" lineClamp={1}>
{tournamentResponse.data.data.name}
{tournamentResponse.data?.data.name}
</Title>
<Tooltip label={`${t('archived_header_label')}`}>
@@ -29,7 +29,7 @@ export default function TournamentLayout({ children, tournament_id }: any) {
color="yellow"
variant="light"
style={{
visibility: tournamentResponse.data.data.status === 'ARCHIVED' ? 'visible' : 'hidden',
visibility: tournamentResponse.data?.data.status === 'ARCHIVED' ? 'visible' : 'hidden',
}}
>
<HiArchiveBoxArrowDown />

View File

@@ -5,12 +5,20 @@ import useSWR, { SWRResponse } from 'swr';
import { Pagination } from '../components/utils/util';
import { SchedulerSettings } from '../interfaces/match';
import { RoundInterface } from '../interfaces/round';
import { Round } from '../interfaces/round';
import { TournamentFilter } from '../interfaces/tournament';
import {
ClubsResponse,
CourtsResponse,
GetClubsClubsGetResponses,
GetTournamentsTournamentsGetResponse,
PlayersResponse,
RankingsResponse,
StageItemInputOptionsResponse,
StageRankingResponse,
TournamentResponse,
TournamentsResponse,
UserPublicResponse,
getClubsClubsGet,
} from '../openapi';
import { RequestResult } from '../openapi/client';
@@ -114,22 +122,28 @@ export function getTournamentByEndpointName(tournament_endpoint_name: string): S
return useSWR(`tournaments?endpoint_name=${tournament_endpoint_name}`, fetcher);
}
export function getTournamentById(tournament_id: number): SWRResponse {
export function getTournamentById(tournament_id: number): SWRResponse<TournamentResponse> {
return useSWR(`tournaments/${tournament_id}`, fetcher);
}
export function getTournaments(filter: TournamentFilter): SWRResponse {
export function getTournaments(filter: TournamentFilter): SWRResponse<TournamentsResponse> {
return useSWR(`tournaments?filter_=${filter}`, fetcher);
}
export function getPlayers(tournament_id: number, not_in_team: boolean = false): SWRResponse {
export function getPlayers(
tournament_id: number,
not_in_team: boolean = false
): SWRResponse<PlayersResponse> {
return useSWR(
`tournaments/${tournament_id}/players?not_in_team=${not_in_team}&limit=100`,
fetcher
);
}
export function getPlayersPaginated(tournament_id: number, pagination: Pagination): SWRResponse {
export function getPlayersPaginated(
tournament_id: number,
pagination: Pagination
): SWRResponse<PlayersResponse> {
return useSWR(
`tournaments/${tournament_id}/players?limit=${pagination.limit}&offset=${pagination.offset}&sort_by=${pagination.sort_by}&sort_direction=${pagination.sort_direction}`,
fetcher
@@ -156,7 +170,9 @@ export function getTeamsLive(tournament_id: number | null): SWRResponse {
});
}
export function getAvailableStageItemInputs(tournament_id: number): SWRResponse {
export function getAvailableStageItemInputs(
tournament_id: number
): SWRResponse<StageItemInputOptionsResponse> {
return useSWR(`tournaments/${tournament_id}/available_inputs`, fetcher);
}
@@ -182,11 +198,11 @@ export function getStagesLive(tournament_id: number | null): SWRResponse {
);
}
export function getRankings(tournament_id: number): SWRResponse {
export function getRankings(tournament_id: number): SWRResponse<RankingsResponse> {
return useSWR(`tournaments/${tournament_id}/rankings`, fetcher);
}
export function getRankingsPerStageItem(tournament_id: number): SWRResponse {
export function getRankingsPerStageItem(tournament_id: number): SWRResponse<StageRankingResponse> {
return useSWR(`tournaments/${tournament_id}/next_stage_rankings`, fetcher);
}
@@ -194,20 +210,20 @@ export function getCourts(tournament_id: number): SWRResponse<CourtsResponse> {
return useSWR(`tournaments/${tournament_id}/courts`, fetcher);
}
export function getCourtsLive(tournament_id: number): SWRResponse {
export function getCourtsLive(tournament_id: number): SWRResponse<CourtsResponse> {
return useSWR(`tournaments/${tournament_id}/courts`, fetcher, {
refreshInterval: 60_000,
});
}
export function getUser(): SWRResponse {
export function getUser(): SWRResponse<UserPublicResponse> {
return useSWR('users/me', fetcher);
}
export function getUpcomingMatches(
tournament_id: number,
stage_item_id: number,
draftRound: RoundInterface | null,
draftRound: Round | null,
schedulerSettings: SchedulerSettings
): SWRResponse {
return useSWR(

View File

@@ -4,8 +4,7 @@ import { assert_not_none } from '../components/utils/assert';
import { groupBy, responseIsValid } from '../components/utils/util';
import { MatchInterface } from '../interfaces/match';
import { StageWithStageItems } from '../interfaces/stage';
import { TeamInterface } from '../interfaces/team';
import { Court } from '../openapi';
import { Court, FullTeamWithPlayers } from '../openapi';
import { getTeams } from './adapter';
export function getTeamsLookup(tournamentId: number) {
@@ -15,7 +14,9 @@ export function getTeamsLookup(tournamentId: number) {
if (!isResponseValid) {
return null;
}
return Object.fromEntries(swrTeamsResponse.data.data.teams.map((x: TeamInterface) => [x.id, x]));
return Object.fromEntries(
swrTeamsResponse.data.data.teams.map((x: FullTeamWithPlayers) => [x.id, x])
);
}
export function getStageItemLookup(swrStagesResponse: SWRResponse) {

View File

@@ -9,9 +9,9 @@ export async function createRanking(tournament_id: number) {
export async function editRanking(
tournament_id: number,
ranking_id: number,
win_points: number,
draw_points: number,
loss_points: number,
win_points: string,
draw_points: string,
loss_points: string,
add_score_points: boolean,
position: number
) {

View File

@@ -43,7 +43,7 @@ export async function updateTournament(
tournament_id: number,
name: string,
dashboard_public: boolean,
dashboard_endpoint: string,
dashboard_endpoint: string | null | undefined,
players_can_be_in_multiple_teams: boolean,
auto_assign_courts: boolean,
start_time: string,

View File

@@ -1,4 +1,4 @@
import { UserBodyInterface, UserToRegisterInterface } from '../interfaces/user';
import { UserToRegister, UserToUpdate } from '../openapi';
import { createAxios, handleRequestError } from './adapter';
export async function performLogin(username: string, password: string) {
@@ -27,7 +27,7 @@ export async function performLogin(username: string, password: string) {
return true;
}
export async function updateUser(user_id: number, user: UserBodyInterface) {
export async function updateUser(user_id: number, user: UserToUpdate) {
return createAxios()
.put(`users/${user_id}`, user)
.catch((response: any) => handleRequestError(response));
@@ -39,7 +39,7 @@ export async function updatePassword(user_id: number, password: string) {
.catch((response: any) => handleRequestError(response));
}
export async function registerUser(user: UserToRegisterInterface, captchaToken: string | null) {
export async function registerUser(user: UserToRegister, captchaToken: string | null) {
return createAxios()
.post('users/register', {
email: user.email,