Skip to content

Commit

Permalink
Tournament form convered over to new format
Browse files Browse the repository at this point in the history
  • Loading branch information
kyle-flynn committed Mar 22, 2024
1 parent 50a7e7f commit 1430ef6
Show file tree
Hide file tree
Showing 11 changed files with 312 additions and 14 deletions.
16 changes: 15 additions & 1 deletion front-end/src/AppRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,17 @@ const TeamEditor = lazy(() =>
import('./apps/teams').then((m) => ({ default: m.TeamEdior }))
);

// Tournament Routes
const TournamentManager = lazy(() =>
import('./apps/tournaments').then((m) => ({ default: m.TournamentManager }))
);
const TournamentEditor = lazy(() =>
import('./apps/tournaments').then((m) => ({ default: m.TournamentEditor }))
);

const SettingsApp = lazy(() => import('./apps/Settings'));
const GlobalSettingsApp = lazy(() => import('./apps/Settings/GlobalSettings'));

const TournamentManager = lazy(() => import('./apps/TournamentManager'));
const MatchManager = lazy(() => import('./apps/MatchManager'));
const ScoringApp = lazy(() => import('./apps/Scoring'));
const AudienceDisplay = lazy(() => import('./apps/AudienceDisplay'));
Expand Down Expand Up @@ -120,6 +127,13 @@ const AppRoutes: AppRoute[] = [
element: TournamentManager,
icon: <HomeIcon />
},
{
name: 'Tournament Editor',
path: '/:eventKey/tournament-manager/edit/:tournamentKey',
group: 0,
element: TournamentEditor,
icon: <HomeIcon />
},
{
name: 'Match Manager',
path: '/:eventKey/match-manager',
Expand Down
10 changes: 8 additions & 2 deletions front-end/src/api/use-tournament-data.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { clientFetcher } from '@toa-lib/client';
import { Tournament } from '@toa-lib/models';
import { apiFetcher, clientFetcher } from '@toa-lib/client';
import { Tournament, tournamentZod } from '@toa-lib/models';
import useSWR from 'swr';

export const postTournaments = async (
tournaments: Tournament[]
Expand All @@ -11,3 +12,8 @@ export const patchTournament = async (tournament: Tournament): Promise<void> =>
'POST',
tournament
);

export const useTournamentsForEvent = (eventKey: string | null | undefined) =>
useSWR<Tournament[]>(eventKey ? `tournament/${eventKey}` : undefined, (url) =>
apiFetcher(url, 'GET', undefined, tournamentZod.array().parse)
);
7 changes: 0 additions & 7 deletions front-end/src/apps/teams/team-manager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { patchTeam, postTeams, useTeamsForEvent } from 'src/api/use-team-data';
import ViewReturn from 'src/components/buttons/ViewReturn/ViewReturn';
import TeamRemovalDialog from 'src/components/dialogs/TeamRemovalDialog';
import { PageLoader } from 'src/components/loading/PageLoader';
import { UnsavedChangesEffect } from 'src/components/sync-effects/UnloadEffect';
import { TeamsTable } from 'src/components/tables/teams-table';
import SaveAddUploadLoadingFab from 'src/components/util/SaveAddUploadLoadingFab';
import { useSnackbar } from 'src/hooks/use-snackbar';
Expand All @@ -25,7 +24,6 @@ export const TeamManager: FC = () => {
const [teams, setTeams] = useRecoilState(
teamsByEventKeyAtomFam(event?.eventKey ?? '')
);
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
const [loading, setLoading] = useState(false);

const { showSnackbar } = useSnackbar();
Expand Down Expand Up @@ -68,19 +66,16 @@ export const TeamManager: FC = () => {
{ ...defaultTeam, eventKey, teamKey: teams.length + 1 },
...prev
]);
setHasUnsavedChanges(true);
};

const handleUpload = async (
e: ChangeEvent<HTMLInputElement>
): Promise<void> => {
console.log('ALDKASLDKFJ');
const { files } = e.target;
if (!files || files.length <= 0 || !event) return;
e.preventDefault();
const importedTeams = await parseTeamsFile(files[0], event.eventKey);
setTeams(importedTeams);
setHasUnsavedChanges(true);
};

const handleEdit = (team: Team) => {
Expand All @@ -93,7 +88,6 @@ export const TeamManager: FC = () => {
setTeams((prevTeams) =>
prevTeams.filter((t) => t.teamKey !== team.teamKey)
);
setHasUnsavedChanges(true);
}
};

Expand All @@ -106,7 +100,6 @@ export const TeamManager: FC = () => {
padding
showSettings
>
<UnsavedChangesEffect hasUnsavedChanges={hasUnsavedChanges} />
<ViewReturn title='Home' href={`/${event.eventKey}`} />
<TeamsTable
event={event}
Expand Down
4 changes: 4 additions & 0 deletions front-end/src/apps/tournaments/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { TournamentManager } from './tournament-manager';
import { TournamentEditor } from './tournament-editor';

export { TournamentManager, TournamentEditor };
21 changes: 21 additions & 0 deletions front-end/src/apps/tournaments/tournament-editor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Typography } from '@mui/material';
import { FC } from 'react';
import { useCurrentEvent } from 'src/api/use-event-data';
import { PageLoader } from 'src/components/loading/PageLoader';
import PaperLayout from 'src/layouts/PaperLayout';

