Refactor prospect filtering and sorting components; remove obsolete ProspectFilterControl and enhance ProspectSortControl with filtering capabilities.
All checks were successful
Build And Push Dev Docker Image / docker (push) Successful in 1m31s

This commit is contained in:
troogs
2026-04-18 16:36:32 +02:00
parent 8e5a37a0c9
commit 297a7c60bd
11 changed files with 193 additions and 129 deletions

View File

@@ -73,6 +73,12 @@
IconClass="fa-solid fa-handshake-simple">
</InteractionRow>
<tr>
<td colspan="3">
<hr style="margin: 10px 0;">
</td>
</tr>
@if (!AppSettings.DisableStepIn)
{
<InteractionRow

View File

@@ -1,102 +0,0 @@
@using FoodsharingSiegen.Contracts.Enums
@using FoodsharingSiegen.Contracts.Model
@inherits FsBase
@code {
[Parameter] public ProspectFilter Filter { get; set; } = new();
[Parameter] public EventCallback<ProspectFilter> FilterChanged { get; set; }
[Parameter] public ProspectStateFilter StateFilter { get; set; }
private async Task WithoutStepInBriefingChangedAsync(bool arg)
{
Filter.WithoutStepInBriefing = arg;
await FilterChanged.InvokeAsync(Filter);
}
private async Task TextChanged(string arg)
{
Filter.Text = arg;
await FilterChanged.InvokeAsync(Filter);
}
private async Task WithoutIdCheckChangedAsync(bool arg)
{
Filter.WithoutIdCheck = arg;
await FilterChanged.InvokeAsync(Filter);
}
private async Task NoActivityChangedAsync(bool arg)
{
Filter.NoActivity = arg;
await FilterChanged.InvokeAsync(Filter);
}
private async Task DeletedOnlyChangedAsync(bool arg)
{
Filter.DeletedOnly = arg;
await FilterChanged.InvokeAsync(Filter);
}
private async Task RecentActivityChangedAsync(bool arg)
{
Filter.RecentActivity = arg;
await FilterChanged.InvokeAsync(Filter);
}
}
<div class="card">
<div class="card-header" style="padding: .5rem;">
<i class="fa-solid fa-filter"></i> Suchfilter
</div>
<div class="card-body" style="padding: .5rem;">
@if (!AppSettings.DisableStepIn)
{
@* WITHOUT STEP IN BRIEFING *@
@if (new[] { ProspectStateFilter.All, ProspectStateFilter.OnBoarding, ProspectStateFilter.Completed }.Contains(StateFilter))
{
<div style="margin-left: 1rem;">
<Switch TValue="bool" Checked="Filter.WithoutStepInBriefing" CheckedChanged="WithoutStepInBriefingChangedAsync" Color="Color.Primary">Ohne @AppSettings.Terms.StepInName</Switch>
</div>
}
}
@* WITHOUT ID CHECK *@
@if (new[] { ProspectStateFilter.All, ProspectStateFilter.Verification, ProspectStateFilter.Completed }.Contains(StateFilter))
{
<div style="margin-left: 1rem;">
<Switch TValue="bool" Checked="Filter.WithoutIdCheck" CheckedChanged="WithoutIdCheckChangedAsync" Color="Color.Primary">Perso noch nicht geprüft</Switch>
</div>
}
@* RECENT ACTIVITY *@
@if (new[] { ProspectStateFilter.All, ProspectStateFilter.OnBoarding, ProspectStateFilter.Verification }.Contains(StateFilter))
{
<div style="margin-left: 1rem;">
<Switch TValue="bool" Checked="Filter.RecentActivity" CheckedChanged="RecentActivityChangedAsync" Color="Color.Primary">Kürzlich geändert (&lt; 6 Monate)</Switch>
</div>
}
@* NO ACTIVITY *@
@if (new[] { ProspectStateFilter.All, ProspectStateFilter.OnBoarding, ProspectStateFilter.Verification }.Contains(StateFilter))
{
<div style="margin-left: 1rem;">
<Switch TValue="bool" Checked="Filter.NoActivity" CheckedChanged="NoActivityChangedAsync" Color="Color.Primary">Lange keine Aktivität (&gt; 6 Monate)</Switch>
</div>
}
@* DELETED ONLY *@
@if (new[] { ProspectStateFilter.All }.Contains(StateFilter))
{
<div style="margin-left: 1rem;">
<Switch TValue="bool" Checked="Filter.DeletedOnly" CheckedChanged="DeletedOnlyChangedAsync" Color="Color.Primary">Gelöschte</Switch>
</div>
}
<TextEdit Text="@Filter.Text" TextChanged="TextChanged" Placeholder="Suchen..." Debounce="true" DebounceInterval="200"/>
</div>
</div>

View File

@@ -8,7 +8,7 @@
[Parameter] public Func<Task>? OnDataChanged { get; set; }
}
<h5>@(Prospects?.Count ?? 0) Einträge</h5>
<h6>@(Prospects?.Count ?? 0) Ergebnisse</h6>
@if (Prospects?.Any() == true)
{

View File

@@ -1,17 +1,52 @@
@using FoodsharingSiegen.Contracts.Enums
@inherits FoodsharingSiegen.Server.BaseClasses.FsBase
<Button Color="Color.Primary"
Width="Width.Px(50)"
Height="Height.Px(50)"
title="Sortieren"
style="min-width: auto;"
Clicked="@OpenSortDialogAsync">
<i class="fa-solid fa-sort"></i>
</Button>
<Button Color="Color.Primary"
Width="Width.Px(50)"
Height="Height.Px(50)"
title="Sortieren"
style="min-width: auto;"
Clicked="@OpenSortDialogAsync">
<i class="fa-solid fa-sort"></i>
</Button>
<div class="badge-row mt-2">
<Button Color="Color.Primary"
Width="Width.Px(50)"
Height="Height.Px(50)"
title="Filtern"
style="min-width: auto;"
Clicked="@OpenFilterDialogAsync">
<i class="fa-solid fa-filter"></i>
</Button>
<div style="flex-grow: 1;" class="mt-3">
<TextEdit Text="@Filter.Text" TextChanged="TextChangedAsync" Placeholder="Suchen..." Debounce="true" DebounceInterval="200" />
</div>
<div class="badge-row mt-1 mb-3">
@if (HasCustomSort)
{
<Badge Color="Color.Primary" Closable="true" CloseClicked="@EventCallback.Factory.Create(this, ResetSortAsync)">@CurrentSortText</Badge>
<Badge class="mr-1" Color="Color.Primary" Closable="true" CloseClicked="@EventCallback.Factory.Create(this, ResetSortAsync)">@CurrentSortText</Badge>
}
@if (Filter.WithoutStepInBriefing)
{
<Badge class="mr-1 mb-1" Color="Color.Info" Closable="true" CloseClicked="@EventCallback.Factory.Create(this, () => DisableFilterAsync(nameof(Filter.WithoutStepInBriefing)))">Ohne @AppSettings.Terms.StepInName</Badge>
}
@if (Filter.WithoutIdCheck)
{
<Badge class="mr-1 mb-1" Color="Color.Info" Closable="true" CloseClicked="@EventCallback.Factory.Create(this, () => DisableFilterAsync(nameof(Filter.WithoutIdCheck)))">Perso noch nicht geprüft</Badge>
}
@if (Filter.RecentActivity)
{
<Badge class="mr-1 mb-1" Color="Color.Info" Closable="true" CloseClicked="@EventCallback.Factory.Create(this, () => DisableFilterAsync(nameof(Filter.RecentActivity)))">Kürzlich geändert</Badge>
}
@if (Filter.NoActivity)
{
<Badge class="mr-1 mb-1" Color="Color.Info" Closable="true" CloseClicked="@EventCallback.Factory.Create(this, () => DisableFilterAsync(nameof(Filter.NoActivity)))">Lange keine Aktivität</Badge>
}
@if (Filter.DeletedOnly)
{
<Badge class="mr-1 mb-1" Color="Color.Info" Closable="true" CloseClicked="@EventCallback.Factory.Create(this, () => DisableFilterAsync(nameof(Filter.DeletedOnly)))">Gelöschte</Badge>
}
</div>

View File

@@ -1,6 +1,7 @@
using Blazorise;
using FoodsharingSiegen.Contracts.Entity;
using FoodsharingSiegen.Contracts.Enums;
using FoodsharingSiegen.Contracts.Model;
using FoodsharingSiegen.Server.Data.Service;
using FoodsharingSiegen.Server.Dialogs;
using FoodsharingSiegen.Server.Service;
@@ -26,6 +27,10 @@ public partial class ProspectSortControl
[Parameter]
public string? StorageKey { get; set; }
[Parameter] public ProspectFilter Filter { get; set; } = new();
[Parameter] public EventCallback<ProspectFilter> FilterChanged { get; set; }
[Parameter] public ProspectStateFilter StateFilter { get; set; } = ProspectStateFilter.All;
protected override async Task OnInitializedAsync()
{
if (!string.IsNullOrEmpty(StorageKey))
@@ -48,6 +53,35 @@ public partial class ProspectSortControl
});
}
private async Task OpenFilterDialogAsync()
{
await ProspectFilterDialog.ShowAsync(ModalService, Filter, StateFilter, async (f) =>
{
Filter = f;
await FilterChanged.InvokeAsync(Filter);
await InvokeAsync(StateHasChanged);
});
}
private async Task TextChangedAsync(string text)
{
Filter.Text = text;
await FilterChanged.InvokeAsync(Filter);
}
private async Task DisableFilterAsync(string filterPropName)
{
switch (filterPropName)
{
case nameof(Filter.WithoutStepInBriefing): Filter.WithoutStepInBriefing = false; break;
case nameof(Filter.WithoutIdCheck): Filter.WithoutIdCheck = false; break;
case nameof(Filter.RecentActivity): Filter.RecentActivity = false; break;
case nameof(Filter.NoActivity): Filter.NoActivity = false; break;
case nameof(Filter.DeletedOnly): Filter.DeletedOnly = false; break;
}
await FilterChanged.InvokeAsync(Filter);
}
private bool HasCustomSort => CurrentSort != ProspectSortOption.NameAscending;
private string CurrentSortText => CurrentSort switch