This commit is contained in:
Paul Schneider 2026-09-02 14:52:17 +01:00
commit 2a36c19610
Signed by: notazof
GPG key ID: 1DD5D838E5343B06
14 changed files with 92 additions and 92 deletions

View file

@ -72,9 +72,9 @@ public class ActivitiesPageViewModelTests
{ {
Paths.Add(path); Paths.Add(path);
if (typeof(T) == typeof(List<ActivityBrowseItemDto>)) if (typeof(T) == typeof(List<ActivityInfo>))
{ {
var activities = new List<ActivityBrowseItemDto> var activities = new List<ActivityInfo>
{ {
new() new()
{ {
@ -82,11 +82,11 @@ public class ActivitiesPageViewModelTests
Name = "Brush", Name = "Brush",
Description = "Coiffure à domicile", Description = "Coiffure à domicile",
PerformerCount = 1, PerformerCount = 1,
Forms = new List<CommandFormSummaryDto> Forms = new List<CommandFormSummary>
{ {
new() { Id = 1, ActionName = "Rdv", Title = "Rendez-vous" } new() { Id = 1, ActionName = "Rdv", Title = "Rendez-vous" }
}, },
Children = new List<ActivityBrowseItemDto> Children = new List<ActivityInfo>
{ {
new() new()
{ {
@ -95,7 +95,7 @@ public class ActivitiesPageViewModelTests
Description = "Spécialisation premium", Description = "Spécialisation premium",
ParentCode = "brush", ParentCode = "brush",
PerformerCount = 1, PerformerCount = 1,
Forms = new List<CommandFormSummaryDto> Forms = new List<CommandFormSummary>
{ {
new() { Id = 2, ActionName = "Rdv", Title = "Rendez-vous premium" } new() { Id = 2, ActionName = "Rdv", Title = "Rendez-vous premium" }
} }
@ -106,14 +106,14 @@ public class ActivitiesPageViewModelTests
return Task.FromResult((T)(object)activities); return Task.FromResult((T)(object)activities);
} }
if (typeof(T) == typeof(List<ActivityPerformerDto>)) if (typeof(T) == typeof(List<PerformerActivity>))
{ {
var performers = path.EndsWith("brush-pro/users", StringComparison.Ordinal) var performers = path.EndsWith("brush-pro/users", StringComparison.Ordinal)
? new List<ActivityPerformerDto> ? new List<PerformerActivity>
{ {
new() { PerformerId = "pro-2", HasPerformerProfile = true, Active = false, UserName = "Bob", ActivityCode = "brush-pro", ActivityName = "Brush Pro", ExtraActivityCount = 2 } new() { PerformerId = "pro-2", HasPerformerProfile = true, Active = false, UserName = "Bob", ActivityCode = "brush-pro", ActivityName = "Brush Pro", ExtraActivityCount = 2 }
} }
: new List<ActivityPerformerDto> : new List<PerformerActivity>
{ {
new() { PerformerId = "pro-1", HasPerformerProfile = true, Active = true, UserName = "Alice", ActivityCode = "brush", ActivityName = "Brush", ExtraActivityCount = 0 } new() { PerformerId = "pro-1", HasPerformerProfile = true, Active = true, UserName = "Alice", ActivityCode = "brush", ActivityName = "Brush", ExtraActivityCount = 0 }
}; };

View file

@ -17,9 +17,9 @@ public class BillingCommandPageViewModelTests
var api = new RecordingApi(); var api = new RecordingApi();
var client = new BillingApiClient(api, "https://business.example/api/v1/"); var client = new BillingApiClient(api, "https://business.example/api/v1/");
var vm = new BillingCommandPageViewModel( var vm = new BillingCommandPageViewModel(
new ActivityBrowseItemDto { Code = "dev", Name = "Développement" }, new ActivityInfo { Code = "dev", Name = "Développement" },
new ActivityUserDisplayItem { PerformerId = "perf-1", UserName = "Alice" }, new ActivityUserDisplayItem { PerformerId = "perf-1", UserName = "Alice" },
new CommandFormSummaryDto { Id = 12, ActionName = "Rdv", Title = "Rendez-vous" }, new CommandFormSummary { Id = 12, ActionName = "Rdv", Title = "Rendez-vous" },
client) client)
{ {
EventDateText = "2026-09-02 14:30", EventDateText = "2026-09-02 14:30",
@ -48,9 +48,9 @@ public class BillingCommandPageViewModelTests
var api = new RecordingApi(); var api = new RecordingApi();
var client = new BillingApiClient(api, "https://business.example/api/v1/"); var client = new BillingApiClient(api, "https://business.example/api/v1/");
var vm = new BillingCommandPageViewModel( var vm = new BillingCommandPageViewModel(
new ActivityBrowseItemDto { Code = "book", Name = "Book" }, new ActivityInfo { Code = "book", Name = "Book" },
new ActivityUserDisplayItem { PerformerId = "perf-2", UserName = "Bob" }, new ActivityUserDisplayItem { PerformerId = "perf-2", UserName = "Bob" },
new CommandFormSummaryDto { Id = 13, ActionName = "Book", Title = "Réservation" }, new CommandFormSummary { Id = 13, ActionName = "Book", Title = "Réservation" },
client); client);
await vm.SubmitCommand.ExecuteAsync(null); await vm.SubmitCommand.ExecuteAsync(null);
@ -65,9 +65,9 @@ public class BillingCommandPageViewModelTests
var api = new RecordingApi(); var api = new RecordingApi();
var client = new BillingApiClient(api, "https://business.example/api/v1/"); var client = new BillingApiClient(api, "https://business.example/api/v1/");
var vm = new BillingCommandPageViewModel( var vm = new BillingCommandPageViewModel(
new ActivityBrowseItemDto { Code = "dev", Name = "Développement" }, new ActivityInfo { Code = "dev", Name = "Développement" },
new ActivityUserDisplayItem { PerformerId = "perf-1", UserName = "Alice" }, new ActivityUserDisplayItem { PerformerId = "perf-1", UserName = "Alice" },
new CommandFormSummaryDto { Id = 12, ActionName = "Rdv", Title = "Rendez-vous" }, new CommandFormSummary { Id = 12, ActionName = "Rdv", Title = "Rendez-vous" },
client) client)
{ {
EventDateText = "2026-09-02 14:30", EventDateText = "2026-09-02 14:30",
@ -98,9 +98,9 @@ public class BillingCommandPageViewModelTests
var api = new RecordingApi(); var api = new RecordingApi();
var client = new BillingApiClient(api, "https://business.example/api/v1/"); var client = new BillingApiClient(api, "https://business.example/api/v1/");
var vm = new BillingCommandPageViewModel( var vm = new BillingCommandPageViewModel(
new ActivityBrowseItemDto { Code = "dev", Name = "Développement" }, new ActivityInfo { Code = "dev", Name = "Développement" },
new ActivityUserDisplayItem { PerformerId = "perf-1", UserName = "Alice" }, new ActivityUserDisplayItem { PerformerId = "perf-1", UserName = "Alice" },
new CommandFormSummaryDto { Id = 12, ActionName = "Rdv", Title = "Rendez-vous" }, new CommandFormSummary { Id = 12, ActionName = "Rdv", Title = "Rendez-vous" },
client); client);
await vm.UseCurrentLocationCommand.ExecuteAsync(null); await vm.UseCurrentLocationCommand.ExecuteAsync(null);
@ -127,9 +127,9 @@ public class BillingCommandPageViewModelTests
}; };
var client = new BillingApiClient(api, "https://business.example/api/v1/"); var client = new BillingApiClient(api, "https://business.example/api/v1/");
var vm = new BillingCommandPageViewModel( var vm = new BillingCommandPageViewModel(
new ActivityBrowseItemDto { Code = "brush", Name = "Brush" }, new ActivityInfo { Code = "brush", Name = "Brush" },
new ActivityUserDisplayItem { PerformerId = "perf-2", UserName = "Bob" }, new ActivityUserDisplayItem { PerformerId = "perf-2", UserName = "Bob" },
new CommandFormSummaryDto { Id = 13, ActionName = "Brush", Title = "Coupe" }, new CommandFormSummary { Id = 13, ActionName = "Brush", Title = "Coupe" },
client) client)
{ {
EventDateText = "2026-09-02 14:30", EventDateText = "2026-09-02 14:30",
@ -163,9 +163,9 @@ public class BillingCommandPageViewModelTests
}; };
var client = new BillingApiClient(api, "https://business.example/api/v1/"); var client = new BillingApiClient(api, "https://business.example/api/v1/");
var vm = new BillingCommandPageViewModel( var vm = new BillingCommandPageViewModel(
new ActivityBrowseItemDto { Code = "mbrush", Name = "MBrush" }, new ActivityInfo { Code = "mbrush", Name = "MBrush" },
new ActivityUserDisplayItem { PerformerId = "perf-3", UserName = "Cara" }, new ActivityUserDisplayItem { PerformerId = "perf-3", UserName = "Cara" },
new CommandFormSummaryDto { Id = 14, ActionName = "MBrush", Title = "Coupe groupée" }, new CommandFormSummary { Id = 14, ActionName = "MBrush", Title = "Coupe groupée" },
client) client)
{ {
EventDateText = "2026-09-03 10:00", EventDateText = "2026-09-03 10:00",
@ -201,9 +201,9 @@ public class BillingCommandPageViewModelTests
}; };
var client = new BillingApiClient(api, "https://business.example/api/v1/"); var client = new BillingApiClient(api, "https://business.example/api/v1/");
var vm = new BillingCommandPageViewModel( var vm = new BillingCommandPageViewModel(
new ActivityBrowseItemDto { Code = "brush", Name = "Brush" }, new ActivityInfo { Code = "brush", Name = "Brush" },
new ActivityUserDisplayItem { PerformerId = "perf-2", UserName = "Bob" }, new ActivityUserDisplayItem { PerformerId = "perf-2", UserName = "Bob" },
new CommandFormSummaryDto { Id = 13, ActionName = "Brush", Title = "Coupe" }, new CommandFormSummary { Id = 13, ActionName = "Brush", Title = "Coupe" },
client); client);
await vm.InitializeAsync(new BillingQueryDetailsDto await vm.InitializeAsync(new BillingQueryDetailsDto

View file

@ -14,9 +14,9 @@ public class BillingQueriesPageViewModelTests
var api = new StubBillingApi(); var api = new StubBillingApi();
var client = new BillingApiClient(api, "https://business.example/api/v1/"); var client = new BillingApiClient(api, "https://business.example/api/v1/");
var vm = new BillingQueriesPageViewModel( var vm = new BillingQueriesPageViewModel(
new ActivityBrowseItemDto { Code = "dev", Name = "Développement" }, new ActivityInfo { Code = "dev", Name = "Développement" },
new ActivityUserDisplayItem { PerformerId = "perf-1", UserName = "Alice" }, new ActivityUserDisplayItem { PerformerId = "perf-1", UserName = "Alice" },
new CommandFormSummaryDto { Id = 1, ActionName = "Rdv", Title = "Rendez-vous" }, new CommandFormSummary { Id = 1, ActionName = "Rdv", Title = "Rendez-vous" },
client); client);
await vm.InitializeAsync(); await vm.InitializeAsync();
@ -33,9 +33,9 @@ public class BillingQueriesPageViewModelTests
var api = new StubBillingApi(); var api = new StubBillingApi();
var client = new BillingApiClient(api, "https://business.example/api/v1/"); var client = new BillingApiClient(api, "https://business.example/api/v1/");
var vm = new BillingQueriesPageViewModel( var vm = new BillingQueriesPageViewModel(
new ActivityBrowseItemDto { Code = "dev", Name = "Développement" }, new ActivityInfo { Code = "dev", Name = "Développement" },
new ActivityUserDisplayItem { PerformerId = "perf-1", UserName = "Alice" }, new ActivityUserDisplayItem { PerformerId = "perf-1", UserName = "Alice" },
new CommandFormSummaryDto { Id = 1, ActionName = "Rdv", Title = "Rendez-vous" }, new CommandFormSummary { Id = 1, ActionName = "Rdv", Title = "Rendez-vous" },
client, client,
isReadOnly: true, isReadOnly: true,
ongoingOnly: true); ongoingOnly: true);
@ -131,4 +131,4 @@ public class BillingQueriesPageViewModelTests
public ValueTask DisposeAsync() => ValueTask.CompletedTask; public ValueTask DisposeAsync() => ValueTask.CompletedTask;
} }
} }

View file

@ -20,16 +20,16 @@ public partial class ActivitiesPageViewModel : ViewModelBase
private bool _syncingSelection; private bool _syncingSelection;
[ObservableProperty] [ObservableProperty]
public partial ObservableCollection<ActivityBrowseItemDto> Activities { get; set; } = new(); public partial ObservableCollection<ActivityInfo> Activities { get; set; } = new();
[ObservableProperty] [ObservableProperty]
public partial ActivityBrowseItemDto? SelectedActivity { get; set; } public partial ActivityInfo? SelectedActivity { get; set; }
[ObservableProperty] [ObservableProperty]
public partial ObservableCollection<ActivityBrowseItemDto> Specializations { get; set; } = new(); public partial ObservableCollection<ActivityInfo> Specializations { get; set; } = new();
[ObservableProperty] [ObservableProperty]
public partial ActivityBrowseItemDto? SelectedSpecialization { get; set; } public partial ActivityInfo? SelectedSpecialization { get; set; }
[ObservableProperty] [ObservableProperty]
public partial ObservableCollection<ActivityUserDisplayItem> Performers { get; set; } = new(); public partial ObservableCollection<ActivityUserDisplayItem> Performers { get; set; } = new();
@ -43,7 +43,7 @@ public partial class ActivitiesPageViewModel : ViewModelBase
[ObservableProperty] [ObservableProperty]
public partial string StatusMessage { get; set; } = "Choisissez une activité."; public partial string StatusMessage { get; set; } = "Choisissez une activité.";
public ActivityBrowseItemDto? CurrentActivity => SelectedSpecialization ?? SelectedActivity; public ActivityInfo? CurrentActivity => SelectedSpecialization ?? SelectedActivity;
public string SelectedActivityLabel => SelectedActivity?.Name ?? "(aucune activité)"; public string SelectedActivityLabel => SelectedActivity?.Name ?? "(aucune activité)";
public string CurrentActivityLabel => CurrentActivity?.Name ?? "(aucune)"; public string CurrentActivityLabel => CurrentActivity?.Name ?? "(aucune)";
public int CurrentFormCount => CurrentActivity?.Forms?.Count ?? 0; public int CurrentFormCount => CurrentActivity?.Forms?.Count ?? 0;
@ -66,19 +66,19 @@ public partial class ActivitiesPageViewModel : ViewModelBase
_billingClient = billingClient ?? throw new ArgumentNullException(nameof(billingClient)); _billingClient = billingClient ?? throw new ArgumentNullException(nameof(billingClient));
} }
partial void OnSelectedActivityChanged(ActivityBrowseItemDto? value) partial void OnSelectedActivityChanged(ActivityInfo? value)
{ {
if (_syncingSelection) return; if (_syncingSelection) return;
_ = ShowActivitySafeAsync(value); _ = ShowActivitySafeAsync(value);
} }
partial void OnSelectedSpecializationChanged(ActivityBrowseItemDto? value) partial void OnSelectedSpecializationChanged(ActivityInfo? value)
{ {
if (_syncingSelection) return; if (_syncingSelection) return;
_ = ShowSpecializationSafeAsync(value); _ = ShowSpecializationSafeAsync(value);
} }
private async Task ShowActivitySafeAsync(ActivityBrowseItemDto? value) private async Task ShowActivitySafeAsync(ActivityInfo? value)
{ {
try try
{ {
@ -94,7 +94,7 @@ public partial class ActivitiesPageViewModel : ViewModelBase
} }
} }
private async Task ShowSpecializationSafeAsync(ActivityBrowseItemDto? value) private async Task ShowSpecializationSafeAsync(ActivityInfo? value)
{ {
try try
{ {
@ -117,7 +117,7 @@ public partial class ActivitiesPageViewModel : ViewModelBase
try try
{ {
var list = await _client.GetCatalogAsync(); var list = await _client.GetCatalogAsync();
Activities = new ObservableCollection<ActivityBrowseItemDto>(list ?? new()); Activities = new ObservableCollection<ActivityInfo>(list ?? new());
var first = Activities.FirstOrDefault(); var first = Activities.FirstOrDefault();
await ShowActivityAsync(first); await ShowActivityAsync(first);
@ -128,15 +128,15 @@ public partial class ActivitiesPageViewModel : ViewModelBase
} }
catch (HttpRequestException ex) when (ex.StatusCode is HttpStatusCode.Unauthorized or HttpStatusCode.Forbidden) catch (HttpRequestException ex) when (ex.StatusCode is HttpStatusCode.Unauthorized or HttpStatusCode.Forbidden)
{ {
Activities = new ObservableCollection<ActivityBrowseItemDto>(); Activities = new ObservableCollection<ActivityInfo>();
Specializations = new ObservableCollection<ActivityBrowseItemDto>(); Specializations = new ObservableCollection<ActivityInfo>();
Performers = new ObservableCollection<ActivityUserDisplayItem>(); Performers = new ObservableCollection<ActivityUserDisplayItem>();
StatusMessage = "Accès refusé pour les activités (scope 'api'). Déconnectez puis reconnectez-vous."; StatusMessage = "Accès refusé pour les activités (scope 'api'). Déconnectez puis reconnectez-vous.";
} }
catch (Exception ex) catch (Exception ex)
{ {
Activities = new ObservableCollection<ActivityBrowseItemDto>(); Activities = new ObservableCollection<ActivityInfo>();
Specializations = new ObservableCollection<ActivityBrowseItemDto>(); Specializations = new ObservableCollection<ActivityInfo>();
Performers = new ObservableCollection<ActivityUserDisplayItem>(); Performers = new ObservableCollection<ActivityUserDisplayItem>();
StatusMessage = $"Erreur: {ex.Message}"; StatusMessage = $"Erreur: {ex.Message}";
} }
@ -146,7 +146,7 @@ public partial class ActivitiesPageViewModel : ViewModelBase
} }
} }
public async Task ShowActivityAsync(ActivityBrowseItemDto? activity) public async Task ShowActivityAsync(ActivityInfo? activity)
{ {
_syncingSelection = true; _syncingSelection = true;
try try
@ -163,7 +163,7 @@ public partial class ActivitiesPageViewModel : ViewModelBase
OnPropertyChanged(nameof(SelectedActivityLabel)); OnPropertyChanged(nameof(SelectedActivityLabel));
OnPropertyChanged(nameof(CurrentActivityLabel)); OnPropertyChanged(nameof(CurrentActivityLabel));
OnPropertyChanged(nameof(CurrentFormCount)); OnPropertyChanged(nameof(CurrentFormCount));
Specializations = new ObservableCollection<ActivityBrowseItemDto>(activity?.Children ?? new()); Specializations = new ObservableCollection<ActivityInfo>(activity?.Children ?? new());
if (activity is null) if (activity is null)
{ {
@ -175,7 +175,7 @@ public partial class ActivitiesPageViewModel : ViewModelBase
await LoadPerformersAsync(activity); await LoadPerformersAsync(activity);
} }
public async Task ShowSpecializationAsync(ActivityBrowseItemDto? specialization) public async Task ShowSpecializationAsync(ActivityInfo? specialization)
{ {
_syncingSelection = true; _syncingSelection = true;
try try
@ -203,7 +203,7 @@ public partial class ActivitiesPageViewModel : ViewModelBase
await LoadPerformersAsync(specialization); await LoadPerformersAsync(specialization);
} }
private async Task LoadPerformersAsync(ActivityBrowseItemDto activity) private async Task LoadPerformersAsync(ActivityInfo activity)
{ {
IsBusy = true; IsBusy = true;
try try

View file

@ -17,7 +17,7 @@ public sealed class ActivityUserDisplayItem
public int ExtraActivityCount { get; init; } public int ExtraActivityCount { get; init; }
public string ExtraActivityLabel { get; init; } = "Pas d'autre activité"; public string ExtraActivityLabel { get; init; } = "Pas d'autre activité";
public static ActivityUserDisplayItem FromDto(ActivityPerformerDto dto) public static ActivityUserDisplayItem FromDto(PerformerActivity dto)
{ {
return new ActivityUserDisplayItem return new ActivityUserDisplayItem
{ {

View file

@ -21,9 +21,9 @@ public partial class BillingCommandPageViewModel : ViewModelBase
{ {
private readonly BillingApiClient _billingClient; private readonly BillingApiClient _billingClient;
public ActivityBrowseItemDto Activity { get; } public ActivityInfo Activity { get; }
public ActivityUserDisplayItem Performer { get; } public ActivityUserDisplayItem Performer { get; }
public CommandFormSummaryDto Form { get; } public CommandFormSummary Form { get; }
[ObservableProperty] [ObservableProperty]
public partial bool IsBusy { get; set; } public partial bool IsBusy { get; set; }
@ -104,9 +104,9 @@ public partial class BillingCommandPageViewModel : ViewModelBase
} }
public BillingCommandPageViewModel( public BillingCommandPageViewModel(
ActivityBrowseItemDto activity, ActivityInfo activity,
ActivityUserDisplayItem performer, ActivityUserDisplayItem performer,
CommandFormSummaryDto form, CommandFormSummary form,
BillingApiClient billingClient) BillingApiClient billingClient)
{ {
Activity = activity ?? throw new ArgumentNullException(nameof(activity)); Activity = activity ?? throw new ArgumentNullException(nameof(activity));
@ -487,4 +487,4 @@ public partial class BillingCommandPageViewModel : ViewModelBase
longitude = parsedLongitude; longitude = parsedLongitude;
return true; return true;
} }
} }

View file

@ -18,9 +18,9 @@ public partial class BillingQueriesPageViewModel : ViewModelBase
{ {
private readonly BillingApiClient _billingClient; private readonly BillingApiClient _billingClient;
public ActivityBrowseItemDto Activity { get; } public ActivityInfo Activity { get; }
public ActivityUserDisplayItem Performer { get; } public ActivityUserDisplayItem Performer { get; }
public CommandFormSummaryDto Form { get; } public CommandFormSummary Form { get; }
public bool IsReadOnly { get; } public bool IsReadOnly { get; }
public bool OngoingOnly { get; } public bool OngoingOnly { get; }
@ -55,9 +55,9 @@ public partial class BillingQueriesPageViewModel : ViewModelBase
} }
public BillingQueriesPageViewModel( public BillingQueriesPageViewModel(
ActivityBrowseItemDto activity, ActivityInfo activity,
ActivityUserDisplayItem performer, ActivityUserDisplayItem performer,
CommandFormSummaryDto form, CommandFormSummary form,
BillingApiClient billingClient, BillingApiClient billingClient,
bool isReadOnly = false, bool isReadOnly = false,
bool ongoingOnly = false) bool ongoingOnly = false)
@ -170,4 +170,4 @@ public partial class BillingQueriesPageViewModel : ViewModelBase
private static bool IsOngoingStatus(QueryStatus status) private static bool IsOngoingStatus(QueryStatus status)
=> status is QueryStatus.Inserted or QueryStatus.Accepted or QueryStatus.InProgress; => status is QueryStatus.Inserted or QueryStatus.Accepted or QueryStatus.InProgress;
} }

View file

@ -15,14 +15,14 @@ public partial class CommandFormsPageViewModel : ViewModelBase
{ {
private readonly BillingApiClient _billingClient; private readonly BillingApiClient _billingClient;
public ActivityBrowseItemDto Activity { get; } public ActivityInfo Activity { get; }
public ActivityUserDisplayItem Performer { get; } public ActivityUserDisplayItem Performer { get; }
[ObservableProperty] [ObservableProperty]
public partial ObservableCollection<CommandFormSummaryDto> Forms { get; set; } public partial ObservableCollection<CommandFormSummary> Forms { get; set; }
[ObservableProperty, NotifyCanExecuteChangedFor(nameof(OpenSelectedFormCommand)), NotifyCanExecuteChangedFor(nameof(OpenQueriesCommand)), NotifyCanExecuteChangedFor(nameof(OpenOngoingQueriesCommand))] [ObservableProperty, NotifyCanExecuteChangedFor(nameof(OpenSelectedFormCommand)), NotifyCanExecuteChangedFor(nameof(OpenQueriesCommand)), NotifyCanExecuteChangedFor(nameof(OpenOngoingQueriesCommand))]
public partial CommandFormSummaryDto? SelectedForm { get; set; } public partial CommandFormSummary? SelectedForm { get; set; }
[ObservableProperty] [ObservableProperty]
public partial string StatusMessage { get; set; } public partial string StatusMessage { get; set; }
@ -43,7 +43,7 @@ public partial class CommandFormsPageViewModel : ViewModelBase
} }
public CommandFormsPageViewModel( public CommandFormsPageViewModel(
ActivityBrowseItemDto activity, ActivityInfo activity,
ActivityUserDisplayItem performer, ActivityUserDisplayItem performer,
BillingApiClient billingClient) BillingApiClient billingClient)
{ {
@ -51,7 +51,7 @@ public partial class CommandFormsPageViewModel : ViewModelBase
Performer = performer ?? throw new ArgumentNullException(nameof(performer)); Performer = performer ?? throw new ArgumentNullException(nameof(performer));
_billingClient = billingClient ?? throw new ArgumentNullException(nameof(billingClient)); _billingClient = billingClient ?? throw new ArgumentNullException(nameof(billingClient));
Forms = new ObservableCollection<CommandFormSummaryDto>((activity.Forms ?? new()) Forms = new ObservableCollection<CommandFormSummary>((activity.Forms ?? new())
.OrderBy(f => f.Title) .OrderBy(f => f.Title)
.ThenBy(f => f.ActionName)); .ThenBy(f => f.ActionName));
SelectedForm = Forms.FirstOrDefault(); SelectedForm = Forms.FirstOrDefault();
@ -81,7 +81,7 @@ public partial class CommandFormsPageViewModel : ViewModelBase
throw new InvalidOperationException("Application PostIt indisponible."); throw new InvalidOperationException("Application PostIt indisponible.");
} }
var vm = new BillingCommandPageViewModel(Activity, Performer, SelectedForm, _billingClient); var vm = SelectedForm.CreateCommandPageViewModel(Activity, Performer, _billingClient);
await vm.InitializeAsync(); await vm.InitializeAsync();
await app.PushPageAsync(vm); await app.PushPageAsync(vm);
} }
@ -131,4 +131,4 @@ public partial class CommandFormsPageViewModel : ViewModelBase
await vm.InitializeAsync(); await vm.InitializeAsync();
await app.PushPageAsync(vm); await app.PushPageAsync(vm);
} }
} }

View file

@ -3,7 +3,7 @@ namespace Yavsc.Abstract.Workflow;
/// <summary> /// <summary>
/// Activity node returned by the browsing API. /// Activity node returned by the browsing API.
/// </summary> /// </summary>
public sealed class ActivityBrowseItemDto public sealed class ActivityInfo
{ {
public string Code { get; set; } = string.Empty; public string Code { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty; public string Name { get; set; } = string.Empty;
@ -12,6 +12,6 @@ public sealed class ActivityBrowseItemDto
public string Photo { get; set; } = string.Empty; public string Photo { get; set; } = string.Empty;
public int Rate { get; set; } public int Rate { get; set; }
public int PerformerCount { get; set; } public int PerformerCount { get; set; }
public List<CommandFormSummaryDto> Forms { get; set; } = new(); public List<CommandFormSummary> Forms { get; set; } = new();
public List<ActivityBrowseItemDto> Children { get; set; } = new(); public List<ActivityInfo> Children { get; set; } = new();
} }

View file

@ -3,7 +3,7 @@ namespace Yavsc.Abstract.Workflow;
/// <summary> /// <summary>
/// Lightweight command-form description exposed to API clients. /// Lightweight command-form description exposed to API clients.
/// </summary> /// </summary>
public sealed class CommandFormSummaryDto public sealed class CommandFormSummary
{ {
public long Id { get; set; } public long Id { get; set; }
public string ActionName { get; set; } = string.Empty; public string ActionName { get; set; } = string.Empty;

View file

@ -3,7 +3,7 @@ namespace Yavsc.Abstract.Workflow;
/// <summary> /// <summary>
/// Lightweight performer description returned for one activity. /// Lightweight performer description returned for one activity.
/// </summary> /// </summary>
public sealed class ActivityPerformerDto public sealed class PerformerActivity
{ {
public string PerformerId { get; set; } = string.Empty; public string PerformerId { get; set; } = string.Empty;
public bool HasPerformerProfile { get; set; } public bool HasPerformerProfile { get; set; }

View file

@ -30,7 +30,7 @@ public sealed class ActivityApiClient
_baseAddress = new Uri(businessBaseAddress, UriKind.Absolute); _baseAddress = new Uri(businessBaseAddress, UriKind.Absolute);
} }
public Task<List<ActivityBrowseItemDto>> GetCatalogAsync( public Task<List<ActivityInfo>> GetCatalogAsync(
string? parentCode = null, string? parentCode = null,
CancellationToken ct = default) CancellationToken ct = default)
{ {
@ -38,23 +38,23 @@ public sealed class ActivityApiClient
? $"{PathPrefix}/catalog" ? $"{PathPrefix}/catalog"
: $"{PathPrefix}/catalog?parentCode={Uri.EscapeDataString(parentCode)}"; : $"{PathPrefix}/catalog?parentCode={Uri.EscapeDataString(parentCode)}";
return _api.CallAsync<List<ActivityBrowseItemDto>>(HttpMethod.Get, Absolute(path), ct: ct); return _api.CallAsync<List<ActivityInfo>>(HttpMethod.Get, Absolute(path), ct: ct);
} }
public Task<List<ActivityPerformerDto>> GetUsersAsync( public Task<List<PerformerActivity>> GetUsersAsync(
string activityCode, string activityCode,
CancellationToken ct = default) CancellationToken ct = default)
{ {
if (string.IsNullOrWhiteSpace(activityCode)) if (string.IsNullOrWhiteSpace(activityCode))
throw new ArgumentException("Activity code is required.", nameof(activityCode)); throw new ArgumentException("Activity code is required.", nameof(activityCode));
return _api.CallAsync<List<ActivityPerformerDto>>( return _api.CallAsync<List<PerformerActivity>>(
HttpMethod.Get, HttpMethod.Get,
Absolute($"{PathPrefix}/{Uri.EscapeDataString(activityCode)}/users"), Absolute($"{PathPrefix}/{Uri.EscapeDataString(activityCode)}/users"),
ct: ct); ct: ct);
} }
public Task<List<ActivityPerformerDto>> GetPerformersAsync( public Task<List<PerformerActivity>> GetPerformersAsync(
string activityCode, string activityCode,
CancellationToken ct = default) CancellationToken ct = default)
=> GetUsersAsync(activityCode, ct); => GetUsersAsync(activityCode, ct);

View file

@ -42,7 +42,7 @@ public sealed class ActivityApiControllerTests : IClassFixture<ApiWebServerFixtu
var response = await http.GetAsync("/api/v1/activity/dev/users", TestContext.Current.CancellationToken); var response = await http.GetAsync("/api/v1/activity/dev/users", TestContext.Current.CancellationToken);
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var payload = await response.Content.ReadFromJsonAsync<List<ActivityPerformerDto>>(TestContext.Current.CancellationToken); var payload = await response.Content.ReadFromJsonAsync<List<PerformerActivity>>(TestContext.Current.CancellationToken);
Assert.NotNull(payload); Assert.NotNull(payload);
Assert.Single(payload!); Assert.Single(payload!);
Assert.Equal("alice", payload[0].PerformerId); Assert.Equal("alice", payload[0].PerformerId);
@ -68,7 +68,7 @@ public sealed class ActivityApiControllerTests : IClassFixture<ApiWebServerFixtu
var response = await http.GetAsync("/api/v1/activity/dev/users", TestContext.Current.CancellationToken); var response = await http.GetAsync("/api/v1/activity/dev/users", TestContext.Current.CancellationToken);
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var payload = await response.Content.ReadFromJsonAsync<List<ActivityPerformerDto>>(TestContext.Current.CancellationToken); var payload = await response.Content.ReadFromJsonAsync<List<PerformerActivity>>(TestContext.Current.CancellationToken);
Assert.NotNull(payload); Assert.NotNull(payload);
Assert.Single(payload!); Assert.Single(payload!);
Assert.Equal("alice", payload[0].PerformerId); Assert.Equal("alice", payload[0].PerformerId);
@ -84,7 +84,7 @@ public sealed class ActivityApiControllerTests : IClassFixture<ApiWebServerFixtu
var catalogResponse = await http.GetAsync("/api/v1/activity/catalog", TestContext.Current.CancellationToken); var catalogResponse = await http.GetAsync("/api/v1/activity/catalog", TestContext.Current.CancellationToken);
Assert.Equal(HttpStatusCode.OK, catalogResponse.StatusCode); Assert.Equal(HttpStatusCode.OK, catalogResponse.StatusCode);
var catalog = await catalogResponse.Content.ReadFromJsonAsync<List<ActivityBrowseItemDto>>(TestContext.Current.CancellationToken); var catalog = await catalogResponse.Content.ReadFromJsonAsync<List<ActivityInfo>>(TestContext.Current.CancellationToken);
Assert.NotNull(catalog); Assert.NotNull(catalog);
var dev = catalog!.Single(a => a.Code == "dev"); var dev = catalog!.Single(a => a.Code == "dev");
@ -93,7 +93,7 @@ public sealed class ActivityApiControllerTests : IClassFixture<ApiWebServerFixtu
var performersResponse = await http.GetAsync("/api/v1/activity/dev/users", TestContext.Current.CancellationToken); var performersResponse = await http.GetAsync("/api/v1/activity/dev/users", TestContext.Current.CancellationToken);
Assert.Equal(HttpStatusCode.OK, performersResponse.StatusCode); Assert.Equal(HttpStatusCode.OK, performersResponse.StatusCode);
var performers = await performersResponse.Content.ReadFromJsonAsync<List<ActivityPerformerDto>>(TestContext.Current.CancellationToken); var performers = await performersResponse.Content.ReadFromJsonAsync<List<PerformerActivity>>(TestContext.Current.CancellationToken);
Assert.NotNull(performers); Assert.NotNull(performers);
Assert.Equal(dev.PerformerCount, performers!.Count); Assert.Equal(dev.PerformerCount, performers!.Count);
Assert.Contains(performers, p => p.PerformerId == "alice"); Assert.Contains(performers, p => p.PerformerId == "alice");
@ -108,7 +108,7 @@ public sealed class ActivityApiControllerTests : IClassFixture<ApiWebServerFixtu
var catalogResponse = await http.GetAsync("/api/v1/activity/catalog", TestContext.Current.CancellationToken); var catalogResponse = await http.GetAsync("/api/v1/activity/catalog", TestContext.Current.CancellationToken);
Assert.Equal(HttpStatusCode.OK, catalogResponse.StatusCode); Assert.Equal(HttpStatusCode.OK, catalogResponse.StatusCode);
var catalog = await catalogResponse.Content.ReadFromJsonAsync<List<ActivityBrowseItemDto>>(TestContext.Current.CancellationToken); var catalog = await catalogResponse.Content.ReadFromJsonAsync<List<ActivityInfo>>(TestContext.Current.CancellationToken);
Assert.NotNull(catalog); Assert.NotNull(catalog);
Assert.DoesNotContain(catalog!, a => a.Code == "ghost"); Assert.DoesNotContain(catalog!, a => a.Code == "ghost");
Assert.Contains(catalog!, a => a.Code == "dev"); Assert.Contains(catalog!, a => a.Code == "dev");
@ -123,13 +123,13 @@ public sealed class ActivityApiControllerTests : IClassFixture<ApiWebServerFixtu
var catalogResponse = await http.GetAsync("/api/v1/activity/catalog", TestContext.Current.CancellationToken); var catalogResponse = await http.GetAsync("/api/v1/activity/catalog", TestContext.Current.CancellationToken);
Assert.Equal(HttpStatusCode.OK, catalogResponse.StatusCode); Assert.Equal(HttpStatusCode.OK, catalogResponse.StatusCode);
var catalog = await catalogResponse.Content.ReadFromJsonAsync<List<ActivityBrowseItemDto>>(TestContext.Current.CancellationToken); var catalog = await catalogResponse.Content.ReadFromJsonAsync<List<ActivityInfo>>(TestContext.Current.CancellationToken);
Assert.NotNull(catalog); Assert.NotNull(catalog);
Assert.Contains(catalog!, a => a.Code == "declared-only"); Assert.Contains(catalog!, a => a.Code == "declared-only");
var response = await http.GetAsync("/api/v1/activity/declared-only/users", TestContext.Current.CancellationToken); var response = await http.GetAsync("/api/v1/activity/declared-only/users", TestContext.Current.CancellationToken);
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var payload = await response.Content.ReadFromJsonAsync<List<ActivityPerformerDto>>(TestContext.Current.CancellationToken); var payload = await response.Content.ReadFromJsonAsync<List<PerformerActivity>>(TestContext.Current.CancellationToken);
Assert.NotNull(payload); Assert.NotNull(payload);
Assert.Single(payload!); Assert.Single(payload!);
Assert.Equal("bob", payload[0].PerformerId); Assert.Equal("bob", payload[0].PerformerId);
@ -149,8 +149,8 @@ public sealed class ActivityApiControllerTests : IClassFixture<ApiWebServerFixtu
Assert.Equal(HttpStatusCode.OK, usersResponse.StatusCode); Assert.Equal(HttpStatusCode.OK, usersResponse.StatusCode);
Assert.Equal(HttpStatusCode.OK, performersResponse.StatusCode); Assert.Equal(HttpStatusCode.OK, performersResponse.StatusCode);
var usersPayload = await usersResponse.Content.ReadFromJsonAsync<List<ActivityPerformerDto>>(TestContext.Current.CancellationToken); var usersPayload = await usersResponse.Content.ReadFromJsonAsync<List<PerformerActivity>>(TestContext.Current.CancellationToken);
var performersPayload = await performersResponse.Content.ReadFromJsonAsync<List<ActivityPerformerDto>>(TestContext.Current.CancellationToken); var performersPayload = await performersResponse.Content.ReadFromJsonAsync<List<PerformerActivity>>(TestContext.Current.CancellationToken);
Assert.NotNull(usersPayload); Assert.NotNull(usersPayload);
Assert.NotNull(performersPayload); Assert.NotNull(performersPayload);

View file

@ -29,7 +29,7 @@ namespace Yavsc.Controllers
} }
[HttpGet("catalog")] [HttpGet("catalog")]
public async Task<ActionResult<IEnumerable<ActivityBrowseItemDto>>> GetCatalog( public async Task<ActionResult<IEnumerable<ActivityInfo>>> GetCatalog(
CancellationToken cancellationToken, CancellationToken cancellationToken,
[FromQuery] string parentCode = null) [FromQuery] string parentCode = null)
{ {
@ -74,7 +74,7 @@ namespace Yavsc.Controllers
} }
[HttpGet("{id}/users")] [HttpGet("{id}/users")]
public async Task<ActionResult<IEnumerable<ActivityPerformerDto>>> GetUsers( public async Task<ActionResult<IEnumerable<PerformerActivity>>> GetUsers(
[FromRoute] string id, [FromRoute] string id,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
@ -97,7 +97,7 @@ namespace Yavsc.Controllers
} }
[HttpGet("{id}/performers")] [HttpGet("{id}/performers")]
public Task<ActionResult<IEnumerable<ActivityPerformerDto>>> GetPerformers( public Task<ActionResult<IEnumerable<PerformerActivity>>> GetPerformers(
[FromRoute] string id, [FromRoute] string id,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
@ -105,7 +105,7 @@ namespace Yavsc.Controllers
return GetUsers(id, cancellationToken); return GetUsers(id, cancellationToken);
} }
private Task<List<ActivityPerformerDto>> QueryDeclaredUsersAsync( private Task<List<PerformerActivity>> QueryDeclaredUsersAsync(
string activityCode, string activityCode,
string activityName, string activityName,
CancellationToken cancellationToken) CancellationToken cancellationToken)
@ -118,7 +118,7 @@ namespace Yavsc.Controllers
from performer in performerProfiles.DefaultIfEmpty() from performer in performerProfiles.DefaultIfEmpty()
where ua.DoesCode == activityCode where ua.DoesCode == activityCode
orderby user != null ? user.UserName : ua.UserId orderby user != null ? user.UserName : ua.UserId
select new ActivityPerformerDto select new PerformerActivity
{ {
PerformerId = ua.UserId, PerformerId = ua.UserId,
HasPerformerProfile = performer != null, HasPerformerProfile = performer != null,
@ -260,11 +260,11 @@ namespace Yavsc.Controllers
return _context.Activities.Count(e => e.Code == id) > 0; return _context.Activities.Count(e => e.Code == id) > 0;
} }
private static ActivityBrowseItemDto ToBrowseItem( private static ActivityInfo ToBrowseItem(
Activity activity, Activity activity,
IReadOnlyDictionary<string, int> performerCounts) IReadOnlyDictionary<string, int> performerCounts)
{ {
return new ActivityBrowseItemDto return new ActivityInfo
{ {
Code = activity.Code, Code = activity.Code,
Name = activity.Name, Name = activity.Name,
@ -274,7 +274,7 @@ namespace Yavsc.Controllers
Rate = activity.Rate, Rate = activity.Rate,
PerformerCount = performerCounts.TryGetValue(activity.Code, out var count) ? count : 0, PerformerCount = performerCounts.TryGetValue(activity.Code, out var count) ? count : 0,
Forms = (activity.Forms ?? Enumerable.Empty<CommandForm>()) Forms = (activity.Forms ?? Enumerable.Empty<CommandForm>())
.Select(f => new CommandFormSummaryDto .Select(f => new CommandFormSummary
{ {
Id = f.Id, Id = f.Id,
ActionName = f.ActionName, ActionName = f.ActionName,
@ -285,7 +285,7 @@ namespace Yavsc.Controllers
.Where(c => !c.Hidden) .Where(c => !c.Hidden)
.Where(c => performerCounts.TryGetValue(c.Code, out var childCount) && childCount > 0) .Where(c => performerCounts.TryGetValue(c.Code, out var childCount) && childCount > 0)
.OrderByDescending(c => c.Rate) .OrderByDescending(c => c.Rate)
.Select(c => new ActivityBrowseItemDto .Select(c => new ActivityInfo
{ {
Code = c.Code, Code = c.Code,
Name = c.Name, Name = c.Name,
@ -295,7 +295,7 @@ namespace Yavsc.Controllers
Rate = c.Rate, Rate = c.Rate,
PerformerCount = performerCounts.TryGetValue(c.Code, out var childCount) ? childCount : 0, PerformerCount = performerCounts.TryGetValue(c.Code, out var childCount) ? childCount : 0,
Forms = (c.Forms ?? Enumerable.Empty<CommandForm>()) Forms = (c.Forms ?? Enumerable.Empty<CommandForm>())
.Select(f => new CommandFormSummaryDto .Select(f => new CommandFormSummary
{ {
Id = f.Id, Id = f.Id,
ActionName = f.ActionName, ActionName = f.ActionName,