Exploration des activités
This commit is contained in:
parent
2a8a4fc4a4
commit
7b92745153
20 changed files with 743 additions and 61 deletions
|
|
@ -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<ActivityPerformerDto>))
|
||||
{
|
||||
var performers = path.EndsWith("brush-pro/performers", StringComparison.Ordinal)
|
||||
var performers = path.EndsWith("brush-pro/users", StringComparison.Ordinal)
|
||||
? new List<ActivityPerformerDto>
|
||||
{
|
||||
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<ActivityPerformerDto>
|
||||
{
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -86,11 +86,6 @@ private void ConfigureRootView(MainView rootView)
|
|||
rootView.NavRoot.PopToRootAsync();
|
||||
};
|
||||
|
||||
sessionStatus.LoginSucceeded += async () =>
|
||||
{
|
||||
await PushMainPageAsync();
|
||||
};
|
||||
|
||||
rootView.SessionBanner.DataContext = sessionStatus;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ public partial class ActivitiesPageViewModel : ViewModelBase
|
|||
public partial ActivityBrowseItemDto? SelectedSpecialization { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial ObservableCollection<ActivityPerformerDto> Performers { get; set; } = new();
|
||||
public partial ObservableCollection<ActivityUserDisplayItem> Performers { get; set; } = new();
|
||||
|
||||
[ObservableProperty]
|
||||
public partial bool IsBusy { get; set; }
|
||||
|
|
@ -122,14 +122,14 @@ public partial class ActivitiesPageViewModel : ViewModelBase
|
|||
{
|
||||
Activities = new ObservableCollection<ActivityBrowseItemDto>();
|
||||
Specializations = new ObservableCollection<ActivityBrowseItemDto>();
|
||||
Performers = new ObservableCollection<ActivityPerformerDto>();
|
||||
Performers = new ObservableCollection<ActivityUserDisplayItem>();
|
||||
StatusMessage = "Accès refusé pour les activités (scope 'api'). Déconnectez puis reconnectez-vous.";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Activities = new ObservableCollection<ActivityBrowseItemDto>();
|
||||
Specializations = new ObservableCollection<ActivityBrowseItemDto>();
|
||||
Performers = new ObservableCollection<ActivityPerformerDto>();
|
||||
Performers = new ObservableCollection<ActivityUserDisplayItem>();
|
||||
StatusMessage = $"Erreur: {ex.Message}";
|
||||
}
|
||||
finally
|
||||
|
|
@ -158,7 +158,7 @@ public partial class ActivitiesPageViewModel : ViewModelBase
|
|||
|
||||
if (activity is null)
|
||||
{
|
||||
Performers = new ObservableCollection<ActivityPerformerDto>();
|
||||
Performers = new ObservableCollection<ActivityUserDisplayItem>();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -197,18 +197,19 @@ public partial class ActivitiesPageViewModel : ViewModelBase
|
|||
IsBusy = true;
|
||||
try
|
||||
{
|
||||
var list = await _client.GetPerformersAsync(activity.Code);
|
||||
Performers = new ObservableCollection<ActivityPerformerDto>(list ?? new());
|
||||
StatusMessage = $"{activity.Name} · {Performers.Count} prestataire(s)";
|
||||
var list = await _client.GetUsersAsync(activity.Code);
|
||||
Performers = new ObservableCollection<ActivityUserDisplayItem>((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<ActivityPerformerDto>();
|
||||
Performers = new ObservableCollection<ActivityUserDisplayItem>();
|
||||
StatusMessage = "Accès refusé pour les activités (scope 'api'). Déconnectez puis reconnectez-vous.";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Performers = new ObservableCollection<ActivityPerformerDto>();
|
||||
Performers = new ObservableCollection<ActivityUserDisplayItem>();
|
||||
StatusMessage = $"Erreur: {ex.Message}";
|
||||
}
|
||||
finally
|
||||
|
|
|
|||
39
src/PostIt/PostIt/ViewModels/ActivityUserDisplayItem.cs
Normal file
39
src/PostIt/PostIt/ViewModels/ActivityUserDisplayItem.cs
Normal file
|
|
@ -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}"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,20 @@
|
|||
x:DataType="vm:ActivitiesPageViewModel"
|
||||
Header="Activités">
|
||||
<Grid RowDefinitions="Auto,*,Auto" Margin="12">
|
||||
<Grid.Styles>
|
||||
<Style Selector="Border.user-badge">
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="CornerRadius" Value="6" />
|
||||
<Setter Property="Padding" Value="5,0" />
|
||||
<Setter Property="MinHeight" Value="16" />
|
||||
</Style>
|
||||
<Style Selector="TextBlock.user-badge-text">
|
||||
<Setter Property="FontSize" Value="9" />
|
||||
<Setter Property="FontWeight" Value="SemiBold" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
</Grid.Styles>
|
||||
|
||||
<StackPanel Grid.Row="0" Orientation="Horizontal" Spacing="8">
|
||||
<Button Content="Rafraîchir" Command="{Binding RefreshCommand}" />
|
||||
<TextBlock Text="Catalogue des activités" FontWeight="Bold" VerticalAlignment="Center" />
|
||||
|
|
@ -22,7 +36,7 @@
|
|||
<StackPanel Spacing="2" Margin="0,0,0,8">
|
||||
<TextBlock Text="{Binding Name}" FontWeight="Bold" />
|
||||
<TextBlock Text="{Binding Description}" TextWrapping="Wrap" FontSize="11" Opacity="0.7" />
|
||||
<TextBlock Text="{Binding PerformerCount, StringFormat='Prestataires: {0}'}"
|
||||
<TextBlock Text="{Binding PerformerCount, StringFormat='Utilisateurs: {0}'}"
|
||||
FontSize="11" Opacity="0.6" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
|
|
@ -43,7 +57,7 @@
|
|||
<StackPanel Spacing="2" Margin="0,0,0,8">
|
||||
<TextBlock Text="{Binding Name}" FontWeight="Bold" />
|
||||
<TextBlock Text="{Binding Description}" TextWrapping="Wrap" FontSize="11" Opacity="0.7" />
|
||||
<TextBlock Text="{Binding PerformerCount, StringFormat='Prestataires: {0}'}"
|
||||
<TextBlock Text="{Binding PerformerCount, StringFormat='Utilisateurs: {0}'}"
|
||||
FontSize="11" Opacity="0.6" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
|
|
@ -52,17 +66,39 @@
|
|||
</Grid>
|
||||
|
||||
<Grid Grid.Column="4" RowDefinitions="Auto,Auto,*">
|
||||
<TextBlock Grid.Row="0" Text="Prestataires" FontWeight="Bold" Margin="0,0,0,8" />
|
||||
<TextBlock Grid.Row="0" Text="Utilisateurs" FontWeight="Bold" Margin="0,0,0,8" />
|
||||
<TextBlock Grid.Row="1"
|
||||
Text="{Binding CurrentActivityLabel, StringFormat='Activité affichée : {0}'}"
|
||||
FontSize="11" Opacity="0.7" Margin="0,0,0,8" />
|
||||
<ListBox Grid.Row="2" ItemsSource="{Binding Performers}">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="wf:ActivityPerformerDto">
|
||||
<DataTemplate x:DataType="vm:ActivityUserDisplayItem">
|
||||
<StackPanel Spacing="2" Margin="0,0,0,8">
|
||||
<TextBlock Text="{Binding UserName}" FontWeight="Bold" />
|
||||
<StackPanel Orientation="Horizontal" Spacing="4">
|
||||
<TextBlock Text="{Binding UserName}" FontWeight="Bold" />
|
||||
<Border IsVisible="{Binding HasPerformerProfile}"
|
||||
Classes="user-badge"
|
||||
Background="#D9F5E5"
|
||||
BorderBrush="#2E7D32"
|
||||
>
|
||||
<TextBlock Text="{Binding PerformerBadgeLabel}"
|
||||
Classes="user-badge-text"
|
||||
Foreground="#1B5E20"
|
||||
/>
|
||||
</Border>
|
||||
<Border IsVisible="{Binding HasPerformerProfile}"
|
||||
Classes="user-badge"
|
||||
Background="{Binding PerformerStatusBadgeBackground}"
|
||||
BorderBrush="{Binding PerformerStatusBadgeBorder}"
|
||||
>
|
||||
<TextBlock Text="{Binding PerformerStatusBadgeLabel}"
|
||||
Classes="user-badge-text"
|
||||
Foreground="{Binding PerformerStatusBadgeForeground}"
|
||||
/>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
<TextBlock Text="{Binding WebSite}" FontSize="11" Opacity="0.7" />
|
||||
<TextBlock Text="{Binding ExtraActivityCount, StringFormat='Autres spécialisations: {0}'}"
|
||||
<TextBlock Text="{Binding ExtraActivityLabel}"
|
||||
FontSize="11" Opacity="0.6" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue