Implement searching via categories
This commit is contained in:
parent
96f409c8d8
commit
82376af904
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
12
frontend/leeds-beer-quest/src/lib/helpers.ts
Normal file
12
frontend/leeds-beer-quest/src/lib/helpers.ts
Normal 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);
|
||||||
|
}
|
@ -28,3 +28,8 @@ export type TVenue = {
|
|||||||
starsValue: number;
|
starsValue: number;
|
||||||
tags: TTag[];
|
tags: TTag[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type TVenueFilters = {
|
||||||
|
tags: TTag[];
|
||||||
|
categories: TCategory[];
|
||||||
|
}
|
@ -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(
|
||||||
<>
|
<>
|
||||||
|
Loading…
Reference in New Issue
Block a user