feat: add AlbumService and PersonService to WASM client

- AlbumService: CRUD operations for albums via API
- PersonService: GetAllAsync for person dropdown
- Register both as Scoped in DI
This commit is contained in:
2026-07-08 13:11:31 +02:00
parent b58c8ebce8
commit 3c1d2ef14b
3 changed files with 105 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
using Butter.Dtos.Album;
using Microsoft.Extensions.Options;
namespace MilkStream.Client.Services;
/// <summary>
/// Provides access to album CRUD and search operations via the API.
/// </summary>
public sealed class AlbumService(
IOptions<ServiceOptions> options,
IHttpClientFactory httpClientFactory,
LoginService loginService,
ILogger<AlbumService> logger
) : AuthServiceBase(options, httpClientFactory, loginService, logger) {
/// <summary>
/// Gets a paginated list of album previews with optional search term.
/// </summary>
/// <param name="page">The zero-based page number.</param>
/// <param name="pageSize">The number of items per page.</param>
/// <param name="search">Optional search term to filter by title.</param>
/// <returns>A list of album previews, or null if the request failed.</returns>
public async Task<List<AlbumPreviewDto>?> GetAlbumsAsync(int page = 0, int pageSize = 30, string? search = null) {
var url = $"/api/album?page={page}&pageSize={pageSize}";
if (!string.IsNullOrEmpty(search))
url += $"&search={Uri.EscapeDataString(search)}";
var response = await SendWithRefreshAsync(() => Client.GetAsync(url));
if (response.IsSuccessStatusCode)
return await response.Content.ReadFromJsonAsync<List<AlbumPreviewDto>>();
return null;
}
/// <summary>
/// Gets a single album by ID with its filtered assets.
/// </summary>
/// <param name="id">The album ID.</param>
/// <returns>The full album details, or null if not found.</returns>
public async Task<AlbumFullDto?> GetAlbumAsync(Guid id) {
var response = await SendWithRefreshAsync(() => Client.GetAsync($"/api/album/{id}"));
if (response.IsSuccessStatusCode)
return await response.Content.ReadFromJsonAsync<AlbumFullDto>();
return null;
}
/// <summary>
/// Creates a new album.
/// </summary>
/// <param name="dto">The album creation data.</param>
public async Task CreateAlbumAsync(AlbumCreateDto dto) {
var response = await Client.PutAsJsonAsync("/api/album", dto);
response.EnsureSuccessStatusCode();
}
/// <summary>
/// Updates an existing album.
/// </summary>
/// <param name="id">The album ID.</param>
/// <param name="dto">The album update data.</param>
public async Task UpdateAlbumAsync(Guid id, AlbumUpdateDto dto) {
var response = await Client.PostAsJsonAsync($"/api/album/{id}", dto);
response.EnsureSuccessStatusCode();
}
/// <summary>
/// Deletes an album by ID.
/// </summary>
/// <param name="id">The album ID.</param>
public async Task DeleteAlbumAsync(Guid id) {
var response = await Client.DeleteAsync($"/api/album/{id}");
response.EnsureSuccessStatusCode();
}
}

View File

@@ -0,0 +1,27 @@
using Butter.Dtos.Person;
using Microsoft.Extensions.Options;
namespace MilkStream.Client.Services;
/// <summary>
/// Provides access to person data via the API.
/// </summary>
public sealed class PersonService(
IOptions<ServiceOptions> options,
IHttpClientFactory httpClientFactory,
LoginService loginService,
ILogger<PersonService> logger
) : AuthServiceBase(options, httpClientFactory, loginService, logger) {
/// <summary>
/// Gets all non-deleted people.
/// </summary>
/// <returns>A list of person previews, or null if the request failed.</returns>
public async Task<List<PersonPreviewDto>?> GetAllAsync() {
var response = await SendWithRefreshAsync(() => Client.GetAsync("/api/person"));
if (response.IsSuccessStatusCode)
return await response.Content.ReadFromJsonAsync<List<PersonPreviewDto>>();
return null;
}
}