Added initial voice work edit logic (set favorite / delete) on Api and UI layers.
All checks were successful
ci / build-test (push) Successful in 2m44s
ci / publish-image (push) Successful in 1m45s

This commit is contained in:
2026-05-07 00:07:20 -04:00
parent 2bd7e3b970
commit 9c9e33ebec
14 changed files with 291 additions and 57 deletions

View File

@@ -11,7 +11,10 @@
UseCurrentColor>
</Icon>
}
<span>@ChildContent</span>
@if (ChildContent is not null)
{
<span>@ChildContent</span>
}
</div>
}
else
@@ -26,7 +29,10 @@ else
UseCurrentColor>
</Icon>
}
<span>@ChildContent</span>
@if (ChildContent is not null)
{
<span>@ChildContent</span>
}
</a>
}
@@ -62,6 +68,12 @@ else
[Parameter]
public EventCallback Click { get; set; }
[Parameter]
public bool IsClickable { get; set; }
[Parameter]
public bool ThickBorder { get; set; }
private string GetClasses()
{
string color = Color.ToString().ToLower();
@@ -72,6 +84,17 @@ else
$"color-{color}"
];
// Experimental
if (ChildContent is null)
{
classNames.Add("j-chip-icon-only");
}
if (ThickBorder)
{
classNames.Add("j-chip-thick-border");
}
switch (Varient)
{
case ElementVarient.Filled:
@@ -99,7 +122,7 @@ else
classNames.Add($"varient-tint");
}
if (Click.HasDelegate || string.IsNullOrWhiteSpace(Url) == false)
if (Click.HasDelegate || string.IsNullOrWhiteSpace(Url) == false || IsClickable)
{
classNames.Add("is-clickable");
}

View File

