diff --git a/src/components/SearchFilters.tsx b/src/components/SearchFilters.tsx index c1153f5..74fe228 100644 --- a/src/components/SearchFilters.tsx +++ b/src/components/SearchFilters.tsx @@ -17,14 +17,6 @@ import CloseIcon from "./icons/CloseIcon"; import Project from "../types/Project"; import FiltersIcon from "./icons/FiltersIcon"; -export interface Filters { - unitTypes: string[]; - views: string[]; - area: [number, number]; - cost: [number, number]; - floor: [number, number]; -} - function SearchFilters({ inModal = false, setInModal, @@ -50,15 +42,172 @@ function SearchFilters({ const [unitTypes, setUnitTypes] = useState([]); const [view, setView] = useState("Any view"); + const [costInModal, setCostInModal] = useState<[number, number]>(cost); + const [areaInModal, setAreaInModal] = useState<[number, number]>(area); + const [floorInModal, setFloorInModal] = useState<[number, number]>(floor); + + const debouncedCost = useDebounce(inModal ? costInModal : cost, 1000); + const debouncedArea = useDebounce(inModal ? areaInModal : area, 1000); + const debouncedFloor = useDebounce(inModal ? floorInModal : floor, 1000); + const [searchParams, setSearchParams] = useSearchParams(); - const { data: filters } = useQuery({ - queryKey: ["filters", project], + const { data: unitTypesInFilters } = useQuery({ + queryKey: [ + "filters", + "unitTypes", + project, + // debouncedArea, + // debouncedCost, + // debouncedFloor, + // view, + searchParams, + ], enabled: !!project, queryFn: () => api - .get(`units/filters?${project ? `project=${project}` : ""}`) - .json(), + .get( + `units/filters/unitTypes?${project ? `project=${project}` : ""}${ + view !== "Any view" ? `&view=${view}` : "" + }${ + debouncedCost[0] >= 0 && debouncedCost[1] >= 0 + ? `&cost=${debouncedCost.map(Math.round).join(",")}` + : "" + }${ + debouncedFloor[0] >= 0 && debouncedFloor[1] >= 0 + ? `&floor=${debouncedFloor.map(Math.round).join(",")}` + : "" + }${ + debouncedArea[0] >= 0 && debouncedArea[1] >= 0 + ? `&area=${debouncedArea.map(Math.round).join(",")}` + : "" + }` + ) + .json(), + }); + + const { data: viewsInFilters } = useQuery({ + queryKey: [ + "filters", + "views", + project, + debouncedArea, + debouncedCost, + debouncedFloor, + unitTypes, + searchParams, + ], + enabled: !!project, + queryFn: () => + api + .get( + `units/filters/views?${project ? `project=${project}` : ""}${unitTypes + .map((unitType) => `&unitTypes=${unitType}`) + .join("")}${ + debouncedCost[0] >= 0 && debouncedCost[1] >= 0 + ? `&cost=${debouncedCost.map(Math.round).join(",")}` + : "" + }${ + debouncedFloor[0] >= 0 && debouncedFloor[1] >= 0 + ? `&floor=${debouncedFloor.map(Math.round).join(",")}` + : "" + }${ + debouncedArea[0] >= 0 && debouncedArea[1] >= 0 + ? `&area=${debouncedArea.map(Math.round).join(",")}` + : "" + }` + ) + .json(), + }); + + const { data: costInFilters } = useQuery({ + queryKey: [ + "filters", + "cost", + project, + // debouncedArea, + // debouncedFloor, + // unitTypes, + // view, + searchParams, + ], + enabled: !!project, + queryFn: () => + api + .get( + `units/filters/cost?${project ? `project=${project}` : ""}${unitTypes + .map((unitType) => `&unitTypes=${unitType}`) + .join("")}${view !== "Any view" ? `&view=${view}` : ""}${ + debouncedFloor[0] >= 0 && debouncedFloor[1] >= 0 + ? `&floor=${debouncedFloor.map(Math.round).join(",")}` + : "" + }${ + debouncedArea[0] >= 0 && debouncedArea[1] >= 0 + ? `&area=${debouncedArea.map(Math.round).join(",")}` + : "" + }` + ) + .json<{ min: number; max: number }>(), + }); + + const { data: floorInFilters } = useQuery({ + queryKey: [ + "filters", + "floor", + project, + // debouncedArea, + // debouncedCost, + // unitTypes, + // view, + searchParams, + ], + enabled: !!project, + queryFn: () => + api + .get( + `units/filters/floor?${project ? `project=${project}` : ""}${unitTypes + .map((unitType) => `&unitTypes=${unitType}`) + .join("")}${view !== "Any view" ? `&view=${view}` : ""}${ + debouncedCost[0] >= 0 && debouncedCost[1] >= 0 + ? `&cost=${debouncedCost.map(Math.round).join(",")}` + : "" + }${ + debouncedArea[0] >= 0 && debouncedArea[1] >= 0 + ? `&area=${debouncedArea.map(Math.round).join(",")}` + : "" + }` + ) + .json<{ min: number; max: number }>(), + }); + + const { data: areaInFilters } = useQuery({ + queryKey: [ + "filters", + "area", + project, + // debouncedCost, + // debouncedFloor, + // unitTypes, + // view, + searchParams, + ], + enabled: !!project, + queryFn: () => + api + .get( + `units/filters/area?${project ? `project=${project}` : ""}${unitTypes + .map((unitType) => `&unitTypes=${unitType}`) + .join("")}${view !== "Any view" ? `&view=${view}` : ""}${ + debouncedCost[0] >= 0 && debouncedCost[1] >= 0 + ? `&cost=${debouncedCost.map(Math.round).join(",")}` + : "" + }${ + debouncedFloor[0] >= 0 && debouncedFloor[1] >= 0 + ? `&floor=${debouncedFloor.map(Math.round).join(",")}` + : "" + }` + ) + .json<{ min: number; max: number }>(), }); useEffect(() => { @@ -76,17 +225,20 @@ function SearchFilters({ window.location.href = "/search"; } - const [costInModal, setCostInModal] = useState<[number, number]>(cost); - const [areaInModal, setAreaInModal] = useState<[number, number]>(area); - const [floorInModal, setFloorInModal] = useState<[number, number]>(floor); - useEffect(() => { - if (filters) { - setCostInModal(filters.cost); - setAreaInModal(filters.area); - setFloorInModal(filters.floor); + if (costInFilters && areaInFilters && floorInFilters) { + setCostInModal([costInFilters.min, costInFilters.max]); + setAreaInModal([areaInFilters.min, areaInFilters.max]); + setFloorInModal([floorInFilters.min, floorInFilters.max]); } - }, [filters, setAreaInModal, setCostInModal, setFloorInModal]); + }, [ + costInFilters, + areaInFilters, + floorInFilters, + setAreaInModal, + setCostInModal, + setFloorInModal, + ]); useEffect(() => { if (inModal) return; @@ -95,10 +247,6 @@ function SearchFilters({ setFloor(floorInModal); }, [setCost, costInModal, setArea, areaInModal, setFloor, floorInModal]); - const debouncedCost = useDebounce(inModal ? costInModal : cost, 500); - const debouncedArea = useDebounce(inModal ? areaInModal : area, 500); - const debouncedFloor = useDebounce(inModal ? floorInModal : floor, 500); - const { data: count } = useQuery({ queryKey: [ "units", @@ -203,6 +351,8 @@ function SearchFilters({ window.scroll({ top: 0, behavior: "smooth" }); } + useEffect(() => {}, []); + return ( <> {inModal && ( @@ -230,164 +380,168 @@ function SearchFilters({ )} -
-
-

- {inModal ? "Filters" : "Search"} -

-
- {project && ( - title === project)! - } - /> - )} -
-
-
-
- {filters && ( - <> -
-

Apartment type

- -
-
- - - - +
+
+ {inModal ? ( + + ) : ( + + {count && ( + + {count} Apartments found + + )} + + )} + + +
+ + + )} ); diff --git a/src/components/SelectedComplexCard.tsx b/src/components/SelectedComplexCard.tsx index 410a7c2..4c0ec46 100644 --- a/src/components/SelectedComplexCard.tsx +++ b/src/components/SelectedComplexCard.tsx @@ -45,7 +45,7 @@ export default function SelectedComplexCard({ marker }: { marker: IMarker }) {
-

+

Rove Home
{marker.title} diff --git a/src/components/modals/DisclaimerModal.tsx b/src/components/modals/DisclaimerModal.tsx index 65dbcb1..0857e74 100644 --- a/src/components/modals/DisclaimerModal.tsx +++ b/src/components/modals/DisclaimerModal.tsx @@ -1,7 +1,7 @@ export default function DisclaimerModal() { return (

-

+

Disclaimer

diff --git a/src/components/modals/PrivacyPolicyModal.tsx b/src/components/modals/PrivacyPolicyModal.tsx index ca9ed3f..b42bbfb 100644 --- a/src/components/modals/PrivacyPolicyModal.tsx +++ b/src/components/modals/PrivacyPolicyModal.tsx @@ -2,7 +2,7 @@ function PrivacyPolicyModal() { return (
-

+

Privacy Policy for IRTH Group and its companies:

diff --git a/src/pages/SearchPage.tsx b/src/pages/SearchPage.tsx index 5cbcf40..fb139d8 100644 --- a/src/pages/SearchPage.tsx +++ b/src/pages/SearchPage.tsx @@ -1,23 +1,23 @@ -import { useInfiniteQuery, useQueryClient } from '@tanstack/react-query'; -import { api } from '../api/ky'; -import { IUnit } from '../types/IUnit'; -import UnitCard from '../components/UnitCard'; -import { useEffect, useRef, useState } from 'react'; -import SearchFilters, { Filters } from '../components/SearchFilters'; -import { useSearchParams } from 'react-router'; -import Button from '../components/ui/Button'; -import FiltersIcon from '../components/icons/FiltersIcon'; -import RestartIcon from '../components/icons/RestartIcon'; -import clsx from 'clsx'; -import { AnimatePresence, motion } from 'motion/react'; -import { useDebounce } from '../hooks/useDebounce'; -import Select from '../components/ui/Select'; +import { useInfiniteQuery } from "@tanstack/react-query"; +import { api } from "../api/ky"; +import { IUnit } from "../types/IUnit"; +import UnitCard from "../components/UnitCard"; +import { useEffect, useRef, useState } from "react"; +import SearchFilters from "../components/SearchFilters"; +import { useSearchParams } from "react-router"; +import Button from "../components/ui/Button"; +import FiltersIcon from "../components/icons/FiltersIcon"; +import RestartIcon from "../components/icons/RestartIcon"; +import clsx from "clsx"; +import { AnimatePresence, motion } from "motion/react"; +import { useDebounce } from "../hooks/useDebounce"; +import Select from "../components/ui/Select"; const SORT_OPTIONS = { - 'Sort by ascending price': 'cost asc', - 'Sort by descending price': 'cost desc', - 'Sort by ascending area': 'sqft asc', - 'Sort by descending area': 'sqft desc', + "Sort by ascending price": "cost asc", + "Sort by descending price": "cost desc", + "Sort by ascending area": "sqft asc", + "Sort by descending area": "sqft desc", }; const STEP = 12; @@ -25,9 +25,9 @@ const STEP = 12; function SearchPage() { const [searchParams] = useSearchParams(); - const project = searchParams.get('project'); - const unitTypes = searchParams.getAll('unitTypes'); - const view = searchParams.get('view'); + const project = searchParams.get("project"); + const unitTypes = searchParams.getAll("unitTypes"); + const view = searchParams.get("view"); const [filtersInModal, setFiltersInModal] = useState(false); @@ -35,19 +35,19 @@ function SearchPage() { const [floor, setFloor] = useState<[number, number]>([-1, -1]); const [area, setArea] = useState<[number, number]>([-1, -1]); - const debouncedCost = useDebounce(cost, 500); - const debouncedFloor = useDebounce(floor, 500); - const debouncedArea = useDebounce(area, 500); + const debouncedCost = useDebounce(cost, 1000); + const debouncedFloor = useDebounce(floor, 1000); + const debouncedArea = useDebounce(area, 1000); const [sort, setSort] = useState( - 'Sort by ascending price' + "Sort by ascending price" ); const { data, fetchNextPage, hasNextPage, isFetchingNextPage } = useInfiniteQuery({ initialPageParam: 0, queryKey: [ - 'units', + "units", project, unitTypes, view, @@ -68,22 +68,22 @@ function SearchPage() { await api .get( `units?offset=${pageParam}&limit=${STEP}${ - project ? `&project=${project}` : '' - }${unitTypes.map((unitType) => `&unitTypes=${unitType}`).join('')}${ - view ? `&view=${view}` : '' + project ? `&project=${project}` : "" + }${unitTypes.map((unitType) => `&unitTypes=${unitType}`).join("")}${ + view ? `&view=${view}` : "" }${ debouncedCost.length > 0 - ? `&cost=${debouncedCost.map(Math.round).join(',')}` - : '' + ? `&cost=${debouncedCost.map(Math.round).join(",")}` + : "" }${ debouncedFloor.length > 0 - ? `&floor=${debouncedFloor.map(Math.round).join(',')}` - : '' + ? `&floor=${debouncedFloor.map(Math.round).join(",")}` + : "" }${ debouncedArea.length > 0 - ? `&area=${debouncedArea.map(Math.round).join(',')}` - : '' - }${sort ? `&order=${SORT_OPTIONS[sort].split(' ').join(',')}` : ''}` + ? `&area=${debouncedArea.map(Math.round).join(",")}` + : "" + }${sort ? `&order=${SORT_OPTIONS[sort].split(" ").join(",")}` : ""}` ) .json(), getNextPageParam: (lastPage, _, lastPageIndex) => @@ -100,7 +100,7 @@ function SearchPage() { (entries) => { if (entries[0].isIntersecting) fetchNextPage(); }, - { rootMargin: '-200px' } + { rootMargin: "-200px" } ); if (observerElement) observer.observe(observerElement); @@ -126,7 +126,7 @@ function SearchPage() { const [footerReached, setFooterReached] = useState(false); useEffect(() => { - const footer = document.querySelector('footer'); + const footer = document.querySelector("footer"); const observer = new IntersectionObserver((entries) => setFooterReached(entries[0].isIntersecting) ); @@ -137,36 +137,36 @@ function SearchPage() { }; }, []); - const [activeFiltersCount, setActiveFiltersCount] = useState(0); + // const [activeFiltersCount, setActiveFiltersCount] = useState(0); - const queryClient = useQueryClient(); + // const queryClient = useQueryClient(); - useEffect(() => { - const filters = queryClient.getQueryData(['filters', project]); - if (filters) { - setActiveFiltersCount( - +!!view + - +!!unitTypes.length + - +(debouncedCost[0] !== filters.cost[0]) + - +(debouncedCost[1] !== filters.cost[1]) + - +(debouncedArea[0] !== filters.area[0]) + - +(debouncedArea[1] !== filters.area[1]) + - +(debouncedFloor[0] !== filters.floor[0]) + - +(debouncedFloor[1] !== filters.floor[1]) - ); - } - }, [ - queryClient, - unitTypes, - view, - project, - debouncedCost, - cost, - debouncedArea, - area, - debouncedFloor, - floor, - ]); + // useEffect(() => { + // const filters = queryClient.getQueryData(["filters", project]); + // if (filters) { + // setActiveFiltersCount( + // +!!view + + // +!!unitTypes.length + + // +(debouncedCost[0] !== filters.minCost) + + // +(debouncedCost[1] !== filters.maxCost) + + // +(debouncedArea[0] !== filters.minArea) + + // +(debouncedArea[1] !== filters.maxArea) + + // +(debouncedFloor[0] !== filters.minFloor) + + // +(debouncedFloor[1] !== filters.maxFloor) + // ); + // } + // }, [ + // queryClient, + // unitTypes, + // view, + // project, + // debouncedCost, + // cost, + // debouncedArea, + // area, + // debouncedFloor, + // floor, + // ]); return ( <> @@ -176,15 +176,15 @@ function SearchPage() { setInModal={setFiltersInModal} {...{ area, cost, floor, setArea, setCost, setFloor }} /> -
+