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))
+ {
+
+ @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
- 📅 Currently Active Round
+
+}
+
+@if (selectedSeason != null)
+{
+ 📋 Selected Season's Round List
- | ID |
+ Round ID |
+ Round Index |
Start Block |
End Block |
-
- | @currentRound?.Id |
- @currentRound?.StartBlock |
- @currentRound?.EndBlock |
-
-
-
-
- 📊 Ranking Data Availability
-
-
-
- | Round |
- Ranking Data Count |
- Status |
-
-
-
- @foreach (var roundRanking in rankingCounts)
+ @foreach (var round in rounds)
{
- | @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)
+{
+
+
+
+ | ID |
+ Start Block |
+ End Block |
+
+
+
+
+ | @currentSeason?.Id |
+ @currentSeason?.StartBlock |
+ @currentSeason?.EndBlock |
+
+
+
+
+ 📅 Currently Active Round
+
+
+
+ | ID |
+ Round Index |
+ Start Block |
+ End Block |
+
+
+
+
+ | @currentRound?.Id |
+ @currentRound?.RoundIndex |
+ @currentRound?.StartBlock |
+ @currentRound?.EndBlock |
+
+
+
+
+ 📊 Ranking Data Availability
+
+
+
+ | Round |
+ Ranking Data Count |
+ Status |
+
+
+
+ @foreach (var roundRanking in rankingCounts)
+ {
+
+ | @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
-
-
-
-}
-
-@if (selectedSeason != null)
-{
- 📋 Selected Season's Round List
-
-
-
- | Round ID |
- Start Block |
- End Block |
-
-
-
- @foreach (var round in rounds)
- {
-
- | @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 @@
-
-
-
-
-