diff --git a/TaikoLocalServer/Controllers/Api/ChallengeCompeteManageController.cs b/TaikoLocalServer/Controllers/Api/ChallengeCompeteManageController.cs index 98d199b..1887030 100644 --- a/TaikoLocalServer/Controllers/Api/ChallengeCompeteManageController.cs +++ b/TaikoLocalServer/Controllers/Api/ChallengeCompeteManageController.cs @@ -49,6 +49,18 @@ public class ChallengeCompeteManageController(IChallengeCompeteService challenge return Ok(response); } + [HttpGet("comp/{compId}")] + [ServiceFilter(typeof(AuthorizeIfRequiredAttribute))] + public async Task> GetChallengeCompe(uint compId) + { + var data = await challengeCompeteService.GetFirstOrDefaultCompete(compId); + if (data == null) return BadRequest(new { Message = $"Compete(CompId={compId}) is Not Exist!"}); + var challengeCompetition = Mappers.ChallengeCompeMappers.MapData(data); + challengeCompetition = await challengeCompeteService.FillData(challengeCompetition); + + return Ok(challengeCompetition); + } + [HttpGet("test/{mode}")] [ServiceFilter(typeof(AuthorizeIfRequiredAttribute))] public ActionResult> testCreateCompete(uint mode) diff --git a/TaikoLocalServer/Services/ChallengeCompeteService.cs b/TaikoLocalServer/Services/ChallengeCompeteService.cs index 5dc5ab5..db81db5 100644 --- a/TaikoLocalServer/Services/ChallengeCompeteService.cs +++ b/TaikoLocalServer/Services/ChallengeCompeteService.cs @@ -4,6 +4,7 @@ using SharedProject.Models; using SharedProject.Models.Responses; using SharedProject.Utils; using Throw; +using static Microsoft.EntityFrameworkCore.DbLoggerCategory; namespace TaikoLocalServer.Services; @@ -125,6 +126,14 @@ public class ChallengeCompeteService : IChallengeCompeteService }; } + public Task GetFirstOrDefaultCompete(uint compId) + { + return context.ChallengeCompeteData + .Include(e => e.Songs).ThenInclude(e => e.BestScores).Include(e => e.Participants) + .Where(c => c.CompId == compId) + .FirstOrDefaultAsync(); + } + public async Task CreateCompete(uint baid, ChallengeCompeteCreateInfo challengeCompeteInfo) { ChallengeCompeteDatum challengeCompeteData = new() diff --git a/TaikoLocalServer/Services/Interfaces/IChallengeCompeteService.cs b/TaikoLocalServer/Services/Interfaces/IChallengeCompeteService.cs index 8f1bc2c..2a63ea5 100644 --- a/TaikoLocalServer/Services/Interfaces/IChallengeCompeteService.cs +++ b/TaikoLocalServer/Services/Interfaces/IChallengeCompeteService.cs @@ -13,6 +13,8 @@ public interface IChallengeCompeteService public Task GetChallengeCompetePage(CompeteModeType mode, uint baid, bool inProgress, int page, int limit, string? search); + public Task GetFirstOrDefaultCompete(uint compId); + public Task CreateCompete(uint baid, ChallengeCompeteCreateInfo challengeCompeteInfo); public Task ParticipateCompete(uint compId, uint baid); diff --git a/TaikoWebUI/Components/ChallengeCompe.razor b/TaikoWebUI/Components/ChallengeCompe.razor index 4781731..9b24846 100644 --- a/TaikoWebUI/Components/ChallengeCompe.razor +++ b/TaikoWebUI/Components/ChallengeCompe.razor @@ -1,30 +1,38 @@ -@inject IDialogService DialogService; +@using Blazored.LocalStorage + @inject HttpClient Client +@inject IDialogService DialogService; +@inject IGameDataService GameDataService +@inject ILocalStorageService LocalStorage @if (ChallengeCompetition != null) { - @if (ChallengeCompetition.CompeteMode == CompeteModeType.Chanllenge) - { - if (Baid == 0) + + @if (ChallengeCompetition.CompeteMode == CompeteModeType.Chanllenge) { - @formatChallengeTitle(Localizer["FullChallengeTitle"]) - } - else if (ChallengeCompetition?.Baid != Baid) - { - @formatChallengeTitle(Localizer["ReceiverChallengeTitle"]) + if (Baid == 0) + { + @formatChallengeTitle(Localizer["FullChallengeTitle"]) + } + else if (ChallengeCompetition?.Baid != Baid) + { + + @formatChallengeTitle(Localizer["ReceiverChallengeTitle"]) + } + else + { + + @formatChallengeTitle(Localizer["CreatorChallengeTitle"]) + } } else { - @formatChallengeTitle(Localizer["CreatorChallengeTitle"]) + @ChallengeCompetition?.CompeteName } - } - else - { - @ChallengeCompetition?.CompeteName - } + @Localizer["Comp ID"]:@ChallengeCompetition?.CompId @Localizer["Describe"]:@ChallengeCompetition?.CompeteDescribe @@ -42,7 +50,9 @@ foreach (var song in ChallengeCompetition.Songs) {
- @song.MusicDetail?.SongName + + @GameDataService.GetMusicNameBySongId(MusicDetailDictionary, song.MusicDetail.SongId, SongNameLanguage)@(song.BestScores.Any(bs => bs.Baid == Baid) ? (" (" + Localizer["Played"] + ")") : "") +
} } @@ -110,6 +120,25 @@ [Parameter] public ChallengeCompetition? ChallengeCompetition { get; set; } [Parameter] public int Baid { get; set; } [Parameter] public EventCallback Refresh { get; set; } + [Parameter] public Dictionary? MusicDetailDictionary { get; set; } = null; + [Parameter] public string? SongNameLanguage { get; set; } = null; + + protected override async Task OnInitializedAsync() + { + base.OnInitialized(); + if (SongNameLanguage == null) SongNameLanguage = await LocalStorage.GetItemAsync("songNameLanguage"); + if (MusicDetailDictionary == null) MusicDetailDictionary = await GameDataService.GetMusicDetailDictionary(); + } + + private string GetSongInfo(ChallengeCompetitionSong song) + { + var songName = GameDataService.GetMusicNameBySongId(MusicDetailDictionary, song.MusicDetail.SongId, SongNameLanguage); + if (song.BestScores.Any(bs => bs.Baid == Baid)) + { + return songName + " (" + Localizer["Played"] + ")"; + } + return songName; + } private bool SelfHoldedChallengeCompetiton() { diff --git a/TaikoWebUI/Components/ChallengeCompeteGrid.razor b/TaikoWebUI/Components/ChallengeCompeteGrid.razor index 960232a..2811837 100644 --- a/TaikoWebUI/Components/ChallengeCompeteGrid.razor +++ b/TaikoWebUI/Components/ChallengeCompeteGrid.razor @@ -1,8 +1,12 @@ -@inject HttpClient Client +@using Blazored.LocalStorage + +@inject HttpClient Client @inject AuthService AuthService +@inject IDialogService DialogService; +@inject IGameDataService GameDataService +@inject ILocalStorageService LocalStorage @inject NavigationManager NavigationManager @inject BreadcrumbsStateContainer BreadcrumbsStateContainer -@inject IDialogService DialogService; @using TaikoWebUI.Components; @using TaikoWebUI.Pages.Dialogs @@ -65,7 +69,11 @@ foreach (var challengeCompetition in response.List) { - + } } @@ -105,6 +113,12 @@ [Parameter] public int Mode { get; set; } + [Parameter] + public Dictionary? MusicDetailDictionary { get; set; } = null; + + [Parameter] + public string? SongNameLanguage { get; set; } = null; + private ChallengeCompetitionResponse? response = new(); private CancellationTokenSource? cts; private int TotalPages { get; set; } = 0; @@ -114,7 +128,7 @@ private string? searchTerm = null; private bool inProgress = false; - private async Task GetUsersData() + private async Task GetChallengeCompetitionData() { isLoading = true; @@ -127,7 +141,7 @@ private async Task UpdateCompete(ChallengeCompetition cc) { - await GetUsersData(); + await GetChallengeCompetitionData(); var updated = response?.List.Find(c => c.CompId == cc.CompId); if (updated != null) { @@ -139,6 +153,9 @@ protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); + if (SongNameLanguage == null) SongNameLanguage = await LocalStorage.GetItemAsync("songNameLanguage"); + if (MusicDetailDictionary == null) MusicDetailDictionary = await GameDataService.GetMusicDetailDictionary(); + if (AuthService.LoginRequired && !AuthService.IsLoggedIn) { await AuthService.LoginWithAuthToken(); @@ -146,18 +163,29 @@ if (AuthService.IsAdmin || !AuthService.LoginRequired) { - await GetUsersData(); + await GetChallengeCompetitionData(); } BreadcrumbsStateContainer.breadcrumbs.Clear(); - BreadcrumbsStateContainer.breadcrumbs.Add(new BreadcrumbItem(Localizer["Users"], href: "/Users")); + if (Mode == 1) + { + BreadcrumbsStateContainer.breadcrumbs.Add(new BreadcrumbItem(Localizer["Challenge"], href: $"/ChallengeCompe/{Baid}/Challenge")); + } + else if (Mode == 2) + { + BreadcrumbsStateContainer.breadcrumbs.Add(new BreadcrumbItem(Localizer["Competition"], href: $"/ChallengeCompe/{Baid}/Competition")); + } + else if (Mode == 3) + { + BreadcrumbsStateContainer.breadcrumbs.Add(new BreadcrumbItem(Localizer["Official Competition"], href: $"/ChallengeCompe/{Baid}/OfficialCompetition")); + } BreadcrumbsStateContainer.NotifyStateChanged(); } private async Task OnPageChange(int page) { currentPage = page; - await GetUsersData(); + await GetChallengeCompetitionData(); } private async Task Debounce(Func action, int delayInMilliseconds) @@ -188,7 +216,7 @@ currentPage = 1; // Debounce the GetUsersData method - await Debounce(GetUsersData, 500); // 500 milliseconds delay + await Debounce(GetChallengeCompetitionData, 500); // 500 milliseconds delay } private async Task OpenDialogAsync(int mode, int maxSongs, int maxDays = 30, int maxParticipant = 20) @@ -205,7 +233,7 @@ if (dialogRet != null) { var result = await dialogRet.GetReturnValueAsync(); - if (result != null && result == true) await GetUsersData(); + if (result != null && result == true) await GetChallengeCompetitionData(); } } } diff --git a/TaikoWebUI/Pages/Dialogs/AddChallengeCompetitionDialog.razor b/TaikoWebUI/Pages/Dialogs/AddChallengeCompetitionDialog.razor index 35cd2b7..22657ef 100644 --- a/TaikoWebUI/Pages/Dialogs/AddChallengeCompetitionDialog.razor +++ b/TaikoWebUI/Pages/Dialogs/AddChallengeCompetitionDialog.razor @@ -1,9 +1,12 @@ @using System.Net -@using TaikoWebUI.Utilities; +@using Blazored.LocalStorage +@using TaikoWebUI.Utilities @inject HttpClient Client @inject ISnackbar Snackbar -@inject IDialogService DialogService; +@inject IDialogService DialogService +@inject IGameDataService GameDataService +@inject ILocalStorageService LocalStorage @@ -36,7 +39,7 @@ { } - + @if (Mode == 1) { @@ -59,9 +62,10 @@ Difficulty difficulty = difficulties[song_idx]; } - @(musicDetails[song_idx].SongId == 0 ? Localizer["No Select"] : musicDetails[song_idx].SongName) - @levels[song_idx] - + @(musicDetails[song_idx].SongId == 0 ? Localizer["No Select"] : GameDataService.GetMusicNameBySongId(MusicDetailDictionary, musicDetails[song_idx].SongId, SongNameLanguage)) + @if (levels[song_idx] > 0) { + @levels[song_idx] + } @if (Info.challengeCompeteSongs.Count > 1) @@ -69,20 +73,20 @@ } - + - - + + @Localizer["Any"] @Localizer["On"] @Localizer["Off"] - + @Localizer["Any"] @Localizer["On"] @Localizer["Off"] - + @Localizer["Any"] @for (uint idx = 0; idx < SpeedStrings.Length; idx++) { @@ -90,7 +94,7 @@ @SpeedStrings[speed_idx] } - + @Localizer["Any"] @foreach (var item in Enum.GetValues()) { @@ -142,6 +146,10 @@ [Parameter] public ChallengeCompeteCreateInfo Info { get; set; } = new(); + private Dictionary MusicDetailDictionary = new(); + + private string? SongNameLanguage; + private static readonly string[] SpeedStrings = { "1.0", "1.1", "1.2", "1.3", "1.4", @@ -168,8 +176,9 @@ private bool OnlyPlayOnce = false; - protected override void OnInitialized() + protected override async Task OnInitializedAsync() { + base.OnInitialized(); _expandeds = new bool[MaxSongs]; musicDetails = new MusicDetail[MaxSongs]; difficulties = new Difficulty[MaxSongs]; @@ -181,6 +190,8 @@ levels[i] = 0; } Info.challengeCompeteSongs.Add(new()); + SongNameLanguage = await LocalStorage.GetItemAsync("songNameLanguage"); + MusicDetailDictionary = await GameDataService.GetMusicDetailDictionary(); } private void AddSong() @@ -192,7 +203,8 @@ { var options = new DialogOptions { CloseOnEscapeKey = true }; var parameters = new DialogParameters(); - parameters.Add("SelectedSong", musicDetails[i]); + parameters.Add("MusicDetailDictionary", MusicDetailDictionary); + parameters.Add("SongNameLanguage", SongNameLanguage); var reference = await DialogService.ShowAsync(Localizer["Select Song"], parameters, options); if (reference != null) diff --git a/TaikoWebUI/Pages/Dialogs/ChooseSongDialog.razor b/TaikoWebUI/Pages/Dialogs/ChooseSongDialog.razor index 4f06d6b..2b993a8 100644 --- a/TaikoWebUI/Pages/Dialogs/ChooseSongDialog.razor +++ b/TaikoWebUI/Pages/Dialogs/ChooseSongDialog.razor @@ -7,7 +7,7 @@ - + @@ -25,7 +25,7 @@ - + @Localizer["Song Title"] @@ -34,7 +34,7 @@ @if (difficulty is not Difficulty.None) { - + @ScoreUtils.GetDifficultyTitle(difficulty) @@ -44,18 +44,18 @@ - @GameDataService.GetMusicNameBySongId(musicDetailDictionary, context.SongId, SongNameLanguage) + @GameDataService.GetMusicNameBySongId(MusicDetailDictionary, context.SongId, SongNameLanguage) @foreach (var difficulty in Enum.GetValues()) { @if (difficulty is not Difficulty.None) { - var starLevel = GameDataService.GetMusicStarLevel(musicDetailDictionary, context.SongId, difficulty); + var starLevel = GameDataService.GetMusicStarLevel(MusicDetailDictionary, context.SongId, difficulty); @if (starLevel > 0) { - @starLevel + @starLevel } else { @@ -83,11 +83,9 @@ [CascadingParameter] MudDialogInstance MudDialog { get; set; } = null!; - [Parameter] public MusicDetail SelectedSong { get; set; } = new(); + [Parameter] public Dictionary? MusicDetailDictionary { get; set; } = null; - private Dictionary musicDetailDictionary = new(); - - private string? SongNameLanguage; + [Parameter] public string? SongNameLanguage { get; set; } = null; private string Search { get; set; } = string.Empty; @@ -96,8 +94,8 @@ protected override async Task OnInitializedAsync() { base.OnInitialized(); - SongNameLanguage = await LocalStorage.GetItemAsync("songNameLanguage"); - musicDetailDictionary = await GameDataService.GetMusicDetailDictionary(); + if (SongNameLanguage == null) SongNameLanguage = await LocalStorage.GetItemAsync("songNameLanguage"); + if (MusicDetailDictionary == null) MusicDetailDictionary = await GameDataService.GetMusicDetailDictionary(); } @@ -119,12 +117,13 @@ return true; } - private void Select(MusicDetail musicDetail, Difficulty difficulty) + private void Select(MusicDetail musicDetail, Difficulty difficulty, int level) { MudDialog.Close(DialogResult.Ok(new SongInfo() { MusicDetail = musicDetail, - Difficulty = difficulty + Difficulty = difficulty, + Level = level, })); }