diff --git a/ArenaService.BackOffice/Components/Pages/CacheInitialization.razor b/ArenaService.BackOffice/Components/Pages/CacheInitialization.razor new file mode 100644 index 0000000..d64048a --- /dev/null +++ b/ArenaService.BackOffice/Components/Pages/CacheInitialization.razor @@ -0,0 +1,217 @@ +@page "/cache-initialization" +@using ArenaService.Shared.Services +@using ArenaService.Shared.Repositories +@using ArenaService.Shared.Models +@using Microsoft.AspNetCore.Authorization +@rendermode InteractiveServer +@attribute [Authorize] +@inject ICacheInitializationService CacheInitializationService +@inject ISeasonCacheRepository SeasonCacheRepo +@inject IRankingRepository RankingRepo +@inject IJSRuntime JSRuntime + +캐시 초기화 + +
+

🔄 캐시 초기화

+ + +

📅 현재 진행 중인 시즌

+ @if (currentSeason != null) + { + + + + + + + + + + + + + + + +
ID시작 블록종료 블록
@currentSeason?.Id@currentSeason?.StartBlock@currentSeason?.EndBlock
+ +

📅 현재 진행 중인 라운드

+ + + + + + + + + + + + + + + + + +
ID라운드 인덱스시작 블록종료 블록
@currentRound?.Id@currentRound?.RoundIndex@currentRound?.StartBlock@currentRound?.EndBlock
+ +

📊 랭킹 데이터 가용성

+ + + + + + + + + + @foreach (var roundRanking in rankingCounts) + { + + + + + + } + +
라운드랭킹 데이터 수상태
@roundRanking.RoundIndex@roundRanking.RankingCount@(roundRanking.RankingCount > 0 ? "✅ 준비됨" : "❌ 불완전")
+ } + else + { +

⚠️ 현재 진행 중인 시즌이 없습니다.

+ } + +
+ + +
+
+
🗑️ 전체 캐시 초기화
+
+
+

모든 랭킹 캐시를 초기화합니다. 이 작업은 되돌릴 수 없습니다.

