From f9628041184f54bf37f8f0db16b5220d1385dd70 Mon Sep 17 00:00:00 2001 From: Erik Vroon Date: Sat, 10 May 2025 16:29:40 +0200 Subject: [PATCH] Use icons for selecting stage items (#1221) ![image](https://github.com/user-attachments/assets/e5f224d9-cd66-4f98-80f9-81a541c8a325) Use icons for stage items in modal to create stage items to improve UX. I made the icons myself so they're not very beautiful --- frontend/public/icons/group-stage-item.svg | 129 +++++ .../icons/single-elimination-stage-item.svg | 196 ++++++++ frontend/public/icons/stage-items.svg | 439 ++++++++++++++++++ frontend/public/icons/swiss-stage-item.svg | 135 ++++++ frontend/public/locales/en/common.json | 3 + frontend/src/components/info/player_list.tsx | 6 +- .../modals/create_stage_item.module.css | 14 + .../components/modals/create_stage_item.tsx | 134 +++++- 8 files changed, 1041 insertions(+), 15 deletions(-) create mode 100644 frontend/public/icons/group-stage-item.svg create mode 100644 frontend/public/icons/single-elimination-stage-item.svg create mode 100644 frontend/public/icons/stage-items.svg create mode 100644 frontend/public/icons/swiss-stage-item.svg create mode 100644 frontend/src/components/modals/create_stage_item.module.css diff --git a/frontend/public/icons/group-stage-item.svg b/frontend/public/icons/group-stage-item.svg new file mode 100644 index 00000000..5ff65978 --- /dev/null +++ b/frontend/public/icons/group-stage-item.svg @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/public/icons/single-elimination-stage-item.svg b/frontend/public/icons/single-elimination-stage-item.svg new file mode 100644 index 00000000..17ba6500 --- /dev/null +++ b/frontend/public/icons/single-elimination-stage-item.svg @@ -0,0 +1,196 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/public/icons/stage-items.svg b/frontend/public/icons/stage-items.svg new file mode 100644 index 00000000..23b3abbc --- /dev/null +++ b/frontend/public/icons/stage-items.svg @@ -0,0 +1,439 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/public/icons/swiss-stage-item.svg b/frontend/public/icons/swiss-stage-item.svg new file mode 100644 index 00000000..5278a28d --- /dev/null +++ b/frontend/public/icons/swiss-stage-item.svg @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/public/locales/en/common.json b/frontend/public/locales/en/common.json index e299679b..620157a6 100644 --- a/frontend/public/locales/en/common.json +++ b/frontend/public/locales/en/common.json @@ -211,6 +211,7 @@ "results_title": "Results", "round_name_input_placeholder": "Best Round Ever", "round_robin_label": "Round Robin", + "round_robin_description": "Each team plays every other team once.", "save_button": "Save", "save_players_button": "Save players", "save_ranking_button": "Save Ranking", @@ -221,6 +222,7 @@ "set_to_new_button": "Set To Now", "sign_in_title": "Sign in", "single_elimination_label": "Single Elimination", + "single_elimination_description": "Teams play against each other, where one loss results in elimination.", "single_player_title": "Single Player", "single_team": "Single Team", "special_character_required": "Includes special character", @@ -233,6 +235,7 @@ "status": "Status", "swiss_difference": "Swiss Difference", "swiss_label": "Swiss", + "swiss_description": "Teams play against equal teams, based on the results of previous matches.", "swiss_score": "Swiss score", "team_count_input_round_robin_label": "Number of teams advancing from the previous stage", "team_count_select_elimination_label": "Number of teams advancing from the previous stage", diff --git a/frontend/src/components/info/player_list.tsx b/frontend/src/components/info/player_list.tsx index 0692ccd2..a6424ff7 100644 --- a/frontend/src/components/info/player_list.tsx +++ b/frontend/src/components/info/player_list.tsx @@ -3,7 +3,11 @@ import { Text } from '@mantine/core'; import { TeamInterface } from '../../interfaces/team'; export default function PlayerList({ team }: { team: TeamInterface }) { - const getPlayerNames = () => team.players.map(p => p.name).sort().join(", ") || "-"; + const getPlayerNames = () => + team.players + .map((p) => p.name) + .sort() + .join(', ') || '-'; return ( diff --git a/frontend/src/components/modals/create_stage_item.module.css b/frontend/src/components/modals/create_stage_item.module.css new file mode 100644 index 00000000..60cea438 --- /dev/null +++ b/frontend/src/components/modals/create_stage_item.module.css @@ -0,0 +1,14 @@ +.socialLink { + padding: 1rem; + border-radius: 1rem; + text-align: center; + font-size: 30px; + font-weight: bold; + text-decoration: none; + display: block; + border: 3px solid #333; +} + +.socialLink:hover { + border: 3px solid #8545c7; +} \ No newline at end of file diff --git a/frontend/src/components/modals/create_stage_item.tsx b/frontend/src/components/modals/create_stage_item.tsx index 3df2d102..46e97cff 100644 --- a/frontend/src/components/modals/create_stage_item.tsx +++ b/frontend/src/components/modals/create_stage_item.tsx @@ -1,4 +1,15 @@ -import { Button, Modal, NumberInput, Select } from '@mantine/core'; +import { + Button, + Card, + Divider, + Grid, + Image, + Modal, + NumberInput, + Select, + Text, + UnstyledButton, +} from '@mantine/core'; import { UseFormReturnType, useForm } from '@mantine/form'; import { GoPlus } from '@react-icons/all-files/go/GoPlus'; import { useTranslation } from 'next-i18next'; @@ -9,6 +20,96 @@ import { StageWithStageItems } from '../../interfaces/stage'; import { Tournament } from '../../interfaces/tournament'; import { getStageItemLookup, getTeamsLookup } from '../../services/lookups'; import { createStageItem } from '../../services/stage_item'; +import { Translator } from '../utils/types'; +import classes from './create_stage_item.module.css'; + +function StageSelectCard({ + title, + description, + image, + selected, + onClick, +}: { + title: string; + description: string; + image: string; + selected: boolean; + onClick: () => void; +}) { + return ( + + + + + + + + {title} + + + + {description} + + + + ); +} + +export function CreateStagesFromTemplateButtons({ + selectedType, + setSelectedType, + t, +}: { + selectedType: 'ROUND_ROBIN' | 'SWISS' | 'SINGLE_ELIMINATION'; + setSelectedType: (type: 'ROUND_ROBIN' | 'SWISS' | 'SINGLE_ELIMINATION') => void; + t: Translator; +}) { + return ( + + + { + setSelectedType('ROUND_ROBIN'); + }} + /> + + + { + setSelectedType('SINGLE_ELIMINATION'); + }} + /> + + + { + setSelectedType('SWISS'); + }} + /> + + + ); +} function TeamCountSelectElimination({ form }: { form: UseFormReturnType }) { const { t } = useTranslation(); @@ -27,7 +128,8 @@ function TeamCountSelectElimination({ form }: { form: UseFormReturnType }) placeholder={t('team_count_select_elimination_placeholder')} searchable limit={20} - mt={24} + mt="1rem" + maw="50%" {...form.getInputProps('team_count_elimination')} /> ); @@ -40,7 +142,8 @@ function TeamCountInputRoundRobin({ form }: { form: UseFormReturnType }) { withAsterisk label={t('team_count_input_round_robin_label')} placeholder="" - mt={24} + mt="1rem" + maw="50%" {...form.getInputProps('team_count_round_robin')} /> ); @@ -62,6 +165,11 @@ function getTeamCount(values: any) { ); } +interface FormValues { + type: 'ROUND_ROBIN' | 'SWISS' | 'SINGLE_ELIMINATION'; + team_count_round_robin: number; + team_count_elimination: number; +} export function CreateStageItemModal({ tournament, stage, @@ -76,7 +184,7 @@ export function CreateStageItemModal({ const { t } = useTranslation(); const [opened, setOpened] = useState(false); - const form = useForm({ + const form = useForm({ initialValues: { type: 'ROUND_ROBIN', team_count_round_robin: 4, team_count_elimination: 2 }, validate: { team_count_round_robin: (value) => (value >= 2 ? null : t('at_least_two_team_validation')), @@ -98,6 +206,7 @@ export function CreateStageItemModal({ opened={opened} onClose={() => setOpened(false)} title={t('add_stage_item_modal_title')} + size="60rem" >
{ @@ -118,17 +227,14 @@ export function CreateStageItemModal({ setOpened(false); })} > -