export const TournamentEditor: FC = () => {
const { data: event } = useCurrentEvent();
return event ? (
<PaperLayout
containerWidth='xl'
header={<Typography variant='h4'>Tournament Manager</Typography>}
title={`/${event.eventKey} | Tournament Editor`}
titleLink={`/${event.eventKey}/tournament-manager`}
>
<div>Tournament Form Here</div>
</PaperLayout>
) : (
<PageLoader />
);
};
104 changes: 104 additions & 0 deletions front-end/src/apps/tournaments/tournament-manager.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { Typography } from '@mui/material';
import { Tournament, defaultTournament } from '@toa-lib/models';
import { FC, useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useRecoilState } from 'recoil';
import { useCurrentEvent } from 'src/api/use-event-data';
import {
patchTournament,
postTournaments,
useTournamentsForEvent
} from 'src/api/use-tournament-data';
import ViewReturn from 'src/components/buttons/ViewReturn/ViewReturn';
import { PageLoader } from 'src/components/loading/PageLoader';
import { TournamentTable } from 'src/components/tables/tournament-table';
import SaveAddUploadLoadingFab from 'src/components/util/SaveAddUploadLoadingFab';
import { useSnackbar } from 'src/hooks/use-snackbar';
import PaperLayout from 'src/layouts/PaperLayout';
import { getDifferences } from 'src/stores/Util';
import { tournamentsByEventKeyAtomFam } from 'src/stores/recoil';

export const TournamentManager: FC = () => {
const { data: event } = useCurrentEvent();
const { data: initialTournaments } = useTournamentsForEvent(event?.eventKey);

const [tournaments, setTournaments] = useRecoilState(
tournamentsByEventKeyAtomFam(event?.eventKey ?? '')
);
const [loading, setLoading] = useState(false);
const { showSnackbar } = useSnackbar();
const navigate = useNavigate();

useEffect(() => {
if (!event) return;
if (initialTournaments && tournaments.length === 0) {
setTournaments(initialTournaments);
}
}, [initialTournaments]);

const handleSave = async () => {
setLoading(true);
try {
if (!event || !initialTournaments) return;
const diffs = getDifferences(
tournaments,
initialTournaments,
'tournamentKey'
);
if (diffs.additions.length > 0) {
await postTournaments(diffs.additions);
}
for (const tournament of diffs.edits) {
await patchTournament(tournament);
}
setLoading(false);
} catch (e) {
const error = e instanceof Error ? `${e.name} ${e.message}` : String(e);
setLoading(false);
showSnackbar('Error while uploading tournaments.', error);
}
};

const handleAdd = () => {
if (!event) return;
const { eventKey } = event;
setTournaments((prev) => [
...prev,
{ ...defaultTournament, eventKey, tournamentKey: '', name: '' }
]);
};

const handleEdit = (tournament: Tournament) => {
navigate(
`/${event?.eventKey}/tournament-manager/edit/${tournament.tournamentKey}`
);
};

return event && initialTournaments ? (
<PaperLayout
containerWidth='xl'
header={<Typography variant='h4'>Tournament Manager</Typography>}
title={`${event.eventKey} | Tournament Manager`}
titleLink={`/${event.eventKey}`}
padding
>
<ViewReturn title='Home' href={`/${event.eventKey}`} sx={{ mb: 1 }} />
<SaveAddUploadLoadingFab
loading={loading}
onAdd={handleAdd}
onSave={handleSave}
canAdd
canSave
addTooltip='Add Tournament'
saveTooltip='Save Tournaments'
/>
<TournamentTable
event={event}
tournaments={tournaments}
onEdit={handleEdit}
/>
</PaperLayout>
) : (
<PageLoader />
);
};
9 changes: 8 additions & 1 deletion front-end/src/components/Dropdowns/TournamentDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,16 @@ import {
interface Props {
value: number;
fullWidth?: boolean;
disabled?: boolean;
onChange: (value: number) => void;
}

const TournamentDropdown: FC<Props> = ({ value, fullWidth, onChange }) => {
const TournamentDropdown: FC<Props> = ({
value,
fullWidth,
disabled,
onChange
}) => {
const handleChange = (event: SelectChangeEvent) =>
onChange(parseInt(event.target.value));

Expand All @@ -33,6 +39,7 @@ const TournamentDropdown: FC<Props> = ({ value, fullWidth, onChange }) => {
<Select
value={value.toString()}
onChange={handleChange}
disabled={disabled}
label='Tournament'
>
<MenuItem value={TEST_LEVEL.toString()}>Test</MenuItem>
Expand Down
6 changes: 4 additions & 2 deletions front-end/src/components/forms/TournamentForm/Fields.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import { Tournament } from '@toa-lib/models';

interface Props {
tournament: Tournament;
disabled?: boolean;
onUpdate: (fields: string[]) => void;
}

const Fields: FC<Props> = ({ tournament, onUpdate }) => {
const Fields: FC<Props> = ({ tournament, disabled, onUpdate }) => {
const handleAdd = () => {
onUpdate([...tournament.fields, `Field ${tournament.fields.length + 1}`]);
};
Expand All @@ -33,7 +34,7 @@ const Fields: FC<Props> = ({ tournament, onUpdate }) => {
spacing={3}
sx={{ paddingTop: (theme) => theme.spacing(1) }}
>
{tournament.fields.map((f, i) => {
{tournament.fields.map((f: string, i: number) => {
const onChange = (e: ChangeEvent<HTMLInputElement>) => {
updateFieldName(i, e.target.value);
};
Expand All @@ -46,6 +47,7 @@ const Fields: FC<Props> = ({ tournament, onUpdate }) => {
value={tournament.fields[i]}
variant='standard'
type='text'
disabled={disabled}
onChange={onChange}
/>
</FormControl>
Expand Down
Loading

0 comments on commit 1430ef6

Please sign in to comment.