@@ -1,4 +1,6 @@
@using JSMR.Application.VoiceWorks.Queries.Search
@using AntDesign
@using JSMR.Application.VoiceWorks.Commands.SetFavorite
@using JSMR.Application.VoiceWorks.Queries.Search
@using JSMR.Domain.Enums
@using JSMR.UI.Blazor.Components.Chips
@using JSMR.UI.Blazor.Enums
@@ -7,6 +9,10 @@
@using System.Globalization
@using Microsoft.AspNetCore.WebUtilities
@inject VoiceWorksClient Client
@inject MessageService MessageService
@inject ModalService ModalService
<div class=@GetCardClasses(Product)>
<div class="j-voice-work-image-container">
<JImage OverlayClass="j-voice-work-image-overlay" ImageClass="j-voice-work-image" Source="@ImageUrlProvider.GetImageUrl(Product, "main")" FallbackSource="@ImageUrlProvider.GetImageUrl(Product, "main", "webp")"></JImage>
@@ -16,12 +22,6 @@
<a href="@Product.ProductUrl" target="_blank">@Product.ProductName</a>
</div>
<BitStack Horizontal="true" Gap="0.5em" AutoHeight Wrap>
@* <MudChip T="string"
Href=@($"https://www.dlsite.com/maniax/circle/profile/=/maker_id/{Product.MakerId}.html")
Target="_blank"
Variant="MudBlazor.Variant.Filled"
Icon="@Icons.Material.Outlined.Circle">@Product.Maker</MudChip> *@
@* <CircleChip Circle="@Product.Circle"></CircleChip> *@
<Chip Graphic="Graphic.Circle" Varient="ElementVarient.Outlined" Color="ColorVarient.Secondary" Url=@($"https://www.dlsite.com/maniax/circle/profile/=/maker_id/{Product.MakerId}.html")>@Product.Maker</Chip>
@if (Product.OriginalCircle is not null)
@@ -31,12 +31,6 @@
@foreach (var creator in Product.Creators)
{
@* <MudChip T="string"
Href=@($"https://www.dlsite.com/maniax/fsr/=/keyword_creater/{creator.Name}")
Target="_blank"
Variant="MudBlazor.Variant.Filled"
Icon="@Icons.Material.Filled.Person">@creator.Name</MudChip> *@
@* <CreatorChip Creator="@creator"></CreatorChip> *@
<Chip Graphic="Graphic.Person" Varient="ElementVarient.Outlined" IconVarient="IconVarient.Fill" Color="ColorVarient.Secondary" Url=@($"https://www.dlsite.com/maniax/fsr/=/keyword_creater/{creator.Name}")>@creator.Name</Chip>
}
</BitStack>
@@ -70,16 +64,9 @@
<div class="j-tags">
@foreach (var tag in Product.Tags)
{
@* <div class="j-tag">@tag.Name</div> *@
<ProductTag Tag="tag"></ProductTag>
}
</div>
@* <div class="j-tags">
@foreach (var tag in Product.Tags)
{
<TagChip Tag="tag"></TagChip>
}
</div> *@
</div>
<div class="j-voice-work-info">
<div class="j-release-date-container">
@@ -102,20 +89,45 @@
<BitStack Horizontal="true" Gap="0.5rem" VerticalAlign="BitAlignment.End" HorizontalAlign="BitAlignment.End">
@if (Product.IsValid != true)
{
<ProductIndicator Graphic="Graphic.Warning" IconVarient="IconVarient.Fill" Color="ColorVarient.Orange" BackgroundColor="ColorVarient.Black"></ProductIndicator>
@* <ProductIndicator Graphic="Graphic.Warning" IconVarient="IconVarient.Fill" Color="ColorVarient.Orange" BackgroundColor="ColorVarient.Black"></ProductIndicator> *@
<Chip Graphic="Graphic.Warning" IconVarient="IconVarient.Fill" Varient="ElementVarient.Outlined" Color="ColorVarient.Orange" ThickBorder></Chip>
}
@if (Product.OriginalProductId is not null)
{
<ProductIndicator Graphic="Graphic.Translate" Color="ColorVarient.Primary" BackgroundColor="ColorVarient.Black"></ProductIndicator>
@* <ProductIndicator Graphic="Graphic.Translate" Color="ColorVarient.Primary" BackgroundColor="ColorVarient.Black"></ProductIndicator> *@
<Chip Graphic="Graphic.Translate" Varient="ElementVarient.Outlined" Color="ColorVarient.Primary" ThickBorder></Chip>
}
@if (Product.Favorite)
{
<ProductIndicator Graphic="Graphic.Star" Color="ColorVarient.Pink" BackgroundColor="ColorVarient.Black"></ProductIndicator>
@* <ProductIndicator Graphic="Graphic.Star" Color="ColorVarient.Pink" BackgroundColor="ColorVarient.Black"></ProductIndicator> *@
<Chip Graphic="Graphic.Star" Varient="ElementVarient.Outlined" Color="ColorVarient.Pink" ThickBorder></Chip>
}
@if (Product.HasTrial || Product.HasChobit)
{
<ProductIndicator Graphic="Graphic.Headphones" Color="ColorVarient.Blue" BackgroundColor="ColorVarient.Black"></ProductIndicator>
@* <ProductIndicator Graphic="Graphic.Headphones" Color="ColorVarient.Blue" BackgroundColor="ColorVarient.Black"></ProductIndicator> *@
<Chip Graphic="Graphic.Headphones" Varient="ElementVarient.Outlined" Color="ColorVarient.Blue" ThickBorder></Chip>
}
<Dropdown Trigger="@([Trigger.Click])">
<Overlay>
<Menu Selectable="false">
@if (!Product.Favorite)
{
<MenuItem OnClick="(e) => SetFavorite(true)">Add to Favorites</MenuItem>
}
@if (Product.Favorite)
{
<MenuItem OnClick="(e) => SetFavorite(false)">Remove from Favorites</MenuItem>
}
@if (Product.IsValid != true)
{
<MenuItem OnClick="(e) => Delete()">Delete</MenuItem>
}
</Menu>
</Overlay>
<ChildContent>
<Chip Graphic="Graphic.Pencil" Varient="ElementVarient.Outlined" Color="ColorVarient.Surface" IsClickable ThickBorder></Chip>
</ChildContent>
</Dropdown>
</BitStack>
</div>
</div>
@@ -194,4 +206,43 @@
default: return code;
}
}
private async Task SetFavorite(bool value)
{
SetVoiceWorkFavoriteRequest request = new(
VoiceWorkId: Product.VoiceWorkId,
IsFavorite: value
);
SetVoiceWorkFavoriteResponse? response = await Client.SetVoiceWorkFavoriteeAsync(request);
if (response is not null)
{
Product.Favorite = response.IsFavorite;
}
//await InvokeAsync(StateHasChanged);
MessageConfig messageConfig = new()
{
Content = $"Product '{Product.ProductName}' has been {(Product.Favorite ? "added to your favorites" : "removed from your favorites")}.",
Type = MessageType.Success
};
_ = MessageService.OpenAsync(messageConfig);
}
private async Task Delete()
{
RenderFragment icon = @<AntDesign.Icon Type="@IconType.Outline.ExclamationCircle" />;
AntDesign.ConfirmOptions options = new()
{
Title = "Are you sure you want to delete the following product?",
Icon = icon,
Content = Product.ProductName
};
await ModalService.ConfirmAsync(options);
}
}