Skip to content

Commit

Permalink
Merge pull request #81 from isd-sgcu/pun/feat/implement-filter
Browse files Browse the repository at this point in the history
feat: filter for homepage and search ( for both /pets, admin/pets, and homepage)
  • Loading branch information
punchanabu authored Feb 25, 2024
2 parents 7939788 + 56d8692 commit abbb754
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 29 deletions.
3 changes: 2 additions & 1 deletion src/app/admin/pets/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const Pets = () => {
}, []);

const [filters, setFilters] = useState<filterState>({
search: "",
dog: false,
cat: false,
male: false,
Expand Down Expand Up @@ -51,7 +52,7 @@ const Pets = () => {
</Container>
<Container className="flex flex-col items-center space-y-6">
<div className="flex w-full flex-row gap-x-4">
<PetSearch variant="red" />
<PetSearch variant="red" filter={filters} setFilters={setFilters} />
<div className="relative">
<PetIcon
isOpen={isOpenFilterPanel}
Expand Down
29 changes: 21 additions & 8 deletions src/app/home/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,35 @@ import Button from "@/components/Button";
import Container from "@/components/Container";
import Divider from "@/components/Divider";
import Banner from "@/components/Main/Banner";
import PetList from "@/components/Main/CardList/PetList";
import PetSuggestionList from "@/components/Main/CardList/PetSuggestionList";
import Filter from "@/components/Main/Filter";
import Heading from "@/components/Pets/Heading";
import Search from "@/components/Search/PetSearch";
import { usePetsQuery } from "@/hooks/queries/usePetsQuery";
import MainLayout from "@/layouts/MainLayout";
import { filterState } from "@/types/filter";
import { useState } from "react";
import { useNavigate } from "react-router-dom";

import PetList from "@/components/Main/CardList/PetList";
import PetSuggestionList from "@/components/Main/CardList/PetSuggestionList";

// Page
const MainPage = () => {
const navigate = useNavigate();

const { data, isLoading } = usePetsQuery();

const [filters, setFilters] = useState<filterState>({
search: "",
dog: false,
cat: false,
male: false,
female: false,
white: false,
black: false,
brown: false,
blonde: false,
minAge: 0,
maxAge: 30,
});
const { data, isLoading } = usePetsQuery(filters);
return (
<>
<Container className="grid grid-cols-1 items-center md:grid-cols-2 md:gap-9 lg:grid-cols-3">
Expand All @@ -31,8 +44,8 @@ const MainPage = () => {
<div className="hidden md:flex">
<Heading onSearch quantity={data?.metadata.total} />
</div>
<Search variant="green" />
<Filter />
<Search variant="green" filter={filters} setFilters={setFilters} />
<Filter filters={filters} setFilters={setFilters} />
</div>
</Container>
<Container className="flex items-center justify-center md:hidden">
Expand All @@ -51,7 +64,7 @@ const MainPage = () => {
<div className="col-span-2">
<PetSuggestionList
isLoading={isLoading}
data={data?.pets.slice(0, 8)}
data={data?.pets?.slice(0, 8)}
/>
</div>
</div>
Expand Down
3 changes: 2 additions & 1 deletion src/app/pets/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const Pets = () => {
}, []);

const [filters, setFilters] = useState<filterState>({
search: "",
dog: false,
cat: false,
male: false,
Expand All @@ -41,7 +42,7 @@ const Pets = () => {
<Heading onSearch quantity={data?.metadata.total} />
</Container>
<Container className="flex flex-row gap-x-4">
<PetSearch variant="red" />
<PetSearch variant="red" filter={filters} setFilters={setFilters} />
<div className="relative">
<PetIcon
isOpen={isOpenFilterPanel}
Expand Down
57 changes: 40 additions & 17 deletions src/components/Main/Filter.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,66 @@
import Button from "@/components/Button";
import { useState } from "react";
import { filterState } from "@/types/filter";

const Filter = () => {
// There are 3 states for filtering in home search (all, dog, cat)
const [filter, setFilter] = useState<string>("all");
interface FilterProps {
filters: filterState;
setFilters: (filters: filterState) => void;
}

const Filter: React.FC<FilterProps> = ({
filters,
setFilters,
}: FilterProps) => {
const allSelected = filters.dog && filters.cat;
const catSelected = filters.cat && !filters.dog;
const dogSelected = filters.dog && !filters.cat;

return (
<div className="flex space-x-3">
<Button
text={"สัตว์เลี้ยงทั้งหมด"}
variant={filter === "all" ? "primary" : "white"}
variant={allSelected ? "primary" : "white"}
className={`flex items-center justify-center py-3 shadow transition-all duration-500
${
filter === "all"
allSelected
? "flex-row bg-primary px-6 text-white"
: "flex-col bg-white px-2.5 text-xs text-accent-gray"
} shrink-0`}
rounded="2xl"
onClick={() => setFilter("all")}
onClick={() =>
setFilters({
...filters,
dog: !allSelected,
cat: !allSelected,
})
}
/>
<Button
text={filter == "cat" ? "แมว" : ""}
variant={filter === "cat" ? "primary" : "white"}
icon={filter === "cat" ? "custom:md:cat-green" : "custom:md:cat-gray"}
text={catSelected ? "แมว" : ""}
variant={catSelected ? "primary" : "white"}
icon={catSelected ? "custom:md:cat-green" : "custom:md:cat-gray"}
className={`flex items-center justify-center space-x-2.5 py-3 shadow transition-all duration-500
${filter === "cat" ? "bg-primary px-12" : "bg-white pl-6 pr-4"}
${catSelected ? "bg-primary px-12" : "bg-white pl-6 pr-4"}
`}
rounded="2xl"
onClick={() => setFilter("cat")}
onClick={() =>
setFilters({
...filters,
dog: false,
cat: !catSelected,
})
}
/>
<Button
text={filter == "dog" ? "สุนัข" : ""}
variant={filter === "dog" ? "primary" : "white"}
icon={filter === "dog" ? "custom:md:dog-white" : "custom:md:dog-gray"}
text={dogSelected ? "สุนัข" : ""}
variant={dogSelected ? "primary" : "white"}
icon={dogSelected ? "custom:md:dog-white" : "custom:md:dog-gray"}
className={`flex items-center justify-center space-x-2.5 py-3 shadow transition-all duration-500
${filter === "dog" ? "bg-primary px-12" : "bg-white pl-6 pr-4"}
${dogSelected ? "bg-primary px-12" : "bg-white pl-6 pr-4"}
`}
rounded="2xl"
onClick={() => setFilter("dog")}
onClick={() =>
setFilters({ ...filters, dog: !dogSelected, cat: false })
}
/>
</div>
);
Expand Down
25 changes: 23 additions & 2 deletions src/components/Search/PetSearch.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,33 @@
import { filterState } from "@/types/filter";
import { Icon } from "@iconify/react";
import React from "react";
import React, { useEffect } from "react";
/*
for pets page use : @custom:md:bubble-red
for home page use: @custom:md:bubble-green
*/
interface PetSearchProps {
variant: "red" | "green";
filter: filterState;
setFilters: React.Dispatch<React.SetStateAction<filterState>>;
}

const PetSearch: React.FC<PetSearchProps> = ({ variant }) => {
const PetSearch: React.FC<PetSearchProps> = ({
variant,
filter,
setFilters,
}) => {
const [inputValue, setInputValue] = React.useState<string>(
filter.search || ""
);

// add debouce time for delay
useEffect(() => {
const delayDebounce = setTimeout(() => {
setFilters({ ...filter, search: inputValue });
}, 500);
return () => clearTimeout(delayDebounce);
}, [inputValue, setFilters, filter]);

return (
<div className="flex w-full flex-row items-center justify-start gap-3 rounded-full bg-white px-6 py-3 shadow">
<div>
Expand All @@ -18,6 +37,8 @@ const PetSearch: React.FC<PetSearchProps> = ({ variant }) => {
type="text"
placeholder="ค้นหาสัตว์เลี้ยง"
className="w-full py-0 outline-none"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
</div>
);
Expand Down
1 change: 1 addition & 0 deletions src/types/filter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
interface filterState {
search: string;
dog: boolean;
cat: boolean;
male: boolean;
Expand Down
4 changes: 4 additions & 0 deletions src/utils/convertFiltertoParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ const convertFiltertoParams = (filters?: filterState) => {
}
const params: Record<string, string | number> = {};

if (filters.search) {
params.search = filters.search;
}

if (filters.dog && filters.cat) {
// skip
} else if (filters.dog) {
Expand Down

0 comments on commit abbb754

Please sign in to comment.