diff --git a/Directory.Packages.props b/Directory.Packages.props
index f3633522..e7548dd6 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -34,4 +34,14 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Marechai.App/Marechai.App.csproj b/Marechai.App/Marechai.App.csproj
index bd744c02..f996c7af 100644
--- a/Marechai.App/Marechai.App.csproj
+++ b/Marechai.App/Marechai.App.csproj
@@ -80,4 +80,14 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/Marechai.App/Presentation/ViewModels/CompanyDetailViewModel.cs b/Marechai.App/Presentation/ViewModels/CompanyDetailViewModel.cs
index 9b11b698..9a107a23 100644
--- a/Marechai.App/Presentation/ViewModels/CompanyDetailViewModel.cs
+++ b/Marechai.App/Presentation/ViewModels/CompanyDetailViewModel.cs
@@ -32,6 +32,9 @@ public partial class CompanyDetailViewModel : ObservableObject
[ObservableProperty]
private int _companyId;
+ [ObservableProperty]
+ private ObservableCollection _companyLogos = [];
+
[ObservableProperty]
private ObservableCollection _computers = [];
@@ -106,6 +109,11 @@ public partial class CompanyDetailViewModel : ObservableObject
///
public bool HasLogoContent => LogoImageSource != null;
+ ///
+ /// Gets whether company has multiple logos
+ ///
+ public bool HasMultipleLogos => CompanyLogos.Count > 1;
+
public IAsyncRelayCommand LoadData { get; }
public ICommand GoBackCommand { get; }
public IAsyncRelayCommand NavigateToMachineCommand { get; }
@@ -130,6 +138,13 @@ public partial class CompanyDetailViewModel : ObservableObject
OnPropertyChanged(nameof(HasLogoContent));
}
+ partial void OnCompanyLogosChanged(ObservableCollection oldValue,
+ ObservableCollection newValue)
+ {
+ // Notify that HasMultipleLogos has changed
+ OnPropertyChanged(nameof(HasMultipleLogos));
+ }
+
partial void OnComputersFilterTextChanged(string value)
{
FilterComputers(value);
@@ -324,6 +339,7 @@ public partial class CompanyDetailViewModel : ObservableObject
IsDataLoaded = false;
FlagImageSource = null;
LogoImageSource = null;
+ CompanyLogos.Clear();
if(CompanyId <= 0)
{
@@ -379,7 +395,7 @@ public partial class CompanyDetailViewModel : ObservableObject
{
try
{
- Stream? logoStream = await _logoCache.GetFlagAsync(Company.LastLogo.Value);
+ Stream? logoStream = await _logoCache.GetLogoAsync(Company.LastLogo.Value);
var logoSource = new SvgImageSource();
await logoSource.SetSourceAsync(logoStream.AsRandomAccessStream());
@@ -395,6 +411,58 @@ public partial class CompanyDetailViewModel : ObservableObject
}
}
+ // Load all logos for carousel
+ try
+ {
+ // Get all logos for this company
+ List logosList = await _companyDetailService.GetCompanyLogosAsync(CompanyId);
+
+ // Convert to list with extracted years for sorting
+ var logosWithYears = logosList.Select(logo => new
+ {
+ Logo = logo,
+ Year = logo.Year != null
+ ? (int?)UntypedNodeExtractor.ExtractInt(logo.Year)
+ : null
+ })
+ .OrderBy(l => l.Year)
+ .ToList();
+
+ var loadedLogos = new ObservableCollection();
+
+ foreach(var logoData in logosWithYears)
+ {
+ try
+ {
+ if(logoData.Logo.Guid == null) continue;
+
+ Stream? logoStream = await _logoCache.GetLogoAsync(logoData.Logo.Guid.Value);
+ var logoSource = new SvgImageSource();
+ await logoSource.SetSourceAsync(logoStream.AsRandomAccessStream());
+
+ loadedLogos.Add(new CompanyLogoItem
+ {
+ LogoGuid = logoData.Logo.Guid.Value,
+ LogoSource = logoSource,
+ Year = logoData.Year
+ });
+ }
+ catch(Exception ex)
+ {
+ _logger.LogError("Failed to load carousel logo: {Exception}", ex.Message);
+ }
+ }
+
+ // Assign the new collection (this will trigger OnCompanyLogosChanged)
+ CompanyLogos = loadedLogos;
+
+ _logger.LogInformation("Loaded {Count} logos for company {CompanyId}", CompanyLogos.Count, CompanyId);
+ }
+ catch(Exception ex)
+ {
+ _logger.LogError("Failed to load company logos for carousel: {Exception}", ex.Message);
+ }
+
// Load computers and consoles made by this company
List machines = await _companyDetailService.GetComputersByCompanyAsync(CompanyId);
Computers.Clear();
@@ -452,4 +520,14 @@ public class CompanyDetailMachine
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
+}
+
+///
+/// Data model for a company logo in the carousel
+///
+public class CompanyLogoItem
+{
+ public Guid LogoGuid { get; set; }
+ public SvgImageSource? LogoSource { get; set; }
+ public int? Year { get; set; }
}
\ No newline at end of file
diff --git a/Marechai.App/Presentation/Views/CompanyDetailPage.xaml b/Marechai.App/Presentation/Views/CompanyDetailPage.xaml
index bd2c9a14..0a5ae832 100644
--- a/Marechai.App/Presentation/Views/CompanyDetailPage.xaml
+++ b/Marechai.App/Presentation/Views/CompanyDetailPage.xaml
@@ -4,6 +4,7 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:utu="using:Uno.Toolkit.UI"
+ xmlns:controls="using:CommunityToolkit.WinUI.UI.Controls"
NavigationCacheMode="Required"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
@@ -201,6 +202,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Marechai.App/Services/Caching/LogoCache.cs b/Marechai.App/Services/Caching/LogoCache.cs
index 500ec06f..12b117a9 100644
--- a/Marechai.App/Services/Caching/LogoCache.cs
+++ b/Marechai.App/Services/Caching/LogoCache.cs
@@ -10,7 +10,7 @@ namespace Marechai.App.Services.Caching;
public sealed class CompanyLogoCache
{
readonly IConfiguration _configuration;
- StorageFolder _flagsFolder;
+ StorageFolder _logosFolder;
public CompanyLogoCache(IConfiguration configuration)
{
@@ -21,32 +21,32 @@ public sealed class CompanyLogoCache
async Task EnsureFolderExistAsync()
{
StorageFolder localFolder = ApplicationData.Current.LocalCacheFolder;
- _flagsFolder = await localFolder.CreateFolderAsync("logos", CreationCollisionOption.OpenIfExists);
+ _logosFolder = await localFolder.CreateFolderAsync("logos", CreationCollisionOption.OpenIfExists);
}
- public async Task GetFlagAsync(Guid companyLogoId)
+ public async Task GetLogoAsync(Guid companyLogoId)
{
var filename = $"{companyLogoId}.svg";
Stream retStream;
- if(await _flagsFolder.TryGetItemAsync(filename) is StorageFile file)
+ if(await _logosFolder.TryGetItemAsync(filename) is StorageFile file)
{
retStream = await file.OpenStreamForReadAsync();
return retStream;
}
- await CacheFlagAsync(companyLogoId);
+ await CacheLogoAsync(companyLogoId);
- file = await _flagsFolder.GetFileAsync(filename);
+ file = await _logosFolder.GetFileAsync(filename);
retStream = await file.OpenStreamForReadAsync();
return retStream;
}
- async Task CacheFlagAsync(Guid companyLogoId)
+ async Task CacheLogoAsync(Guid companyLogoId)
{
var filename = $"{companyLogoId}.svg";
string baseUrl = _configuration.GetSection("ApiClient:Url").Value;
@@ -56,7 +56,7 @@ public sealed class CompanyLogoCache
response.EnsureSuccessStatusCode();
using Stream stream = await response.Content.ReadAsStreamAsync();
- StorageFile file = await _flagsFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
+ StorageFile file = await _logosFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
using Stream fileStream = await file.OpenStreamForWriteAsync();
await stream.CopyToAsync(fileStream);
diff --git a/Marechai.App/Services/CompanyDetailService.cs b/Marechai.App/Services/CompanyDetailService.cs
index b66b7588..cb4032c1 100644
--- a/Marechai.App/Services/CompanyDetailService.cs
+++ b/Marechai.App/Services/CompanyDetailService.cs
@@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
-using Marechai.App.Models;
namespace Marechai.App.Services;
@@ -12,7 +11,7 @@ namespace Marechai.App.Services;
///
public class CompanyDetailService
{
- private readonly ApiClient _apiClient;
+ private readonly ApiClient _apiClient;
private readonly ILogger _logger;
public CompanyDetailService(ApiClient apiClient, ILogger logger)
@@ -64,7 +63,9 @@ public class CompanyDetailService
if(machines == null) return [];
- _logger.LogInformation("Successfully fetched {Count} computers for company {CompanyId}", machines.Count, companyId);
+ _logger.LogInformation("Successfully fetched {Count} computers for company {CompanyId}",
+ machines.Count,
+ companyId);
return machines;
}
@@ -98,4 +99,31 @@ public class CompanyDetailService
return null;
}
}
-}
+
+ ///
+ /// Gets all logos for a company
+ ///
+ public async Task> GetCompanyLogosAsync(int companyId)
+ {
+ try
+ {
+ _logger.LogInformation("Fetching logos for company {CompanyId}", companyId);
+
+ List? logos = await _apiClient.Companies[companyId].Logos.GetAsync();
+
+ if(logos == null) return [];
+
+ _logger.LogInformation("Successfully fetched {Count} logos for company {CompanyId}",
+ logos.Count,
+ companyId);
+
+ return logos;
+ }
+ catch(Exception ex)
+ {
+ _logger.LogError(ex, "Error fetching logos for company {CompanyId}", companyId);
+
+ return [];
+ }
+ }
+}
\ No newline at end of file