Show country flag in company detail page.

This commit is contained in:
2025-11-15 15:26:47 +00:00
parent c6cac9e04a
commit cfdef93787
5 changed files with 86 additions and 14 deletions

View File

@@ -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>();

View File

@@ -36,6 +36,7 @@
Navigation;
ThemeService;
SkiaRenderer;
Svg;
</UnoFeatures>
</PropertyGroup>
<ItemGroup>

View File

@@ -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);

View File

@@ -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 -->

View File

@@ -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();