+ + + 버튼 상태: isLoading=@isLoading, currentSeason=@(currentSeason != null), currentRound=@(currentRound != null) + +
+
+ + @if (!string.IsNullOrEmpty(message)) + { + + } +
+ +@code { + private bool isLoading = false; + private string message = ""; + private string alertClass = ""; + private (int Id, long StartBlock, long EndBlock)? currentSeason; + private (int Id, int RoundIndex, long StartBlock, long EndBlock)? currentRound; + private List<(int RoundIndex, int RankingCount)> rankingCounts = new(); + + protected override async Task OnInitializedAsync() + { + try + { + Console.WriteLine("OnInitializedAsync 시작"); + currentSeason = await SeasonCacheRepo.GetSeasonAsync(); + currentRound = await SeasonCacheRepo.GetRoundAsync(); + + if (currentSeason.HasValue && currentRound.HasValue) + { + await LoadRankingCounts(currentSeason.Value.Id, currentRound.Value.RoundIndex); + } + + Console.WriteLine($"초기화 완료 - isLoading: {isLoading}, currentSeason: {currentSeason}, currentRound: {currentRound}"); + StateHasChanged(); + } + catch (Exception ex) + { + Console.WriteLine($"OnInitializedAsync 오류: {ex}"); + message = $"시즌 정보를 불러오는 중 오류가 발생했습니다: {ex.Message}"; + alertClass = "alert-danger"; + StateHasChanged(); + } + } + + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + await JSRuntime.InvokeVoidAsync("console.log", "CacheInitialization 페이지가 로드되었습니다."); + await JSRuntime.InvokeVoidAsync("console.log", "SignalR 연결 상태를 확인하세요."); + } + } + + private async Task LoadRankingCounts(int seasonId, int currentRoundIndex) + { + rankingCounts.Clear(); + + for (int offset = -1; offset <= 1; offset++) + { + int roundToCheck = currentRoundIndex + offset; + if (roundToCheck < 1) { + continue; + } + + int rankingCount = await RankingRepo.GetRankingCountAsync(seasonId, roundToCheck); + rankingCounts.Add((roundToCheck, rankingCount)); + } + } + + private async Task InitializeRankingCacheAsync() + { + Console.WriteLine("InitializeRankingCacheAsync 시작"); + isLoading = true; + message = ""; + StateHasChanged(); + + try + { + Console.WriteLine($"시즌 ID: {currentSeason!.Value.Id}, 라운드 인덱스: {currentRound!.Value.RoundIndex}"); + var result = await CacheInitializationService.InitializeRankingCacheAsync(currentSeason!.Value.Id, currentRound!.Value.Id); + + Console.WriteLine($"캐시 초기화 결과: {result}"); + + if (result) + { + message = "모든 랭킹 캐시가 성공적으로 초기화되었습니다."; + alertClass = "alert-success"; + + await Task.Delay(1000); + await LoadRankingCounts(currentSeason!.Value.Id, currentRound!.Value.RoundIndex); + } + else + { + message = "캐시 초기화에 실패했습니다."; + alertClass = "alert-danger"; + } + } + catch (Exception ex) + { + Console.WriteLine($"오류 발생: {ex}"); + message = $"캐시 초기화 중 오류가 발생했습니다: {ex.Message}"; + alertClass = "alert-danger"; + } + finally + { + isLoading = false; + StateHasChanged(); + } + } +} \ No newline at end of file diff --git a/ArenaService.BackOffice/Components/Pages/ManageSeasons.razor b/ArenaService.BackOffice/Components/Pages/ManageSeasons.razor index ae6f9df..b37dc6a 100644 --- a/ArenaService.BackOffice/Components/Pages/ManageSeasons.razor +++ b/ArenaService.BackOffice/Components/Pages/ManageSeasons.razor @@ -1,210 +1,433 @@ @page "/manage-seasons" @using Microsoft.AspNetCore.Authorization -@using ArenaService.Shared.Repositories +@using ArenaService.Shared.Constants @using ArenaService.Shared.Services @using ArenaService.Shared.Models +@using ArenaService.Shared.Repositories @using Microsoft.EntityFrameworkCore @attribute [Authorize] @rendermode InteractiveServer -@inject ISeasonRepository SeasonRepo +@inject ISeasonRepository SeasonRepository @inject ISeasonCacheRepository SeasonCacheRepo -@inject IRankingRepository RankingRepo -@inject IRoundRepository RoundRepo -@inject ISeasonPreparationService SeasonPreparationService -@inject IRoundPreparationService RoundPreparationService +@inject ISeasonBlockAdjustmentService SeasonBlockAdjustmentService +@inject ISeasonService SeasonService @inject NavigationManager NavigationManager -

🏆 Season Management

+

🏆 Season List

- -

📅 Currently Active Season

-@if (currentSeason != null) +@if (loading) { +

Loading...

+} +else +{ +

📅 Season List

+ + + + + + + + - - - - - + @foreach (var season in paginatedSeasons) + { + + + + + + + + + + + + + + }
IDSeason Group ID Start Block End BlockTypeRound IntervalRequired MedalsTotal PrizeBattle Ticket PolicyRefresh Ticket PolicyActions
@currentSeason?.Id@currentSeason?.StartBlock@currentSeason?.EndBlock
@season.Id + @if (editingSeasonId == season.Id) + { + + } + else + { + @season.SeasonGroupId + } + @season.StartBlock@season.EndBlock + @if (editingSeasonId == season.Id) + { + + } + else + { + @season.ArenaType + } + + @if (editingSeasonId == season.Id) + { + + } + else + { + @season.RoundInterval + } + + @if (editingSeasonId == season.Id) + { + + } + else + { + @season.RequiredMedalCount + } + + @if (editingSeasonId == season.Id) + { + + } + else + { + @season.TotalPrize + } + + @if (editingSeasonId == season.Id) + { + + } + else + { + @season.BattleTicketPolicy.Name + } + + @if (editingSeasonId == season.Id) + { + + } + else + { + @season.RefreshTicketPolicy.Name + } + + @if (editingSeasonId == season.Id) + { + + + } + else + { + + + @if (deletableSeasonIds.Contains(season.Id)) + { + + } + else + { + + } + } +
-

📅 Currently Active Round

+ +} + +@if (selectedSeason != null) +{ +

📋 Selected Season's Round List

- + + - - - - - - -
IDRound IDRound Index Start Block End Block
@currentRound?.Id@currentRound?.StartBlock@currentRound?.EndBlock
- -

📊 Ranking Data Availability

- - - - - - - - - - @foreach (var roundRanking in rankingCounts) + @foreach (var round in rounds) { - - - + + + + }
RoundRanking Data CountStatus
@roundRanking.RoundOffset@roundRanking.RankingCount@(roundRanking.RankingCount > 0 ? "✅ Ready" : "❌ Incomplete")@round.Id@round.RoundIndex@round.StartBlock@round.EndBlock
-} -else -{ -

⚠️ No active season currently.

-} -
+

