diff --git a/backend/bracket/routes/users.py b/backend/bracket/routes/users.py index 392784f1..6231e50d 100644 --- a/backend/bracket/routes/users.py +++ b/backend/bracket/routes/users.py @@ -34,8 +34,13 @@ from bracket.utils.types import assert_some router = APIRouter() +@router.get("/users/me", response_model=UserPublicResponse) +async def get_user(user_public: UserPublic = Depends(user_authenticated)) -> UserPublicResponse: + return UserPublicResponse(data=user_public) + + @router.get("/users/{user_id}", response_model=UserPublicResponse) -async def get_user( +async def get_me( user_id: int, user_public: UserPublic = Depends(user_authenticated) ) -> UserPublicResponse: if user_public.id != user_id: diff --git a/backend/tests/integration_tests/api/users_test.py b/backend/tests/integration_tests/api/users_test.py index b24cd49b..4ae09c95 100644 --- a/backend/tests/integration_tests/api/users_test.py +++ b/backend/tests/integration_tests/api/users_test.py @@ -13,9 +13,7 @@ from tests.integration_tests.sql import assert_row_count_and_clear async def test_users_endpoint( startup_and_shutdown_uvicorn_server: None, auth_context: AuthContext ) -> None: - assert await send_auth_request( - HTTPMethod.GET, f"users/{auth_context.user.id}", auth_context, {} - ) == { + expected_data = { "data": { "email": auth_context.user.email, "created": "2000-01-01T00:00:00Z", @@ -25,6 +23,13 @@ async def test_users_endpoint( }, } + assert ( + await send_auth_request(HTTPMethod.GET, f"users/{auth_context.user.id}", auth_context, {}) + == expected_data + ) + + assert await send_auth_request(HTTPMethod.GET, "users/me", auth_context, {}) == expected_data + async def test_create_user( startup_and_shutdown_uvicorn_server: None, auth_context: AuthContext diff --git a/frontend/public/locales/en/common.json b/frontend/public/locales/en/common.json index dfb52268..42818205 100644 --- a/frontend/public/locales/en/common.json +++ b/frontend/public/locales/en/common.json @@ -1,223 +1,224 @@ { - "not_found_title": "You have found a secret place.", - "not_found_description": "Unfortunately, this is only a 404 page. You may have mistyped the address, or the page has been moved to another URL.", - "back_home_nav": "Take me back to home page", - "clubs_title": "clubs", - "empty_name_validation": "Name cannot be empty", - "empty_email_validation": "Invalid email", - "empty_password_validation": "Password cannot be empty", - "too_short_name_validation": "Name is too short", - "too_short_dashboard_link_validation": "Dashboard link is short", - "too_short_password_validation": "Password is too short", - "invalid_email_validation": "Invalid email", - "invalid_password_validation": "Invalid password", - "create_account_title": "Create a new account", - "create_demo_account_title": "Create demo account", - "start_demo_button": "Start demo", - "demo_policy_title": "Demo policy", - "demo_description": "To test Bracket, you can start a demo. A demo will last for 30 minutes, after which your demo account be deleted. Please make fair use of it.", - "create_account_alert_title": "Unavailable", - "create_account_alert_description": "Account creation is disabled on this domain for now since bracket is still in beta phase", - "create_account_button": "Create Account", - "email_input_label": "Email Address", - "email_input_placeholder": "Your email", - "name_input_label": "Name", - "name_input_placeholder": "Your name", - "password_input_label": "Password", - "password_input_placeholder": "Your password", - "back_to_login_nav": "Back to login page", - "tournaments_title": "tournaments", - "tournament_title": "tournament", - "login_success_title": "Login successful", - "welcome_title": "Welcome to", - "sign_in_title": "Sign in", - "forgot_password_button": "Forgot password?", - "edit_profile_title": "Edit Profile", - "match_filter_option_all": "All matches", - "match_filter_option_past": "Hide past matches", - "match_filter_option_current": "Current matches", - "name_filter_options_team": "Team names", - "name_filter_options_player": "Player names", - "view_dashboard_button": "View Dashboard", - "add_court_title": "Add Court", - "create_court_button": "Create Court", - "court_name_input_placeholder": "Best Court Ever", - "no_matches_description": "No matches yet", - "drop_match_alert_title": "Drop a match here", - "schedule_title": "Schedule", - "schedule_description": "Schedule All Unscheduled Matches", - "club_choose_title": "Please choose a club", - "start_time_choose_title": "Please choose a start time", - "duration_minutes_choose_title": "Please choose a duration of the matches", - "margin_minutes_choose_title": "Please choose a margin between matches", - "tournament_name_input_placeholder": "Best Tournament Ever", - "club_select_placeholder": "Pick a club for this tournament", - "planning_of_matches_legend": "Planning of matches", - "planning_of_matches_description": "Start of the tournament", - "match_duration_label": "Match duration (minutes)", - "time_between_matches_label": "Time between matches (minutes)", - "dashboard_settings_title": "Dashboard Settings", - "dashboard_link_label": "Dashboard link", - "dashboard_link_placeholder": "best_tournament", - "dashboard_public_description": "Allow anyone to see the dashboard of rounds and matches", - "miscellaneous_title": "Miscellaneous", - "miscellaneous_label": "Allow players to be in multiple teams", - "auto_assign_courts_label": "Automatically assign courts to matches", - "save_button": "Save", - "copy_dashboard_url_button": "Copy Dashboard URL", - "copied_dashboard_url_button": "Copied Dashboard URL", - "filter_stage_item_label": "Filter on stage item", - "filter_stage_item_placeholder": "No filter", - "team_title": "Team", - "current_matches_badge": "Current matches", - "next_matches_badge": "Next matches", - "no_round_title": "No round", - "no_round_description": "There are no rounds in this stage item yet", - "add_round_button": "Add Round", - "no_round_found_title": "No rounds found", - "no_round_found_description": "Please wait for the organiser to add them.", - "no_round_found_in_stage_description": "There are no rounds in this stage yet", - "tournament_not_started_title": "Tournament has not started yet", - "tournament_not_started_description": "Please wait for the tournament to start.", - "edit_name_button": "Edit Name", - "delete_button": "Delete", - "active_badge_label": "Active", - "auto_create_matches_button": "Add new matches automatically", - "add_stage_button": "Add Stage", - "next_stage_button": "Go to Next Stage", - "previous_stage_button": "Go to Previous Stage", - "multiple_teams_input_label": "Add multiple teams. Put every team on a separate line", - "multiple_teams_input_placeholder": "Team 1", - "multiple_players_input_label": "Add multiple players. Put every player on a separate line", - "multiple_players_input_placeholder": "Player 1", - "edit_details_tab_title": "Edit details", - "edit_password_tab_title": "Edit password", - "no_team_members_description": "No members", - "active_next_round_modal_title": "Assign times and courts to matches of next round", - "active_next_round_modal_description": "This will assign times and courts to matches of next round, which is the round after the current activated (green) round.", - "active_next_round_modal_choose_description": "You can choose to either (check the checkbox or not):", - "checkbox_status_checked": "Checked", - "checkbox_status_unchecked": "Unchecked", - "active_next_round_modal_choose_option_unchecked": "Use default timing (the next matches will be planned tightly after the matches of the active round end, taking margin into account)", - "active_next_round_modal_choose_option_checked": "Adjust the start times of the next matches to start immediately(now). This will be done by modifying the margin times of the matches in the previous round.", - "adjust_start_times_checkbox_label": "Adjust start time of matches in this round to the current time", - "accept_policy_checkbox": "I have read the policy above", - "policy_not_accepted": "Please indicate that you have read the policy", - "plan_next_round_button": "Plan next round", - "edit_club_button": "Edit Club", - "create_club_button": "Create Club", - "club_name_input_placeholder": "Best Club Ever", - "team_count_select_elimination_label": "Number of teams advancing from the previous stage", - "team_count_select_elimination_placeholder": "2, 4, 8 etc.", - "team_count_input_round_robin_label": "Number of teams advancing from the previous stage", - "none": "None", - "at_least_two_team_validation": "Need at least two teams", - "stage_type_select_label": "Stage type", - "round_robin_label": "Round Robin", - "single_elimination_label": "Single Elimination", - "swiss_label": "Swiss", - "create_stage_item_button": "Create Stage Item", - "add_stage_item_modal_title": "Add Stage Item", - "remove_match_button": "Remove Match", - "negative_score_validation": "Score cannot be negative", - "negative_match_duration_validation": "Match duration cannot be negative", - "negative_match_margin_validation": "Match margin cannot be negative", - "edit_match_modal_title": "Edit Match", - "score_of_label": "Score of", - "custom_match_duration_label": "Custom match duration", - "customize_checkbox_label": "Customize", - "custom_match_margin_label": "Custom match margin", - "set_to_new_button": "Set To Now", - "minutes": "minutes", - "at_least_one_player_validation": "Enter at least one player", - "active_players_checkbox_label": "These players are active", - "active_player_checkbox_label": "This player is active", - "player_name_input_placeholder": "Best Player Ever", - "save_players_button": "Save players", - "single_player_title": "Single Player", - "multiple_players_title": "Multiple Players", - "create_player_modal_title": "Create Player", - "add_player_button": "Add Player", - "edit_player": "Edit Player", - "delete_round_button": "Delete Round", - "edit_round": "Edit Round", - "round_name_input_placeholder": "Best Round Ever", - "active_round_checkbox_label": "This round is active", - "draft_round_checkbox_label": "This round is a draft round", - "home_title": "Home", - "home_spotlight_description": "Get to home page", - "clubs_spotlight_description": "View, add or delete clubs", - "user_settings_title": "User Settings", - "user_settings_spotlight_description": "Change name, email, password etc.", - "planning_title": "Planning", - "planning_spotlight_description": "Change planning of matches", - "teams_title": "teams", - "teams_spotlight_description": "View, add or delete teams", - "players_title": "players", - "players_spotlight_description": "View, add or delete players", - "stage_title": "Stages", - "stage_spotlight_description": "Change the layout of the tournament", - "courts_title": "courts", - "court_spotlight_description": "View, add or delete courts", - "tournament_setting_title": "Tournament Settings", - "tournament_setting_spotlight_description": "Change the settings of the tournament", - "nothing_found_placeholder": "Nothing found ...", - "search_placeholder": "Search ...", - "at_least_one_team_validation": "Enter at least one team", - "active_teams_checkbox_label": "These teams are active", - "team_name_input_placeholder": "Best Team Ever", - "active_team_checkbox_label": "This team is active", - "team_member_select_title": "Team members", - "single_team": "Single Team", - "multiple_teams": "Multiple Teams", - "add_team_button": "Add Team", - "edit_team_title": "Edit Team", - "club_select_label": "Club", - "now_button": "NOW", - "logout_title": "Logout", - "user_title": "User", - "more_title": "More", - "website_title": "Website", - "github_title": "Github", - "api_docs_title": "API docs", - "elo_input_label": "Max ELO difference", - "only_recommended_input_group_label": "Only show teams that played less matches", - "only_recommended_radio_label": "Only recommended", - "all_matches_radio_label": "All matches", - "max_results_input_label": "Max results", - "iterations_input_label": "Iterations", - "delete_club_button": "Delete Club", - "title": "Title", - "name_field_text": "name", - "delete_court_button": "Delete Court", - "win_distribution_text_win": "wins", - "win_distribution_text_draws": "draws", - "win_distribution_text_losses": "losses", - "delete_player_button": "Delete Player", - "status": "Status", - "created": "Created", - "elo_score": "ELO score", - "swiss_score": "Swiss score", - "name_table_header": "Name", - "member_table_header": "Members", - "active": "Active", - "inactive": "Inactive", - "delete_team_button": "Delete Team", - "delete_tournament_button": "Delete Tournament", - "edit_tournament_button": "Edit Tournament", - "recommended_badge_title": "Recommended", - "upcoming_matches_empty_table_info": "upcoming matches", - "elo_difference": "ELO Difference", - "swiss_difference": "Swiss Difference", - "could_not_find_any_alert": "Could not find any", - "dropzone_accept_text": "Drop files here", - "dropzone_reject_text": "Image must be less than 10MB", - "dropzone_idle_text": "Upload Logo", - "upload_placeholder": "Drop a file here to upload as tournament logo.", - "number_required": "Includes number", - "lowercase_required": "Includes lowercase letter", - "uppercase_required": "Includes uppercase letter", - "special_character_required": "Includes special character", - "8_characters_required": "Has at least 8 characters", - "create_tournament_button": "Create Tournament" + "8_characters_required": "Has at least 8 characters", + "accept_policy_checkbox": "I have read the policy above", + "active": "Active", + "active_badge_label": "Active", + "active_next_round_modal_choose_description": "You can choose to either (check the checkbox or not):", + "active_next_round_modal_choose_option_checked": "Adjust the start times of the next matches to start immediately(now). This will be done by modifying the margin times of the matches in the previous round.", + "active_next_round_modal_choose_option_unchecked": "Use default timing (the next matches will be planned tightly after the matches of the active round end, taking margin into account)", + "active_next_round_modal_description": "This will assign times and courts to matches of next round, which is the round after the current activated (green) round.", + "active_next_round_modal_title": "Assign times and courts to matches of next round", + "active_player_checkbox_label": "This player is active", + "active_players_checkbox_label": "These players are active", + "active_round_checkbox_label": "This round is active", + "active_team_checkbox_label": "This team is active", + "active_teams_checkbox_label": "These teams are active", + "add_court_title": "Add Court", + "add_player_button": "Add Player", + "add_round_button": "Add Round", + "add_stage_button": "Add Stage", + "add_stage_item_modal_title": "Add Stage Item", + "add_team_button": "Add Team", + "adjust_start_times_checkbox_label": "Adjust start time of matches in this round to the current time", + "all_matches_radio_label": "All matches", + "api_docs_title": "API docs", + "at_least_one_player_validation": "Enter at least one player", + "at_least_one_team_validation": "Enter at least one team", + "at_least_two_team_validation": "Need at least two teams", + "auto_assign_courts_label": "Automatically assign courts to matches", + "auto_create_matches_button": "Add new matches automatically", + "back_home_nav": "Take me back to home page", + "back_to_login_nav": "Back to login page", + "checkbox_status_checked": "Checked", + "checkbox_status_unchecked": "Unchecked", + "club_choose_title": "Please choose a club", + "club_name_input_placeholder": "Best Club Ever", + "club_select_label": "Club", + "club_select_placeholder": "Pick a club for this tournament", + "clubs_spotlight_description": "View, add or delete clubs", + "clubs_title": "clubs", + "copied_dashboard_url_button": "Copied Dashboard URL", + "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", + "create_account_button": "Create Account", + "create_account_title": "Create a new account", + "create_club_button": "Create Club", + "create_court_button": "Create Court", + "create_demo_account_title": "Create demo account", + "create_player_modal_title": "Create Player", + "create_stage_item_button": "Create Stage Item", + "create_tournament_button": "Create Tournament", + "created": "Created", + "current_matches_badge": "Current matches", + "custom_match_duration_label": "Custom match duration", + "custom_match_margin_label": "Custom match margin", + "customize_checkbox_label": "Customize", + "dashboard_link_label": "Dashboard link", + "dashboard_link_placeholder": "best_tournament", + "dashboard_public_description": "Allow anyone to see the dashboard of rounds and matches", + "dashboard_settings_title": "Dashboard Settings", + "delete_button": "Delete", + "delete_club_button": "Delete Club", + "delete_court_button": "Delete Court", + "delete_player_button": "Delete Player", + "delete_round_button": "Delete Round", + "delete_team_button": "Delete Team", + "delete_tournament_button": "Delete Tournament", + "demo_description": "To test Bracket, you can start a demo. A demo will last for 30 minutes, after which your demo account be deleted. Please make fair use of it.", + "demo_policy_title": "Demo policy", + "draft_round_checkbox_label": "This round is a draft round", + "drop_match_alert_title": "Drop a match here", + "dropzone_accept_text": "Drop files here", + "dropzone_idle_text": "Upload Logo", + "dropzone_reject_text": "Image must be less than 10MB", + "duration_minutes_choose_title": "Please choose a duration of the matches", + "edit_club_button": "Edit Club", + "edit_details_tab_title": "Edit details", + "edit_match_modal_title": "Edit Match", + "edit_name_button": "Edit Name", + "edit_password_tab_title": "Edit password", + "edit_player": "Edit Player", + "edit_profile_title": "Edit Profile", + "edit_round": "Edit Round", + "edit_team_title": "Edit Team", + "edit_tournament_button": "Edit Tournament", + "elo_difference": "ELO Difference", + "elo_input_label": "Max ELO difference", + "elo_score": "ELO score", + "email_input_label": "Email Address", + "email_input_placeholder": "Your email", + "empty_email_validation": "Invalid email", + "empty_name_validation": "Name cannot be empty", + "empty_password_validation": "Password cannot be empty", + "filter_stage_item_label": "Filter on stage item", + "filter_stage_item_placeholder": "No filter", + "forgot_password_button": "Forgot password?", + "github_title": "Github", + "home_spotlight_description": "Get to home page", + "home_title": "Home", + "inactive": "Inactive", + "invalid_email_validation": "Invalid email", + "invalid_password_validation": "Invalid password", + "iterations_input_label": "Iterations", + "login_success_title": "Login successful", + "logout_title": "Logout", + "lowercase_required": "Includes lowercase letter", + "margin_minutes_choose_title": "Please choose a margin between matches", + "match_duration_label": "Match duration (minutes)", + "match_filter_option_all": "All matches", + "match_filter_option_current": "Current matches", + "match_filter_option_past": "Hide past matches", + "max_results_input_label": "Max results", + "member_table_header": "Members", + "minutes": "minutes", + "miscellaneous_label": "Allow players to be in multiple teams", + "miscellaneous_title": "Miscellaneous", + "more_title": "More", + "multiple_players_input_label": "Add multiple players. Put every player on a separate line", + "multiple_players_input_placeholder": "Player 1", + "multiple_players_title": "Multiple Players", + "multiple_teams": "Multiple Teams", + "multiple_teams_input_label": "Add multiple teams. Put every team on a separate line", + "multiple_teams_input_placeholder": "Team 1", + "name_field_text": "name", + "name_filter_options_player": "Player names", + "name_filter_options_team": "Team names", + "name_input_label": "Name", + "name_input_placeholder": "Your name", + "name_table_header": "Name", + "negative_match_duration_validation": "Match duration cannot be negative", + "negative_match_margin_validation": "Match margin cannot be negative", + "negative_score_validation": "Score cannot be negative", + "next_matches_badge": "Next matches", + "next_stage_button": "Go to 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_round_description": "There are no rounds in this stage item yet", + "no_round_found_description": "Please wait for the organiser to add them.", + "no_round_found_in_stage_description": "There are no rounds in this stage yet", + "no_round_found_title": "No rounds found", + "no_round_title": "No round", + "no_team_members_description": "No members", + "none": "None", + "not_found_description": "Unfortunately, this is only a 404 page. You may have mistyped the address, or the page has been moved to another URL.", + "not_found_title": "You have found a secret place.", + "nothing_found_placeholder": "Nothing found ...", + "now_button": "NOW", + "number_required": "Includes number", + "only_recommended_input_group_label": "Only show teams that played less matches", + "only_recommended_radio_label": "Only recommended", + "password_input_label": "Password", + "password_input_placeholder": "Your password", + "plan_next_round_button": "Plan next round", + "planning_of_matches_description": "Start of the tournament", + "planning_of_matches_legend": "Planning of matches", + "planning_spotlight_description": "Change planning of matches", + "planning_title": "Planning", + "player_name_input_placeholder": "Best Player Ever", + "players_spotlight_description": "View, add or delete players", + "players_title": "players", + "policy_not_accepted": "Please indicate that you have read the policy", + "previous_stage_button": "Go to Previous Stage", + "recommended_badge_title": "Recommended", + "remove_match_button": "Remove Match", + "round_name_input_placeholder": "Best Round Ever", + "round_robin_label": "Round Robin", + "save_button": "Save", + "save_players_button": "Save players", + "schedule_description": "Schedule All Unscheduled Matches", + "schedule_title": "Schedule", + "score_of_label": "Score of", + "search_placeholder": "Search ...", + "set_to_new_button": "Set To Now", + "sign_in_title": "Sign in", + "single_elimination_label": "Single Elimination", + "single_player_title": "Single Player", + "single_team": "Single Team", + "special_character_required": "Includes special character", + "stage_spotlight_description": "Change the layout of the tournament", + "stage_title": "Stages", + "stage_type_select_label": "Stage type", + "start_demo_button": "Start demo", + "start_time_choose_title": "Please choose a start time", + "status": "Status", + "swiss_difference": "Swiss Difference", + "swiss_label": "Swiss", + "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", + "team_count_select_elimination_placeholder": "2, 4, 8 etc.", + "team_member_select_title": "Team members", + "team_name_input_placeholder": "Best Team Ever", + "team_title": "Team", + "teams_spotlight_description": "View, add or delete teams", + "teams_title": "teams", + "time_between_matches_label": "Time between matches (minutes)", + "title": "Title", + "too_short_dashboard_link_validation": "Dashboard link is short", + "too_short_name_validation": "Name is too short", + "too_short_password_validation": "Password is too short", + "tournament_name_input_placeholder": "Best Tournament Ever", + "tournament_not_started_description": "Please wait for the tournament to start.", + "tournament_not_started_title": "Tournament has not started yet", + "tournament_setting_spotlight_description": "Change the settings of the tournament", + "tournament_setting_title": "Tournament Settings", + "tournament_title": "tournament", + "tournaments_title": "tournaments", + "upcoming_matches_empty_table_info": "upcoming matches", + "upload_placeholder": "Drop a file here to upload as tournament logo.", + "uppercase_required": "Includes uppercase letter", + "user_settings_spotlight_description": "Change name, email, password etc.", + "user_settings_title": "User Settings", + "user_title": "User", + "view_dashboard_button": "View Dashboard", + "website_title": "Website", + "welcome_title": "Welcome to", + "win_distribution_text_draws": "draws", + "win_distribution_text_losses": "losses", + "win_distribution_text_win": "wins" } \ No newline at end of file diff --git a/frontend/public/locales/nl/common.json b/frontend/public/locales/nl/common.json index 11afb15b..bf55539d 100644 --- a/frontend/public/locales/nl/common.json +++ b/frontend/public/locales/nl/common.json @@ -1,223 +1,224 @@ { - "not_found_title": "Je hebt een geheime plek gevonden.", - "not_found_description": "Helaas, dit is een 404 pagina. ", - "back_home_nav": "Breng me terug naar de startpagina", - "clubs_title": "Clubs", - "empty_name_validation": "Naam mag niet leeg zijn", - "empty_email_validation": "Ongeldige e-mail", - "empty_password_validation": "Wachtwoord mag niet leeg zijn", - "too_short_name_validation": "Naam is te kort", - "too_short_dashboard_link_validation": "Dashboard link is kort", - "too_short_password_validation": "Wachtwoord is te kort", - "invalid_email_validation": "Ongeldige e-mail", - "invalid_password_validation": "Ongeldig wachtwoord", - "create_account_title": "Maak een nieuw account aan", - "create_demo_account_title": "Maak een demo-account aan", - "start_demo_button": "Demo starten", - "demo_policy_title": "Demo richtlijnen", - "demo_description": "Om Bracket te testen, kun je een demo starten. Een demo duurt 30 minuten, waarna je account verwijderd wordt. Maak er geen misbruik van.", - "create_account_alert_title": "Niet beschikbaar", - "create_account_alert_description": "Het aanmaken van een account is voorlopig uitgeschakeld op dit domein", - "create_account_button": "Account aanmaken", - "email_input_label": "E-mailadres", - "email_input_placeholder": "Jouw email", - "name_input_label": "Naam", - "name_input_placeholder": "Uw naam", - "password_input_label": "Wachtwoord", - "password_input_placeholder": "Je wachtwoord", - "back_to_login_nav": "Terug naar de inlogpagina", - "tournaments_title": "toernooien", - "tournament_title": "toernooi", - "login_success_title": "Login succesvol", - "welcome_title": "Welkom bij", - "sign_in_title": "Inloggen", - "forgot_password_button": "Wachtwoord vergeten?", - "edit_profile_title": "Bewerk profiel", - "match_filter_option_all": "Alle wedstrijden", - "match_filter_option_past": "Verberg eerdere wedstrijden", - "match_filter_option_current": "Huidige wedstrijden", - "name_filter_options_team": "Teamnamen", - "name_filter_options_player": "Namen van spelers", - "view_dashboard_button": "Dashboard bekijken", + "8_characters_required": "Heeft minimaal 8 tekens", + "accept_policy_checkbox": "Ik heb de bovenstaande richtlijnen gelezen", + "active": "Actief", + "active_badge_label": "Actief", + "active_next_round_modal_choose_description": "U kunt kiezen uit een van de volgende opties (vink het selectievakje aan of niet):", + "active_next_round_modal_choose_option_checked": "Pas de starttijden van de volgende wedstrijden aan om direct te beginnen.", + "active_next_round_modal_choose_option_unchecked": "Gebruik standaardtiming (de volgende wedstrijden worden strak gepland na het einde van de wedstrijden van de actieve ronde, rekening houdend met de marge)", + "active_next_round_modal_description": "Hierdoor worden tijden en speelvelden toegewezen aan wedstrijden van de volgende ronde, wat de ronde is na de huidige geactiveerde (groene) ronde.", + "active_next_round_modal_title": "Wijs tijden en banen toe aan wedstrijden van de volgende ronde", + "active_player_checkbox_label": "Deze speler is actief", + "active_players_checkbox_label": "Deze spelers zijn actief", + "active_round_checkbox_label": "Deze ronde is actief", + "active_team_checkbox_label": "Dit team is actief", + "active_teams_checkbox_label": "Deze teams zijn actief", "add_court_title": "Veld toevoegen", - "create_court_button": "Veld creëren", - "court_name_input_placeholder": "Beste veld ooit", - "no_matches_description": "Nog geen wedstrijden", - "drop_match_alert_title": "Plaats hier een wedstrijd", - "schedule_title": "Schema", - "schedule_description": "Plan alle ongeplande wedstrijden", + "add_player_button": "Speler toevoegen", + "add_round_button": "Ronde toevoegen", + "add_stage_button": "Fase toevoegen", + "add_stage_item_modal_title": "Fase-item toevoegen", + "add_team_button": "Team Toevoegen", + "adjust_start_times_checkbox_label": "Pas de starttijd van wedstrijden in deze ronde aan naar de huidige tijd", + "all_matches_radio_label": "Alle wedstrijden", + "api_docs_title": "API documentatie", + "at_least_one_player_validation": "Voer minimaal één speler in", + "at_least_one_team_validation": "Voer minimaal één team in", + "at_least_two_team_validation": "Er zijn minimaal twee teams nodig", + "auto_assign_courts_label": "Wijs automatisch velden toe aan wedstrijden", + "auto_create_matches_button": "Voeg automatisch nieuwe wedstrijden toe", + "back_home_nav": "Breng me terug naar de startpagina", + "back_to_login_nav": "Terug naar de inlogpagina", + "checkbox_status_checked": "Geselecteerd", + "checkbox_status_unchecked": "Gedeselecteerd", "club_choose_title": "Kies een club", - "start_time_choose_title": "Kies een starttijd", - "duration_minutes_choose_title": "Vul de duur van de wedstrijden in", - "margin_minutes_choose_title": "Vul de marge tussen wedstrijden in", - "tournament_name_input_placeholder": "Beste Toernooi Ooit", + "club_name_input_placeholder": "Beste Club Ooit", + "club_select_label": "Club", "club_select_placeholder": "Kies een club voor dit toernooi", - "planning_of_matches_legend": "Planning van de wedstrijden", - "planning_of_matches_description": "Begin van het toernooi", - "match_duration_label": "Wedstrijdduur (minuten)", - "time_between_matches_label": "Tijd tussen de wedstrijden (minuten)", - "dashboard_settings_title": "Dashboardinstellingen", + "clubs_spotlight_description": "Clubs bekijken, toevoegen of verwijderen", + "clubs_title": "Clubs", + "copied_dashboard_url_button": "Dashboard URL Gekopieerd", + "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", + "create_account_button": "Account aanmaken", + "create_account_title": "Maak een nieuw account aan", + "create_club_button": "Club aanmaken", + "create_court_button": "Veld creëren", + "create_demo_account_title": "Maak een demo-account aan", + "create_player_modal_title": "Speler aanmaken", + "create_stage_item_button": "Fase-item aanmaken", + "create_tournament_button": "Toernooi maken", + "created": "Gemaakt", + "current_matches_badge": "Huidige wedstrijden", + "custom_match_duration_label": "Aangepaste wedstrijdduur", + "custom_match_margin_label": "Aangepaste matchmarge", + "customize_checkbox_label": "Aanpassen", "dashboard_link_label": "Dashboard-link", "dashboard_link_placeholder": "beste_toernooi", "dashboard_public_description": "Laat iedereen het dashboard van rondes en wedstrijden zien", - "miscellaneous_title": "Overig", - "miscellaneous_label": "Spelers kunnen in meerdere teams zitten", - "auto_assign_courts_label": "Wijs automatisch velden toe aan wedstrijden", - "save_button": "Opslaan", - "copy_dashboard_url_button": "Kopieer de Dashboard URL", - "copied_dashboard_url_button": "Dashboard URL Gekopieerd", - "filter_stage_item_label": "Filter op item", - "filter_stage_item_placeholder": "Geen filter", - "team_title": "Team", - "current_matches_badge": "Huidige wedstrijden", - "next_matches_badge": "Volgende wedstrijden", - "no_round_title": "Geen ronde", - "no_round_description": "Er zijn nog geen rondes in dit fase-item", - "add_round_button": "Ronde toevoegen", - "no_round_found_title": "Geen rondes gevonden", - "no_round_found_description": "Wacht tot de organisator ze heeft toegevoegd.", - "no_round_found_in_stage_description": "Er zijn nog geen rondes in deze fase", - "tournament_not_started_title": "Het toernooi is nog niet begonnen", - "tournament_not_started_description": "Wacht tot het toernooi begint.", - "edit_name_button": "Naam bewerken", + "dashboard_settings_title": "Dashboardinstellingen", "delete_button": "Verwijderen", - "active_badge_label": "Actief", - "auto_create_matches_button": "Voeg automatisch nieuwe wedstrijden toe", - "add_stage_button": "Fase toevoegen", - "next_stage_button": "Ga naar de volgende fase", - "previous_stage_button": "Ga naar vorige fase", - "multiple_teams_input_label": "Voeg meerdere teams toe. Voer elk team op een aparte regel in", - "multiple_teams_input_placeholder": "Team 1", - "multiple_players_input_label": "Voeg meerdere spelers toe. Voer elke speler op een aparte regel in", - "multiple_players_input_placeholder": "Speler 1", - "edit_details_tab_title": "Details bewerken", - "edit_password_tab_title": "Wachtwoord bewerken", - "no_team_members_description": "Geen leden", - "active_next_round_modal_title": "Wijs tijden en banen toe aan wedstrijden van de volgende ronde", - "active_next_round_modal_description": "Hierdoor worden tijden en speelvelden toegewezen aan wedstrijden van de volgende ronde, wat de ronde is na de huidige geactiveerde (groene) ronde.", - "active_next_round_modal_choose_description": "U kunt kiezen uit een van de volgende opties (vink het selectievakje aan of niet):", - "checkbox_status_checked": "Geselecteerd", - "checkbox_status_unchecked": "Gedeselecteerd", - "active_next_round_modal_choose_option_unchecked": "Gebruik standaardtiming (de volgende wedstrijden worden strak gepland na het einde van de wedstrijden van de actieve ronde, rekening houdend met de marge)", - "active_next_round_modal_choose_option_checked": "Pas de starttijden van de volgende wedstrijden aan om direct te beginnen.", - "adjust_start_times_checkbox_label": "Pas de starttijd van wedstrijden in deze ronde aan naar de huidige tijd", - "accept_policy_checkbox": "Ik heb de bovenstaande richtlijnen gelezen", - "policy_not_accepted": "Geef aan dat u de richtlijnen heeft gelezen", - "plan_next_round_button": "Volgende ronde plannen", - "edit_club_button": "Club bewerken", - "create_club_button": "Club aanmaken", - "club_name_input_placeholder": "Beste Club Ooit", - "team_count_select_elimination_label": "Aantal teams dat doorgaat van de vorige fase", - "team_count_select_elimination_placeholder": "2, 4, 8 etc.", - "team_count_input_round_robin_label": "Aantal teams dat doorgaat van de vorige fase", - "none": "Geen", - "at_least_two_team_validation": "Er zijn minimaal twee teams nodig", - "stage_type_select_label": "Fasetype", - "round_robin_label": "Round Robin", - "single_elimination_label": "Enkele eliminatie", - "swiss_label": "Zwitsers", - "create_stage_item_button": "Fase-item aanmaken", - "add_stage_item_modal_title": "Fase-item toevoegen", - "remove_match_button": "Wedstrijd verwijderen", - "negative_score_validation": "Score kan niet negatief zijn", - "negative_match_duration_validation": "De wedstrijdduur kan niet negatief zijn", - "negative_match_margin_validation": "Matchmarge kan niet negatief zijn", - "edit_match_modal_title": "Wedstrijd bewerken", - "score_of_label": "Score van", - "custom_match_duration_label": "Aangepaste wedstrijdduur", - "customize_checkbox_label": "Aanpassen", - "custom_match_margin_label": "Aangepaste matchmarge", - "set_to_new_button": "Instellen op Nu", - "minutes": "minuten", - "at_least_one_player_validation": "Voer minimaal één speler in", - "active_players_checkbox_label": "Deze spelers zijn actief", - "active_player_checkbox_label": "Deze speler is actief", - "player_name_input_placeholder": "Beste speler ooit", - "save_players_button": "Spelers opslaan", - "single_player_title": "Enkele speler", - "multiple_players_title": "Meerdere spelers", - "create_player_modal_title": "Speler aanmaken", - "add_player_button": "Speler toevoegen", - "edit_player": "Speler bewerken", - "delete_round_button": "Ronde verwijderen", - "edit_round": "Ronde bewerken", - "round_name_input_placeholder": "Beste Ronde Ooit", - "active_round_checkbox_label": "Deze ronde is actief", - "draft_round_checkbox_label": "Deze ronde is een conceptronde", - "home_title": "Start", - "home_spotlight_description": "Ga naar de startpagina", - "clubs_spotlight_description": "Clubs bekijken, toevoegen of verwijderen", - "user_settings_title": "Gebruikersinstellingen", - "user_settings_spotlight_description": "Wijzig naam, e-mailadres, wachtwoord etc.", - "planning_title": "Planning", - "planning_spotlight_description": "Wijzig de planning van de wedstrijden", - "teams_title": "teams", - "teams_spotlight_description": "Teams bekijken, toevoegen of verwijderen", - "players_title": "spelers", - "players_spotlight_description": "Spelers bekijken, toevoegen of verwijderen", - "stage_title": "Fasen", - "stage_spotlight_description": "Verander de indeling van het toernooi", - "courts_title": "velden", - "court_spotlight_description": "Velden bekijken, toevoegen of verwijderen", - "tournament_setting_title": "Toernooi-instellingen", - "tournament_setting_spotlight_description": "Wijzig de instellingen van het toernooi", - "nothing_found_placeholder": "Niets gevonden ...", - "search_placeholder": "Zoeken ...", - "at_least_one_team_validation": "Voer minimaal één team in", - "active_teams_checkbox_label": "Deze teams zijn actief", - "team_name_input_placeholder": "Beste Team Ooit", - "active_team_checkbox_label": "Dit team is actief", - "team_member_select_title": "Teamleden", - "single_team": "Enkel team", - "multiple_teams": "Meerdere teams", - "add_team_button": "Team Toevoegen", - "edit_team_title": "Bewerk Team", - "club_select_label": "Club", - "now_button": "NU", - "logout_title": "Uitloggen", - "user_title": "Gebruiker", - "more_title": "Meer", - "website_title": "Website", - "github_title": "Github", - "api_docs_title": "API documentatie", - "elo_input_label": "Maximaal ELO-verschil", - "only_recommended_input_group_label": "Toon alleen teams die minder wedstrijden hebben gespeeld", - "only_recommended_radio_label": "Alleen aanbevolen", - "all_matches_radio_label": "Alle wedstrijden", - "max_results_input_label": "Maximale resultaten", - "iterations_input_label": "Iteraties", "delete_club_button": "Club verwijderen", - "title": "Titel", - "name_field_text": "naam", "delete_court_button": "Veld verwijderen", - "win_distribution_text_win": "zeges", - "win_distribution_text_draws": "gelijkspellen", - "win_distribution_text_losses": "verliezen", "delete_player_button": "Speler verwijderen", - "status": "Status", - "created": "Gemaakt", - "elo_score": "ELO-score", - "swiss_score": "Zwitserse score", - "name_table_header": "Naam", - "member_table_header": "Leden", - "active": "Actief", - "inactive": "Inactief", + "delete_round_button": "Ronde verwijderen", "delete_team_button": "Team verwijderen", "delete_tournament_button": "Toernooi verwijderen", - "edit_tournament_button": "Toernooi bewerken", - "recommended_badge_title": "Aanbevolen", - "upcoming_matches_empty_table_info": "komende wedstrijden", - "elo_difference": "ELO-verschil", - "swiss_difference": "Zwitsers verschil", - "could_not_find_any_alert": "Kon er geen vinden", + "demo_description": "Om Bracket te testen, kun je een demo starten. Een demo duurt 30 minuten, waarna je account verwijderd wordt. Maak er geen misbruik van.", + "demo_policy_title": "Demo richtlijnen", + "draft_round_checkbox_label": "Deze ronde is een conceptronde", + "drop_match_alert_title": "Plaats hier een wedstrijd", "dropzone_accept_text": "Upload hier bestanden", - "dropzone_reject_text": "De afbeelding moet kleiner zijn dan 10 MB", "dropzone_idle_text": "Logo uploaden", - "upload_placeholder": "Plaats hier een bestand om te uploaden als toernooilogo.", - "number_required": "Heeft een nummer", + "dropzone_reject_text": "De afbeelding moet kleiner zijn dan 10 MB", + "duration_minutes_choose_title": "Vul de duur van de wedstrijden in", + "edit_club_button": "Club bewerken", + "edit_details_tab_title": "Details bewerken", + "edit_match_modal_title": "Wedstrijd bewerken", + "edit_name_button": "Naam bewerken", + "edit_password_tab_title": "Wachtwoord bewerken", + "edit_player": "Speler bewerken", + "edit_profile_title": "Bewerk profiel", + "edit_round": "Ronde bewerken", + "edit_team_title": "Bewerk Team", + "edit_tournament_button": "Toernooi bewerken", + "elo_difference": "ELO-verschil", + "elo_input_label": "Maximaal ELO-verschil", + "elo_score": "ELO-score", + "email_input_label": "E-mailadres", + "email_input_placeholder": "Jouw email", + "empty_email_validation": "Ongeldige e-mail", + "empty_name_validation": "Naam mag niet leeg zijn", + "empty_password_validation": "Wachtwoord mag niet leeg zijn", + "filter_stage_item_label": "Filter op item", + "filter_stage_item_placeholder": "Geen filter", + "forgot_password_button": "Wachtwoord vergeten?", + "github_title": "Github", + "home_spotlight_description": "Ga naar de startpagina", + "home_title": "Start", + "inactive": "Inactief", + "invalid_email_validation": "Ongeldige e-mail", + "invalid_password_validation": "Ongeldig wachtwoord", + "iterations_input_label": "Iteraties", + "login_success_title": "Login succesvol", + "logout_title": "Uitloggen", "lowercase_required": "Heeft een kleine letter", - "uppercase_required": "Heeft een hoofdletter", + "margin_minutes_choose_title": "Vul de marge tussen wedstrijden in", + "match_duration_label": "Wedstrijdduur (minuten)", + "match_filter_option_all": "Alle wedstrijden", + "match_filter_option_current": "Huidige wedstrijden", + "match_filter_option_past": "Verberg eerdere wedstrijden", + "max_results_input_label": "Maximale resultaten", + "member_table_header": "Leden", + "minutes": "minuten", + "miscellaneous_label": "Spelers kunnen in meerdere teams zitten", + "miscellaneous_title": "Overig", + "more_title": "Meer", + "multiple_players_input_label": "Voeg meerdere spelers toe. Voer elke speler op een aparte regel in", + "multiple_players_input_placeholder": "Speler 1", + "multiple_players_title": "Meerdere spelers", + "multiple_teams": "Meerdere teams", + "multiple_teams_input_label": "Voeg meerdere teams toe. Voer elk team op een aparte regel in", + "multiple_teams_input_placeholder": "Team 1", + "name_field_text": "naam", + "name_filter_options_player": "Namen van spelers", + "name_filter_options_team": "Teamnamen", + "name_input_label": "Naam", + "name_input_placeholder": "Uw naam", + "name_table_header": "Naam", + "negative_match_duration_validation": "De wedstrijdduur kan niet negatief zijn", + "negative_match_margin_validation": "Matchmarge kan niet negatief zijn", + "negative_score_validation": "Score kan niet negatief zijn", + "next_matches_badge": "Volgende wedstrijden", + "next_stage_button": "Ga naar de volgende fase", + "no_matches_description": "Voeg eerst fases en fase onderdelen toe. Vervolgens kunnen wedstrijden gepland worden middels de knop rechtsboven.", + "no_matches_title": "Nog geen wedstrijden gepland", + "no_round_description": "Er zijn nog geen rondes in dit fase-item", + "no_round_found_description": "Wacht tot de organisator ze heeft toegevoegd.", + "no_round_found_in_stage_description": "Er zijn nog geen rondes in deze fase", + "no_round_found_title": "Geen rondes gevonden", + "no_round_title": "Geen ronde", + "no_team_members_description": "Geen leden", + "none": "Geen", + "not_found_description": "Helaas, dit is een 404 pagina. ", + "not_found_title": "Je hebt een geheime plek gevonden.", + "nothing_found_placeholder": "Niets gevonden ...", + "now_button": "NU", + "number_required": "Heeft een nummer", + "only_recommended_input_group_label": "Toon alleen teams die minder wedstrijden hebben gespeeld", + "only_recommended_radio_label": "Alleen aanbevolen", + "password_input_label": "Wachtwoord", + "password_input_placeholder": "Je wachtwoord", + "plan_next_round_button": "Volgende ronde plannen", + "planning_of_matches_description": "Begin van het toernooi", + "planning_of_matches_legend": "Planning van de wedstrijden", + "planning_spotlight_description": "Wijzig de planning van de wedstrijden", + "planning_title": "Planning", + "player_name_input_placeholder": "Beste speler ooit", + "players_spotlight_description": "Spelers bekijken, toevoegen of verwijderen", + "players_title": "spelers", + "policy_not_accepted": "Geef aan dat u de richtlijnen heeft gelezen", + "previous_stage_button": "Ga naar vorige fase", + "recommended_badge_title": "Aanbevolen", + "remove_match_button": "Wedstrijd verwijderen", + "round_name_input_placeholder": "Beste Ronde Ooit", + "round_robin_label": "Round Robin", + "save_button": "Opslaan", + "save_players_button": "Spelers opslaan", + "schedule_description": "Plan alle ongeplande wedstrijden", + "schedule_title": "Schema", + "score_of_label": "Score van", + "search_placeholder": "Zoeken ...", + "set_to_new_button": "Instellen op Nu", + "sign_in_title": "Inloggen", + "single_elimination_label": "Enkele eliminatie", + "single_player_title": "Enkele speler", + "single_team": "Enkel team", "special_character_required": "Heeft een speciaal karakter", - "8_characters_required": "Heeft minimaal 8 tekens", - "create_tournament_button": "Toernooi maken" + "stage_spotlight_description": "Verander de indeling van het toernooi", + "stage_title": "Fasen", + "stage_type_select_label": "Fasetype", + "start_demo_button": "Demo starten", + "start_time_choose_title": "Kies een starttijd", + "status": "Status", + "swiss_difference": "Zwitsers verschil", + "swiss_label": "Zwitsers", + "swiss_score": "Zwitserse score", + "team_count_input_round_robin_label": "Aantal teams dat doorgaat van de vorige fase", + "team_count_select_elimination_label": "Aantal teams dat doorgaat van de vorige fase", + "team_count_select_elimination_placeholder": "2, 4, 8 etc.", + "team_member_select_title": "Teamleden", + "team_name_input_placeholder": "Beste Team Ooit", + "team_title": "Team", + "teams_spotlight_description": "Teams bekijken, toevoegen of verwijderen", + "teams_title": "teams", + "time_between_matches_label": "Tijd tussen de wedstrijden (minuten)", + "title": "Titel", + "too_short_dashboard_link_validation": "Dashboard link is kort", + "too_short_name_validation": "Naam is te kort", + "too_short_password_validation": "Wachtwoord is te kort", + "tournament_name_input_placeholder": "Beste Toernooi Ooit", + "tournament_not_started_description": "Wacht tot het toernooi begint.", + "tournament_not_started_title": "Het toernooi is nog niet begonnen", + "tournament_setting_spotlight_description": "Wijzig de instellingen van het toernooi", + "tournament_setting_title": "Toernooi-instellingen", + "tournament_title": "toernooi", + "tournaments_title": "toernooien", + "upcoming_matches_empty_table_info": "komende wedstrijden", + "upload_placeholder": "Plaats hier een bestand om te uploaden als toernooilogo.", + "uppercase_required": "Heeft een hoofdletter", + "user_settings_spotlight_description": "Wijzig naam, e-mailadres, wachtwoord etc.", + "user_settings_title": "Gebruikersinstellingen", + "user_title": "Gebruiker", + "view_dashboard_button": "Dashboard bekijken", + "website_title": "Website", + "welcome_title": "Welkom bij", + "win_distribution_text_draws": "gelijkspellen", + "win_distribution_text_losses": "verliezen", + "win_distribution_text_win": "zeges" } diff --git a/frontend/public/locales/zh-CN/common.json b/frontend/public/locales/zh-CN/common.json index 001fbc9a..e922e179 100644 --- a/frontend/public/locales/zh-CN/common.json +++ b/frontend/public/locales/zh-CN/common.json @@ -1,216 +1,216 @@ { - "not_found_title": "你找到了一个秘密地方。", - "not_found_description": "不幸的是,这只是一个404页面。你可能输入了错误的地址,或者页面已经被移动到另一个URL。", - "back_home_nav": "带我回到主页", - "clubs_title": "俱乐部", - "empty_name_validation": "名称不能为空", - "empty_email_validation": "无效的电子邮件", - "empty_password_validation": "密码不能为空", - "too_short_name_validation": "名称太短", - "too_short_dashboard_link_validation": "仪表板链接太短", - "too_short_password_validation": "密码太短", - "invalid_email_validation": "无效的电子邮件", - "invalid_password_validation": "无效的密码", - "create_account_title": "创建一个新的计数", - "create_account_alert_title": "不可用", - "create_account_alert_description": "由于括号仍处于测试阶段,因此暂时禁用了此域上的帐户创建", - "create_account_button": "创建帐户", - "email_input_label": "电子邮件地址", - "email_input_placeholder": "你的电子邮件", - "name_input_label": "名称", - "name_input_placeholder": "你的名称", - "password_input_label": "密码", - "password_input_placeholder": "你的密码", - "back_to_login_nav": "返回登录页面", - "tournaments_title": "锦标赛", - "tournament_title": "锦标赛", - "login_success_title": "登录成功", - "welcome_title": "欢迎来到", - "sign_in_title": "登录", - "forgot_password_button": "忘记密码?", - "edit_profile_title": "编辑个人资料", - "match_filter_option_all": "所有比赛", - "match_filter_option_past": "隐藏过去的比赛", - "match_filter_option_current": "当前的比赛", - "name_filter_options_team": "团队名称", - "name_filter_options_player": "玩家名称", - "view_dashboard_button": "查看仪表板", - "add_court_title": "添加法院", - "create_court_button": "创建法院", - "court_name_input_placeholder":"最好的法院", - "no_matches_description": "还没有比赛", - "drop_match_alert_title": "在这里放下一场比赛", - "schedule_title": "时间表", - "schedule_description": "安排所有未安排的比赛", - "club_choose_title": "请选择一个俱乐部", - "start_time_choose_title": "请选择开始时间", - "duration_minutes_choose_title": "请选择比赛的持续时间", - "margin_minutes_choose_title": "请选择比赛之间的间隔", - "tournament_name_input_placeholder": "最佳锦标赛", - "club_select_placeholder": "为此锦标赛选择一个俱乐部", - "planning_of_matches_legend": "比赛规划", - "planning_of_matches_description": "锦标赛开始", - "match_duration_label": "比赛持续时间(分钟)", - "time_between_matches_label": "比赛间隔时间(分钟)", - "dashboard_settings_title": "仪表板设置", - "dashboard_link_label": "仪表板链接", - "dashboard_link_placeholder": "最佳锦标赛", - "dashboard_public_description": "允许任何人查看轮次和比赛的仪表板", - "miscellaneous_title": "杂项", - "miscellaneous_label": "允许玩家加入多个队伍", - "auto_assign_courts_label": "自动为比赛分配场地", - "save_button": "保存", - "copy_dashboard_url_button": "复制仪表板URL", - "copied_dashboard_url_button": "已复制仪表板URL", - "filter_stage_item_label": "筛选阶段项目", - "filter_stage_item_placeholder": "无筛选", - "team_title": "队伍", - "current_matches_badge": "当前比赛", - "next_matches_badge": "下一场比赛", - "no_round_title": "无轮次", - "no_round_description": "此阶段项目尚无轮次", - "add_round_button": "添加轮次", - "no_round_found_title": "未找到轮次", - "no_round_found_description": "请等待组织者添加。", - "no_round_found_in_stage_description": "此阶段尚无轮次", - "tournament_not_started_title": "锦标赛尚未开始", - "tournament_not_started_description": "请等待锦标赛开始。", - "edit_name_button": "编辑名称", - "delete_button": "删除", - "active_badge_label": "活跃", - "auto_create_matches_button": "自动添加新比赛", - "add_stage_button": "添加阶段", - "next_stage_button": "前往下一阶段", - "previous_stage_button": "前往上一阶段", - "multiple_teams_input_label": "添加多个队伍。每行放一个队伍", - "multiple_teams_input_placeholder": "队伍1", - "multiple_players_input_label": "添加多个玩家。每行放一个玩家", - "multiple_players_input_placeholder": "玩家1", - "edit_details_tab_title": "编辑详情", - "edit_password_tab_title": "编辑密码", - "no_team_members_description": "无成员", - "active_next_round_modal_title": "为下一轮比赛分配时间和场地", - "active_next_round_modal_description": "这将为下一轮比赛(即当前激活(绿色)轮次之后的轮次)分配时间和场地。", - "active_next_round_modal_choose_description": "你可以选择(勾选或不勾选复选框):", - "checkbox_status_checked": "已勾选", - "checkbox_status_unchecked": "未勾选", - "active_next_round_modal_choose_option_unchecked": "使用默认时间(下一场比赛将在当前轮次结束后紧接着计划,考虑到间隔时间)", - "active_next_round_modal_choose_option_checked": "调整下一场比赛的开始时间为立即开始(现在)。这将通过修改上一轮比赛的间隔时间来完成。", - "adjust_start_times_checkbox_label": "将本轮比赛的开始时间调整为当前时间", - "plan_next_round_button": "计划下一轮", - "edit_club_button": "编辑俱乐部", - "create_club_button": "创建俱乐部", - "club_name_input_placeholder": "最佳俱乐部", - "team_count_select_elimination_label": "从上一阶段晋级的队伍数量", - "team_count_select_elimination_placeholder": "2,4,8等", - "team_count_input_round_robin_label": "从上一阶段晋级的队伍数量", - "none": "无", - "at_least_two_team_validation": "需要至少两个队伍", - "stage_type_select_label": "阶段类型", - "round_robin_label": "循环赛", - "single_elimination_label": "单淘汰赛", - "swiss_label": "瑞士制", - "create_stage_item_button": "创建阶段项目", - "add_stage_item_modal_title": "添加阶段项目", - "remove_match_button": "移除比赛", - "negative_score_validation": "分数不能为负", - "negative_match_duration_validation": "比赛持续时间不能为负", - "negative_match_margin_validation": "比赛间隔时间不能为负", - "edit_match_modal_title": "编辑比赛", - "score_of_label": "得分", - "custom_match_duration_label": "自定义比赛持续时间", - "customize_checkbox_label": "自定义", - "custom_match_margin_label": "自定义比赛间隔时间", - "minutes": "分钟", - "at_least_one_player_validation": "输入至少一个玩家", - "active_players_checkbox_label": "这些玩家是活跃的", - "active_player_checkbox_label": "这个玩家是活跃的", - "player_name_input_placeholder": "最佳玩家", - "save_players_button": "保存玩家", - "single_player_title": "单个玩家", - "multiple_players_title": "多个玩家", - "create_player_modal_title": "创建玩家", - "add_player_button": "添加玩家", - "edit_player": "编辑玩家", - "delete_round_button": "删除轮次", - "edit_round": "编辑轮次", - "round_name_input_placeholder": "最佳轮次", - "active_round_checkbox_label": "这个轮次是活跃的", - "draft_round_checkbox_label": "这个轮次是草稿轮次", - "home_title": "主页", - "home_spotlight_description": "前往主页", - "clubs_spotlight_description": "查看、添加或删除俱乐部", - "user_settings_title": "用户设置", - "user_settings_spotlight_description": "更改名称、电子邮件、密码等", - "planning_title": "规划", - "planning_spotlight_description": "更改比赛规划", - "teams_title": "队伍", - "teams_spotlight_description": "查看、添加或删除队伍", - "players_title": "玩家", - "players_spotlight_description": "查看、添加或删除玩家", - "stage_title": "阶段", - "stage_spotlight_description": "更改锦标赛的布局", - "courts_title": "场地", - "court_spotlight_description": "查看、添加或删除场地", - "tournament_setting_title": "锦标赛设置", - "tournament_setting_spotlight_description": "更改锦标赛的设置", - "nothing_found_placeholder": "未找到任何内容...", - "search_placeholder": "搜索...", - "at_least_one_team_validation": "输入至少一个队伍", - "active_teams_checkbox_label": "这些队伍是活跃的", - "team_name_input_placeholder": "最佳队伍", - "active_team_checkbox_label": "这个队伍是活跃的", - "team_member_select_title": "队伍成员", - "single_team": "单个队伍", - "multiple_teams": "多个队伍", - "add_team_button": "添加队伍", - "edit_team_title": "编辑队伍", - "club_select_label": "俱乐部", - "now_button": "现在", - "logout_title": "登出", - "user_title": "用户", - "more_title": "更多", - "website_title": "网站", - "github_title": "Github", - "api_docs_title": "API 文档", - "elo_input_label": "最大 ELO 差值", - "only_recommended_input_group_label": "只显示比赛次数较少的队伍", - "only_recommended_radio_label": "只推荐", - "all_matches_radio_label": "所有比赛", - "max_results_input_label": "最大结果", - "iterations_input_label": "迭代", - "delete_club_button": "删除俱乐部", - "title": "标题", - "name_field_text": "名称", - "delete_court_button": "删除场地", - "win_distribution_text_win": "胜利", - "win_distribution_text_draws": "平局", - "win_distribution_text_losses": "失败", - "delete_player_button": "删除玩家", - "status": "状态", - "created": "已创建", - "elo_score": "ELO 分数", - "swiss_score": "瑞士分数", - "name_table_header": "名称", - "member_table_header": "成员", - "active": "活跃", - "inactive": "不活跃", - "delete_team_button": "删除队伍", - "delete_tournament_button": "删除锦标赛", - "edit_tournament_button": "编辑锦标赛", - "recommended_badge_title": "推荐", - "upcoming_matches_empty_table_info":"即将进行的比赛", - "elo_difference": "ELO 差值", - "swiss_difference": "瑞士差值", - "could_not_find_any_alert": "找不到任何", - "dropzone_accept_text": "在此处放置文件", - "dropzone_reject_text": "图片必须小于 10MB", - "dropzone_idle_text": "上传标志", - "upload_placeholder": "在此处放置文件以上传为锦标赛标志。", - "number_required": "包含数字", - "lowercase_required": "包含小写字母", - "uppercase_required": "包含大写字母", - "special_character_required": "包含特殊字符", - "8_characters_required": "至少有 8 个字符", - "create_tournament_button": "创建锦标赛" + "8_characters_required": "至少有 8 个字符", + "active": "活跃", + "active_badge_label": "活跃", + "active_next_round_modal_choose_description": "你可以选择(勾选或不勾选复选框):", + "active_next_round_modal_choose_option_checked": "调整下一场比赛的开始时间为立即开始(现在)。这将通过修改上一轮比赛的间隔时间来完成。", + "active_next_round_modal_choose_option_unchecked": "使用默认时间(下一场比赛将在当前轮次结束后紧接着计划,考虑到间隔时间)", + "active_next_round_modal_description": "这将为下一轮比赛(即当前激活(绿色)轮次之后的轮次)分配时间和场地。", + "active_next_round_modal_title": "为下一轮比赛分配时间和场地", + "active_player_checkbox_label": "这个玩家是活跃的", + "active_players_checkbox_label": "这些玩家是活跃的", + "active_round_checkbox_label": "这个轮次是活跃的", + "active_team_checkbox_label": "这个队伍是活跃的", + "active_teams_checkbox_label": "这些队伍是活跃的", + "add_court_title": "添加法院", + "add_player_button": "添加玩家", + "add_round_button": "添加轮次", + "add_stage_button": "添加阶段", + "add_stage_item_modal_title": "添加阶段项目", + "add_team_button": "添加队伍", + "adjust_start_times_checkbox_label": "将本轮比赛的开始时间调整为当前时间", + "all_matches_radio_label": "所有比赛", + "api_docs_title": "API 文档", + "at_least_one_player_validation": "输入至少一个玩家", + "at_least_one_team_validation": "输入至少一个队伍", + "at_least_two_team_validation": "需要至少两个队伍", + "auto_assign_courts_label": "自动为比赛分配场地", + "auto_create_matches_button": "自动添加新比赛", + "back_home_nav": "带我回到主页", + "back_to_login_nav": "返回登录页面", + "checkbox_status_checked": "已勾选", + "checkbox_status_unchecked": "未勾选", + "club_choose_title": "请选择一个俱乐部", + "club_name_input_placeholder": "最佳俱乐部", + "club_select_label": "俱乐部", + "club_select_placeholder": "为此锦标赛选择一个俱乐部", + "clubs_spotlight_description": "查看、添加或删除俱乐部", + "clubs_title": "俱乐部", + "copied_dashboard_url_button": "已复制仪表板URL", + "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": "不可用", + "create_account_button": "创建帐户", + "create_account_title": "创建一个新的计数", + "create_club_button": "创建俱乐部", + "create_court_button": "创建法院", + "create_player_modal_title": "创建玩家", + "create_stage_item_button": "创建阶段项目", + "create_tournament_button": "创建锦标赛", + "created": "已创建", + "current_matches_badge": "当前比赛", + "custom_match_duration_label": "自定义比赛持续时间", + "custom_match_margin_label": "自定义比赛间隔时间", + "customize_checkbox_label": "自定义", + "dashboard_link_label": "仪表板链接", + "dashboard_link_placeholder": "最佳锦标赛", + "dashboard_public_description": "允许任何人查看轮次和比赛的仪表板", + "dashboard_settings_title": "仪表板设置", + "delete_button": "删除", + "delete_club_button": "删除俱乐部", + "delete_court_button": "删除场地", + "delete_player_button": "删除玩家", + "delete_round_button": "删除轮次", + "delete_team_button": "删除队伍", + "delete_tournament_button": "删除锦标赛", + "draft_round_checkbox_label": "这个轮次是草稿轮次", + "drop_match_alert_title": "在这里放下一场比赛", + "dropzone_accept_text": "在此处放置文件", + "dropzone_idle_text": "上传标志", + "dropzone_reject_text": "图片必须小于 10MB", + "duration_minutes_choose_title": "请选择比赛的持续时间", + "edit_club_button": "编辑俱乐部", + "edit_details_tab_title": "编辑详情", + "edit_match_modal_title": "编辑比赛", + "edit_name_button": "编辑名称", + "edit_password_tab_title": "编辑密码", + "edit_player": "编辑玩家", + "edit_profile_title": "编辑个人资料", + "edit_round": "编辑轮次", + "edit_team_title": "编辑队伍", + "edit_tournament_button": "编辑锦标赛", + "elo_difference": "ELO 差值", + "elo_input_label": "最大 ELO 差值", + "elo_score": "ELO 分数", + "email_input_label": "电子邮件地址", + "email_input_placeholder": "你的电子邮件", + "empty_email_validation": "无效的电子邮件", + "empty_name_validation": "名称不能为空", + "empty_password_validation": "密码不能为空", + "filter_stage_item_label": "筛选阶段项目", + "filter_stage_item_placeholder": "无筛选", + "forgot_password_button": "忘记密码?", + "github_title": "Github", + "home_spotlight_description": "前往主页", + "home_title": "主页", + "inactive": "不活跃", + "invalid_email_validation": "无效的电子邮件", + "invalid_password_validation": "无效的密码", + "iterations_input_label": "迭代", + "login_success_title": "登录成功", + "logout_title": "登出", + "lowercase_required": "包含小写字母", + "margin_minutes_choose_title": "请选择比赛之间的间隔", + "match_duration_label": "比赛持续时间(分钟)", + "match_filter_option_all": "所有比赛", + "match_filter_option_current": "当前的比赛", + "match_filter_option_past": "隐藏过去的比赛", + "max_results_input_label": "最大结果", + "member_table_header": "成员", + "minutes": "分钟", + "miscellaneous_label": "允许玩家加入多个队伍", + "miscellaneous_title": "杂项", + "more_title": "更多", + "multiple_players_input_label": "添加多个玩家。每行放一个玩家", + "multiple_players_input_placeholder": "玩家1", + "multiple_players_title": "多个玩家", + "multiple_teams": "多个队伍", + "multiple_teams_input_label": "添加多个队伍。每行放一个队伍", + "multiple_teams_input_placeholder": "队伍1", + "name_field_text": "名称", + "name_filter_options_player": "玩家名称", + "name_filter_options_team": "团队名称", + "name_input_label": "名称", + "name_input_placeholder": "你的名称", + "name_table_header": "名称", + "negative_match_duration_validation": "比赛持续时间不能为负", + "negative_match_margin_validation": "比赛间隔时间不能为负", + "negative_score_validation": "分数不能为负", + "next_matches_badge": "下一场比赛", + "next_stage_button": "前往下一阶段", + "no_matches_title": "还没有比赛", + "no_round_description": "此阶段项目尚无轮次", + "no_round_found_description": "请等待组织者添加。", + "no_round_found_in_stage_description": "此阶段尚无轮次", + "no_round_found_title": "未找到轮次", + "no_round_title": "无轮次", + "no_team_members_description": "无成员", + "none": "无", + "not_found_description": "不幸的是,这只是一个404页面。你可能输入了错误的地址,或者页面已经被移动到另一个URL。", + "not_found_title": "你找到了一个秘密地方。", + "nothing_found_placeholder": "未找到任何内容...", + "now_button": "现在", + "number_required": "包含数字", + "only_recommended_input_group_label": "只显示比赛次数较少的队伍", + "only_recommended_radio_label": "只推荐", + "password_input_label": "密码", + "password_input_placeholder": "你的密码", + "plan_next_round_button": "计划下一轮", + "planning_of_matches_description": "锦标赛开始", + "planning_of_matches_legend": "比赛规划", + "planning_spotlight_description": "更改比赛规划", + "planning_title": "规划", + "player_name_input_placeholder": "最佳玩家", + "players_spotlight_description": "查看、添加或删除玩家", + "players_title": "玩家", + "previous_stage_button": "前往上一阶段", + "recommended_badge_title": "推荐", + "remove_match_button": "移除比赛", + "round_name_input_placeholder": "最佳轮次", + "round_robin_label": "循环赛", + "save_button": "保存", + "save_players_button": "保存玩家", + "schedule_description": "安排所有未安排的比赛", + "schedule_title": "时间表", + "score_of_label": "得分", + "search_placeholder": "搜索...", + "sign_in_title": "登录", + "single_elimination_label": "单淘汰赛", + "single_player_title": "单个玩家", + "single_team": "单个队伍", + "special_character_required": "包含特殊字符", + "stage_spotlight_description": "更改锦标赛的布局", + "stage_title": "阶段", + "stage_type_select_label": "阶段类型", + "start_time_choose_title": "请选择开始时间", + "status": "状态", + "swiss_difference": "瑞士差值", + "swiss_label": "瑞士制", + "swiss_score": "瑞士分数", + "team_count_input_round_robin_label": "从上一阶段晋级的队伍数量", + "team_count_select_elimination_label": "从上一阶段晋级的队伍数量", + "team_count_select_elimination_placeholder": "2,4,8等", + "team_member_select_title": "队伍成员", + "team_name_input_placeholder": "最佳队伍", + "team_title": "队伍", + "teams_spotlight_description": "查看、添加或删除队伍", + "teams_title": "队伍", + "time_between_matches_label": "比赛间隔时间(分钟)", + "title": "标题", + "too_short_dashboard_link_validation": "仪表板链接太短", + "too_short_name_validation": "名称太短", + "too_short_password_validation": "密码太短", + "tournament_name_input_placeholder": "最佳锦标赛", + "tournament_not_started_description": "请等待锦标赛开始。", + "tournament_not_started_title": "锦标赛尚未开始", + "tournament_setting_spotlight_description": "更改锦标赛的设置", + "tournament_setting_title": "锦标赛设置", + "tournament_title": "锦标赛", + "tournaments_title": "锦标赛", + "upcoming_matches_empty_table_info": "即将进行的比赛", + "upload_placeholder": "在此处放置文件以上传为锦标赛标志。", + "uppercase_required": "包含大写字母", + "user_settings_spotlight_description": "更改名称、电子邮件、密码等", + "user_settings_title": "用户设置", + "user_title": "用户", + "view_dashboard_button": "查看仪表板", + "website_title": "网站", + "welcome_title": "欢迎来到", + "win_distribution_text_draws": "平局", + "win_distribution_text_losses": "失败", + "win_distribution_text_win": "胜利" } \ No newline at end of file diff --git a/frontend/src/components/brackets/brackets.tsx b/frontend/src/components/brackets/brackets.tsx index b19170bd..ea33bd37 100644 --- a/frontend/src/components/brackets/brackets.tsx +++ b/frontend/src/components/brackets/brackets.tsx @@ -1,7 +1,6 @@ import { Alert, Button, Container, Grid, Group, Skeleton } from '@mantine/core'; import { GoPlus } from '@react-icons/all-files/go/GoPlus'; import { IconAlertCircle } from '@tabler/icons-react'; -import { TFunction } from 'i18next'; import { useTranslation } from 'next-i18next'; import React from 'react'; import { SWRResponse } from 'swr'; @@ -13,11 +12,12 @@ import { StageItemWithRounds, stageItemIsHandledAutomatically } from '../../inte import { TournamentMinimal } from '../../interfaces/tournament'; import { createRound } from '../../services/round'; import ActivateNextRoundModal from '../modals/activate_next_round_modal'; +import { Translator } from '../utils/types'; import { responseIsValid } from '../utils/util'; import Round from './round'; function getRoundsGridCols( - t: TFunction<'translation', undefined>, + t: Translator, stageItem: StageItemWithRounds, tournamentData: TournamentMinimal, swrStagesResponse: SWRResponse, diff --git a/frontend/src/components/buttons/create_stage.tsx b/frontend/src/components/buttons/create_stage.tsx index d5a93914..6e880346 100644 --- a/frontend/src/components/buttons/create_stage.tsx +++ b/frontend/src/components/buttons/create_stage.tsx @@ -32,3 +32,29 @@ export default function CreateStageButton({ ); } + +export function CreateStageButtonLarge({ + tournament, + swrStagesResponse, +}: { + tournament: Tournament; + swrStagesResponse: SWRResponse; +}) { + const { t } = useTranslation(); + + return ( + + ); +} diff --git a/frontend/src/components/info/player_score.tsx b/frontend/src/components/info/player_score.tsx index 738700fb..dc394658 100644 --- a/frontend/src/components/info/player_score.tsx +++ b/frontend/src/components/info/player_score.tsx @@ -13,7 +13,7 @@ export function PlayerScore({ score, min_score, max_score, decimals }: ScoreProp return ( - {score.toFixed(decimals)} + {Number(score).toFixed(decimals)} ); diff --git a/frontend/src/components/modals/create_stage_item.tsx b/frontend/src/components/modals/create_stage_item.tsx index c22c091d..3f5eef88 100644 --- a/frontend/src/components/modals/create_stage_item.tsx +++ b/frontend/src/components/modals/create_stage_item.tsx @@ -120,6 +120,7 @@ export function CreateStageItemModal({ }, }); + // TODO: Refactor lookups into one request. const teamsMap = getTeamsLookup(tournament != null ? tournament.id : -1); const stageItemMap = getStageItemLookup(swrStagesResponse); diff --git a/frontend/src/components/no_content/empty_table_info.module.css b/frontend/src/components/no_content/empty_table_info.module.css new file mode 100644 index 00000000..c33a75e9 --- /dev/null +++ b/frontend/src/components/no_content/empty_table_info.module.css @@ -0,0 +1,40 @@ +.root { + padding-top: rem(80px); + padding-bottom: rem(120px); + background-color: var(--mantine-color-blue-filled); +} + +.label { + text-align: center; + font-weight: 900; + font-size: rem(220px); + line-height: 1; + margin-bottom: calc(var(--mantine-spacing-xl) * 1.5); + color: light-dark(var(--mantine-color-black), var(--mantine-color-white)); + + @media (max-width: $mantine-breakpoint-sm) { + font-size: rem(120px); + } +} + +.title { + font-family: + Greycliff CF, + var(--mantine-font-family); + text-align: center; + font-weight: 900; + font-size: rem(38px); + color: light-dark(var(--mantine-color-black), var(--mantine-color-white)); + + @media (max-width: $mantine-breakpoint-sm) { + font-size: rem(32px); + } +} + +.description { + max-width: rem(540px); + margin: auto; + margin-top: var(--mantine-spacing-xl); + margin-bottom: calc(var(--mantine-spacing-xl) * 1.5); + color: light-dark(var(--mantine-color-black), var(--mantine-color-white)); +} diff --git a/frontend/src/components/no_content/empty_table_info.tsx b/frontend/src/components/no_content/empty_table_info.tsx new file mode 100644 index 00000000..d972a30b --- /dev/null +++ b/frontend/src/components/no_content/empty_table_info.tsx @@ -0,0 +1,44 @@ +import { Alert, Container, Group, Text, Title } from '@mantine/core'; +import { IconAlertCircle } from '@tabler/icons-react'; +import { useTranslation } from 'next-i18next'; +import React from 'react'; +import { MdOutlineConstruction } from 'react-icons/md'; + +import classes from './empty_table_info.module.css'; + +export function EmptyTableInfo({ + entity_name, + message = '', +}: { + entity_name: string; + message?: string; +}) { + const { t } = useTranslation(); + return ( + } + title={`No ${entity_name} found`} + color="blue" + radius="lg" + mt={8} + > + {t('could_not_find_any_alert')} {entity_name} + {message} + + ); +} + +export function NoContent({ title, description }: { title: string; description?: string }) { + return ( + +
+ +
+ {title} + + {description} + + +
+ ); +} diff --git a/frontend/src/components/tables/clubs.tsx b/frontend/src/components/tables/clubs.tsx index 89940ac0..0e2a9009 100644 --- a/frontend/src/components/tables/clubs.tsx +++ b/frontend/src/components/tables/clubs.tsx @@ -7,8 +7,9 @@ import { Club } from '../../interfaces/club'; import { deleteClub } from '../../services/club'; import DeleteButton from '../buttons/delete'; import ClubModal from '../modals/club_modal'; -import { EmptyTableInfo } from '../utils/empty_table_info'; +import { EmptyTableInfo } from '../no_content/empty_table_info'; import RequestErrorAlert from '../utils/error_alert'; +import { TableSkeletonSingleColumn } from '../utils/skeletons'; import TableLayout, { ThNotSortable, ThSortable, getTableState, sortTableEntries } from './table'; export default function ClubsTable({ swrClubsResponse }: { swrClubsResponse: SWRResponse }) { @@ -17,6 +18,9 @@ export default function ClubsTable({ swrClubsResponse }: { swrClubsResponse: SWR const { t } = useTranslation(); if (swrClubsResponse.error) return ; + if (swrClubsResponse.isLoading || swrClubsResponse.isValidating) { + return ; + } const rows = clubs .sort((p1: Club, p2: Club) => sortTableEntries(p1, p2, tableState)) diff --git a/frontend/src/components/tables/courts.tsx b/frontend/src/components/tables/courts.tsx index 7f30c6d3..2a43e7ec 100644 --- a/frontend/src/components/tables/courts.tsx +++ b/frontend/src/components/tables/courts.tsx @@ -1,5 +1,4 @@ import { Table } from '@mantine/core'; -import { useTranslation } from 'next-i18next'; import React from 'react'; import { SWRResponse } from 'swr'; @@ -7,21 +6,28 @@ import { Court } from '../../interfaces/court'; import { Tournament } from '../../interfaces/tournament'; import { deleteCourt } from '../../services/court'; import DeleteButton from '../buttons/delete'; -import { EmptyTableInfo } from '../utils/empty_table_info'; +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 { t } = useTranslation(); const courts: Court[] = swrCourtsResponse.data != null ? swrCourtsResponse.data.data : []; const tableState = getTableState('id'); + if (swrCourtsResponse.isLoading || swrCourtsResponse.isValidating) { + return ; + } + if (swrCourtsResponse.error) return ; const rows = courts diff --git a/frontend/src/components/tables/players.tsx b/frontend/src/components/tables/players.tsx index ed46f86e..8d757d1f 100644 --- a/frontend/src/components/tables/players.tsx +++ b/frontend/src/components/tables/players.tsx @@ -10,9 +10,10 @@ import DeleteButton from '../buttons/delete'; import { PlayerScore } from '../info/player_score'; import { WinDistribution } from '../info/player_statistics'; import PlayerUpdateModal from '../modals/player_update_modal'; +import { EmptyTableInfo } from '../no_content/empty_table_info'; import { DateTime } from '../utils/datetime'; -import { EmptyTableInfo } from '../utils/empty_table_info'; import RequestErrorAlert from '../utils/error_alert'; +import { TableSkeletonSingleColumn } from '../utils/skeletons'; import TableLayout, { ThNotSortable, ThSortable, getTableState, sortTableEntries } from './table'; export function WinDistributionTitle() { @@ -52,6 +53,10 @@ export default function PlayersTable({ if (swrPlayersResponse.error) return ; + if (swrPlayersResponse.isLoading || swrPlayersResponse.isValidating) { + return ; + } + const rows = players .sort((p1: Player, p2: Player) => sortTableEntries(p1, p2, tableState)) .map((player) => ( diff --git a/frontend/src/components/tables/standings.tsx b/frontend/src/components/tables/standings.tsx index 278f44f7..caa4944b 100644 --- a/frontend/src/components/tables/standings.tsx +++ b/frontend/src/components/tables/standings.tsx @@ -7,7 +7,7 @@ import { TeamInterface } from '../../interfaces/team'; import PlayerList from '../info/player_list'; import { PlayerScore } from '../info/player_score'; import { WinDistribution } from '../info/player_statistics'; -import { EmptyTableInfo } from '../utils/empty_table_info'; +import { EmptyTableInfo } from '../no_content/empty_table_info'; import RequestErrorAlert from '../utils/error_alert'; import { WinDistributionTitle } from './players'; import { ThNotSortable, ThSortable, getTableState, sortTableEntries } from './table'; diff --git a/frontend/src/components/tables/teams.tsx b/frontend/src/components/tables/teams.tsx index 3c5e68ac..179e96ee 100644 --- a/frontend/src/components/tables/teams.tsx +++ b/frontend/src/components/tables/teams.tsx @@ -9,9 +9,10 @@ import { deleteTeam } from '../../services/team'; import DeleteButton from '../buttons/delete'; import PlayerList from '../info/player_list'; import TeamUpdateModal from '../modals/team_update_modal'; +import { EmptyTableInfo } from '../no_content/empty_table_info'; import { DateTime } from '../utils/datetime'; -import { EmptyTableInfo } from '../utils/empty_table_info'; import RequestErrorAlert from '../utils/error_alert'; +import { TableSkeletonSingleColumn } from '../utils/skeletons'; import TableLayout, { ThNotSortable, ThSortable, getTableState, sortTableEntries } from './table'; export default function TeamsTable({ @@ -27,6 +28,10 @@ export default function TeamsTable({ const tableState = getTableState('name'); if (swrTeamsResponse.error) return ; + if (swrTeamsResponse.isLoading || swrTeamsResponse.isValidating) { + return ; + } + const rows = teams .sort((p1: TeamInterface, p2: TeamInterface) => sortTableEntries(p1, p2, tableState)) .map((team) => ( diff --git a/frontend/src/components/tables/tournaments.tsx b/frontend/src/components/tables/tournaments.tsx index ba102fa8..c473554a 100644 --- a/frontend/src/components/tables/tournaments.tsx +++ b/frontend/src/components/tables/tournaments.tsx @@ -9,9 +9,10 @@ import { SWRResponse } from 'swr'; import { Tournament } from '../../interfaces/tournament'; import { deleteTournament } from '../../services/tournament'; import DeleteButton from '../buttons/delete'; +import { EmptyTableInfo } from '../no_content/empty_table_info'; import { DateTime } from '../utils/datetime'; -import { EmptyTableInfo } from '../utils/empty_table_info'; import RequestErrorAlert from '../utils/error_alert'; +import { TableSkeletonSingleColumn } from '../utils/skeletons'; import TableLayout, { ThNotSortable, ThSortable, getTableState, sortTableEntries } from './table'; export default function TournamentsTable({ @@ -26,6 +27,9 @@ export default function TournamentsTable({ if (swrTournamentsResponse.error) { return ; } + if (swrTournamentsResponse.isLoading || swrTournamentsResponse.isValidating) { + return ; + } const tournaments: Tournament[] = swrTournamentsResponse.data != null ? swrTournamentsResponse.data.data : []; diff --git a/frontend/src/components/tables/upcoming_matches.tsx b/frontend/src/components/tables/upcoming_matches.tsx index c438c9eb..0722c4b4 100644 --- a/frontend/src/components/tables/upcoming_matches.tsx +++ b/frontend/src/components/tables/upcoming_matches.tsx @@ -9,7 +9,7 @@ import { MatchCreateBodyInterface, UpcomingMatchInterface } from '../../interfac import { Tournament } from '../../interfaces/tournament'; import { createMatch } from '../../services/match'; import PlayerList from '../info/player_list'; -import { EmptyTableInfo } from '../utils/empty_table_info'; +import { EmptyTableInfo } from '../no_content/empty_table_info'; import RequestErrorAlert from '../utils/error_alert'; import TableLayout, { ThNotSortable, ThSortable, getTableState, sortTableEntries } from './table'; diff --git a/frontend/src/components/utils/empty_table_info.tsx b/frontend/src/components/utils/empty_table_info.tsx deleted file mode 100644 index 39e3c024..00000000 --- a/frontend/src/components/utils/empty_table_info.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { Alert } from '@mantine/core'; -import { IconAlertCircle } from '@tabler/icons-react'; -import { useTranslation } from 'next-i18next'; -import React from 'react'; - -export function EmptyTableInfo({ - entity_name, - message = '', -}: { - entity_name: string; - message?: string; -}) { - const { t } = useTranslation(); - return ( - } - title={`No ${entity_name} found`} - color="blue" - radius="lg" - mt={8} - > - {t('could_not_find_any_alert')} {entity_name} - {message} - - ); -} diff --git a/frontend/src/components/utils/skeletons.tsx b/frontend/src/components/utils/skeletons.tsx index bfe91410..38751322 100644 --- a/frontend/src/components/utils/skeletons.tsx +++ b/frontend/src/components/utils/skeletons.tsx @@ -11,6 +11,16 @@ export function GenericSkeleton() { ); } +export function TableSkeletonSingleColumn() { + return ( + <> + + + + + ); +} + export function TableSkeletonTwoColumns() { return (
@@ -31,3 +41,22 @@ export function TableSkeletonTwoColumns() {
); } + +export function TableSkeletonTwoColumnsSmall() { + return ( +
+ + + + + + + + + + + + +
+ ); +} diff --git a/frontend/src/components/utils/types.tsx b/frontend/src/components/utils/types.tsx new file mode 100644 index 00000000..1e44775f --- /dev/null +++ b/frontend/src/components/utils/types.tsx @@ -0,0 +1,3 @@ +import { TFunction } from 'i18next/index'; + +export type Translator = TFunction<'translation', undefined>; diff --git a/frontend/src/pages/tournaments/[id]/courts.tsx b/frontend/src/pages/tournaments/[id]/courts.tsx index 18533f33..60d8321a 100644 --- a/frontend/src/pages/tournaments/[id]/courts.tsx +++ b/frontend/src/pages/tournaments/[id]/courts.tsx @@ -2,17 +2,18 @@ import { Button, Container, Divider, 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, getTournaments } from '../../../services/adapter'; import { createCourt } from '../../../services/court'; import TournamentLayout from '../_tournament_layout'; -function CreateCourtForm(tournament: Tournament, swrCourtsResponse: SWRResponse) { - const { t } = useTranslation(); +function CreateCourtForm(t: Translator, tournament: Tournament, swrCourtsResponse: SWRResponse) { const form = useForm({ initialValues: { name: '' }, validate: { @@ -52,12 +53,13 @@ export default function CourtsPage() { const tournamentDataFull = tournaments.filter( (tournament) => tournament.id === tournamentData.id )[0]; + const { t } = useTranslation(); return ( - - {CreateCourtForm(tournamentDataFull, swrCourtsResponse)} + + {CreateCourtForm(t, tournamentDataFull, swrCourtsResponse)} ); diff --git a/frontend/src/pages/tournaments/[id]/schedule.tsx b/frontend/src/pages/tournaments/[id]/schedule.tsx index e77701c0..49a6bc95 100644 --- a/frontend/src/pages/tournaments/[id]/schedule.tsx +++ b/frontend/src/pages/tournaments/[id]/schedule.tsx @@ -5,7 +5,9 @@ import { useTranslation } from 'next-i18next'; import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; import React from 'react'; +import { NoContent } from '../../../components/no_content/empty_table_info'; import { Time } from '../../../components/utils/datetime'; +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'; @@ -94,7 +96,7 @@ function ScheduleColumn({ matches.length < 1 ? ( } - title={t('no_matches_description')} + title={t('no_matches_title')} color="gray" radius="md" > @@ -119,10 +121,12 @@ function ScheduleColumn({ } function Schedule({ + t, stageItemsLookup, matchesLookup, schedule, }: { + t: Translator; stageItemsLookup: any; matchesLookup: any; schedule: { court: Court; matches: MatchInterface[] }[]; @@ -136,6 +140,11 @@ function Schedule({ matches={item.matches} /> )); + + if (columns.length < 1) { + return ; + } + return {columns}; } @@ -200,6 +209,7 @@ export default function SchedulePage() { }} > tournament.id === tournamentData.id )[0]; - return ( - - - ; + } else if (stages.length < 1) { + content = ( + + + - - - - - - - ); + + ); + } else { + content = ( + <> + + + + + + + + + ); + } + + return {content}; } export const getServerSideProps = async ({ locale }: { locale: string }) => ({ diff --git a/frontend/src/pages/user.tsx b/frontend/src/pages/user.tsx index 920f1df1..138d1486 100644 --- a/frontend/src/pages/user.tsx +++ b/frontend/src/pages/user.tsx @@ -1,10 +1,10 @@ -import { Stack, Title } from '@mantine/core'; +import { Group, Stack, Title } from '@mantine/core'; import { useTranslation } from 'next-i18next'; import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; import UserForm from '../components/forms/user'; -import { checkForAuthError, getTournaments, getUser } from '../services/adapter'; -import { getLogin } from '../services/local_storage'; +import { TableSkeletonSingleColumn } from '../components/utils/skeletons'; +import { checkForAuthError, getUser } from '../services/adapter'; import Layout from './_layout'; export const getServerSideProps = async ({ locale }: { locale: string }) => ({ @@ -14,23 +14,27 @@ export const getServerSideProps = async ({ locale }: { locale: string }) => ({ }); export default function HomePage() { - let user = null; const { t } = useTranslation(); - const swrTournamentsResponse = getTournaments(); - checkForAuthError(swrTournamentsResponse); + const swrUserResponse = getUser(); + checkForAuthError(swrUserResponse); + const user = swrUserResponse.data != null ? swrUserResponse.data.data : null; - if (typeof window !== 'undefined') { - const swrUserResponse = getUser(getLogin().user_id); - user = swrUserResponse.data != null ? swrUserResponse.data.data : null; + let content; + content = user != null ? : null; + + if (swrUserResponse.isValidating || swrUserResponse.isLoading) { + content = ( + + + + ); } - const form = user != null ? : null; - return ( {t('edit_profile_title')} - {form} + {content} ); } diff --git a/frontend/src/services/adapter.tsx b/frontend/src/services/adapter.tsx index 64651071..670df664 100644 --- a/frontend/src/services/adapter.tsx +++ b/frontend/src/services/adapter.tsx @@ -112,7 +112,10 @@ export function getTournaments(): SWRResponse { } export function getPlayers(tournament_id: number, not_in_team: boolean = false): SWRResponse { - return useSWR(`tournaments/${tournament_id}/players?not_in_team=${not_in_team}`, fetcher); + return useSWR( + `tournaments/${tournament_id}/players?not_in_team=${not_in_team}&limit=100`, + fetcher + ); } export function getPlayersPaginated(tournament_id: number, pagination: Pagination): SWRResponse { @@ -123,7 +126,7 @@ export function getPlayersPaginated(tournament_id: number, pagination: Paginatio } export function getTeams(tournament_id: number): SWRResponse { - return useSWR(`tournaments/${tournament_id}/teams`, fetcher); + return useSWR(`tournaments/${tournament_id}/teams?limit=100`, fetcher); } export function getTeamsPaginated(tournament_id: number, pagination: Pagination): SWRResponse { @@ -177,8 +180,8 @@ export function getCourtsLive(tournament_id: number): SWRResponse { }); } -export function getUser(user_id: number): SWRResponse { - return useSWR(`users/${user_id}`, fetcher); +export function getUser(): SWRResponse { + return useSWR('users/me', fetcher); } export function getUpcomingMatches( @@ -220,7 +223,7 @@ export function checkForAuthError(response: any) { } if (responseHasAuthError(response)) { createAxios() - .get('clubs') + .get('users/me') .then(() => {}) .catch((error: any) => { if (error.toJSON().status === 401) {