Simplified and enhnaced voice work page.
This commit is contained in:
233
JSMR.UI.Blazor/Filters/VoiceWorkFilterState.cs
Normal file
233
JSMR.UI.Blazor/Filters/VoiceWorkFilterState.cs
Normal file
@@ -0,0 +1,233 @@
|
||||
using JSMR.Application.Common.Search;
|
||||
using JSMR.Application.Enums;
|
||||
using JSMR.Application.VoiceWorks.Queries.Search;
|
||||
using JSMR.Domain.Enums;
|
||||
using JSMR.UI.Blazor.Enums;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using System.Globalization;
|
||||
|
||||
namespace JSMR.UI.Blazor.Filters;
|
||||
|
||||
public sealed record VoiceWorkFilterState
|
||||
{
|
||||
// Core
|
||||
public string? Keywords { get; init; }
|
||||
public Locale Locale { get; init; } = Locale.English;
|
||||
|
||||
// Statuses
|
||||
public SaleStatus? SaleStatus { get; init; }
|
||||
public CircleStatus? CircleStatus { get; init; }
|
||||
public TagStatus? TagStatus { get; init; }
|
||||
public CreatorStatus? CreatorStatus { get; init; }
|
||||
|
||||
// Multi-selects
|
||||
public int[] TagIds { get; init; } = Array.Empty<int>();
|
||||
public bool IncludeAllTags { get; init; }
|
||||
public int[] CreatorIds { get; init; } = Array.Empty<int>();
|
||||
public bool IncludeAllCreators { get; init; }
|
||||
public Language[] SupportedLanguages { get; init; } = Array.Empty<Language>();
|
||||
public AgeRating[] AgeRatings { get; init; } = Array.Empty<AgeRating>();
|
||||
|
||||
// Misc flags
|
||||
public bool ShowFavorite { get; init; }
|
||||
public bool ShowInvalid { get; init; }
|
||||
|
||||
// Dates (use yyyy-MM-dd in URL)
|
||||
public DateOnly? ReleaseDateStart { get; init; }
|
||||
public DateOnly? ReleaseDateEnd { get; init; }
|
||||
|
||||
// Sorting & paging
|
||||
public VoiceWorkSort Sort { get; init; } = VoiceWorkSort.ReleaseDateNewToOld;
|
||||
public int PageNumber { get; init; } = 1;
|
||||
public int PageSize { get; init; } = 100;
|
||||
|
||||
// ---- Query <-> State helpers ----
|
||||
public Dictionary<string, string?> ToQuery()
|
||||
{
|
||||
Dictionary<string, string?> query = [];
|
||||
|
||||
void Set(string key, string? value, bool includeWhenEmpty = false)
|
||||
{
|
||||
if (includeWhenEmpty || !string.IsNullOrWhiteSpace(value))
|
||||
query[key] = value;
|
||||
}
|
||||
|
||||
string Join<T>(IEnumerable<T> xs) => string.Join(",", xs);
|
||||
|
||||
Set("keywords", Keywords);
|
||||
|
||||
if (Locale != Locale.English)
|
||||
Set("locale", Locale.ToString());
|
||||
|
||||
if (SaleStatus is not null)
|
||||
Set("sale", SaleStatus.ToString());
|
||||
|
||||
if (CircleStatus is not null)
|
||||
Set("circle", CircleStatus.ToString());
|
||||
|
||||
if (TagStatus is not null)
|
||||
Set("tag", TagStatus.ToString());
|
||||
|
||||
if (CreatorStatus is not null)
|
||||
Set("creator", CreatorStatus.ToString());
|
||||
|
||||
if (TagIds.Length > 0)
|
||||
Set("tagIds", Join(TagIds));
|
||||
|
||||
if (IncludeAllTags)
|
||||
Set("allTags", "1");
|
||||
|
||||
if (CreatorIds.Length > 0)
|
||||
Set("creatorIds", Join(CreatorIds));
|
||||
|
||||
if (IncludeAllCreators)
|
||||
Set("allCreators", "1");
|
||||
|
||||
if (SupportedLanguages.Length > 0)
|
||||
Set("langs", Join(SupportedLanguages));
|
||||
|
||||
if (AgeRatings.Length > 0)
|
||||
Set("ages", Join(AgeRatings));
|
||||
|
||||
if (ShowFavorite)
|
||||
Set("fav", "1");
|
||||
|
||||
if (ShowInvalid)
|
||||
Set("invalid", "1");
|
||||
|
||||
if (ReleaseDateStart is not null)
|
||||
Set("rs", ReleaseDateStart.Value.ToString("yyyy-MM-dd"));
|
||||
|
||||
if (ReleaseDateEnd is not null)
|
||||
Set("re", ReleaseDateEnd.Value.ToString("yyyy-MM-dd"));
|
||||
|
||||
if (Sort != VoiceWorkSort.ReleaseDateNewToOld)
|
||||
Set("sort", Sort.ToString());
|
||||
|
||||
if (PageNumber != 1)
|
||||
Set("pageNumber", PageNumber.ToString(CultureInfo.InvariantCulture));
|
||||
|
||||
if (PageSize != 100)
|
||||
Set("pageSize", PageSize.ToString(CultureInfo.InvariantCulture));
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
public static VoiceWorkFilterState FromQuery(string query)
|
||||
{
|
||||
var dict = QueryHelpers.ParseQuery(query);
|
||||
|
||||
T? GetEnum<T>(string key) where T : struct, Enum
|
||||
=> dict.TryGetValue(key, out var v) && Enum.TryParse<T>(v!, true, out var e) ? e : null;
|
||||
|
||||
string? Get(string key) => dict.TryGetValue(key, out var v) ? v!.ToString() : null;
|
||||
int[] GetInts(string key) => Get(key)?.Split(',', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray() ?? Array.Empty<int>();
|
||||
TEnum[] GetEnums<TEnum>(string key) where TEnum : struct, Enum
|
||||
=> Get(key)?.Split(',', StringSplitOptions.RemoveEmptyEntries).Select(s => Enum.TryParse<TEnum>(s, true, out var e) ? e : (TEnum?)null).Where(e => e is not null).Select(e => e!.Value).ToArray()
|
||||
?? Array.Empty<TEnum>();
|
||||
DateOnly? GetDate(string key) => DateOnly.TryParseExact(Get(key), "yyyy-MM-dd", out var d) ? d : null;
|
||||
bool Has(string key) => dict.ContainsKey(key);
|
||||
|
||||
return new VoiceWorkFilterState
|
||||
{
|
||||
Keywords = Get("keywords"),
|
||||
Locale = GetEnum<Locale>("locale") ?? Locale.English,
|
||||
|
||||
SaleStatus = GetEnum<SaleStatus>("sale"),
|
||||
CircleStatus = GetEnum<CircleStatus>("circle"),
|
||||
TagStatus = GetEnum<TagStatus>("tag"),
|
||||
CreatorStatus = GetEnum<CreatorStatus>("creator"),
|
||||
|
||||
TagIds = GetInts("tagIds"),
|
||||
IncludeAllTags = Has("allTags"),
|
||||
CreatorIds = GetInts("creatorIds"),
|
||||
IncludeAllCreators = Has("allCreators"),
|
||||
SupportedLanguages = GetEnums<Language>("langs"),
|
||||
AgeRatings = GetEnums<AgeRating>("ages"),
|
||||
|
||||
ShowFavorite = Has("fav"),
|
||||
ShowInvalid = Has("invalid"),
|
||||
|
||||
ReleaseDateStart = GetDate("rs"),
|
||||
ReleaseDateEnd = GetDate("re"),
|
||||
|
||||
Sort = GetEnum<VoiceWorkSort>("sort") ?? VoiceWorkSort.ReleaseDateNewToOld,
|
||||
PageNumber = int.TryParse(Get("pageNumber"), out var pageNumber) ? Math.Max(1, pageNumber) : 1,
|
||||
PageSize = int.TryParse(Get("pageSize"), out var pageSize) ? pageSize : 100
|
||||
};
|
||||
}
|
||||
|
||||
public SearchVoiceWorksRequest ToSearchRequest()
|
||||
{
|
||||
return new(
|
||||
Options: new()
|
||||
{
|
||||
Criteria = new()
|
||||
{
|
||||
Keywords = Keywords,
|
||||
Locale = Locale,
|
||||
SaleStatus = SaleStatus,
|
||||
CircleStatus = CircleStatus,
|
||||
TagStatus = TagStatus,
|
||||
CreatorStatus = CreatorStatus,
|
||||
TagIds = TagIds,
|
||||
IncludeAllTags = IncludeAllTags,
|
||||
CreatorIds = CreatorIds,
|
||||
IncludeAllCreators = IncludeAllCreators,
|
||||
ShowFavoriteVoiceWorks = ShowFavorite,
|
||||
ShowInvalidVoiceWorks = ShowInvalid,
|
||||
SupportedLanguages = SupportedLanguages,
|
||||
AgeRatings = AgeRatings,
|
||||
ReleaseDateStart = ReleaseDateStart,
|
||||
ReleaseDateEnd = ReleaseDateEnd,
|
||||
//MinDownloads = MinDownloads
|
||||
},
|
||||
SortOptions = GetSortOptions(),
|
||||
PageNumber = PageNumber,
|
||||
PageSize = PageSize
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private SortOption<VoiceWorkSortField>[] GetSortOptions()
|
||||
{
|
||||
switch (Sort)
|
||||
{
|
||||
case VoiceWorkSort.ReleaseDateNewToOld:
|
||||
return
|
||||
[
|
||||
new(GetReleaseDateVoiceWorkSortField(), SortDirection.Descending)
|
||||
];
|
||||
case VoiceWorkSort.ReleaseDateOldToNew:
|
||||
return
|
||||
[
|
||||
new(GetReleaseDateVoiceWorkSortField(), SortDirection.Ascending)
|
||||
];
|
||||
case VoiceWorkSort.BestSelling:
|
||||
return
|
||||
[
|
||||
new(VoiceWorkSortField.Downloads, SortDirection.Descending)
|
||||
];
|
||||
case VoiceWorkSort.MostFavorited:
|
||||
return
|
||||
[
|
||||
new(VoiceWorkSortField.WishlistCount, SortDirection.Descending)
|
||||
];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
private VoiceWorkSortField GetReleaseDateVoiceWorkSortField()
|
||||
{
|
||||
switch (SaleStatus)
|
||||
{
|
||||
case Application.VoiceWorks.Queries.Search.SaleStatus.Available:
|
||||
return VoiceWorkSortField.ReleaseDate;
|
||||
case Application.VoiceWorks.Queries.Search.SaleStatus.Upcoming:
|
||||
return VoiceWorkSortField.ExpectedReleaseDate;
|
||||
default:
|
||||
return VoiceWorkSortField.AnyReleaseDate;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user