mirror of
https://github.com/claunia/marechai.git
synced 2026-07-08 17:57:08 +00:00
303 lines
11 KiB
C#
303 lines
11 KiB
C#
#nullable enable
|
||
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Collections.ObjectModel;
|
||
using System.Threading.Tasks;
|
||
using System.Windows.Input;
|
||
using Marechai.App.Navigation;
|
||
using Marechai.App.Presentation.Views;
|
||
using Marechai.App.Services;
|
||
using Microsoft.UI.Xaml;
|
||
using Microsoft.UI.Xaml.Data;
|
||
|
||
namespace Marechai.App.Presentation.ViewModels;
|
||
|
||
[Bindable]
|
||
public partial class PersonViewViewModel : ObservableObject, IRegionAware
|
||
{
|
||
private readonly IStringLocalizer _localizer;
|
||
private readonly ILogger<PersonViewViewModel> _logger;
|
||
private readonly PeopleService _peopleService;
|
||
private readonly IRegionManager _regionManager;
|
||
|
||
private string? _navigationSource;
|
||
private int _currentPersonId;
|
||
|
||
[ObservableProperty]
|
||
private string _personName = string.Empty;
|
||
|
||
[ObservableProperty]
|
||
private string? _alias;
|
||
|
||
[ObservableProperty]
|
||
private string? _displayName;
|
||
|
||
[ObservableProperty]
|
||
private string? _birthDateDisplay;
|
||
|
||
[ObservableProperty]
|
||
private string? _deathDateDisplay;
|
||
|
||
[ObservableProperty]
|
||
private string? _countryOfBirth;
|
||
|
||
[ObservableProperty]
|
||
private string? _webpage;
|
||
|
||
[ObservableProperty]
|
||
private string? _twitter;
|
||
|
||
[ObservableProperty]
|
||
private string? _facebook;
|
||
|
||
[ObservableProperty]
|
||
private string _errorMessage = string.Empty;
|
||
|
||
[ObservableProperty]
|
||
private bool _hasError;
|
||
|
||
[ObservableProperty]
|
||
private bool _isDataLoaded;
|
||
|
||
[ObservableProperty]
|
||
private bool _isLoading;
|
||
|
||
// Visibility flags
|
||
[ObservableProperty]
|
||
private Visibility _showAlias = Visibility.Collapsed;
|
||
|
||
[ObservableProperty]
|
||
private Visibility _showDisplayName = Visibility.Collapsed;
|
||
|
||
[ObservableProperty]
|
||
private Visibility _showBirthDate = Visibility.Collapsed;
|
||
|
||
[ObservableProperty]
|
||
private Visibility _showDeathDate = Visibility.Collapsed;
|
||
|
||
[ObservableProperty]
|
||
private Visibility _showCountry = Visibility.Collapsed;
|
||
|
||
[ObservableProperty]
|
||
private Visibility _showWebpage = Visibility.Collapsed;
|
||
|
||
[ObservableProperty]
|
||
private Visibility _showTwitter = Visibility.Collapsed;
|
||
|
||
[ObservableProperty]
|
||
private Visibility _showFacebook = Visibility.Collapsed;
|
||
|
||
[ObservableProperty]
|
||
private Visibility _showCompanies = Visibility.Collapsed;
|
||
|
||
[ObservableProperty]
|
||
private Visibility _showBooks = Visibility.Collapsed;
|
||
|
||
[ObservableProperty]
|
||
private Visibility _showDocuments = Visibility.Collapsed;
|
||
|
||
[ObservableProperty]
|
||
private Visibility _showMagazines = Visibility.Collapsed;
|
||
|
||
[ObservableProperty]
|
||
private Visibility _showSoftware = Visibility.Collapsed;
|
||
|
||
public PersonViewViewModel(ILogger<PersonViewViewModel> logger, IRegionManager regionManager,
|
||
PeopleService peopleService, IStringLocalizer localizer)
|
||
{
|
||
_logger = logger;
|
||
_regionManager = regionManager;
|
||
_peopleService = peopleService;
|
||
_localizer = localizer;
|
||
}
|
||
|
||
public ObservableCollection<string> Companies { get; } = [];
|
||
public ObservableCollection<string> Books { get; } = [];
|
||
public ObservableCollection<string> Documents { get; } = [];
|
||
public ObservableCollection<string> Magazines { get; } = [];
|
||
public ObservableCollection<string> SoftwareCredits { get; } = [];
|
||
|
||
public bool IsNavigationTarget(NavigationContext navigationContext) => false;
|
||
|
||
public void OnNavigatedFrom(NavigationContext navigationContext) { }
|
||
|
||
public void OnNavigatedTo(NavigationContext navigationContext)
|
||
{
|
||
if(navigationContext.Parameters.TryGetValue<string>(NavParamKeys.NavigationSource, out string? source))
|
||
_navigationSource = source;
|
||
|
||
if(navigationContext.Parameters.TryGetValue<int>(NavParamKeys.PersonId, out int personId))
|
||
{
|
||
_currentPersonId = personId;
|
||
_ = LoadPersonAsync(personId);
|
||
}
|
||
}
|
||
|
||
[RelayCommand]
|
||
public Task GoBack()
|
||
{
|
||
if(_regionManager.TryGoBack(RegionNames.Content))
|
||
return Task.CompletedTask;
|
||
|
||
switch(_navigationSource)
|
||
{
|
||
case nameof(PeopleListViewModel):
|
||
_regionManager.RequestNavigate(RegionNames.Content, nameof(PeopleListPage));
|
||
|
||
break;
|
||
|
||
default:
|
||
_regionManager.RequestNavigate(RegionNames.Content, nameof(PeoplePage));
|
||
|
||
break;
|
||
}
|
||
|
||
return Task.CompletedTask;
|
||
}
|
||
|
||
[RelayCommand]
|
||
public Task LoadData()
|
||
{
|
||
HasError = false;
|
||
ErrorMessage = string.Empty;
|
||
|
||
return Task.CompletedTask;
|
||
}
|
||
|
||
public async Task LoadPersonAsync(int personId)
|
||
{
|
||
try
|
||
{
|
||
IsLoading = true;
|
||
IsDataLoaded = false;
|
||
HasError = false;
|
||
ErrorMessage = string.Empty;
|
||
Companies.Clear();
|
||
Books.Clear();
|
||
Documents.Clear();
|
||
Magazines.Clear();
|
||
SoftwareCredits.Clear();
|
||
|
||
PersonDto? person = await _peopleService.GetPersonByIdAsync(personId);
|
||
|
||
if(person is null)
|
||
{
|
||
HasError = true;
|
||
ErrorMessage = _localizer["Person not found"];
|
||
IsLoading = false;
|
||
|
||
return;
|
||
}
|
||
|
||
// Populate basic information
|
||
PersonName = person.DisplayName ?? person.Alias ?? $"{person.Name} {person.Surname}".Trim();
|
||
Alias = person.Alias;
|
||
DisplayName = person.DisplayName;
|
||
CountryOfBirth = person.Country;
|
||
Webpage = person.Webpage;
|
||
Twitter = person.Twitter;
|
||
Facebook = person.Facebook;
|
||
|
||
if(person.Birthdate.HasValue && person.Birthdate.Value.Year > 1)
|
||
BirthDateDisplay = DatePrecisionFormatter.Format(person.Birthdate, person.BirthdatePrecision);
|
||
|
||
if(person.DeathDate.HasValue)
|
||
DeathDateDisplay = DatePrecisionFormatter.Format(person.DeathDate, person.DeathDatePrecision);
|
||
|
||
// Load related entities in parallel
|
||
Task<List<PersonByCompanyDto>> companiesTask = _peopleService.GetCompaniesByPersonAsync(personId);
|
||
Task<List<PersonByBookDto>> booksTask = _peopleService.GetBooksByPersonAsync(personId);
|
||
Task<List<PersonByDocumentDto>> documentsTask = _peopleService.GetDocumentsByPersonAsync(personId);
|
||
Task<List<PersonByMagazineDto>> magazinesTask = _peopleService.GetMagazinesByPersonAsync(personId);
|
||
Task<List<PersonBySoftwareDto>> softwareTask = _peopleService.GetSoftwareByPersonAsync(personId);
|
||
await Task.WhenAll(companiesTask, booksTask, documentsTask, magazinesTask, softwareTask);
|
||
|
||
// Populate companies
|
||
foreach(PersonByCompanyDto company in companiesTask.Result)
|
||
{
|
||
string name = company.CompanyName ?? string.Empty;
|
||
string display = name;
|
||
|
||
if(!string.IsNullOrWhiteSpace(company.Position))
|
||
display += $" — {company.Position}";
|
||
|
||
if(company.Ongoing == true)
|
||
display += $" ({_localizer["OngoingText"].Value})";
|
||
else if(company.Start != null || company.End != null)
|
||
{
|
||
string start = company.Start?.DateTime.ToString("yyyy") ?? "?";
|
||
string end = company.End?.DateTime.ToString("yyyy") ?? "?";
|
||
display += $" ({start}–{end})";
|
||
}
|
||
|
||
Companies.Add(display);
|
||
}
|
||
|
||
// Populate books
|
||
foreach(PersonByBookDto book in booksTask.Result)
|
||
{
|
||
string title = book.BookTitle ?? string.Empty;
|
||
string? role = book.Role;
|
||
string display = !string.IsNullOrEmpty(role) ? $"{title} ({role})" : title;
|
||
Books.Add(display);
|
||
}
|
||
|
||
// Populate documents
|
||
foreach(PersonByDocumentDto document in documentsTask.Result)
|
||
{
|
||
string title = document.DocumentTitle ?? string.Empty;
|
||
string? role = document.Role;
|
||
string display = !string.IsNullOrEmpty(role) ? $"{title} ({role})" : title;
|
||
Documents.Add(display);
|
||
}
|
||
|
||
// Populate magazines
|
||
foreach(PersonByMagazineDto magazine in magazinesTask.Result)
|
||
{
|
||
string title = magazine.MagazineTitle ?? string.Empty;
|
||
string? role = magazine.Role;
|
||
string display = !string.IsNullOrEmpty(role) ? $"{title} ({role})" : title;
|
||
Magazines.Add(display);
|
||
}
|
||
|
||
// Populate software credits
|
||
foreach(PersonBySoftwareDto credit in softwareTask.Result)
|
||
{
|
||
string name = credit.SoftwareName ?? string.Empty;
|
||
string? role = credit.Role;
|
||
string display = !string.IsNullOrEmpty(role) ? $"{name} ({role})" : name;
|
||
SoftwareCredits.Add(display);
|
||
}
|
||
|
||
UpdateVisibilities();
|
||
IsDataLoaded = true;
|
||
IsLoading = false;
|
||
}
|
||
catch(Exception ex)
|
||
{
|
||
_logger.LogError(ex, "Error loading person {PersonId}", personId);
|
||
HasError = true;
|
||
ErrorMessage = ex.Message;
|
||
IsLoading = false;
|
||
}
|
||
}
|
||
|
||
private void UpdateVisibilities()
|
||
{
|
||
ShowAlias = !string.IsNullOrEmpty(Alias) ? Visibility.Visible : Visibility.Collapsed;
|
||
ShowDisplayName = !string.IsNullOrEmpty(DisplayName) ? Visibility.Visible : Visibility.Collapsed;
|
||
ShowBirthDate = !string.IsNullOrEmpty(BirthDateDisplay) ? Visibility.Visible : Visibility.Collapsed;
|
||
ShowDeathDate = !string.IsNullOrEmpty(DeathDateDisplay) ? Visibility.Visible : Visibility.Collapsed;
|
||
ShowCountry = !string.IsNullOrEmpty(CountryOfBirth) ? Visibility.Visible : Visibility.Collapsed;
|
||
ShowWebpage = !string.IsNullOrEmpty(Webpage) ? Visibility.Visible : Visibility.Collapsed;
|
||
ShowTwitter = !string.IsNullOrEmpty(Twitter) ? Visibility.Visible : Visibility.Collapsed;
|
||
ShowFacebook = !string.IsNullOrEmpty(Facebook) ? Visibility.Visible : Visibility.Collapsed;
|
||
ShowCompanies = Companies.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
|
||
ShowBooks = Books.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
|
||
ShowDocuments = Documents.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
|
||
ShowMagazines = Magazines.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
|
||
ShowSoftware = SoftwareCredits.Count > 0 ? Visibility.Visible : Visibility.Collapsed;
|
||
}
|
||
}
|