From 420034930ff1ea649e4521edf9820a3d40060562 Mon Sep 17 00:00:00 2001 From: Erik Vroon Date: Thu, 24 Oct 2024 21:56:21 +0200 Subject: [PATCH 01/15] Allow changing inputs after creating stage item --- backend/bracket/models/db/stage_item.py | 8 +- backend/bracket/routes/models.py | 4 +- backend/bracket/routes/stage_items.py | 6 - backend/bracket/routes/stages.py | 10 +- backend/bracket/sql/stage_items.py | 55 +- backend/bracket/utils/db_init.py | 19 +- .../api/activate_next_stage_test.py | 12 +- .../api/auto_scheduling_matches_test.py | 12 +- .../integration_tests/api/inputs_test.py | 15 +- .../api/scheduling_matches_test.py | 12 +- frontend/next-env.d.ts | 2 +- frontend/src/components/builder/builder.tsx | 140 +- .../components/modals/create_stage_item.tsx | 73 +- frontend/src/interfaces/stage_item.tsx | 2 +- frontend/src/interfaces/stage_item_input.tsx | 5 + frontend/src/services/adapter.tsx | 4 +- frontend/yarn.lock | 1674 ++++++++--------- 17 files changed, 1051 insertions(+), 1002 deletions(-) diff --git a/backend/bracket/models/db/stage_item.py b/backend/bracket/models/db/stage_item.py index 70e190949..57aa07cb9 100644 --- a/backend/bracket/models/db/stage_item.py +++ b/backend/bracket/models/db/stage_item.py @@ -47,12 +47,18 @@ class StageItemCreateBody(BaseModelORM): name: str | None = None type: StageType team_count: int = Field(ge=2, le=64) - inputs: list[StageItemInputCreateBody] ranking_id: RankingId | None = None def get_name_or_default_name(self) -> str: return self.name if self.name is not None else self.type.value.replace("_", " ").title() + +class StageItemWithInputsCreate(StageItemCreateBody): + inputs: list[StageItemInputCreateBody] + + def get_name_or_default_name(self) -> str: + return self.name if self.name is not None else self.type.value.replace("_", " ").title() + @model_validator(mode="before") def handle_inputs_length(cls, values: Any) -> Any: if ("inputs" in values and "team_count" in values) and ( diff --git a/backend/bracket/routes/models.py b/backend/bracket/routes/models.py index 28e07e30b..6192dc0cd 100644 --- a/backend/bracket/routes/models.py +++ b/backend/bracket/routes/models.py @@ -17,7 +17,7 @@ from bracket.models.db.user import UserPublic from bracket.models.db.util import StageWithStageItems from bracket.routes.auth import Token -from bracket.utils.id_types import StageItemId, StageItemInputId +from bracket.utils.id_types import StageId, StageItemId, StageItemInputId DataT = TypeVar("DataT") @@ -105,7 +105,7 @@ class RankingsResponse(DataResponse[list[Ranking]]): class StageItemInputOptionsResponse( - DataResponse[list[StageItemInputOptionTentative | StageItemInputOptionFinal]] + DataResponse[dict[StageId, list[StageItemInputOptionTentative | StageItemInputOptionFinal]]] ): pass diff --git a/backend/bracket/routes/stage_items.py b/backend/bracket/routes/stage_items.py index 37bf40827..714c45bd5 100644 --- a/backend/bracket/routes/stage_items.py +++ b/backend/bracket/routes/stage_items.py @@ -55,12 +55,6 @@ async def create_stage_item( stage_body: StageItemCreateBody, user: UserPublic = Depends(user_authenticated_for_tournament), ) -> SuccessResponse: - if stage_body.team_count != len(stage_body.inputs): - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail="Team count doesn't match number of inputs", - ) - await check_foreign_keys_belong_to_tournament(stage_body, tournament_id) stages = await get_full_tournament_details(tournament_id) diff --git a/backend/bracket/routes/stages.py b/backend/bracket/routes/stages.py index 0f8efca9c..eb18b42e9 100644 --- a/backend/bracket/routes/stages.py +++ b/backend/bracket/routes/stages.py @@ -137,18 +137,18 @@ async def activate_next_stage( @router.get( - "/tournaments/{tournament_id}/stages/{stage_id}/available_inputs", + "/tournaments/{tournament_id}/available_inputs", response_model=StageItemInputOptionsResponse, ) async def get_available_inputs( tournament_id: TournamentId, - stage_id: StageId, _: UserPublic = Depends(user_authenticated_for_tournament), - stage: Stage = Depends(stage_dependency), ) -> StageItemInputOptionsResponse: stages = await get_full_tournament_details(tournament_id) teams = await get_teams_with_members(tournament_id) - available_inputs = determine_available_inputs(stage_id, teams, stages) + available_inputs = { + stage.id: determine_available_inputs(stage.id, teams, stages) for stage in stages + } return StageItemInputOptionsResponse(data=available_inputs) @@ -157,7 +157,7 @@ async def get_rankings( tournament_id: TournamentId, stage_id: StageId, _: UserPublic = Depends(user_authenticated_for_tournament), - stage_without_details: Stage = Depends(stage_dependency), + __: Stage = Depends(stage_dependency), ) -> StageRankingResponse: """ Get the rankings for the stage items in this stage. diff --git a/backend/bracket/sql/stage_items.py b/backend/bracket/sql/stage_items.py index a5fb2683f..2b8af9475 100644 --- a/backend/bracket/sql/stage_items.py +++ b/backend/bracket/sql/stage_items.py @@ -1,5 +1,5 @@ from bracket.database import database -from bracket.models.db.stage_item import StageItem, StageItemCreateBody +from bracket.models.db.stage_item import StageItem, StageItemCreateBody, StageItemWithInputsCreate from bracket.models.db.util import StageItemWithRounds from bracket.sql.rankings import get_default_rankings_in_tournament from bracket.sql.stage_item_inputs import sql_create_stage_item_input @@ -7,39 +7,46 @@ from bracket.utils.id_types import StageItemId, TournamentId -async def sql_create_stage_item( - tournament_id: TournamentId, stage_item: StageItemCreateBody +async def sql_create_stage_item_with_inputs( + tournament_id: TournamentId, stage_item: StageItemWithInputsCreate ) -> StageItem: async with database.transaction(): - query = """ - INSERT INTO stage_items (type, stage_id, name, team_count, ranking_id) - VALUES (:stage_item_type, :stage_id, :name, :team_count, :ranking_id) - RETURNING * - """ - result = await database.fetch_one( - query=query, - values={ - "stage_item_type": stage_item.type.value, - "stage_id": stage_item.stage_id, - "name": stage_item.get_name_or_default_name(), - "team_count": stage_item.team_count, - "ranking_id": stage_item.ranking_id - if stage_item.ranking_id - else (await get_default_rankings_in_tournament(tournament_id)).id, - }, + stage_item_result = await sql_create_stage_item( + tournament_id, StageItemCreateBody(**stage_item.model_dump()) ) - if result is None: - raise ValueError("Could not create stage") - - stage_item_result = StageItem.model_validate(dict(result._mapping)) - for input_ in stage_item.inputs: await sql_create_stage_item_input(tournament_id, stage_item_result.id, input_) return stage_item_result +async def sql_create_stage_item( + tournament_id: TournamentId, stage_item: StageItemCreateBody +) -> StageItem: + query = """ + INSERT INTO stage_items (type, stage_id, name, team_count, ranking_id) + VALUES (:stage_item_type, :stage_id, :name, :team_count, :ranking_id) + RETURNING * + """ + result = await database.fetch_one( + query=query, + values={ + "stage_item_type": stage_item.type.value, + "stage_id": stage_item.stage_id, + "name": stage_item.get_name_or_default_name(), + "team_count": stage_item.team_count, + "ranking_id": stage_item.ranking_id + if stage_item.ranking_id + else (await get_default_rankings_in_tournament(tournament_id)).id, + }, + ) + if result is None: + raise ValueError("Could not create stage") + + return StageItem.model_validate(dict(result._mapping)) + + async def sql_delete_stage_item(stage_item_id: StageItemId) -> None: query = """ DELETE FROM stage_items diff --git a/backend/bracket/utils/db_init.py b/backend/bracket/utils/db_init.py index 55fb77265..1e968dfae 100644 --- a/backend/bracket/utils/db_init.py +++ b/backend/bracket/utils/db_init.py @@ -18,7 +18,10 @@ from bracket.models.db.ranking import RankingInsertable from bracket.models.db.round import RoundInsertable from bracket.models.db.stage import StageInsertable -from bracket.models.db.stage_item import StageItemCreateBody, StageItemInsertable +from bracket.models.db.stage_item import ( + StageItemInsertable, + StageItemWithInputsCreate, +) from bracket.models.db.stage_item_inputs import ( StageItemInputCreateBodyFinal, StageItemInputCreateBodyTentative, @@ -44,7 +47,7 @@ users_x_clubs, ) from bracket.sql.matches import sql_update_match -from bracket.sql.stage_items import sql_create_stage_item +from bracket.sql.stage_items import sql_create_stage_item_with_inputs from bracket.sql.stages import get_full_tournament_details from bracket.sql.tournaments import sql_get_tournament from bracket.sql.users import create_user, get_user @@ -295,9 +298,9 @@ async def insert_dummy( await insert_dummy(DUMMY_COURT1, CourtId, {"tournament_id": tournament_id_1}) await insert_dummy(DUMMY_COURT2, CourtId, {"tournament_id": tournament_id_1}) - stage_item_1 = await sql_create_stage_item( + stage_item_1 = await sql_create_stage_item_with_inputs( tournament_id_1, - StageItemCreateBody( + StageItemWithInputsCreate( stage_id=stage_id_1, name=DUMMY_STAGE_ITEM1.name, team_count=DUMMY_STAGE_ITEM1.team_count, @@ -322,9 +325,9 @@ async def insert_dummy( ], ), ) - stage_item_2 = await sql_create_stage_item( + stage_item_2 = await sql_create_stage_item_with_inputs( tournament_id_1, - StageItemCreateBody( + StageItemWithInputsCreate( stage_id=stage_id_1, name=DUMMY_STAGE_ITEM2.name, team_count=DUMMY_STAGE_ITEM2.team_count, @@ -349,9 +352,9 @@ async def insert_dummy( ], ), ) - stage_item_3 = await sql_create_stage_item( + stage_item_3 = await sql_create_stage_item_with_inputs( tournament_id_1, - StageItemCreateBody( + StageItemWithInputsCreate( stage_id=stage_id_2, name=DUMMY_STAGE_ITEM3.name, team_count=DUMMY_STAGE_ITEM3.team_count, diff --git a/backend/tests/integration_tests/api/activate_next_stage_test.py b/backend/tests/integration_tests/api/activate_next_stage_test.py index 44c9e4670..a2e50d2b8 100644 --- a/backend/tests/integration_tests/api/activate_next_stage_test.py +++ b/backend/tests/integration_tests/api/activate_next_stage_test.py @@ -1,6 +1,6 @@ from bracket.logic.scheduling.builder import build_matches_for_stage_item from bracket.models.db.match import MatchBody, MatchWithDetailsDefinitive -from bracket.models.db.stage_item import StageItemCreateBody +from bracket.models.db.stage_item import StageItemWithInputsCreate from bracket.models.db.stage_item_inputs import ( StageItemInputCreateBodyFinal, StageItemInputCreateBodyTentative, @@ -8,7 +8,7 @@ from bracket.models.db.util import StageWithStageItems from bracket.sql.matches import sql_update_match from bracket.sql.shared import sql_delete_stage_item_with_foreign_keys -from bracket.sql.stage_items import sql_create_stage_item +from bracket.sql.stage_items import sql_create_stage_item_with_inputs from bracket.sql.stages import get_full_tournament_details from bracket.utils.dummy_records import ( DUMMY_COURT1, @@ -55,9 +55,9 @@ async def test_activate_next_stage( ) as team_inserted_4, ): tournament_id = auth_context.tournament.id - stage_item_1 = await sql_create_stage_item( + stage_item_1 = await sql_create_stage_item_with_inputs( tournament_id, - StageItemCreateBody( + StageItemWithInputsCreate( stage_id=stage_inserted_1.id, name=DUMMY_STAGE_ITEM1.name, team_count=DUMMY_STAGE_ITEM1.team_count, @@ -82,9 +82,9 @@ async def test_activate_next_stage( ], ), ) - stage_item_2 = await sql_create_stage_item( + stage_item_2 = await sql_create_stage_item_with_inputs( tournament_id, - StageItemCreateBody( + StageItemWithInputsCreate( stage_id=stage_inserted_2.id, name=DUMMY_STAGE_ITEM3.name, team_count=2, diff --git a/backend/tests/integration_tests/api/auto_scheduling_matches_test.py b/backend/tests/integration_tests/api/auto_scheduling_matches_test.py index 4c09019b9..ba5034f7e 100644 --- a/backend/tests/integration_tests/api/auto_scheduling_matches_test.py +++ b/backend/tests/integration_tests/api/auto_scheduling_matches_test.py @@ -1,13 +1,13 @@ from heliclockter import datetime_utc from bracket.models.db.round import RoundInsertable -from bracket.models.db.stage_item import StageItemCreateBody, StageType +from bracket.models.db.stage_item import StageItemWithInputsCreate, StageType from bracket.models.db.stage_item_inputs import ( StageItemInputCreateBodyFinal, ) from bracket.sql.rounds import get_round_by_id, sql_create_round from bracket.sql.shared import sql_delete_stage_item_with_foreign_keys -from bracket.sql.stage_items import sql_create_stage_item +from bracket.sql.stage_items import sql_create_stage_item_with_inputs from bracket.sql.stages import get_full_tournament_details from bracket.utils.dummy_records import ( DUMMY_COURT1, @@ -48,9 +48,9 @@ async def test_schedule_matches_auto( ) as team_inserted_2, ): tournament_id = auth_context.tournament.id - stage_item_1 = await sql_create_stage_item( + stage_item_1 = await sql_create_stage_item_with_inputs( tournament_id, - StageItemCreateBody( + StageItemWithInputsCreate( stage_id=stage_inserted_1.id, name=DUMMY_STAGE_ITEM1.name, team_count=2, @@ -111,9 +111,9 @@ async def test_start_next_round( ) as team_inserted_2, ): tournament_id = auth_context.tournament.id - stage_item_1 = await sql_create_stage_item( + stage_item_1 = await sql_create_stage_item_with_inputs( tournament_id, - StageItemCreateBody( + StageItemWithInputsCreate( stage_id=stage_inserted_1.id, name=DUMMY_STAGE_ITEM1.name, team_count=2, diff --git a/backend/tests/integration_tests/api/inputs_test.py b/backend/tests/integration_tests/api/inputs_test.py index 6e6caef46..df14db2dd 100644 --- a/backend/tests/integration_tests/api/inputs_test.py +++ b/backend/tests/integration_tests/api/inputs_test.py @@ -25,23 +25,12 @@ async def test_available_inputs( inserted_stage( DUMMY_STAGE1.model_copy(update={"tournament_id": auth_context.tournament.id}) ) as stage_inserted_1, - # inserted_stage( - # DUMMY_STAGE2.model_copy(update={'tournament_id': auth_context.tournament.id}) - # ) as stage_inserted_2, inserted_stage_item( DUMMY_STAGE_ITEM1.model_copy( update={"stage_id": stage_inserted_1.id, "ranking_id": auth_context.ranking.id} ) ), ): - response = await send_tournament_request( - HTTPMethod.GET, f"stages/{stage_inserted_1.id}/available_inputs", auth_context - ) + response = await send_tournament_request(HTTPMethod.GET, "available_inputs", auth_context) - assert response == { - "data": [ - {"team_id": team_inserted.id}, - # {'winner_from_stage_item_id': 1, 'winner_position': 1}, - # {'winner_from_stage_item_id': 1, 'winner_position': 2}, - ] - } + assert response == {"data": {str(stage_inserted_1.id): [{"team_id": team_inserted.id}]}} diff --git a/backend/tests/integration_tests/api/scheduling_matches_test.py b/backend/tests/integration_tests/api/scheduling_matches_test.py index 168545ed6..d8ac118ae 100644 --- a/backend/tests/integration_tests/api/scheduling_matches_test.py +++ b/backend/tests/integration_tests/api/scheduling_matches_test.py @@ -1,11 +1,11 @@ from bracket.logic.scheduling.builder import build_matches_for_stage_item -from bracket.models.db.stage_item import StageItemCreateBody +from bracket.models.db.stage_item import StageItemWithInputsCreate from bracket.models.db.stage_item_inputs import ( StageItemInputCreateBodyFinal, StageItemInputCreateBodyTentative, ) from bracket.sql.shared import sql_delete_stage_item_with_foreign_keys -from bracket.sql.stage_items import sql_create_stage_item +from bracket.sql.stage_items import sql_create_stage_item_with_inputs from bracket.sql.stages import get_full_tournament_details from bracket.utils.dummy_records import ( DUMMY_COURT1, @@ -51,9 +51,9 @@ async def test_schedule_all_matches( ) as team_inserted_4, ): tournament_id = auth_context.tournament.id - stage_item_1 = await sql_create_stage_item( + stage_item_1 = await sql_create_stage_item_with_inputs( tournament_id, - StageItemCreateBody( + StageItemWithInputsCreate( stage_id=stage_inserted_1.id, name=DUMMY_STAGE_ITEM1.name, team_count=DUMMY_STAGE_ITEM1.team_count, @@ -78,9 +78,9 @@ async def test_schedule_all_matches( ], ), ) - stage_item_2 = await sql_create_stage_item( + stage_item_2 = await sql_create_stage_item_with_inputs( tournament_id, - StageItemCreateBody( + StageItemWithInputsCreate( stage_id=stage_inserted_1.id, name=DUMMY_STAGE_ITEM3.name, team_count=2, diff --git a/frontend/next-env.d.ts b/frontend/next-env.d.ts index 4f11a03dc..a4a7b3f5c 100644 --- a/frontend/next-env.d.ts +++ b/frontend/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. +// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. diff --git a/frontend/src/components/builder/builder.tsx b/frontend/src/components/builder/builder.tsx index 69b663740..edbd2b9ba 100644 --- a/frontend/src/components/builder/builder.tsx +++ b/frontend/src/components/builder/builder.tsx @@ -1,4 +1,16 @@ -import { ActionIcon, Badge, Card, Group, Menu, Stack, Text } from '@mantine/core'; +import { + ActionIcon, + Badge, + Card, + Combobox, + Group, + Input, + InputBase, + Menu, + Stack, + Text, + useCombobox, +} from '@mantine/core'; import { IconDots, IconPencil, IconTrash } from '@tabler/icons-react'; import assert from 'assert'; import { useTranslation } from 'next-i18next'; @@ -10,9 +22,14 @@ import { SWRResponse } from 'swr'; import { Ranking } from '../../interfaces/ranking'; import { StageWithStageItems } from '../../interfaces/stage'; import { StageItemWithRounds } from '../../interfaces/stage_item'; -import { StageItemInput, formatStageItemInput } from '../../interfaces/stage_item_input'; +import { + StageItemInputChoice, + StageItemInputOption, + formatStageItemInput, +} from '../../interfaces/stage_item_input'; import { TeamInterface } from '../../interfaces/team'; import { Tournament } from '../../interfaces/tournament'; +import { getAvailableStageItemInputs } from '../../services/adapter'; import { getStageItemLookup, getTeamsLookup } from '../../services/lookups'; import { deleteStage } from '../../services/stage'; import { deleteStageItem } from '../../services/stage_item'; @@ -21,29 +38,108 @@ import { CreateStageItemModal } from '../modals/create_stage_item'; import { UpdateStageModal } from '../modals/update_stage'; import { UpdateStageItemModal } from '../modals/update_stage_item'; import RequestErrorAlert from '../utils/error_alert'; +import { responseIsValid } from '../utils/util'; + +function StageItemInputComboBox({ + current_key, + availableInputs, +}: { + current_key: string | null; + availableInputs: StageItemInputChoice[]; +}) { + const combobox = useCombobox({ + onDropdownClose: () => combobox.resetSelectedOption(), + }); + + const [value, setValue] = useState(current_key); + + const options = availableInputs.map((option: StageItemInputChoice) => ( + {option.label} + )); + + return ( + { + setValue(val); + combobox.closeDropdown(); + }} + > + + combobox.toggleDropdown()} + style={{ border: '0rem' }} + > + {value || Pick value} + + + + + {options} + + + ); +} + +export function getAvailableInputs( + swrAvailableInputsResponse: SWRResponse, + teamsMap: any, + stageItemMap: any +) { + const getComboBoxOptionForStageItemInput = (stage_item_input: StageItemInputOption) => { + if (stage_item_input.winner_from_stage_item_id == null) { + if (stage_item_input.team_id == null) return null; + const team = teamsMap[stage_item_input.team_id]; + if (team == null) return null; + return { + value: `${stage_item_input.team_id}`, + label: team.name, + }; + } + + assert(stage_item_input.winner_position != null); + const stageItem = stageItemMap[stage_item_input.winner_from_stage_item_id]; + + if (stageItem == null) return null; + return { + value: `${stage_item_input.winner_from_stage_item_id}_${stage_item_input.winner_position}`, + label: `${formatStageItemInput(stage_item_input.winner_position, stageItem.name)}`, + }; + }; + return responseIsValid(swrAvailableInputsResponse) + ? Object.keys(swrAvailableInputsResponse.data.data).reduce((result: any, stage_id: string) => { + const option = swrAvailableInputsResponse.data.data[stage_id]; + result[stage_id] = option.map((opt: StageItemInputOption) => + getComboBoxOptionForStageItemInput(opt) + ); + return result; + }, {}) + : {}; +} function StageItemInputSectionLast({ - input, team, teamStageItem, lastInList, + availableInputs, }: { - input: StageItemInput; team: TeamInterface | null; teamStageItem: TeamInterface | null; lastInList: boolean; + availableInputs: StageItemInputChoice[]; }) { assert(team != null || teamStageItem != null); - const content = team - ? team.name - : // @ts-ignore - formatStageItemInput(input.winner_position, teamStageItem.name); const opts = lastInList ? { pt: 'xs', mb: '-0.5rem' } : { py: 'xs', withBorder: true }; return ( - {content} + ); } @@ -53,17 +149,20 @@ function StageItemRow({ tournament, stageItem, swrStagesResponse, + stageItemsLookup, + availableInputs, rankings, }: { teamsMap: any; tournament: Tournament; stageItem: StageItemWithRounds; + stageItemsLookup: any; swrStagesResponse: SWRResponse; + availableInputs: StageItemInputChoice[]; rankings: Ranking[]; }) { const { t } = useTranslation(); const [opened, setOpened] = useState(false); - const stageItemsLookup = getStageItemLookup(swrStagesResponse); const inputs = stageItem.inputs .sort((i1, i2) => (i1.slot > i2.slot ? 1 : -1)) @@ -77,7 +176,7 @@ function StageItemRow({ @@ -145,21 +244,33 @@ function StageColumn({ tournament, stage, swrStagesResponse, + swrAvailableInputsResponse, rankings, }: { tournament: Tournament; stage: StageWithStageItems; swrStagesResponse: SWRResponse; + swrAvailableInputsResponse: SWRResponse; rankings: Ranking[]; }) { const { t } = useTranslation(); const [opened, setOpened] = useState(false); const teamsMap = getTeamsLookup(tournament != null ? tournament.id : -1); + const stageItemsLookup = getStageItemLookup(swrStagesResponse); if (teamsMap == null) { return null; } + const availableInputs = getAvailableInputs( + swrAvailableInputsResponse, + teamsMap, + stageItemsLookup + )[stage.id]; + if (availableInputs == null) { + return null; + } + const rows = stage.stage_items .sort((i1: StageItemWithRounds, i2: StageItemWithRounds) => (i1.name > i2.name ? 1 : -1)) .map((stageItem: StageItemWithRounds) => ( @@ -168,7 +279,9 @@ function StageColumn({ teamsMap={teamsMap} tournament={tournament} stageItem={stageItem} + stageItemsLookup={stageItemsLookup} swrStagesResponse={swrStagesResponse} + availableInputs={availableInputs} rankings={rankings} /> )); @@ -238,8 +351,12 @@ export default function Builder({ }) { const stages: StageWithStageItems[] = swrStagesResponse.data != null ? swrStagesResponse.data.data : []; + const swrAvailableInputsResponse = getAvailableStageItemInputs(tournament.id); if (swrStagesResponse.error) return ; + if (swrAvailableInputsResponse.error) { + return ; + } const cols = stages .sort((s1: StageWithStageItems, s2: StageWithStageItems) => (s1.id > s2.id ? 1 : -1)) @@ -248,6 +365,7 @@ export default function Builder({ key={stage.id} tournament={tournament} swrStagesResponse={swrStagesResponse} + swrAvailableInputsResponse={swrAvailableInputsResponse} stage={stage} rankings={rankings} /> diff --git a/frontend/src/components/modals/create_stage_item.tsx b/frontend/src/components/modals/create_stage_item.tsx index 02ff9eef2..e4888b4cb 100644 --- a/frontend/src/components/modals/create_stage_item.tsx +++ b/frontend/src/components/modals/create_stage_item.tsx @@ -1,18 +1,15 @@ -import { Button, Divider, Modal, NumberInput, Select } from '@mantine/core'; +import { Button, Modal, NumberInput, Select } from '@mantine/core'; import { UseFormReturnType, useForm } from '@mantine/form'; import { GoPlus } from '@react-icons/all-files/go/GoPlus'; -import assert from 'assert'; import { useTranslation } from 'next-i18next'; import React, { useState } from 'react'; import { SWRResponse } from 'swr'; import { StageWithStageItems } from '../../interfaces/stage'; -import { StageItemInputOption, formatStageItemInput } from '../../interfaces/stage_item_input'; import { Tournament } from '../../interfaces/tournament'; import { getAvailableStageItemInputs } from '../../services/adapter'; import { getStageItemLookup, getTeamsLookup } from '../../services/lookups'; import { createStageItem } from '../../services/stage_item'; -import { responseIsValid } from '../utils/util'; function TeamCountSelectElimination({ form }: { form: UseFormReturnType }) { const { t } = useTranslation(); @@ -56,30 +53,6 @@ function TeamCountInput({ form }: { form: UseFormReturnType }) { return ; } -function StageItemInput({ - form, - possibleOptions, - index, -}: { - form: UseFormReturnType; - index: number; - possibleOptions: any[]; -}) { - const { t } = useTranslation(); - return ( -