mirror of
https://github.com/claunia/marechai.git
synced 2025-12-16 11:04:25 +00:00
Show country flag in company detail page.
This commit is contained in:
@@ -2,6 +2,7 @@ using System.Net.Http;
|
||||
using Marechai.App.Presentation.ViewModels;
|
||||
using Marechai.App.Presentation.Views;
|
||||
using Marechai.App.Services;
|
||||
using Marechai.App.Services.Caching;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Uno.Extensions;
|
||||
using Uno.Extensions.Configuration;
|
||||
@@ -106,6 +107,7 @@ public partial class App : Application
|
||||
.ConfigureServices((context, services) =>
|
||||
{
|
||||
// Register application services
|
||||
services.AddSingleton<FlagCache>();
|
||||
services.AddSingleton<NewsService>();
|
||||
services.AddSingleton<NewsViewModel>();
|
||||
services.AddSingleton<ComputersService>();
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
Navigation;
|
||||
ThemeService;
|
||||
SkiaRenderer;
|
||||
Svg;
|
||||
</UnoFeatures>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -3,20 +3,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using Marechai.App.Helpers;
|
||||
using Marechai.App.Presentation.Models;
|
||||
using Marechai.App.Services;
|
||||
using Marechai.App.Services.Caching;
|
||||
using Marechai.Data;
|
||||
using Microsoft.UI.Xaml.Media.Imaging;
|
||||
using Uno.Extensions.Navigation;
|
||||
using Windows.Storage.Streams;
|
||||
|
||||
namespace Marechai.App.Presentation.ViewModels;
|
||||
|
||||
public partial class CompanyDetailViewModel : ObservableObject
|
||||
{
|
||||
private readonly CompanyDetailService _companyDetailService;
|
||||
private readonly FlagCache _flagCache;
|
||||
private readonly IStringLocalizer _localizer;
|
||||
private readonly ILogger<CompanyDetailViewModel> _logger;
|
||||
private readonly INavigator _navigator;
|
||||
@@ -57,13 +62,20 @@ public partial class CompanyDetailViewModel : ObservableObject
|
||||
[ObservableProperty]
|
||||
private bool _isLoading;
|
||||
|
||||
[ObservableProperty]
|
||||
private SvgImageSource? _flagImageSource;
|
||||
|
||||
[ObservableProperty]
|
||||
private CompanyDto? _soldToCompany;
|
||||
|
||||
public CompanyDetailViewModel(CompanyDetailService companyDetailService, IStringLocalizer localizer,
|
||||
ILogger<CompanyDetailViewModel> logger, INavigator navigator)
|
||||
public CompanyDetailViewModel(CompanyDetailService companyDetailService,
|
||||
FlagCache flagCache,
|
||||
IStringLocalizer localizer,
|
||||
ILogger<CompanyDetailViewModel> logger,
|
||||
INavigator navigator)
|
||||
{
|
||||
_companyDetailService = companyDetailService;
|
||||
_flagCache = flagCache;
|
||||
_localizer = localizer;
|
||||
_logger = logger;
|
||||
_navigator = navigator;
|
||||
@@ -82,6 +94,11 @@ public partial class CompanyDetailViewModel : ObservableObject
|
||||
/// </summary>
|
||||
public string CompanyFoundedDateDisplay => Company != null ? GetFoundedDateDisplay(Company) : string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether flag content is available
|
||||
/// </summary>
|
||||
public bool HasFlagContent => FlagImageSource != null;
|
||||
|
||||
public IAsyncRelayCommand LoadData { get; }
|
||||
public ICommand GoBackCommand { get; }
|
||||
public IAsyncRelayCommand<CompanyDetailMachine> NavigateToMachineCommand { get; }
|
||||
@@ -94,6 +111,12 @@ public partial class CompanyDetailViewModel : ObservableObject
|
||||
OnPropertyChanged(nameof(CompanyFoundedDateDisplay));
|
||||
}
|
||||
|
||||
partial void OnFlagImageSourceChanged(SvgImageSource? oldValue, SvgImageSource? newValue)
|
||||
{
|
||||
// Notify that HasFlagContent has changed
|
||||
OnPropertyChanged(nameof(HasFlagContent));
|
||||
}
|
||||
|
||||
partial void OnComputersFilterTextChanged(string value)
|
||||
{
|
||||
FilterComputers(value);
|
||||
@@ -286,6 +309,7 @@ public partial class CompanyDetailViewModel : ObservableObject
|
||||
ErrorMessage = string.Empty;
|
||||
HasError = false;
|
||||
IsDataLoaded = false;
|
||||
FlagImageSource = null;
|
||||
|
||||
if(CompanyId <= 0)
|
||||
{
|
||||
@@ -306,7 +330,28 @@ public partial class CompanyDetailViewModel : ObservableObject
|
||||
return;
|
||||
}
|
||||
|
||||
// Load sold-to company if applicable
|
||||
// Load flag if country is available
|
||||
if(Company.CountryId is not null)
|
||||
{
|
||||
try
|
||||
{
|
||||
short countryCode = (short)UntypedNodeExtractor.ExtractInt(Company.CountryId);
|
||||
var flagStream = await _flagCache.GetFlagAsync(countryCode);
|
||||
|
||||
var flagSource = new SvgImageSource();
|
||||
await flagSource.SetSourceAsync(flagStream.AsRandomAccessStream());
|
||||
FlagImageSource = flagSource;
|
||||
|
||||
_logger.LogInformation("Successfully loaded flag for country code {CountryCode}",
|
||||
countryCode);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
_logger.LogError("Failed to load flag for country {CountryId}: {Exception}",
|
||||
Company.CountryId, ex.Message);
|
||||
// Continue without flag if loading fails
|
||||
}
|
||||
}
|
||||
if(Company.SoldToId != null)
|
||||
{
|
||||
int soldToId = UntypedNodeExtractor.ExtractInt(Company.SoldToId);
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
NavigationCacheMode="Required"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
|
||||
|
||||
<Page.Resources>
|
||||
</Page.Resources>
|
||||
|
||||
<Grid utu:SafeArea.Insets="VisibleBounds">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
@@ -113,14 +116,35 @@
|
||||
<!-- Country -->
|
||||
<StackPanel Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||
CornerRadius="8"
|
||||
Padding="12"
|
||||
Spacing="8">
|
||||
<TextBlock Text="Country"
|
||||
FontSize="14"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource SystemBaseMediumColor}" />
|
||||
<TextBlock Text="{Binding Company.Country}"
|
||||
FontSize="14" />
|
||||
Padding="12">
|
||||
<Grid ColumnSpacing="12">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Country Name and Label -->
|
||||
<StackPanel Grid.Column="0"
|
||||
Spacing="4">
|
||||
<TextBlock Text="Country"
|
||||
FontSize="14"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource SystemBaseMediumColor}" />
|
||||
<TextBlock Text="{Binding Company.Country}"
|
||||
FontSize="14"
|
||||
VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Country Flag -->
|
||||
<Image Grid.Column="1"
|
||||
Width="48"
|
||||
Height="32"
|
||||
Stretch="UniformToFill"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Right"
|
||||
Source="{Binding FlagImageSource}"
|
||||
Visibility="{Binding HasFlagContent, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Address -->
|
||||
|
||||
@@ -26,7 +26,7 @@ public sealed class FlagCache
|
||||
|
||||
public async Task<Stream> GetFlagAsync(short countryCode)
|
||||
{
|
||||
var filename = $"{countryCode}.svg";
|
||||
var filename = $"{countryCode:D3}.svg";
|
||||
|
||||
Stream retStream;
|
||||
|
||||
@@ -48,9 +48,9 @@ public sealed class FlagCache
|
||||
|
||||
async Task CacheFlagAsync(short countryCode)
|
||||
{
|
||||
var filename = $"{countryCode}.svg";
|
||||
var filename = $"{countryCode:D3}.svg";
|
||||
string baseUrl = _configuration.GetSection("ApiClient:Url").Value;
|
||||
string flagUrl = baseUrl + $"/assets/flags/{filename}";
|
||||
string flagUrl = baseUrl + $"/assets/flags/countries/{filename}";
|
||||
using var httpClient = new HttpClient();
|
||||
using HttpResponseMessage response = await httpClient.GetAsync(flagUrl);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
Reference in New Issue
Block a user