mirror of
https://github.com/evroon/bracket.git
synced 2026-04-28 11:10:53 -04:00
Improve planning page (#895)
This commit is contained in:
@@ -43,7 +43,6 @@
|
||||
"copy_dashboard_url_button": "Dashboard-URL kopieren",
|
||||
"could_not_find_any_alert": "Konnte keine finden",
|
||||
"court_name_input_placeholder": "Bestes Spielfeld aller Zeiten",
|
||||
"court_spotlight_description": "Spielfelder ansehen, hinzufügen oder löschen",
|
||||
"courts_title": "Spielfeld",
|
||||
"create_account_alert_description": "Kontoerstellung ist auf dieser Domain momentan deaktiviert, da sich bracket noch in der Beta-Phase befindet.",
|
||||
"create_account_alert_title": "Nicht verfügbar",
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
"copy_dashboard_url_button": "Copy Dashboard URL",
|
||||
"could_not_find_any_alert": "Could not find any",
|
||||
"court_name_input_placeholder": "Best Court Ever",
|
||||
"court_spotlight_description": "View, add or delete courts",
|
||||
"courts_title": "courts",
|
||||
"create_account_alert_description": "Account creation is disabled on this domain for now since bracket is still in beta phase",
|
||||
"create_account_alert_title": "Unavailable",
|
||||
@@ -152,6 +151,7 @@
|
||||
"next_stage_button": "Next Stage",
|
||||
"no_matches_description": "First, add matches by creating stages and stage items. Then, schedule them using the button in the topright corner.",
|
||||
"no_matches_title": "No matches scheduled yet",
|
||||
"no_courts_title": "No courts yet",
|
||||
"no_players_title": "No players yet",
|
||||
"no_round_description": "There are no rounds in this stage item yet",
|
||||
"no_round_found_description": "Please wait for the organiser to add them.",
|
||||
@@ -194,6 +194,7 @@
|
||||
"save_players_button": "Save players",
|
||||
"save_ranking_button": "Save Ranking",
|
||||
"schedule_description": "Schedule All Unscheduled Matches",
|
||||
"no_courts_description": "No courts have been created yet. First, create the tournament structure by adding stages and stage items. Then, create courts here and schedule matches on these courts.",
|
||||
"schedule_title": "Schedule",
|
||||
"score_of_label": "Score of",
|
||||
"search_placeholder": "Search ...",
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
"copy_dashboard_url_button": "Copiar URL del Tablero",
|
||||
"could_not_find_any_alert": "No se pudo encontrar ninguna",
|
||||
"court_name_input_placeholder": "Mejor tribunal nunca",
|
||||
"court_spotlight_description": "Visualizar, añadir o eliminar tribunales",
|
||||
"courts_title": "cortes",
|
||||
"create_account_alert_description": "La creación de cuenta está desactivada en este dominio por ahora ya que el corchete todavía está en fase beta",
|
||||
"create_account_alert_title": "Unavailable",
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
"copy_dashboard_url_button": "Copier l'URL du tableau de bord",
|
||||
"could_not_find_any_alert": "Aucun résultat trouvé",
|
||||
"court_name_input_placeholder": "Le Meilleur Des Terrains",
|
||||
"court_spotlight_description": "Voir, ajouter ou supprimer des terrains",
|
||||
"courts_title": "Terrains",
|
||||
"create_account_alert_description": "Pour le moment, la création de compte est désactivée sur ce domaine car Bracket est toujours en phase bêta",
|
||||
"create_account_alert_title": "Indisponible",
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
"copy_dashboard_url_button": "Kopieer de Dashboard URL",
|
||||
"could_not_find_any_alert": "Kon er geen vinden",
|
||||
"court_name_input_placeholder": "Beste veld ooit",
|
||||
"court_spotlight_description": "Velden bekijken, toevoegen of verwijderen",
|
||||
"courts_title": "velden",
|
||||
"create_account_alert_description": "Het aanmaken van een account is voorlopig uitgeschakeld op dit domein",
|
||||
"create_account_alert_title": "Niet beschikbaar",
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
"copy_dashboard_url_button": "Copiar URL do painel",
|
||||
"could_not_find_any_alert": "Não foi possível encontrar nenhum",
|
||||
"court_name_input_placeholder": "Melhor Tribunal já",
|
||||
"court_spotlight_description": "Visualizar, adicionar ou excluir tribunais",
|
||||
"courts_title": "Tribunais",
|
||||
"create_account_alert_description": "A criação de conta está desabilitada neste domínio por enquanto já que o parêntese ainda está na fase beta",
|
||||
"create_account_alert_title": "Unavailable",
|
||||
|
||||
@@ -43,7 +43,6 @@
|
||||
"copy_dashboard_url_button": "复制仪表板URL",
|
||||
"could_not_find_any_alert": "找不到任何",
|
||||
"court_name_input_placeholder": "最好的场地",
|
||||
"court_spotlight_description": "查看、添加或删除场地",
|
||||
"courts_title": "场地",
|
||||
"create_account_alert_description": "由于括号仍处于测试阶段,因此暂时禁用了此域上的帐户创建",
|
||||
"create_account_alert_title": "不可用",
|
||||
|
||||
@@ -100,7 +100,7 @@ function StageItemRow({
|
||||
<Menu withinPortal position="bottom-end" shadow="sm">
|
||||
<Menu.Target>
|
||||
<ActionIcon variant="transparent" color="gray">
|
||||
<IconDots size="1.5rem" />
|
||||
<IconDots size="1.25rem" />
|
||||
</ActionIcon>
|
||||
</Menu.Target>
|
||||
|
||||
@@ -190,7 +190,7 @@ function StageColumn({
|
||||
<Menu withinPortal position="bottom-end" shadow="sm">
|
||||
<Menu.Target>
|
||||
<ActionIcon variant="transparent" color="gray">
|
||||
<IconDots size="1rem" />
|
||||
<IconDots size="1.25rem" />
|
||||
</ActionIcon>
|
||||
</Menu.Target>
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ export function NextStageButton({ tournamentData, swrStagesResponse }: any) {
|
||||
return (
|
||||
<Button
|
||||
size="md"
|
||||
style={{ marginBottom: 10 }}
|
||||
mb="10"
|
||||
color="indigo"
|
||||
leftSection={<IconSquareArrowRight size={24} />}
|
||||
onClick={async () => {
|
||||
@@ -29,7 +29,7 @@ export function PreviousStageButton({ tournamentData, swrStagesResponse }: any)
|
||||
return (
|
||||
<Button
|
||||
size="md"
|
||||
style={{ marginBottom: 10 }}
|
||||
mb="10"
|
||||
color="indigo"
|
||||
leftSection={<IconSquareArrowLeft size={24} />}
|
||||
onClick={async () => {
|
||||
|
||||
65
frontend/src/components/modals/create_court_modal.tsx
Normal file
65
frontend/src/components/modals/create_court_modal.tsx
Normal file
@@ -0,0 +1,65 @@
|
||||
import { Button, Modal, TextInput } from '@mantine/core';
|
||||
import { useForm } from '@mantine/form';
|
||||
import { GoPlus } from '@react-icons/all-files/go/GoPlus';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import React, { useState } from 'react';
|
||||
import { SWRResponse } from 'swr';
|
||||
|
||||
import { createCourt } from '../../services/court';
|
||||
|
||||
export default function CourtModal({
|
||||
tournamentId,
|
||||
swrCourtsResponse,
|
||||
buttonSize,
|
||||
}: {
|
||||
buttonSize: 'xs' | 'lg';
|
||||
tournamentId: number;
|
||||
swrCourtsResponse: SWRResponse;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [opened, setOpened] = useState(false);
|
||||
const form = useForm({
|
||||
initialValues: {
|
||||
name: '',
|
||||
},
|
||||
|
||||
validate: {
|
||||
name: (value) => (value.length > 0 ? null : t('too_short_name_validation')),
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal opened={opened} onClose={() => setOpened(false)} title={t('add_court_title')}>
|
||||
<form
|
||||
onSubmit={form.onSubmit(async (values) => {
|
||||
await createCourt(tournamentId, values.name);
|
||||
await swrCourtsResponse.mutate();
|
||||
setOpened(false);
|
||||
})}
|
||||
>
|
||||
<TextInput
|
||||
withAsterisk
|
||||
label={t('name_input_label')}
|
||||
placeholder={t('court_name_input_placeholder')}
|
||||
{...form.getInputProps('name')}
|
||||
/>
|
||||
|
||||
<Button fullWidth style={{ marginTop: 10 }} color="green" type="submit">
|
||||
{t('save_button')}
|
||||
</Button>
|
||||
</form>
|
||||
</Modal>
|
||||
<Button
|
||||
variant="outline"
|
||||
color="green"
|
||||
size={buttonSize}
|
||||
style={{ marginRight: 10 }}
|
||||
onClick={() => setOpened(true)}
|
||||
leftSection={<GoPlus size={24} />}
|
||||
>
|
||||
{t('add_court_title')}
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -203,7 +203,6 @@ export function CreateStageItemModal({
|
||||
variant="outline"
|
||||
color="green"
|
||||
size="xs"
|
||||
style={{ marginRight: 10 }}
|
||||
onClick={() => setOpened(true)}
|
||||
leftSection={<GoPlus size={24} />}
|
||||
>
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
IconScoreboard,
|
||||
IconSearch,
|
||||
IconSettings,
|
||||
IconSoccerField,
|
||||
IconTrophy,
|
||||
IconUser,
|
||||
IconUsers,
|
||||
@@ -84,13 +83,6 @@ export function BracketSpotlight() {
|
||||
onClick: () => router.push(`/tournaments/${tournamentId}/stages`),
|
||||
leftSection: <IconTrophy size="1.2rem" />,
|
||||
},
|
||||
{
|
||||
id: 'courts',
|
||||
title: t('courts_title'),
|
||||
description: t('court_spotlight_description'),
|
||||
onClick: () => router.push(`/tournaments/${tournamentId}/courts`),
|
||||
leftSection: <IconSoccerField size="1.2rem" />,
|
||||
},
|
||||
{
|
||||
id: 'tournament settings',
|
||||
title: t('tournament_setting_title'),
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
IconHome,
|
||||
IconScoreboard,
|
||||
IconSettings,
|
||||
IconSoccerField,
|
||||
IconTrophy,
|
||||
IconUser,
|
||||
IconUsers,
|
||||
@@ -130,11 +129,6 @@ export function TournamentLinks({ tournament_id }: any) {
|
||||
label: capitalize(t('teams_title')),
|
||||
link: `${tm_prefix}/teams`,
|
||||
},
|
||||
{
|
||||
icon: IconSoccerField,
|
||||
label: capitalize(t('courts_title')),
|
||||
link: `${tm_prefix}/courts`,
|
||||
},
|
||||
{
|
||||
icon: IconCalendar,
|
||||
label: capitalize(t('planning_title')),
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
import { Table } from '@mantine/core';
|
||||
import React from 'react';
|
||||
import { SWRResponse } from 'swr';
|
||||
|
||||
import { Court } from '../../interfaces/court';
|
||||
import { Tournament } from '../../interfaces/tournament';
|
||||
import { deleteCourt } from '../../services/court';
|
||||
import DeleteButton from '../buttons/delete';
|
||||
import { EmptyTableInfo } from '../no_content/empty_table_info';
|
||||
import RequestErrorAlert from '../utils/error_alert';
|
||||
import { TableSkeletonSingleColumn } from '../utils/skeletons';
|
||||
import { Translator } from '../utils/types';
|
||||
import TableLayout, { ThNotSortable, getTableState, sortTableEntries } from './table';
|
||||
|
||||
export default function CourtsTable({
|
||||
t,
|
||||
tournament,
|
||||
swrCourtsResponse,
|
||||
}: {
|
||||
t: Translator;
|
||||
tournament: Tournament;
|
||||
swrCourtsResponse: SWRResponse;
|
||||
}) {
|
||||
const courts: Court[] = swrCourtsResponse.data != null ? swrCourtsResponse.data.data : [];
|
||||
const tableState = getTableState('id');
|
||||
|
||||
if (swrCourtsResponse.isLoading) {
|
||||
return <TableSkeletonSingleColumn />;
|
||||
}
|
||||
|
||||
if (swrCourtsResponse.error) return <RequestErrorAlert error={swrCourtsResponse.error} />;
|
||||
|
||||
const rows = courts
|
||||
.sort((s1: Court, s2: Court) => sortTableEntries(s1, s2, tableState))
|
||||
.map((court) => (
|
||||
<Table.Tr key={court.id}>
|
||||
<Table.Td>{court.name}</Table.Td>
|
||||
<Table.Td>
|
||||
<DeleteButton
|
||||
onClick={async () => {
|
||||
await deleteCourt(tournament.id, court.id);
|
||||
await swrCourtsResponse.mutate();
|
||||
}}
|
||||
title={t('delete_court_button')}
|
||||
style={{ float: 'right' }}
|
||||
/>
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
));
|
||||
|
||||
if (rows.length < 1) return <EmptyTableInfo entity_name={t('courts_title')} />;
|
||||
|
||||
return (
|
||||
<TableLayout>
|
||||
<Table.Thead>
|
||||
<Table.Tr>
|
||||
<ThNotSortable>{t('title')}</ThNotSortable>
|
||||
<ThNotSortable>{null}</ThNotSortable>
|
||||
</Table.Tr>
|
||||
</Table.Thead>
|
||||
<Table.Tbody>{rows}</Table.Tbody>
|
||||
</TableLayout>
|
||||
);
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
import { Button, Container, Fieldset, Grid, TextInput } from '@mantine/core';
|
||||
import { useForm } from '@mantine/form';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
|
||||
import React from 'react';
|
||||
import { SWRResponse } from 'swr';
|
||||
|
||||
import CourtsTable from '../../../components/tables/courts';
|
||||
import { Translator } from '../../../components/utils/types';
|
||||
import { getTournamentIdFromRouter } from '../../../components/utils/util';
|
||||
import { Tournament } from '../../../interfaces/tournament';
|
||||
import { getCourts, getTournamentById } from '../../../services/adapter';
|
||||
import { createCourt } from '../../../services/court';
|
||||
import TournamentLayout from '../_tournament_layout';
|
||||
|
||||
function CreateCourtForm(t: Translator, tournament: Tournament, swrCourtsResponse: SWRResponse) {
|
||||
const form = useForm({
|
||||
initialValues: { name: '' },
|
||||
validate: {
|
||||
name: (value) => (value.length > 0 ? null : t('too_short_name_validation')),
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<form
|
||||
onSubmit={form.onSubmit(async (values) => {
|
||||
await createCourt(tournament.id, values.name);
|
||||
await swrCourtsResponse.mutate();
|
||||
})}
|
||||
>
|
||||
<Fieldset legend={t('add_court_title')} radius="md">
|
||||
<TextInput
|
||||
withAsterisk
|
||||
label={t('name_input_label')}
|
||||
placeholder={t('court_name_input_placeholder')}
|
||||
{...form.getInputProps('name')}
|
||||
/>
|
||||
<Button fullWidth style={{ marginTop: 16 }} color="green" type="submit">
|
||||
{t('create_court_button')}
|
||||
</Button>
|
||||
</Fieldset>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
export default function CourtsPage() {
|
||||
const { tournamentData } = getTournamentIdFromRouter();
|
||||
const swrCourtsResponse = getCourts(tournamentData.id);
|
||||
|
||||
const swrTournamentResponse = getTournamentById(tournamentData.id);
|
||||
const tournamentDataFull =
|
||||
swrTournamentResponse.data != null ? swrTournamentResponse.data.data : null;
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<TournamentLayout tournament_id={tournamentData.id}>
|
||||
<Container maw="100rem">
|
||||
<Grid grow>
|
||||
<Grid.Col span={{ lg: 8 }}>
|
||||
<CourtsTable
|
||||
t={t}
|
||||
tournament={tournamentDataFull}
|
||||
swrCourtsResponse={swrCourtsResponse}
|
||||
/>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={{ lg: 4 }}>
|
||||
{CreateCourtForm(t, tournamentDataFull, swrCourtsResponse)}
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</Container>
|
||||
</TournamentLayout>
|
||||
);
|
||||
}
|
||||
|
||||
export const getServerSideProps = async ({ locale }: { locale: string }) => ({
|
||||
props: {
|
||||
...(await serverSideTranslations(locale, ['common'])),
|
||||
},
|
||||
});
|
||||
@@ -1,10 +1,24 @@
|
||||
import { DragDropContext, Draggable, Droppable } from '@hello-pangea/dnd';
|
||||
import { Alert, Badge, Button, Card, Grid, Group, Stack, Text, Title } from '@mantine/core';
|
||||
import { IconAlertCircle, IconCalendarPlus } from '@tabler/icons-react';
|
||||
import {
|
||||
ActionIcon,
|
||||
Alert,
|
||||
Badge,
|
||||
Button,
|
||||
Card,
|
||||
Grid,
|
||||
Group,
|
||||
Menu,
|
||||
Stack,
|
||||
Text,
|
||||
Title,
|
||||
} from '@mantine/core';
|
||||
import { IconAlertCircle, IconCalendarPlus, IconDots, IconTrash } from '@tabler/icons-react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
|
||||
import React, { useState } from 'react';
|
||||
import { SWRResponse } from 'swr';
|
||||
|
||||
import CourtModal from '../../../components/modals/create_court_modal';
|
||||
import MatchModal from '../../../components/modals/match_modal';
|
||||
import { NoContent } from '../../../components/no_content/empty_table_info';
|
||||
import { Time } from '../../../components/utils/datetime';
|
||||
@@ -12,7 +26,9 @@ import { Translator } from '../../../components/utils/types';
|
||||
import { getTournamentIdFromRouter, responseIsValid } from '../../../components/utils/util';
|
||||
import { Court } from '../../../interfaces/court';
|
||||
import { MatchInterface, formatMatchTeam1, formatMatchTeam2 } from '../../../interfaces/match';
|
||||
import { TournamentMinimal } from '../../../interfaces/tournament';
|
||||
import { getCourts, getStages } from '../../../services/adapter';
|
||||
import { deleteCourt } from '../../../services/court';
|
||||
import {
|
||||
getMatchLookup,
|
||||
getMatchLookupByCourt,
|
||||
@@ -78,16 +94,20 @@ function ScheduleRow({
|
||||
}
|
||||
|
||||
function ScheduleColumn({
|
||||
tournamentId,
|
||||
court,
|
||||
matches,
|
||||
openMatchModal,
|
||||
stageItemsLookup,
|
||||
swrCourtsResponse,
|
||||
matchesLookup,
|
||||
}: {
|
||||
tournamentId: number;
|
||||
court: Court;
|
||||
matches: MatchInterface[];
|
||||
openMatchModal: any;
|
||||
stageItemsLookup: any;
|
||||
swrCourtsResponse: SWRResponse;
|
||||
matchesLookup: any;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
@@ -119,7 +139,31 @@ function ScheduleColumn({
|
||||
{(provided) => (
|
||||
<div {...provided.droppableProps} ref={provided.innerRef}>
|
||||
<div style={{ width: '25rem' }}>
|
||||
<h4>{court.name}</h4>
|
||||
<Group justify="space-between">
|
||||
<Group>
|
||||
<h4 style={{ marginTop: '0', margin: 'auto' }}>{court.name}</h4>
|
||||
</Group>
|
||||
<Menu withinPortal position="bottom-end" shadow="sm">
|
||||
<Menu.Target>
|
||||
<ActionIcon variant="transparent" color="gray">
|
||||
<IconDots size="1.25rem" />
|
||||
</ActionIcon>
|
||||
</Menu.Target>
|
||||
|
||||
<Menu.Dropdown>
|
||||
<Menu.Item
|
||||
leftSection={<IconTrash size="1.5rem" />}
|
||||
onClick={async () => {
|
||||
await deleteCourt(tournamentId, court.id);
|
||||
await swrCourtsResponse.mutate();
|
||||
}}
|
||||
color="red"
|
||||
>
|
||||
{t('delete_court_button')}
|
||||
</Menu.Item>
|
||||
</Menu.Dropdown>
|
||||
</Menu>
|
||||
</Group>
|
||||
{rows}
|
||||
{noItemsAlert}
|
||||
{provided.placeholder}
|
||||
@@ -132,12 +176,16 @@ function ScheduleColumn({
|
||||
|
||||
function Schedule({
|
||||
t,
|
||||
tournament,
|
||||
swrCourtsResponse,
|
||||
stageItemsLookup,
|
||||
matchesLookup,
|
||||
schedule,
|
||||
openMatchModal,
|
||||
}: {
|
||||
t: Translator;
|
||||
tournament: TournamentMinimal;
|
||||
swrCourtsResponse: SWRResponse;
|
||||
stageItemsLookup: any;
|
||||
matchesLookup: any;
|
||||
schedule: { court: Court; matches: MatchInterface[] }[];
|
||||
@@ -145,6 +193,8 @@ function Schedule({
|
||||
}) {
|
||||
const columns = schedule.map((item) => (
|
||||
<ScheduleColumn
|
||||
tournamentId={tournament.id}
|
||||
swrCourtsResponse={swrCourtsResponse}
|
||||
stageItemsLookup={stageItemsLookup}
|
||||
matchesLookup={matchesLookup}
|
||||
key={item.court.id}
|
||||
@@ -154,8 +204,26 @@ function Schedule({
|
||||
/>
|
||||
));
|
||||
|
||||
if (columns.length < 1) {
|
||||
return <NoContent title={t('no_matches_title')} description={t('no_matches_description')} />;
|
||||
columns.push(
|
||||
<div style={{ width: '25rem' }}>
|
||||
<CourtModal
|
||||
swrCourtsResponse={swrCourtsResponse}
|
||||
tournamentId={tournament.id}
|
||||
buttonSize="xs"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
if (columns.length < 2) {
|
||||
return (
|
||||
<Stack align="center">
|
||||
<NoContent title={t('no_courts_title')} description={t('no_courts_description')} />
|
||||
<CourtModal
|
||||
swrCourtsResponse={swrCourtsResponse}
|
||||
tournamentId={tournament.id}
|
||||
buttonSize="lg"
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -213,21 +281,23 @@ export default function SchedulePage() {
|
||||
<Title>{t('planning_title')}</Title>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={6}>
|
||||
<Group justify="right">
|
||||
<Button
|
||||
color="indigo"
|
||||
size="md"
|
||||
variant="filled"
|
||||
style={{ marginBottom: 10 }}
|
||||
leftSection={<IconCalendarPlus size={24} />}
|
||||
onClick={async () => {
|
||||
await scheduleMatches(tournamentData.id);
|
||||
await swrStagesResponse.mutate();
|
||||
}}
|
||||
>
|
||||
{t('schedule_description')}
|
||||
</Button>
|
||||
</Group>
|
||||
{data.length < 1 ? null : (
|
||||
<Group justify="right">
|
||||
<Button
|
||||
color="indigo"
|
||||
size="md"
|
||||
variant="filled"
|
||||
style={{ marginBottom: 10 }}
|
||||
leftSection={<IconCalendarPlus size={24} />}
|
||||
onClick={async () => {
|
||||
await scheduleMatches(tournamentData.id);
|
||||
await swrStagesResponse.mutate();
|
||||
}}
|
||||
>
|
||||
{t('schedule_description')}
|
||||
</Button>
|
||||
</Group>
|
||||
)}
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
<Group grow mt="1rem">
|
||||
@@ -245,6 +315,8 @@ export default function SchedulePage() {
|
||||
>
|
||||
<Schedule
|
||||
t={t}
|
||||
tournament={tournamentData}
|
||||
swrCourtsResponse={swrCourtsResponse}
|
||||
schedule={data}
|
||||
stageItemsLookup={stageItemsLookup}
|
||||
matchesLookup={matchesLookup}
|
||||
|
||||
Reference in New Issue
Block a user