🔧 Adjust Season End Block

+
+ +
+
+ + +
+ +
+ ⚠️ Warning: This action will affect all subsequent seasons and rounds. + If you decrease the end block, some rounds may be deleted or adjusted. +
+} - +

🆕 Add New Season

- - + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ - - -@if (seasonMessage is not null) +@if (message is not null) { -

@seasonMessage

+

@message

} -
+@code { + private List paginatedSeasons = new(); + private List rounds = new(); + private Season? selectedSeason; + private int currentPage = 1; + private int pageSize = 10; + private int totalSeasons = 0; + private bool loading = true; - -
- - -
+ private int newStartBlock; + private int newRoundInterval; + private int newRoundCount; + private ArenaType newArenaType = ArenaType.SEASON; + private int newRequiredMedalCount; + private int newTotalPrize; + private int newBattlePolicyId; + private int newRefreshPolicyId; + private string? message; - + private int editingSeasonId; + private Season editingSeason = new(); -@if (roundMessage is not null) -{ -

@roundMessage

-} + private long newEndBlock; + private int newSeasonGroupId; -@code { - private (int Id, long StartBlock, long EndBlock)? currentSeason; - private (int Id, long StartBlock, long EndBlock)? currentRound; - private List<(int RoundOffset, int RankingCount)> rankingCounts = new(); - private int seasonId; - private int roundId; - private string? seasonMessage; - private string? roundMessage; + private HashSet deletableSeasonIds = new(); protected override async Task OnInitializedAsync() { - try - { - currentSeason = await SeasonCacheRepo.GetSeasonAsync(); - currentRound = await SeasonCacheRepo.GetRoundAsync(); + newStartBlock = await SeasonRepository.GetLastSeasonEndBlockAsync() + 1 ?? 1; + totalSeasons = await SeasonRepository.GetTotalSeasonsCountAsync(); + await LoadSeasons(); + } - if (currentSeason.HasValue && currentRound.HasValue) + private async Task LoadSeasons() + { + loading = true; + paginatedSeasons = await SeasonRepository.GetSeasonsPagedAsync(currentPage, pageSize, q => q.Include(s => + s.Rounds).Include(s => s.BattleTicketPolicy).Include(s => s.RefreshTicketPolicy)); + + // 현재 캐싱된 block index 가져오기 + var currentBlockIndex = await SeasonCacheRepo.GetBlockIndexAsync(); + deletableSeasonIds.Clear(); + + foreach (var season in paginatedSeasons) + { + if (season.StartBlock >= currentBlockIndex) { - await LoadRankingCounts(currentSeason.Value.Id, currentRound.Value.Id); + deletableSeasonIds.Add(season.Id); } } + + loading = false; + } + + private async Task AddSeason() + { + try + { + await SeasonRepository.AddSeasonWithRoundsAsync( + newStartBlock, + newRoundInterval, + newRoundCount, + newSeasonGroupId, + newArenaType, + newRequiredMedalCount, + newTotalPrize, + newBattlePolicyId, + newRefreshPolicyId + ); + + totalSeasons = await SeasonRepository.GetTotalSeasonsCountAsync(); + + NavigationManager.NavigateTo(NavigationManager.Uri, forceLoad: true); + } catch (Exception ex) { - Console.WriteLine($"⚠️ Error occurred while loading active season data: {ex.Message}"); + message = $"❌ Failed to add season: {ex.Message}"; } } - private async Task LoadRankingCounts(int seasonId, int currentRoundId) + private async Task SelectSeason(Season season) { - rankingCounts.Clear(); + selectedSeason = season; + rounds = season.Rounds.OrderBy(r => r.StartBlock).ToList(); + newEndBlock = season.EndBlock; + } - for (int offset = -1; offset <= 2; offset++) + private async Task NextPage() + { + if (CanGoNext) { - int roundToCheck = currentRoundId + offset; - int rankingCount = await RankingRepo.GetRankingCountAsync(seasonId, roundToCheck); - rankingCounts.Add((currentRoundId + offset, rankingCount)); + currentPage++; + await LoadSeasons(); } } - private async Task InitializeSeason() + private async Task PreviousPage() { - seasonMessage = "Initializing season..."; - try + if (CanGoPrevious) { - var season = await SeasonRepo.GetSeasonAsync(seasonId, q => q.Include(s => s.Rounds)); - - if (season == null) - { - seasonMessage = "❌ Season not found."; - return; - } + currentPage--; + await LoadSeasons(); + } + } - var firstRound = season.Rounds.OrderBy(r => r.StartBlock).FirstOrDefault(); + private int totalPages => (int)Math.Ceiling((double)totalSeasons / pageSize); + private bool CanGoPrevious => currentPage > 1; + private bool CanGoNext => currentPage < totalPages; - if (firstRound == null) - { - seasonMessage = "⚠️ No rounds exist for this season."; - return; - } + private void StartEdit(Season season) + { + editingSeasonId = season.Id; + editingSeason = new Season + { + Id = season.Id, + SeasonGroupId = season.SeasonGroupId, + ArenaType = season.ArenaType, + RoundInterval = season.RoundInterval, + RequiredMedalCount = season.RequiredMedalCount, + TotalPrize = season.TotalPrize, + BattleTicketPolicyId = season.BattleTicketPolicyId, + RefreshTicketPolicyId = season.RefreshTicketPolicyId + }; + } - await SeasonPreparationService.PrepareSeasonAsync((season, firstRound)); + private async Task SaveSeason(int seasonId) + { + try + { + await SeasonRepository.UpdateSeasonAsync( + seasonId, + editingSeason.SeasonGroupId, + editingSeason.ArenaType, + editingSeason.RoundInterval, + editingSeason.RequiredMedalCount, + editingSeason.TotalPrize, + editingSeason.BattleTicketPolicyId, + editingSeason.RefreshTicketPolicyId + ); - seasonMessage = "✅ Season initialized successfully!"; - NavigationManager.NavigateTo(NavigationManager.Uri, forceLoad: true); + editingSeasonId = 0; + message = "✅ Season updated successfully!"; + await LoadSeasons(); } catch (Exception ex) { - seasonMessage = $"❌ Error occurred: {ex.Message}"; + message = $"❌ Failed to save season: {ex.Message}"; } } - private async Task PrepareNextRound() + private void CancelEdit() { - roundMessage = "Preparing next round..."; - try - { - var round = await RoundRepo.GetRoundAsync(roundId, q => q.Include(r => r.Season)); - var season = await SeasonRepo.GetSeasonAsync(round!.SeasonId, q => q.Include(s => s.Rounds)); + editingSeasonId = 0; + message = null; + } - if (round == null || round.Season == null) - { - roundMessage = "❌ Round not found."; - return; - } + private async Task AdjustSeasonEndBlock() + { + if (selectedSeason == null) return; - await RoundPreparationService.PrepareNextRoundWithSnapshotAsync((season, round)); + try + { + await SeasonBlockAdjustmentService.AdjustSeasonEndBlockAsync(selectedSeason.Id, newEndBlock); + message = "✅ Season end block adjusted successfully!"; + selectedSeason = null; + rounds.Clear(); + await LoadSeasons(); + } + catch (Exception ex) + { + message = $"❌ Failed to adjust season end block: {ex.Message}"; + } + } - roundMessage = "✅ Next round prepared successfully!"; - NavigationManager.NavigateTo(NavigationManager.Uri, forceLoad: true); + private async Task DeleteSeason(int seasonId) + { + try + { + await SeasonService.DeleteSeasonAsync(seasonId); + message = "✅ Season deleted successfully!"; + totalSeasons = await SeasonRepository.GetTotalSeasonsCountAsync(); + await LoadSeasons(); } catch (Exception ex) { - roundMessage = $"❌ Error occurred: {ex.Message}"; + message = $"❌ Failed to delete season: {ex.Message}"; } } } diff --git a/ArenaService.BackOffice/Components/Pages/RankingCache.razor b/ArenaService.BackOffice/Components/Pages/RankingCache.razor new file mode 100644 index 0000000..d059732 --- /dev/null +++ b/ArenaService.BackOffice/Components/Pages/RankingCache.razor @@ -0,0 +1,216 @@ +@page "/ranking-cache" +@using Microsoft.AspNetCore.Authorization +@using ArenaService.Shared.Repositories +@using ArenaService.Shared.Services +@using ArenaService.Shared.Models +@using Microsoft.EntityFrameworkCore +@attribute [Authorize] +@rendermode InteractiveServer +@inject ISeasonRepository SeasonRepo +@inject ISeasonCacheRepository SeasonCacheRepo +@inject IRankingRepository RankingRepo +@inject IRoundRepository RoundRepo +@inject ISeasonPreparationService SeasonPreparationService +@inject IRoundPreparationService RoundPreparationService +@inject NavigationManager NavigationManager + +

🏆 Season Management

+ + +

📅 Currently Active Season

+@if (currentSeason != null) +{ + + + + + + + + + + + + + + + +
IDStart BlockEnd Block
@currentSeason?.Id@currentSeason?.StartBlock@currentSeason?.EndBlock
+ +

📅 Currently Active Round

+ + + + + + + + + + + + + + + + + +
IDRound IndexStart BlockEnd Block
@currentRound?.Id@currentRound?.RoundIndex@currentRound?.StartBlock@currentRound?.EndBlock
+ +

📊 Ranking Data Availability

+ + + + + + + + + + @foreach (var roundRanking in rankingCounts) + { + + + + + + } + +
RoundRanking Data CountStatus
@roundRanking.RoundOffset@roundRanking.RankingCount@(roundRanking.RankingCount > 0 ? "✅ Ready" : "❌ Incomplete")
+} +else +{ +

⚠️ No active season currently.

+} + +
+ + +
+ + +
+ + + +@if (seasonMessage is not null) +{ +

@seasonMessage

+} + +
+ + +
+ + +
+ + + +@if (roundMessage is not null) +{ +

@roundMessage

+} + +@code { + private (int Id, long StartBlock, long EndBlock)? currentSeason; + private (int Id, int RoundIndex, long StartBlock, long EndBlock)? currentRound; + private List<(int RoundOffset, int RankingCount)> rankingCounts = new(); + private int seasonId; + private int roundId; + private string? seasonMessage; + private string? roundMessage; + + protected override async Task OnInitializedAsync() + { + try + { + currentSeason = await SeasonCacheRepo.GetSeasonAsync(); + currentRound = await SeasonCacheRepo.GetRoundAsync(); + + if (currentSeason.HasValue && currentRound.HasValue) + { + await LoadRankingCounts(currentSeason.Value.Id, currentRound.Value.RoundIndex); + } + } + catch (Exception ex) + { + Console.WriteLine($"⚠️ Error occurred while loading active season data: {ex.Message}"); + } + } + + private async Task LoadRankingCounts(int seasonId, int currentRoundIndex) + { + rankingCounts.Clear(); + + for (int offset = -1; offset <= 1; offset++) + { + int roundToCheck = currentRoundIndex + offset; + if (roundToCheck < 1) { + continue; + } + + int rankingCount = await RankingRepo.GetRankingCountAsync(seasonId, roundToCheck); + rankingCounts.Add((roundToCheck, rankingCount)); + } + } + + private async Task InitializeSeason() + { + seasonMessage = "Initializing season..."; + try + { + var season = await SeasonRepo.GetSeasonAsync(seasonId, q => q.Include(s => s.Rounds)); + + if (season == null) + { + seasonMessage = "❌ Season not found."; + return; + } + + var firstRound = season.Rounds.OrderBy(r => r.RoundIndex).FirstOrDefault(); + + if (firstRound == null) + { + seasonMessage = "⚠️ No rounds exist for this season."; + return; + } + + await SeasonPreparationService.PrepareSeasonAsync((season, firstRound)); + + seasonMessage = "✅ Season initialized successfully!"; + NavigationManager.NavigateTo(NavigationManager.Uri, forceLoad: true); + } + catch (Exception ex) + { + seasonMessage = $"❌ Error occurred: {ex.Message}"; + } + } + + private async Task PrepareNextRound() + { + roundMessage = "Preparing next round..."; + try + { + var round = await RoundRepo.GetRoundAsync(roundId, q => q.Include(r => r.Season)); + var season = await SeasonRepo.GetSeasonAsync(round!.SeasonId, q => q.Include(s => s.Rounds)); + + if (round == null || round.Season == null) + { + roundMessage = "❌ Round not found."; + return; + } + + await RoundPreparationService.PrepareNextRoundWithSnapshotAsync((season, round)); + + roundMessage = "✅ Next round prepared successfully!"; + NavigationManager.NavigateTo(NavigationManager.Uri, forceLoad: true); + } + catch (Exception ex) + { + roundMessage = $"❌ Error occurred: {ex.Message}"; + } + } +} diff --git a/ArenaService.BackOffice/Components/Pages/Seasons.razor b/ArenaService.BackOffice/Components/Pages/Seasons.razor deleted file mode 100644 index 63e020b..0000000 --- a/ArenaService.BackOffice/Components/Pages/Seasons.razor +++ /dev/null @@ -1,376 +0,0 @@ -@page "/seasons" -@using Microsoft.AspNetCore.Authorization -@using ArenaService.Shared.Constants -@using ArenaService.Shared.Services -@using ArenaService.Shared.Models -@using ArenaService.Shared.Repositories -@using Microsoft.EntityFrameworkCore -@attribute [Authorize] -@rendermode InteractiveServer -@inject ISeasonRepository SeasonRepository -@inject ISeasonCacheRepository SeasonCacheRepo -@inject ISeasonBlockAdjustmentService SeasonBlockAdjustmentService -@inject NavigationManager NavigationManager - -

🏆 Season List

- -@if (loading) -{ -

Loading...

-} -else -{ -

📅 Season List

- - - - - - - - - - - - - - - - - - @foreach (var season in paginatedSeasons) - { - - - - - - - - - - - - - - } - -
IDSeason Group IDStart BlockEnd BlockTypeRound IntervalRequired MedalsTotal PrizeBattle Ticket PolicyRefresh Ticket PolicyActions
@season.Id@season.SeasonGroupId@season.StartBlock@season.EndBlock - @if (editingSeasonId == season.Id) - { - - } - else - { - @season.ArenaType - } - - @if (editingSeasonId == season.Id) - { - - } - else - { - @season.RoundInterval - } - - @if (editingSeasonId == season.Id) - { - - } - else - { - @season.RequiredMedalCount - } - - @if (editingSeasonId == season.Id) - { - - } - else - { - @season.TotalPrize - } - - @if (editingSeasonId == season.Id) - { - - } - else - { - @season.BattleTicketPolicy.Name - } - - @if (editingSeasonId == season.Id) - { - - } - else - { - @season.RefreshTicketPolicy.Name - } - - @if (editingSeasonId == season.Id) - { - - - } - else - { - - - } -
- - -} - -@if (selectedSeason != null) -{ -

📋 Selected Season's Round List

- - - - - - - - - - @foreach (var round in rounds) - { - - - - - - } - -
Round IDStart BlockEnd Block
@round.Id@round.StartBlock@round.EndBlock
- -

🔧 Adjust Season End Block

-
- -
-
- - -
- -
- ⚠️ Warning: This action will affect all subsequent seasons and rounds. - If you decrease the end block, some rounds may be deleted or adjusted. -
-} - -

🆕 Add New Season

-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
- - -@if (message is not null) -{ -

@message

-} - -@code { - private List paginatedSeasons = new(); - private List rounds = new(); - private Season? selectedSeason; - private int currentPage = 1; - private int pageSize = 10; - private int totalSeasons = 0; - private bool loading = true; - - private int newStartBlock; - private int newRoundInterval; - private int newRoundCount; - private ArenaType newArenaType = ArenaType.SEASON; - private int newRequiredMedalCount; - private int newTotalPrize; - private int newBattlePolicyId; - private int newRefreshPolicyId; - private string? message; - - private int editingSeasonId; - private Season editingSeason = new(); - - private long newEndBlock; - - protected override async Task OnInitializedAsync() - { - newStartBlock = await SeasonRepository.GetLastSeasonEndBlockAsync() + 1 ?? 1; - totalSeasons = await SeasonRepository.GetTotalSeasonsCountAsync(); - await LoadSeasons(); - } - - private async Task LoadSeasons() - { - loading = true; - paginatedSeasons = await SeasonRepository.GetSeasonsPagedAsync(currentPage, pageSize, q => q.Include(s => - s.Rounds).Include(s => s.BattleTicketPolicy).Include(s => s.RefreshTicketPolicy)); - loading = false; - } - - private async Task AddSeason() - { - try - { - await SeasonRepository.AddSeasonWithRoundsAsync( - newStartBlock, - newRoundInterval, - newRoundCount, - 0, - newArenaType, - newRequiredMedalCount, - newTotalPrize, - newBattlePolicyId, - newRefreshPolicyId - ); - - totalSeasons = await SeasonRepository.GetTotalSeasonsCountAsync(); - - NavigationManager.NavigateTo(NavigationManager.Uri, forceLoad: true); - } - catch (Exception ex) - { - message = $"❌ Failed to add season: {ex.Message}"; - } - } - - private async Task SelectSeason(Season season) - { - selectedSeason = season; - rounds = season.Rounds.OrderBy(r => r.StartBlock).ToList(); - newEndBlock = season.EndBlock; - } - - private async Task NextPage() - { - if (CanGoNext) - { - currentPage++; - await LoadSeasons(); - } - } - - private async Task PreviousPage() - { - if (CanGoPrevious) - { - currentPage--; - await LoadSeasons(); - } - } - - private int totalPages => (int)Math.Ceiling((double)totalSeasons / pageSize); - private bool CanGoPrevious => currentPage > 1; - private bool CanGoNext => currentPage < totalPages; - - private void StartEdit(Season season) - { - editingSeasonId = season.Id; - editingSeason = new Season - { - Id = season.Id, - ArenaType = season.ArenaType, - RoundInterval = season.RoundInterval, - RequiredMedalCount = season.RequiredMedalCount, - TotalPrize = season.TotalPrize, - BattleTicketPolicyId = season.BattleTicketPolicyId, - RefreshTicketPolicyId = season.RefreshTicketPolicyId - }; - } - - private async Task SaveSeason(int seasonId) - { - try - { - await SeasonRepository.UpdateSeasonAsync( - seasonId, - editingSeason.ArenaType, - editingSeason.RoundInterval, - editingSeason.RequiredMedalCount, - editingSeason.TotalPrize, - editingSeason.BattleTicketPolicyId, - editingSeason.RefreshTicketPolicyId - ); - - editingSeasonId = 0; - message = "✅ Season updated successfully!"; - await LoadSeasons(); - } - catch (Exception ex) - { - message = $"❌ Failed to save season: {ex.Message}"; - } - } - - private void CancelEdit() - { - editingSeasonId = 0; - message = null; - } - - private async Task AdjustSeasonEndBlock() - { - if (selectedSeason == null) return; - - try - { - await SeasonBlockAdjustmentService.AdjustSeasonEndBlockAsync(selectedSeason.Id, newEndBlock); - message = "✅ Season end block adjusted successfully!"; - selectedSeason = null; - rounds.Clear(); - await LoadSeasons(); - } - catch (Exception ex) - { - message = $"❌ Failed to adjust season end block: {ex.Message}"; - } - } -} diff --git a/ArenaService.BackOffice/Components/Shared/NavMenu.razor b/ArenaService.BackOffice/Components/Shared/NavMenu.razor index 7731a7c..b65153c 100644 --- a/ArenaService.BackOffice/Components/Shared/NavMenu.razor +++ b/ArenaService.BackOffice/Components/Shared/NavMenu.razor @@ -1,48 +1,53 @@ - - - - -