yavsc/src/Yavsc.Api.Client/ActivityApiClient.cs

106 lines
3.6 KiB
C#
Raw Normal View History

2026-08-30 23:55:09 +01:00
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Yavsc.Abstract.Workflow;
namespace Yavsc.Api.Client;
/// <summary>
/// HTTP client for browsing business activities and their performers.
/// Uses absolute URLs so it can coexist with other Yavsc clients that
2026-08-31 03:37:09 +01:00
/// target a different API host on the same shared transport. The same
/// activity payload also carries the eligible billing forms for a
/// selected performer/activity pair.
2026-08-30 23:55:09 +01:00
/// </summary>
public sealed class ActivityApiClient
{
private const string PathPrefix = "activity";
private readonly IYavscApiClient _api;
private readonly Func<string> _businessBaseAddress;
private readonly Func<string?> _avatarBaseAddress;
2026-08-30 23:55:09 +01:00
public ActivityApiClient(IYavscApiClient api, string businessBaseAddress, string? avatarBaseAddress = null)
: this(
api,
() => businessBaseAddress,
() => avatarBaseAddress)
{
}
public ActivityApiClient(
IYavscApiClient api,
Func<string> businessBaseAddress,
Func<string?>? avatarBaseAddress = null)
2026-08-30 23:55:09 +01:00
{
_api = api ?? throw new ArgumentNullException(nameof(api));
_businessBaseAddress = businessBaseAddress ?? throw new ArgumentNullException(nameof(businessBaseAddress));
_avatarBaseAddress = avatarBaseAddress ?? (() => null);
2026-08-30 23:55:09 +01:00
// Validate initial values early to fail fast on invalid setup.
_ = ResolveBusinessBaseAddress();
_ = ResolveAvatarBaseAddress();
2026-08-30 23:55:09 +01:00
}
2026-09-02 14:52:17 +01:00
public Task<List<ActivityInfo>> GetCatalogAsync(
2026-08-30 23:55:09 +01:00
string? parentCode = null,
CancellationToken ct = default)
{
var path = string.IsNullOrWhiteSpace(parentCode)
? $"{PathPrefix}/catalog"
: $"{PathPrefix}/catalog?parentCode={Uri.EscapeDataString(parentCode)}";
2026-09-02 14:52:17 +01:00
return _api.CallAsync<List<ActivityInfo>>(HttpMethod.Get, Absolute(path), ct: ct);
2026-08-30 23:55:09 +01:00
}
2026-09-02 14:52:17 +01:00
public Task<List<PerformerActivity>> GetUsersAsync(
2026-08-30 23:55:09 +01:00
string activityCode,
CancellationToken ct = default)
{
if (string.IsNullOrWhiteSpace(activityCode))
throw new ArgumentException("Activity code is required.", nameof(activityCode));
2026-09-02 14:52:17 +01:00
return _api.CallAsync<List<PerformerActivity>>(
2026-08-30 23:55:09 +01:00
HttpMethod.Get,
2026-08-31 02:14:04 +01:00
Absolute($"{PathPrefix}/{Uri.EscapeDataString(activityCode)}/users"),
2026-08-30 23:55:09 +01:00
ct: ct);
}
2026-09-02 14:52:17 +01:00
public Task<List<PerformerActivity>> GetPerformersAsync(
2026-08-31 02:14:04 +01:00
string activityCode,
CancellationToken ct = default)
=> GetUsersAsync(activityCode, ct);
public string BuildAvatarXsUrl(string? userName)
{
var siteRoot = new Uri(ResolveAvatarBaseAddress(), "/");
if (string.IsNullOrWhiteSpace(userName))
{
return new Uri(siteRoot, "images/Users/icon_user.xs.png").ToString();
}
return new Uri(siteRoot, $"avatars/{Uri.EscapeDataString(userName)}.xs.png").ToString();
}
private string Absolute(string relativePath) => new Uri(ResolveBusinessBaseAddress(), relativePath).ToString();
private Uri ResolveBusinessBaseAddress()
{
var raw = _businessBaseAddress();
if (string.IsNullOrWhiteSpace(raw))
throw new InvalidOperationException("Business base address is required.");
return new Uri(raw, UriKind.Absolute);
}
private Uri ResolveAvatarBaseAddress()
{
var raw = _avatarBaseAddress();
return string.IsNullOrWhiteSpace(raw)
? ResolveBusinessBaseAddress()
: new Uri(raw, UriKind.Absolute);
}
2026-08-30 23:55:09 +01:00
}