Team Registration view v1
This commit is contained in:
@@ -1,9 +1,41 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace TournamentOrganizer.ViewModels;
|
||||
|
||||
public partial class MainViewModel : ViewModelBase
|
||||
{
|
||||
[ObservableProperty]
|
||||
private string _greeting = "Welcome to Avalonia!";
|
||||
}
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
namespace TournamentOrganizer.ViewModels;
|
||||
|
||||
public partial class MainViewModel : ViewModelBase
|
||||
{
|
||||
[ObservableProperty]
|
||||
private ViewModelBase _currentView;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _title = "Tournament Organizer";
|
||||
|
||||
public MainViewModel()
|
||||
{
|
||||
CurrentView = new HomeViewModel();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void NavigateToHome()
|
||||
{
|
||||
CurrentView = new HomeViewModel();
|
||||
Title = "Tournament Organizer";
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task NavigateToTeams()
|
||||
{
|
||||
var teamsVm = new TeamsViewModel();
|
||||
CurrentView = teamsVm;
|
||||
Title = "Teams Management";
|
||||
await teamsVm.LoadTeams();
|
||||
}
|
||||
}
|
||||
|
||||
public partial class HomeViewModel : ViewModelBase
|
||||
{
|
||||
[ObservableProperty]
|
||||
private string _welcomeMessage = "Welcome to Tournament Organizer!";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,470 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using TournamentOrganizer.Models;
|
||||
|
||||
namespace TournamentOrganizer.ViewModels;
|
||||
|
||||
public partial class TeamsViewModel : ViewModelBase
|
||||
{
|
||||
private readonly TournamentContext _context;
|
||||
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<TeamDisplay> _teams = [];
|
||||
|
||||
[ObservableProperty]
|
||||
private TeamDisplay? _selectedTeam;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _teamName = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<PlayerEntry> _players = [];
|
||||
|
||||
[ObservableProperty]
|
||||
private PlayerEntry? _selectedPlayer;
|
||||
|
||||
[ObservableProperty]
|
||||
private PlayerEntry? _selectedLeader;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _newPlayerName = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _newPlayerContact = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _filterMemberName = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _filterEventName = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _filterTournamentName = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isEditing;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _statusMessage = string.Empty;
|
||||
|
||||
public TeamsViewModel()
|
||||
{
|
||||
_context = new TournamentContext();
|
||||
}
|
||||
|
||||
public async Task LoadTeams()
|
||||
{
|
||||
var query = _context.Teams
|
||||
.Include(t => t.Players)
|
||||
.Include(t => t.Leader)
|
||||
.Include(t => t.Matches)
|
||||
.ThenInclude(tp => tp.Round)
|
||||
.ThenInclude(m => m.Tournament)
|
||||
.ThenInclude(t => t.Event)
|
||||
.AsSplitQuery();
|
||||
|
||||
var allTeams = await query.ToListAsync();
|
||||
|
||||
var filtered = allTeams.AsEnumerable();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(FilterMemberName))
|
||||
{
|
||||
var filter = FilterMemberName.ToLower();
|
||||
filtered = filtered.Where(t => t.Players.Any(p => p.Name.ToLower().Contains(filter)));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(FilterEventName))
|
||||
{
|
||||
var filter = FilterEventName.ToLower();
|
||||
filtered = filtered.Where(t => GetAssociatedEvents(t).Any(e => e.ToLower().Contains(filter)));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(FilterTournamentName))
|
||||
{
|
||||
var filter = FilterTournamentName.ToLower();
|
||||
filtered = filtered.Where(t => GetAssociatedTournaments(t).Any(tn => tn.ToLower().Contains(filter)));
|
||||
}
|
||||
|
||||
Teams.Clear();
|
||||
foreach (var team in filtered)
|
||||
{
|
||||
Teams.Add(new TeamDisplay(team));
|
||||
}
|
||||
|
||||
SelectedTeam = null;
|
||||
IsEditing = false;
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task RefreshTeams()
|
||||
{
|
||||
await LoadTeams();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void CreateNewTeam()
|
||||
{
|
||||
TeamName = "New Team";
|
||||
Players.Clear();
|
||||
SelectedLeader = null;
|
||||
SelectedPlayer = null;
|
||||
IsEditing = true;
|
||||
SelectedTeam = null;
|
||||
NewPlayerName = string.Empty;
|
||||
NewPlayerContact = string.Empty;
|
||||
StatusMessage = "Creating new team";
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task SaveTeam()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(TeamName))
|
||||
{
|
||||
StatusMessage = "Team name is required";
|
||||
return;
|
||||
}
|
||||
|
||||
if (Players.Count == 0)
|
||||
{
|
||||
StatusMessage = "Team must have at least one member";
|
||||
return;
|
||||
}
|
||||
|
||||
Team? team;
|
||||
if (SelectedTeam != null && SelectedTeam.Id > 0)
|
||||
{
|
||||
team = await _context.Teams
|
||||
.Include(t => t.Players)
|
||||
.FirstOrDefaultAsync(t => t.Id == SelectedTeam.Id);
|
||||
|
||||
if (team == null)
|
||||
{
|
||||
StatusMessage = "Team not found";
|
||||
return;
|
||||
}
|
||||
|
||||
team.Name = TeamName;
|
||||
|
||||
var existingPlayerIds = team.Players.Select(p => p.Id).ToHashSet();
|
||||
var currentPlayerIds = Players.Where(p => p.Id > 0).Select(p => p.Id).ToHashSet();
|
||||
|
||||
var playersToRemove = team.Players.Where(p => !currentPlayerIds.Contains(p.Id)).ToList();
|
||||
foreach (var player in playersToRemove)
|
||||
{
|
||||
team.Players.Remove(player);
|
||||
_context.Players.Remove(player);
|
||||
}
|
||||
|
||||
foreach (var entry in Players)
|
||||
{
|
||||
if (entry.Id > 0)
|
||||
{
|
||||
var existing = team.Players.FirstOrDefault(p => p.Id == entry.Id);
|
||||
if (existing != null)
|
||||
{
|
||||
existing.Name = entry.Name;
|
||||
existing.Contact = entry.Contact;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var newPlayer = new Player
|
||||
{
|
||||
Name = entry.Name,
|
||||
Contact = entry.Contact,
|
||||
Team = team
|
||||
};
|
||||
team.Players.Add(newPlayer);
|
||||
entry.Id = newPlayer.Id;
|
||||
}
|
||||
}
|
||||
|
||||
if (SelectedLeader != null)
|
||||
{
|
||||
var leader = team.Players.FirstOrDefault(p =>
|
||||
(SelectedLeader.Id > 0 && p.Id == SelectedLeader.Id) ||
|
||||
(SelectedLeader.Id == 0 && p.Name == SelectedLeader.Name && p.Contact == SelectedLeader.Contact));
|
||||
team.Leader = leader;
|
||||
}
|
||||
else
|
||||
{
|
||||
team.Leader = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
team = new Team
|
||||
{
|
||||
Name = TeamName,
|
||||
Players = [],
|
||||
Matches = []
|
||||
};
|
||||
|
||||
var playerEntries = new List<(PlayerEntry Entry, Player Player)>();
|
||||
foreach (var entry in Players)
|
||||
{
|
||||
var player = new Player
|
||||
{
|
||||
Name = entry.Name,
|
||||
Contact = entry.Contact,
|
||||
Team = team
|
||||
};
|
||||
team.Players.Add(player);
|
||||
playerEntries.Add((entry, player));
|
||||
}
|
||||
|
||||
_context.Teams.Add(team);
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
if (team.Players.Count > 0)
|
||||
{
|
||||
int leaderIndex = 0;
|
||||
if (SelectedLeader != null)
|
||||
{
|
||||
var idx = Players.IndexOf(SelectedLeader);
|
||||
if (idx >= 0) leaderIndex = idx;
|
||||
}
|
||||
|
||||
team.LeaderId = playerEntries[leaderIndex].Player.Id;
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
StatusMessage = $"Team '{TeamName}' saved successfully";
|
||||
await LoadTeams();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private async Task DeleteTeam()
|
||||
{
|
||||
if (SelectedTeam == null || SelectedTeam.Id == 0)
|
||||
{
|
||||
StatusMessage = "Select a team to delete";
|
||||
return;
|
||||
}
|
||||
|
||||
var team = await _context.Teams
|
||||
.Include(t => t.Players)
|
||||
.FirstOrDefaultAsync(t => t.Id == SelectedTeam.Id);
|
||||
|
||||
if (team == null)
|
||||
{
|
||||
StatusMessage = "Team not found";
|
||||
return;
|
||||
}
|
||||
|
||||
_context.Teams.Remove(team);
|
||||
await _context.SaveChangesAsync();
|
||||
StatusMessage = $"Team '{team.Name}' deleted";
|
||||
await LoadTeams();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void AddPlayer()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(NewPlayerName))
|
||||
{
|
||||
StatusMessage = "Player name is required";
|
||||
return;
|
||||
}
|
||||
|
||||
var entry = new PlayerEntry
|
||||
{
|
||||
Name = NewPlayerName,
|
||||
Contact = NewPlayerContact
|
||||
};
|
||||
Players.Add(entry);
|
||||
|
||||
if (SelectedLeader == null)
|
||||
{
|
||||
SelectedLeader = entry;
|
||||
}
|
||||
|
||||
NewPlayerName = string.Empty;
|
||||
NewPlayerContact = string.Empty;
|
||||
StatusMessage = $"Player '{entry.Name}' added";
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void RemovePlayer()
|
||||
{
|
||||
if (SelectedPlayer == null)
|
||||
{
|
||||
StatusMessage = "Select a player to remove";
|
||||
return;
|
||||
}
|
||||
|
||||
var wasLeader = SelectedLeader == SelectedPlayer;
|
||||
Players.Remove(SelectedPlayer);
|
||||
|
||||
if (wasLeader)
|
||||
{
|
||||
SelectedLeader = Players.FirstOrDefault();
|
||||
}
|
||||
|
||||
SelectedPlayer = null;
|
||||
StatusMessage = "Player removed";
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void SetLeader()
|
||||
{
|
||||
if (SelectedPlayer == null)
|
||||
{
|
||||
StatusMessage = "Select a player to make leader";
|
||||
return;
|
||||
}
|
||||
|
||||
SelectedLeader = SelectedPlayer;
|
||||
StatusMessage = $"{SelectedPlayer.Name} is now the leader";
|
||||
}
|
||||
|
||||
partial void OnSelectedTeamChanged(TeamDisplay? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
IsEditing = false;
|
||||
return;
|
||||
}
|
||||
|
||||
TeamName = value.Name;
|
||||
Players.Clear();
|
||||
foreach (var player in value.Players)
|
||||
{
|
||||
Players.Add(player);
|
||||
}
|
||||
|
||||
SelectedLeader = Players.FirstOrDefault(p => p.Id == value.LeaderId);
|
||||
SelectedPlayer = null;
|
||||
IsEditing = true;
|
||||
NewPlayerName = string.Empty;
|
||||
NewPlayerContact = string.Empty;
|
||||
StatusMessage = $"Editing team '{value.Name}'";
|
||||
}
|
||||
|
||||
partial void OnFilterMemberNameChanged(string value) => ApplyFilters();
|
||||
partial void OnFilterEventNameChanged(string value) => ApplyFilters();
|
||||
partial void OnFilterTournamentNameChanged(string value) => ApplyFilters();
|
||||
|
||||
private async void ApplyFilters()
|
||||
{
|
||||
await LoadTeams();
|
||||
}
|
||||
|
||||
private static List<string> GetAssociatedEvents(Team team)
|
||||
{
|
||||
var events = new List<string>();
|
||||
if (team.Matches != null)
|
||||
{
|
||||
foreach (var tp in team.Matches)
|
||||
{
|
||||
if (tp.Round?.Tournament?.Event != null)
|
||||
{
|
||||
var eventName = tp.Round.Tournament.Event.Name;
|
||||
if (!events.Contains(eventName))
|
||||
{
|
||||
events.Add(eventName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return events;
|
||||
}
|
||||
|
||||
private static List<string> GetAssociatedTournaments(Team team)
|
||||
{
|
||||
var tournaments = new List<string>();
|
||||
if (team.Matches != null)
|
||||
{
|
||||
foreach (var tp in team.Matches)
|
||||
{
|
||||
if (tp.Round?.Tournament != null)
|
||||
{
|
||||
var tournamentName = GetTournamentDisplayName(tp.Round.Tournament);
|
||||
if (!tournaments.Contains(tournamentName))
|
||||
{
|
||||
tournaments.Add(tournamentName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return tournaments;
|
||||
}
|
||||
|
||||
public static string GetTournamentDisplayName(Tournament tournament)
|
||||
{
|
||||
return $"{tournament.Game.Name} @ {tournament.Event.Name}";
|
||||
}
|
||||
}
|
||||
|
||||
public class TeamDisplay
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public int? LeaderId { get; set; }
|
||||
public string? LeaderName { get; set; }
|
||||
public List<PlayerEntry> Players { get; set; } = [];
|
||||
public List<string> AssociatedEvents { get; set; } = [];
|
||||
public List<string> AssociatedTournaments { get; set; } = [];
|
||||
|
||||
public TeamDisplay() { }
|
||||
|
||||
public TeamDisplay(Team team)
|
||||
{
|
||||
Id = team.Id;
|
||||
Name = team.Name;
|
||||
LeaderId = team.LeaderId;
|
||||
LeaderName = team.Leader?.Name;
|
||||
Players = team.Players?.Select(p => new PlayerEntry(p)).ToList() ?? [];
|
||||
|
||||
var events = new HashSet<string>();
|
||||
var tournaments = new HashSet<string>();
|
||||
|
||||
if (team.Matches != null)
|
||||
{
|
||||
foreach (var tp in team.Matches)
|
||||
{
|
||||
if (tp.Round?.Tournament != null)
|
||||
{
|
||||
tournaments.Add(TeamsViewModel.GetTournamentDisplayName(tp.Round.Tournament));
|
||||
if (tp.Round.Tournament.Event != null)
|
||||
{
|
||||
events.Add(tp.Round.Tournament.Event.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AssociatedEvents = events.ToList();
|
||||
AssociatedTournaments = tournaments.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public partial class PlayerEntry : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
private int _id;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _name = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _contact = string.Empty;
|
||||
|
||||
public PlayerEntry() { }
|
||||
|
||||
public PlayerEntry(Player player)
|
||||
{
|
||||
Id = player.Id;
|
||||
Name = player.Name;
|
||||
Contact = player.Contact;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user