Moved search bar into separate component and fixed results display.

This commit is contained in:
Harrison Deng 2021-05-26 16:57:45 -05:00
parent 2d1f599bbf
commit 3c63ebc613
5 changed files with 64 additions and 32 deletions

View File

@ -17,10 +17,5 @@ namespace MultiShop.Client.Listing
public Search.Status Status { get; set; }
private protected abstract string GetCategoryTag(ResultsProfile.Category category);
public ListingView(Search.Status status)
{
this.Status = status;
}
}
}

View File

@ -75,10 +75,6 @@
@code {
public override Views View => Views.Table;
public TableView(Search.Status status) : base(status)
{
}
private protected override string GetCategoryTag(ResultsProfile.Category c)
{
switch (c)

View File

@ -1,14 +1,15 @@
@page "/search/{Query?}"
@using MultiShop.Client.Extensions
@using MultiShop.Client.Listing
<div class="my-2">
<div class="input-group my-2">
<input type="text" class="form-control" placeholder="What are you looking for?" aria-label="What are you looking for?" id="search-input" @bind="Query" @onkeyup="@(async (a) => {if (a.Code == "Enter" || a.Code == "NumpadEnter") await PerformSearch(Query);})" disabled="@status.Searching" >
<div class="input-group-append">
<ToggleableButton class="btn btn-outline-secondary" title="Configure" OnToggleCallback="@((t) => status.SearchConfiguring = t)"><span class="oi oi-cog align-text-top"></span></ToggleableButton>
<button class="btn btn-outline-primary" type="button" @onclick="@(async () => await PerformSearch(Query))" disabled="@status.Searching">Search</button>
</div>
<SearchBar SearchPlaceholder="What are you looking for?" OnSearchRequested="@PerformSearch" @ref="searchBar">
<Append>
<ToggleableButton class="btn btn-outline-secondary" title="Configure" OnToggleCallback="@((t) => {status.SearchConfiguring = t; StateHasChanged();})"><span class="oi oi-cog align-text-top"></span></ToggleableButton>
</Append>
</SearchBar>
</div>
@if (status.SearchConfiguring)
{
@ -238,7 +239,12 @@
<div>
@if (listings.Count > 0)
{
@listingViews[CurrentView]
@switch (CurrentView)
{
case Views.Table:
<TableView Listings="@listings" Status="@status"></TableView>
break;
}
}
</div>
</div>

View File

@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.Extensions.Logging;
using MultiShop.Client.Shared;
using MultiShop.Client.Extensions;
using MultiShop.Client.Listing;
using MultiShop.Shared.Models;
@ -17,6 +18,10 @@ namespace MultiShop.Client.Pages
{
[Inject]
private ILogger<Search> Logger { get; set; }
[Inject]
private HttpClient Http { get; set; }
[CascadingParameter]
Task<AuthenticationState> AuthenticationStateTask { get; set; }
@ -26,13 +31,10 @@ namespace MultiShop.Client.Pages
[Parameter]
public string Query { get; set; }
[Inject]
private HttpClient Http { get; set; }
private SearchBar searchBar;
private Status status = new Status();
private Dictionary<Views, ListingView> listingViews;
private Views CurrentView = Views.Table;
private SearchProfile activeSearchProfile;
@ -46,11 +48,7 @@ namespace MultiShop.Client.Pages
await base.OnInitializedAsync();
AuthenticationState authState = await AuthenticationStateTask;
listingViews = new Dictionary<Views, ListingView>() {
{Views.Table, new TableView(status)}
};
if (authState.User.Identity.IsAuthenticated) {
Logger.LogDebug($"User \"{authState.User.Identity.Name}\" is authenticated. Checking for saved profiles.");
HttpResponseMessage searchProfileResponse = await Http.GetAsync("Profile/Search");
@ -84,10 +82,21 @@ namespace MultiShop.Client.Pages
}
}
protected override async Task OnAfterRenderAsync(bool firstRender) {
await base.OnAfterRenderAsync(firstRender);
if (firstRender) {
searchBar.Query = Query;
searchBar.Searching = true;
await PerformSearch(Query);
searchBar.Searching = false;
}
}
private async Task PerformSearch(string query)
{
if (string.IsNullOrWhiteSpace(query)) return;
if (status.Searching) return;
SearchProfile searchProfile = activeSearchProfile.DeepCopy();
status.Searching = true;
Logger.LogDebug($"Received search request for \"{query}\".");
resultsChecked = 0;
@ -96,10 +105,10 @@ namespace MultiShop.Client.Pages
List<ProductListingInfo>>();
foreach (string shopName in Shops.Keys)
{
if (activeSearchProfile.ShopStates[shopName])
if (searchProfile.ShopStates[shopName])
{
Logger.LogDebug($"Querying \"{shopName}\" for products.");
Shops[shopName].SetupSession(query, activeSearchProfile.Currency);
Shops[shopName].SetupSession(query, searchProfile.Currency);
int shopViableResults = 0;
await foreach (ProductListing listing in Shops[shopName])
{
@ -111,12 +120,12 @@ namespace MultiShop.Client.Pages
}
if (listing.Shipping == null && !activeSearchProfile.KeepUnknownShipping || (activeSearchProfile.EnableMaxShippingFee && listing.Shipping > activeSearchProfile.MaxShippingFee)) continue;
if (listing.Shipping == null && !searchProfile.KeepUnknownShipping || (searchProfile.EnableMaxShippingFee && listing.Shipping > searchProfile.MaxShippingFee)) continue;
float shippingDifference = listing.Shipping != null ? listing.Shipping.Value : 0;
if (!(listing.LowerPrice + shippingDifference >= activeSearchProfile.LowerPrice && (!activeSearchProfile.EnableUpperPrice || listing.UpperPrice + shippingDifference <= activeSearchProfile.UpperPrice))) continue;
if ((listing.Rating == null && !activeSearchProfile.KeepUnrated) && activeSearchProfile.MinRating > (listing.Rating == null ? 0 : listing.Rating)) continue;
if ((listing.PurchaseCount == null && !activeSearchProfile.KeepUnknownPurchaseCount) || activeSearchProfile.MinPurchases > (listing.PurchaseCount == null ? 0 : listing.PurchaseCount)) continue;
if ((listing.ReviewCount == null && !activeSearchProfile.KeepUnknownRatingCount) || activeSearchProfile.MinReviews > (listing.ReviewCount == null ? 0 : listing.ReviewCount)) continue;
if (!(listing.LowerPrice + shippingDifference >= searchProfile.LowerPrice && (!searchProfile.EnableUpperPrice || listing.UpperPrice + shippingDifference <= searchProfile.UpperPrice))) continue;
if ((listing.Rating == null && !searchProfile.KeepUnrated) && searchProfile.MinRating > (listing.Rating == null ? 0 : listing.Rating)) continue;
if ((listing.PurchaseCount == null && !searchProfile.KeepUnknownPurchaseCount) || searchProfile.MinPurchases > (listing.PurchaseCount == null ? 0 : listing.PurchaseCount)) continue;
if ((listing.ReviewCount == null && !searchProfile.KeepUnknownRatingCount) || searchProfile.MinReviews > (listing.ReviewCount == null ? 0 : listing.ReviewCount)) continue;
ProductListingInfo info = new ProductListingInfo(listing, shopName);
listings.Add(info);
@ -142,7 +151,7 @@ namespace MultiShop.Client.Pages
}
shopViableResults += 1;
if (shopViableResults >= activeSearchProfile.MaxResults) break;
if (shopViableResults >= searchProfile.MaxResults) break;
}
Logger.LogDebug($"\"{shopName}\" has completed. There are {listings.Count} results in total.");
}

View File

@ -0,0 +1,26 @@
<input type="text" class="form-control" placeholder=@SearchPlaceholder aria-label=@SearchPlaceholder id="search-input" @bind="Query" @onkeyup="@(async (a) => {if (a.Code == "Enter" || a.Code == "NumpadEnter") await Search();})" disabled="@Searching">
<div class="input-group-append">
@Append
<button class="btn btn-outline-primary" type="button" @onclick="@(async () => await Search())" disabled="@Searching">Search</button>
</div>
@code {
[Parameter]
public RenderFragment Append { get; set; }
[Parameter]
public string SearchPlaceholder { get; set; }
public string Query { get; set; }
[Parameter]
public EventCallback<string> OnSearchRequested { get; set; }
public bool Searching { get; set; }
public async Task Search()
{
Searching = true;
await OnSearchRequested.InvokeAsync(Query);
Searching = false;
}
}