From 82376af90465bc66d864b1252808ca05b8ed3d39 Mon Sep 17 00:00:00 2001 From: Stedoss <29103029+Stedoss@users.noreply.github.com> Date: Mon, 31 Oct 2022 23:04:14 +0000 Subject: [PATCH] Implement searching via categories --- .../Controllers/VenueController.cs | 5 +++-- .../Data/Services/Interfaces/IVenueService.cs | 1 + .../Data/Services/VenueService.cs | 17 +++++++++++++++++ frontend/leeds-beer-quest/src/lib/api.ts | 9 ++++++--- frontend/leeds-beer-quest/src/lib/helpers.ts | 12 ++++++++++++ frontend/leeds-beer-quest/src/lib/types.ts | 5 +++++ frontend/leeds-beer-quest/src/pages/index.tsx | 17 ++++++++++++----- 7 files changed, 56 insertions(+), 10 deletions(-) create mode 100644 frontend/leeds-beer-quest/src/lib/helpers.ts diff --git a/backend/LeedsBeerQuest.API/LeedsBeerQuest.API/Controllers/VenueController.cs b/backend/LeedsBeerQuest.API/LeedsBeerQuest.API/Controllers/VenueController.cs index ac151cd..17fbf8c 100644 --- a/backend/LeedsBeerQuest.API/LeedsBeerQuest.API/Controllers/VenueController.cs +++ b/backend/LeedsBeerQuest.API/LeedsBeerQuest.API/Controllers/VenueController.cs @@ -15,9 +15,10 @@ public class VenueController : ControllerBase } [HttpGet] - public async Task GetAll() + public async Task GetVenues([FromQuery] string[]? categories = null, [FromQuery] string[]? tags = null) { - var venues = await _venueService.GetAllVenues(); + var venues = await _venueService.GetFilteredVenues(null, categories); + return Ok(venues); } diff --git a/backend/LeedsBeerQuest.API/LeedsBeerQuest.API/Data/Services/Interfaces/IVenueService.cs b/backend/LeedsBeerQuest.API/LeedsBeerQuest.API/Data/Services/Interfaces/IVenueService.cs index 66b0d88..1488b68 100644 --- a/backend/LeedsBeerQuest.API/LeedsBeerQuest.API/Data/Services/Interfaces/IVenueService.cs +++ b/backend/LeedsBeerQuest.API/LeedsBeerQuest.API/Data/Services/Interfaces/IVenueService.cs @@ -6,4 +6,5 @@ public interface IVenueService { public Task> GetAllVenues(); public Task GetVenue(int venueId); + public Task> GetFilteredVenues(string[]? tags = null, string[]? categories = null); } \ No newline at end of file diff --git a/backend/LeedsBeerQuest.API/LeedsBeerQuest.API/Data/Services/VenueService.cs b/backend/LeedsBeerQuest.API/LeedsBeerQuest.API/Data/Services/VenueService.cs index 64e2a18..3638bab 100644 --- a/backend/LeedsBeerQuest.API/LeedsBeerQuest.API/Data/Services/VenueService.cs +++ b/backend/LeedsBeerQuest.API/LeedsBeerQuest.API/Data/Services/VenueService.cs @@ -29,4 +29,21 @@ public class VenueService : IVenueService .Include(v => v.Tags) .SingleOrDefaultAsync(v => v.Id == venueId); } + + public async Task> GetFilteredVenues(string[]? tags = null, string[]? categories = null) + { + var venues = _context.Venues + .Include(v => v.Category) + .Include(v => v.Tags); + + + IQueryable filteredVenues = venues; + + if (categories is { Length: > 0 }) + { + filteredVenues = venues.Where(v => categories.Contains(v.Category.Name)); + } + + return await filteredVenues.ToListAsync(); + } } \ No newline at end of file diff --git a/frontend/leeds-beer-quest/src/lib/api.ts b/frontend/leeds-beer-quest/src/lib/api.ts index b071539..7fc4b74 100644 --- a/frontend/leeds-beer-quest/src/lib/api.ts +++ b/frontend/leeds-beer-quest/src/lib/api.ts @@ -1,10 +1,13 @@ -import { TCategory, TTag, TVenue } from "./types"; +import { ArrayToArrayUrlParams } from "./helpers"; +import { TCategory, TTag, TVenue, TVenueFilters } from "./types"; export class API { constructor(private baseAPIUrl: string) {} - getVenues = async (): Promise => { - const response = await fetch(`${this.baseAPIUrl}/venue`); + getVenues = async (venueFilters: TVenueFilters | null): Promise => { + 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(); } diff --git a/frontend/leeds-beer-quest/src/lib/helpers.ts b/frontend/leeds-beer-quest/src/lib/helpers.ts new file mode 100644 index 0000000..6c54fff --- /dev/null +++ b/frontend/leeds-beer-quest/src/lib/helpers.ts @@ -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); +} \ No newline at end of file diff --git a/frontend/leeds-beer-quest/src/lib/types.ts b/frontend/leeds-beer-quest/src/lib/types.ts index a2df943..0a43a81 100644 --- a/frontend/leeds-beer-quest/src/lib/types.ts +++ b/frontend/leeds-beer-quest/src/lib/types.ts @@ -27,4 +27,9 @@ export type TVenue = { starsAmenities: number; starsValue: number; tags: TTag[]; +} + +export type TVenueFilters = { + tags: TTag[]; + categories: TCategory[]; } \ No newline at end of file diff --git a/frontend/leeds-beer-quest/src/pages/index.tsx b/frontend/leeds-beer-quest/src/pages/index.tsx index 8494b45..f2c47d3 100644 --- a/frontend/leeds-beer-quest/src/pages/index.tsx +++ b/frontend/leeds-beer-quest/src/pages/index.tsx @@ -1,22 +1,29 @@ import { useQuery, useQueryClient } from "@tanstack/react-query"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { DropdownFilter } from "../components/dropdown-filter"; import { VenueGrid } from "../components/venue-grid"; import { API } from "../lib/api"; import { Environment } from "../lib/environment"; -import { TCategory, TTag, TVenue } from "../lib/types"; +import { TCategory, TTag, TVenue, TVenueFilters } from "../lib/types"; export function Index() { + const [filteredTags, setFilteredTags] = useState([]); + const [filteredCategories, setFilteredCategories] = useState([]); + const api = new API(Environment.BaseAPIUrl); - const { data: venueData } = useQuery(["venues"], api.getVenues); + const queryClient = useQueryClient(); + + const { data: venueData } = useQuery(["venues", filteredCategories], () => api.getVenues({categories: filteredCategories, tags: filteredTags})); const { data: categoryData } = useQuery(["categories"], api.getCategories); const { data: tagData } = useQuery(["tags"], api.getTags); - const [filteredTags, setFilteredTags] = useState([]); - const [filteredCategories, setFilteredCategories] = useState([]); + // useEffect(() => { + // console.log("useeffect called!"); + // queryClient.invalidateQueries(["venues"]); + // }, [filteredCategories]); return( <>