Implement searching via categories

This commit is contained in:
Stedoss 2022-10-31 23:04:14 +00:00
parent 96f409c8d8
commit 82376af904
7 changed files with 56 additions and 10 deletions

View File

@ -15,9 +15,10 @@ public class VenueController : ControllerBase
} }
[HttpGet] [HttpGet]
public async Task<IActionResult> GetAll() public async Task<IActionResult> GetVenues([FromQuery] string[]? categories = null, [FromQuery] string[]? tags = null)
{ {
var venues = await _venueService.GetAllVenues(); var venues = await _venueService.GetFilteredVenues(null, categories);
return Ok(venues); return Ok(venues);
} }

View File

@ -6,4 +6,5 @@ public interface IVenueService
{ {
public Task<IEnumerable<Venue>> GetAllVenues(); public Task<IEnumerable<Venue>> GetAllVenues();
public Task<Venue?> GetVenue(int venueId); public Task<Venue?> GetVenue(int venueId);
public Task<IEnumerable<Venue>> GetFilteredVenues(string[]? tags = null, string[]? categories = null);
} }

View File

@ -29,4 +29,21 @@ public class VenueService : IVenueService
.Include(v => v.Tags) .Include(v => v.Tags)
.SingleOrDefaultAsync(v => v.Id == venueId); .SingleOrDefaultAsync(v => v.Id == venueId);
} }
public async Task<IEnumerable<Venue>> GetFilteredVenues(string[]? tags = null, string[]? categories = null)
{
var venues = _context.Venues
.Include(v => v.Category)
.Include(v => v.Tags);
IQueryable<Venue> filteredVenues = venues;
if (categories is { Length: > 0 })
{
filteredVenues = venues.Where(v => categories.Contains(v.Category.Name));
}
return await filteredVenues.ToListAsync();
}
} }

View File

@ -1,10 +1,13 @@
import { TCategory, TTag, TVenue } from "./types"; import { ArrayToArrayUrlParams } from "./helpers";
import { TCategory, TTag, TVenue, TVenueFilters } from "./types";
export class API { export class API {
constructor(private baseAPIUrl: string) {} constructor(private baseAPIUrl: string) {}
getVenues = async (): Promise<TVenue[]> => { getVenues = async (venueFilters: TVenueFilters | null): Promise<TVenue[]> => {
const response = await fetch(`${this.baseAPIUrl}/venue`); const categoriesParams = ArrayToArrayUrlParams("categories", venueFilters?.categories.map((c) => c.name) ?? []);
const response = await fetch(`${this.baseAPIUrl}/venue${categoriesParams}`);
console.log(`calling ${this.baseAPIUrl}/venue${categoriesParams}`);
return await response.json(); return await response.json();
} }

View File

@ -0,0 +1,12 @@
export function ArrayToArrayUrlParams(paramName: string, params: string[], isFirstParam: boolean = true): string {
if (params.length === 0) {
return "";
}
let paramString = isFirstParam ? "?" : "&";
params.forEach((param) => {
paramString += `${paramName}=${param}&`;
});
return paramString.slice(0, -1);
}

View File

@ -27,4 +27,9 @@ export type TVenue = {
starsAmenities: number; starsAmenities: number;
starsValue: number; starsValue: number;
tags: TTag[]; tags: TTag[];
}
export type TVenueFilters = {
tags: TTag[];
categories: TCategory[];
} }

View File

@ -1,22 +1,29 @@
import { useQuery, useQueryClient } from "@tanstack/react-query"; import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useState } from "react"; import { useEffect, useState } from "react";
import { DropdownFilter } from "../components/dropdown-filter"; import { DropdownFilter } from "../components/dropdown-filter";
import { VenueGrid } from "../components/venue-grid"; import { VenueGrid } from "../components/venue-grid";
import { API } from "../lib/api"; import { API } from "../lib/api";
import { Environment } from "../lib/environment"; import { Environment } from "../lib/environment";
import { TCategory, TTag, TVenue } from "../lib/types"; import { TCategory, TTag, TVenue, TVenueFilters } from "../lib/types";
export function Index() { export function Index() {
const [filteredTags, setFilteredTags] = useState<TTag[]>([]);
const [filteredCategories, setFilteredCategories] = useState<TCategory[]>([]);
const api = new API(Environment.BaseAPIUrl); const api = new API(Environment.BaseAPIUrl);
const { data: venueData } = useQuery<TVenue[], Error>(["venues"], api.getVenues); const queryClient = useQueryClient();
const { data: venueData } = useQuery<TVenue[], Error>(["venues", filteredCategories], () => api.getVenues({categories: filteredCategories, tags: filteredTags}));
const { data: categoryData } = useQuery<TCategory[], Error>(["categories"], api.getCategories); const { data: categoryData } = useQuery<TCategory[], Error>(["categories"], api.getCategories);
const { data: tagData } = useQuery<TTag[], Error>(["tags"], api.getTags); const { data: tagData } = useQuery<TTag[], Error>(["tags"], api.getTags);
const [filteredTags, setFilteredTags] = useState<TTag[]>([]); // useEffect(() => {
const [filteredCategories, setFilteredCategories] = useState<TCategory[]>([]); // console.log("useeffect called!");
// queryClient.invalidateQueries(["venues"]);
// }, [filteredCategories]);
return( return(
<> <>