Added SearchPageBase class and implemented it on the voice works page and circles page. Turned off AOT compilation.

This commit is contained in:
2025-11-27 18:28:57 -05:00
parent 6817fa7353
commit 403c436a34
10 changed files with 341 additions and 321 deletions

View File

@@ -0,0 +1,64 @@
using JSMR.Application.Circles.Queries.Search;
using Microsoft.AspNetCore.WebUtilities;
using System.Globalization;
namespace JSMR.UI.Blazor.Filters;
public sealed record CircleFilterState : IFilterState<SearchCirclesRequest>
{
public string? Keywords { get; init; }
public CircleStatus? Status { get; init; }
public int PageNumber { get; init; } = 1;
public int PageSize { get; init; } = 100;
public QueryParameters ToQuery()
{
QueryParameters query = [];
query.Set("keywords", Keywords);
if (Status is not null)
query.Set("circle", Status.ToString());
if (PageNumber != 1)
query.Set("pageNumber", PageNumber.ToString(CultureInfo.InvariantCulture));
if (PageSize != 100)
query.Set("pageSize", PageSize.ToString(CultureInfo.InvariantCulture));
return query;
}
public static CircleFilterState FromQuery(string query)
{
QueryParameters queryParameters = new(QueryHelpers.ParseQuery(query));
return new CircleFilterState
{
Keywords = queryParameters.GetValue("keywords"),
Status = queryParameters.GetEnum<CircleStatus>("circle"),
PageNumber = Math.Max(1, queryParameters.GetInteger("pageNumber", 1)),
PageSize = queryParameters.GetInteger("pageSize", defaultValue: 100)
};
}
public SearchCirclesRequest ToSearchRequest()
{
return new(
Options: new()
{
PageNumber = PageNumber,
PageSize = PageSize,
Criteria = new()
{
Name = Keywords,
Status = Status
},
SortOptions =
[
new(CircleSortField.Name, Application.Common.Search.SortDirection.Ascending)
]
}
);
}
}

View File

@@ -0,0 +1,7 @@
namespace JSMR.UI.Blazor.Filters;
public interface IFilterState<TSearchRequest>
{
QueryParameters ToQuery();
TSearchRequest ToSearchRequest();
}

View File

@@ -0,0 +1,51 @@
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Primitives;
namespace JSMR.UI.Blazor.Filters;
public class QueryParameters : Dictionary<string, string?>
{
public QueryParameters()
{
}
public QueryParameters(IEnumerable<KeyValuePair<string, StringValues>> items)
{
foreach (var kv in items)
{
this[kv.Key] = kv.Value.ToString();
}
}
public static QueryParameters FromQueryString(string query)
=> new(QueryHelpers.ParseQuery(query));
public void Set(string key, string? value, bool includeWhenEmpty = false)
{
if (includeWhenEmpty || !string.IsNullOrWhiteSpace(value))
this[key] = value;
}
public bool Has(string key) => ContainsKey(key);
public string? GetValue(string key) => TryGetValue(key, out var value) ? value!.ToString() : null;
public string[] GetValues(string key) => GetValue(key)?.Split(',', StringSplitOptions.RemoveEmptyEntries) ?? [];
public int GetInteger(string key, int defaultValue)
=> TryGetValue(key, out var value) && int.TryParse(value, out int intValue) ? intValue : defaultValue;
public int[] GetIntegers(string key) => [.. GetValues(key).Select(int.Parse)];
public T? GetEnum<T>(string key) where T : struct, Enum
=> TryGetValue(key, out var value) && Enum.TryParse<T>(value!, true, out var enumValue) ? enumValue : null;
public TEnum[] GetEnums<TEnum>(string key) where TEnum : struct, Enum
=> GetValues(key).Select(value =>
Enum.TryParse<TEnum>(value, true, out var enumValue)
? enumValue
: (TEnum?)null).Where(e => e is not null).Select(e => e!.Value).ToArray()
?? [];
public DateOnly? GetDate(string key, string? format = "yyyy-MM-dd")
=> DateOnly.TryParseExact(GetValue(key), format, out var date) ? date : null;
}

View File

@@ -8,6 +8,13 @@ using System.Globalization;
namespace JSMR.UI.Blazor.Filters;
public abstract record FilterStateBase<TSearchRequest> : IFilterState<TSearchRequest>
{
public abstract QueryParameters ToQuery();
public abstract TSearchRequest ToSearchRequest();
//public static abstract IFilterState<TSearchRequest> FromQuery(string query);
}
public sealed record VoiceWorkFilterState
{
// Core