From 7b9274515344bb149da640486ba2fdd28026f1e6 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Mon, 31 Aug 2026 02:14:04 +0100 Subject: [PATCH] =?UTF-8?q?Exploration=20des=20activit=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 8 + .../ActivitiesPageViewModelTests.cs | 18 +- src/PostIt/PostIt/App.axaml.cs | 5 - .../ViewModels/ActivitiesPageViewModel.cs | 19 +- .../ViewModels/ActivityUserDisplayItem.cs | 39 ++++ src/PostIt/PostIt/Views/ActivitiesPage.axaml | 48 +++- .../Workflow/ActivityPerformerDto.cs | 1 + src/Yavsc.Api.Client/ActivityApiClient.cs | 9 +- .../ActivityApiControllerTests.cs | 161 ++++++++++++++ src/Yavsc.Api.Test/ApiCollection.cs | 6 + src/Yavsc.Api.Test/Directory.Packages.props | 7 + .../Fixtures/ApiWebServerFixture.cs | 210 ++++++++++++++++++ src/Yavsc.Api.Test/HomeControllerTests.cs | 69 ++++++ src/Yavsc.Api.Test/Yavsc.Api.Test.csproj | 33 +++ .../Business/ActivityApiController.cs | 71 ++++-- .../Contracting/SIRENExceptionsController.cs | 34 ++- src/Yavsc.Org/Controllers/HomeController.cs | 28 ++- src/Yavsc.Org/Views/Manage/SetActivity.cshtml | 2 +- .../Views/SIRENExceptions/Create.cshtml | 21 +- yavsc.sln | 15 ++ 20 files changed, 743 insertions(+), 61 deletions(-) create mode 100644 src/PostIt/PostIt/ViewModels/ActivityUserDisplayItem.cs create mode 100644 src/Yavsc.Api.Test/ActivityApiControllerTests.cs create mode 100644 src/Yavsc.Api.Test/ApiCollection.cs create mode 100644 src/Yavsc.Api.Test/Directory.Packages.props create mode 100644 src/Yavsc.Api.Test/Fixtures/ApiWebServerFixture.cs create mode 100644 src/Yavsc.Api.Test/HomeControllerTests.cs create mode 100644 src/Yavsc.Api.Test/Yavsc.Api.Test.csproj diff --git a/CHANGELOG.md b/CHANGELOG.md index ec42b81b..1a2efb4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [1.0.8-rc10] - unstable + +### Added + +### Changed + +### Fixed + ## [1.0.8-rc9] - unstable ### Added diff --git a/src/PostIt/PostIt.Tests/ActivitiesPageViewModelTests.cs b/src/PostIt/PostIt.Tests/ActivitiesPageViewModelTests.cs index 124777e0..da166fa6 100644 --- a/src/PostIt/PostIt.Tests/ActivitiesPageViewModelTests.cs +++ b/src/PostIt/PostIt.Tests/ActivitiesPageViewModelTests.cs @@ -14,10 +14,10 @@ public class ActivitiesPageViewModelTests var client = new ActivityApiClient(api, "https://business.example/api/v1/"); await client.GetCatalogAsync("brush", TestContext.Current.CancellationToken); - await client.GetPerformersAsync("brush-pro", TestContext.Current.CancellationToken); + await client.GetUsersAsync("brush-pro", TestContext.Current.CancellationToken); Assert.Equal("https://business.example/api/v1/activity/catalog?parentCode=brush", api.Paths[0]); - Assert.Equal("https://business.example/api/v1/activity/brush-pro/performers", api.Paths[1]); + Assert.Equal("https://business.example/api/v1/activity/brush-pro/users", api.Paths[1]); } [Fact] @@ -34,12 +34,20 @@ public class ActivitiesPageViewModelTests Assert.Equal("brush", vm.CurrentActivity?.Code); Assert.Single(vm.Performers); Assert.Equal("Alice", vm.Performers[0].UserName); + Assert.True(vm.Performers[0].HasPerformerProfile); + Assert.True(vm.Performers[0].IsPerformerActive); + Assert.Equal("Actif", vm.Performers[0].PerformerStatusBadgeLabel); + Assert.Equal("Pas d'autre activité", vm.Performers[0].ExtraActivityLabel); await vm.ShowSpecializationAsync(vm.Specializations[0]); Assert.Equal("brush-pro", vm.CurrentActivity?.Code); Assert.Single(vm.Performers); Assert.Equal("Bob", vm.Performers[0].UserName); + Assert.True(vm.Performers[0].HasPerformerProfile); + Assert.False(vm.Performers[0].IsPerformerActive); + Assert.Equal("Inactif", vm.Performers[0].PerformerStatusBadgeLabel); + Assert.Equal("Autres spécialisations: 2", vm.Performers[0].ExtraActivityLabel); Assert.Contains("brush pro", vm.StatusMessage, StringComparison.OrdinalIgnoreCase); await vm.ShowSpecializationAsync(null); @@ -86,14 +94,14 @@ public class ActivitiesPageViewModelTests if (typeof(T) == typeof(List)) { - var performers = path.EndsWith("brush-pro/performers", StringComparison.Ordinal) + var performers = path.EndsWith("brush-pro/users", StringComparison.Ordinal) ? new List { - new() { PerformerId = "pro-2", UserName = "Bob", ActivityCode = "brush-pro", ActivityName = "Brush Pro" } + new() { PerformerId = "pro-2", HasPerformerProfile = true, Active = false, UserName = "Bob", ActivityCode = "brush-pro", ActivityName = "Brush Pro", ExtraActivityCount = 2 } } : new List { - new() { PerformerId = "pro-1", UserName = "Alice", ActivityCode = "brush", ActivityName = "Brush" } + new() { PerformerId = "pro-1", HasPerformerProfile = true, Active = true, UserName = "Alice", ActivityCode = "brush", ActivityName = "Brush", ExtraActivityCount = 0 } }; return Task.FromResult((T)(object)performers); diff --git a/src/PostIt/PostIt/App.axaml.cs b/src/PostIt/PostIt/App.axaml.cs index f43aa1d9..d3fbf651 100644 --- a/src/PostIt/PostIt/App.axaml.cs +++ b/src/PostIt/PostIt/App.axaml.cs @@ -86,11 +86,6 @@ private void ConfigureRootView(MainView rootView) rootView.NavRoot.PopToRootAsync(); }; - sessionStatus.LoginSucceeded += async () => - { - await PushMainPageAsync(); - }; - rootView.SessionBanner.DataContext = sessionStatus; } diff --git a/src/PostIt/PostIt/ViewModels/ActivitiesPageViewModel.cs b/src/PostIt/PostIt/ViewModels/ActivitiesPageViewModel.cs index 57e387c9..e39a2c18 100644 --- a/src/PostIt/PostIt/ViewModels/ActivitiesPageViewModel.cs +++ b/src/PostIt/PostIt/ViewModels/ActivitiesPageViewModel.cs @@ -29,7 +29,7 @@ public partial class ActivitiesPageViewModel : ViewModelBase public partial ActivityBrowseItemDto? SelectedSpecialization { get; set; } [ObservableProperty] - public partial ObservableCollection Performers { get; set; } = new(); + public partial ObservableCollection Performers { get; set; } = new(); [ObservableProperty] public partial bool IsBusy { get; set; } @@ -122,14 +122,14 @@ public partial class ActivitiesPageViewModel : ViewModelBase { Activities = new ObservableCollection(); Specializations = new ObservableCollection(); - Performers = new ObservableCollection(); + Performers = new ObservableCollection(); StatusMessage = "Accès refusé pour les activités (scope 'api'). Déconnectez puis reconnectez-vous."; } catch (Exception ex) { Activities = new ObservableCollection(); Specializations = new ObservableCollection(); - Performers = new ObservableCollection(); + Performers = new ObservableCollection(); StatusMessage = $"Erreur: {ex.Message}"; } finally @@ -158,7 +158,7 @@ public partial class ActivitiesPageViewModel : ViewModelBase if (activity is null) { - Performers = new ObservableCollection(); + Performers = new ObservableCollection(); return; } @@ -197,18 +197,19 @@ public partial class ActivitiesPageViewModel : ViewModelBase IsBusy = true; try { - var list = await _client.GetPerformersAsync(activity.Code); - Performers = new ObservableCollection(list ?? new()); - StatusMessage = $"{activity.Name} · {Performers.Count} prestataire(s)"; + var list = await _client.GetUsersAsync(activity.Code); + Performers = new ObservableCollection((list ?? new()) + .Select(ActivityUserDisplayItem.FromDto)); + StatusMessage = $"{activity.Name} · {Performers.Count} utilisateur(s)"; } catch (HttpRequestException ex) when (ex.StatusCode is HttpStatusCode.Unauthorized or HttpStatusCode.Forbidden) { - Performers = new ObservableCollection(); + Performers = new ObservableCollection(); StatusMessage = "Accès refusé pour les activités (scope 'api'). Déconnectez puis reconnectez-vous."; } catch (Exception ex) { - Performers = new ObservableCollection(); + Performers = new ObservableCollection(); StatusMessage = $"Erreur: {ex.Message}"; } finally diff --git a/src/PostIt/PostIt/ViewModels/ActivityUserDisplayItem.cs b/src/PostIt/PostIt/ViewModels/ActivityUserDisplayItem.cs new file mode 100644 index 00000000..ee06b883 --- /dev/null +++ b/src/PostIt/PostIt/ViewModels/ActivityUserDisplayItem.cs @@ -0,0 +1,39 @@ +using Yavsc.Abstract.Workflow; + +namespace PostIt.ViewModels; + +public sealed class ActivityUserDisplayItem +{ + public string PerformerId { get; init; } = string.Empty; + public bool HasPerformerProfile { get; init; } + public string PerformerBadgeLabel { get; init; } = "Profil pro"; + public bool IsPerformerActive { get; init; } + public string PerformerStatusBadgeLabel { get; init; } = "Inactif"; + public string PerformerStatusBadgeBackground { get; init; } = "#FDECEA"; + public string PerformerStatusBadgeBorder { get; init; } = "#C62828"; + public string PerformerStatusBadgeForeground { get; init; } = "#8E0000"; + public string UserName { get; init; } = string.Empty; + public string WebSite { get; init; } = string.Empty; + public int ExtraActivityCount { get; init; } + public string ExtraActivityLabel { get; init; } = "Pas d'autre activité"; + + public static ActivityUserDisplayItem FromDto(ActivityPerformerDto dto) + { + return new ActivityUserDisplayItem + { + PerformerId = dto.PerformerId, + HasPerformerProfile = dto.HasPerformerProfile, + UserName = dto.UserName, + WebSite = dto.WebSite, + IsPerformerActive = dto.Active, + PerformerStatusBadgeLabel = dto.Active ? "Actif" : "Inactif", + PerformerStatusBadgeBackground = dto.Active ? "#E6F7EC" : "#FDECEA", + PerformerStatusBadgeBorder = dto.Active ? "#2E7D32" : "#C62828", + PerformerStatusBadgeForeground = dto.Active ? "#1B5E20" : "#8E0000", + ExtraActivityCount = dto.ExtraActivityCount, + ExtraActivityLabel = dto.ExtraActivityCount == 0 + ? "Pas d'autre activité" + : $"Autres spécialisations: {dto.ExtraActivityCount}" + }; + } +} diff --git a/src/PostIt/PostIt/Views/ActivitiesPage.axaml b/src/PostIt/PostIt/Views/ActivitiesPage.axaml index d3cddb30..8dd88c6f 100644 --- a/src/PostIt/PostIt/Views/ActivitiesPage.axaml +++ b/src/PostIt/PostIt/Views/ActivitiesPage.axaml @@ -6,6 +6,20 @@ x:DataType="vm:ActivitiesPageViewModel" Header="Activités"> + + + + +