From 8a32b5c84143be3167580ab2ff9358de35eee25f Mon Sep 17 00:00:00 2001 From: Erik Vroon Date: Sun, 8 Sep 2024 11:14:50 +0200 Subject: [PATCH] Improve planning page (#895) --- frontend/public/locales/de/common.json | 1 - frontend/public/locales/en/common.json | 3 +- frontend/public/locales/es/common.json | 1 - frontend/public/locales/fr/common.json | 1 - frontend/public/locales/nl/common.json | 1 - frontend/public/locales/pt/common.json | 1 - frontend/public/locales/zh/common.json | 1 - frontend/src/components/builder/builder.tsx | 4 +- .../components/buttons/next_stage_button.tsx | 4 +- .../components/modals/create_court_modal.tsx | 65 ++++++++++ .../components/modals/create_stage_item.tsx | 1 - frontend/src/components/modals/spotlight.tsx | 8 -- .../src/components/navbar/_main_links.tsx | 6 - frontend/src/components/tables/courts.tsx | 64 ---------- .../src/pages/tournaments/[id]/courts.tsx | 79 ------------ .../src/pages/tournaments/[id]/schedule.tsx | 112 ++++++++++++++---- 16 files changed, 163 insertions(+), 189 deletions(-) create mode 100644 frontend/src/components/modals/create_court_modal.tsx delete mode 100644 frontend/src/components/tables/courts.tsx delete mode 100644 frontend/src/pages/tournaments/[id]/courts.tsx diff --git a/frontend/public/locales/de/common.json b/frontend/public/locales/de/common.json index 347b8886..332238ac 100644 --- a/frontend/public/locales/de/common.json +++ b/frontend/public/locales/de/common.json @@ -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", diff --git a/frontend/public/locales/en/common.json b/frontend/public/locales/en/common.json index 085e7648..35a084ff 100644 --- a/frontend/public/locales/en/common.json +++ b/frontend/public/locales/en/common.json @@ -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 ...", diff --git a/frontend/public/locales/es/common.json b/frontend/public/locales/es/common.json index 3c20730a..36f52c6f 100644 --- a/frontend/public/locales/es/common.json +++ b/frontend/public/locales/es/common.json @@ -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", diff --git a/frontend/public/locales/fr/common.json b/frontend/public/locales/fr/common.json index 8fe681bf..a8d08b61 100644 --- a/frontend/public/locales/fr/common.json +++ b/frontend/public/locales/fr/common.json @@ -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", diff --git a/frontend/public/locales/nl/common.json b/frontend/public/locales/nl/common.json index ab9b7423..4454e635 100644 --- a/frontend/public/locales/nl/common.json +++ b/frontend/public/locales/nl/common.json @@ -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", diff --git a/frontend/public/locales/pt/common.json b/frontend/public/locales/pt/common.json index e00e2884..cc340980 100644 --- a/frontend/public/locales/pt/common.json +++ b/frontend/public/locales/pt/common.json @@ -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", diff --git a/frontend/public/locales/zh/common.json b/frontend/public/locales/zh/common.json index fd90cdeb..2df3ce2c 100644 --- a/frontend/public/locales/zh/common.json +++ b/frontend/public/locales/zh/common.json @@ -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": "不可用", diff --git a/frontend/src/components/builder/builder.tsx b/frontend/src/components/builder/builder.tsx index fdab1539..763205eb 100644 --- a/frontend/src/components/builder/builder.tsx +++ b/frontend/src/components/builder/builder.tsx @@ -100,7 +100,7 @@ function StageItemRow({ - + @@ -190,7 +190,7 @@ function StageColumn({ - + diff --git a/frontend/src/components/buttons/next_stage_button.tsx b/frontend/src/components/buttons/next_stage_button.tsx index 1434d8fe..fc717b4b 100644 --- a/frontend/src/components/buttons/next_stage_button.tsx +++ b/frontend/src/components/buttons/next_stage_button.tsx @@ -10,7 +10,7 @@ export function NextStageButton({ tournamentData, swrStagesResponse }: any) { return ( + + + + + ); +} diff --git a/frontend/src/components/modals/create_stage_item.tsx b/frontend/src/components/modals/create_stage_item.tsx index e840526c..02ff9eef 100644 --- a/frontend/src/components/modals/create_stage_item.tsx +++ b/frontend/src/components/modals/create_stage_item.tsx @@ -203,7 +203,6 @@ export function CreateStageItemModal({ variant="outline" color="green" size="xs" - style={{ marginRight: 10 }} onClick={() => setOpened(true)} leftSection={} > diff --git a/frontend/src/components/modals/spotlight.tsx b/frontend/src/components/modals/spotlight.tsx index a5298d31..db6d6371 100644 --- a/frontend/src/components/modals/spotlight.tsx +++ b/frontend/src/components/modals/spotlight.tsx @@ -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: , }, - { - id: 'courts', - title: t('courts_title'), - description: t('court_spotlight_description'), - onClick: () => router.push(`/tournaments/${tournamentId}/courts`), - leftSection: , - }, { id: 'tournament settings', title: t('tournament_setting_title'), diff --git a/frontend/src/components/navbar/_main_links.tsx b/frontend/src/components/navbar/_main_links.tsx index fd604b5c..64aeb135 100644 --- a/frontend/src/components/navbar/_main_links.tsx +++ b/frontend/src/components/navbar/_main_links.tsx @@ -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')), diff --git a/frontend/src/components/tables/courts.tsx b/frontend/src/components/tables/courts.tsx deleted file mode 100644 index 8fb26bfe..00000000 --- a/frontend/src/components/tables/courts.tsx +++ /dev/null @@ -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 ; - } - - if (swrCourtsResponse.error) return ; - - const rows = courts - .sort((s1: Court, s2: Court) => sortTableEntries(s1, s2, tableState)) - .map((court) => ( - - {court.name} - - { - await deleteCourt(tournament.id, court.id); - await swrCourtsResponse.mutate(); - }} - title={t('delete_court_button')} - style={{ float: 'right' }} - /> - - - )); - - if (rows.length < 1) return ; - - return ( - - - - {t('title')} - {null} - - - {rows} - - ); -} diff --git a/frontend/src/pages/tournaments/[id]/courts.tsx b/frontend/src/pages/tournaments/[id]/courts.tsx deleted file mode 100644 index cb6edf06..00000000 --- a/frontend/src/pages/tournaments/[id]/courts.tsx +++ /dev/null @@ -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 ( -
{ - await createCourt(tournament.id, values.name); - await swrCourtsResponse.mutate(); - })} - > -
- - -
-
- ); -} - -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 ( - - - - - - - - {CreateCourtForm(t, tournamentDataFull, swrCourtsResponse)} - - - - - ); -} - -export const getServerSideProps = async ({ locale }: { locale: string }) => ({ - props: { - ...(await serverSideTranslations(locale, ['common'])), - }, -}); diff --git a/frontend/src/pages/tournaments/[id]/schedule.tsx b/frontend/src/pages/tournaments/[id]/schedule.tsx index 37de256c..975ed6fe 100644 --- a/frontend/src/pages/tournaments/[id]/schedule.tsx +++ b/frontend/src/pages/tournaments/[id]/schedule.tsx @@ -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) => (
-

{court.name}

+ + +

{court.name}

+
+ + + + + + + + + } + onClick={async () => { + await deleteCourt(tournamentId, court.id); + await swrCourtsResponse.mutate(); + }} + color="red" + > + {t('delete_court_button')} + + + +
{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) => ( )); - if (columns.length < 1) { - return ; + columns.push( +
+ +
+ ); + if (columns.length < 2) { + return ( + + + + + ); } return ( @@ -213,21 +281,23 @@ export default function SchedulePage() { {t('planning_title')} - - - + {data.length < 1 ? null : ( + + + + )} @@ -245,6 +315,8 @@ export default function SchedulePage() { >