|
|
|
@@ -2,7 +2,6 @@
|
|
|
|
|
import { useQuery } from "@tanstack/react-query";
|
|
|
|
|
import RestartIcon from "./icons/RestartIcon";
|
|
|
|
|
import Button from "./ui/Button";
|
|
|
|
|
import MultiRangeSlider from "./ui/MultiRangeSlider";
|
|
|
|
|
import { api } from "../api/ky";
|
|
|
|
|
import { RefObject, useEffect, useState } from "react";
|
|
|
|
|
import { useSearchParams } from "react-router";
|
|
|
|
@@ -16,6 +15,7 @@ import { AnimatePresence, motion } from "motion/react";
|
|
|
|
|
import CloseIcon from "./icons/CloseIcon";
|
|
|
|
|
import Project from "../types/Project";
|
|
|
|
|
import FiltersIcon from "./icons/FiltersIcon";
|
|
|
|
|
import MultiRangeSlider from "./ui/MultiRangeSlider";
|
|
|
|
|
|
|
|
|
|
function SearchFilters({
|
|
|
|
|
inModal = false,
|
|
|
|
@@ -40,16 +40,24 @@ function SearchFilters({
|
|
|
|
|
}) {
|
|
|
|
|
const [project, setProject] = useState<string>();
|
|
|
|
|
const [unitTypes, setUnitTypes] = useState<string[]>([]);
|
|
|
|
|
const [view, setView] = useState<string>("Any view");
|
|
|
|
|
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 [costInModal, setCostInModal] = useState(cost);
|
|
|
|
|
const [areaInModal, setAreaInModal] = useState(area);
|
|
|
|
|
const [floorInModal, setFloorInModal] = useState(floor);
|
|
|
|
|
|
|
|
|
|
const debouncedCost = useDebounce(inModal ? costInModal : cost, 1000);
|
|
|
|
|
const debouncedArea = useDebounce(inModal ? areaInModal : area, 1000);
|
|
|
|
|
const debouncedFloor = useDebounce(inModal ? floorInModal : floor, 1000);
|
|
|
|
|
|
|
|
|
|
const [costChanged, setCostChanged] = useState(true);
|
|
|
|
|
const [areaChanged, setAreaChanged] = useState(true);
|
|
|
|
|
const [floorChanged, setFloorChanged] = useState(true);
|
|
|
|
|
|
|
|
|
|
const debouncedCostChanged = useDebounce(costChanged, 1000);
|
|
|
|
|
const debouncedAreaChanged = useDebounce(areaChanged, 1000);
|
|
|
|
|
const debouncedFloorChanged = useDebounce(floorChanged, 1000);
|
|
|
|
|
|
|
|
|
|
const [searchParams, setSearchParams] = useSearchParams();
|
|
|
|
|
|
|
|
|
|
const { data: unitTypesInFilters } = useQuery({
|
|
|
|
@@ -57,11 +65,10 @@ function SearchFilters({
|
|
|
|
|
"filters",
|
|
|
|
|
"unitTypes",
|
|
|
|
|
project,
|
|
|
|
|
// debouncedArea,
|
|
|
|
|
// debouncedCost,
|
|
|
|
|
// debouncedFloor,
|
|
|
|
|
// view,
|
|
|
|
|
searchParams,
|
|
|
|
|
debouncedCostChanged ? debouncedCost : undefined,
|
|
|
|
|
debouncedAreaChanged ? debouncedArea : undefined,
|
|
|
|
|
debouncedFloorChanged ? debouncedFloor : undefined,
|
|
|
|
|
view,
|
|
|
|
|
],
|
|
|
|
|
enabled: !!project,
|
|
|
|
|
queryFn: () =>
|
|
|
|
@@ -71,15 +78,15 @@ function SearchFilters({
|
|
|
|
|
view !== "Any view" ? `&view=${view}` : ""
|
|
|
|
|
}${
|
|
|
|
|
debouncedCost[0] >= 0 && debouncedCost[1] >= 0
|
|
|
|
|
? `&cost=${debouncedCost.map(Math.round).join(",")}`
|
|
|
|
|
? `&cost=${debouncedCost.map(Math.round).join()}`
|
|
|
|
|
: ""
|
|
|
|
|
}${
|
|
|
|
|
debouncedFloor[0] >= 0 && debouncedFloor[1] >= 0
|
|
|
|
|
? `&floor=${debouncedFloor.map(Math.round).join(",")}`
|
|
|
|
|
? `&floor=${debouncedFloor.map(Math.round).join()}`
|
|
|
|
|
: ""
|
|
|
|
|
}${
|
|
|
|
|
debouncedArea[0] >= 0 && debouncedArea[1] >= 0
|
|
|
|
|
? `&area=${debouncedArea.map(Math.round).join(",")}`
|
|
|
|
|
? `&area=${debouncedArea.map(Math.round).join()}`
|
|
|
|
|
: ""
|
|
|
|
|
}`
|
|
|
|
|
)
|
|
|
|
@@ -91,11 +98,10 @@ function SearchFilters({
|
|
|
|
|
"filters",
|
|
|
|
|
"views",
|
|
|
|
|
project,
|
|
|
|
|
debouncedArea,
|
|
|
|
|
debouncedCost,
|
|
|
|
|
debouncedFloor,
|
|
|
|
|
debouncedCostChanged ? debouncedCost : undefined,
|
|
|
|
|
debouncedAreaChanged ? debouncedArea : undefined,
|
|
|
|
|
debouncedFloorChanged ? debouncedFloor : undefined,
|
|
|
|
|
unitTypes,
|
|
|
|
|
searchParams,
|
|
|
|
|
],
|
|
|
|
|
enabled: !!project,
|
|
|
|
|
queryFn: () =>
|
|
|
|
@@ -105,15 +111,15 @@ function SearchFilters({
|
|
|
|
|
.map((unitType) => `&unitTypes=${unitType}`)
|
|
|
|
|
.join("")}${
|
|
|
|
|
debouncedCost[0] >= 0 && debouncedCost[1] >= 0
|
|
|
|
|
? `&cost=${debouncedCost.map(Math.round).join(",")}`
|
|
|
|
|
? `&cost=${debouncedCost.map(Math.round).join()}`
|
|
|
|
|
: ""
|
|
|
|
|
}${
|
|
|
|
|
debouncedFloor[0] >= 0 && debouncedFloor[1] >= 0
|
|
|
|
|
? `&floor=${debouncedFloor.map(Math.round).join(",")}`
|
|
|
|
|
? `&floor=${debouncedFloor.map(Math.round).join()}`
|
|
|
|
|
: ""
|
|
|
|
|
}${
|
|
|
|
|
debouncedArea[0] >= 0 && debouncedArea[1] >= 0
|
|
|
|
|
? `&area=${debouncedArea.map(Math.round).join(",")}`
|
|
|
|
|
? `&area=${debouncedArea.map(Math.round).join()}`
|
|
|
|
|
: ""
|
|
|
|
|
}`
|
|
|
|
|
)
|
|
|
|
@@ -125,11 +131,10 @@ function SearchFilters({
|
|
|
|
|
"filters",
|
|
|
|
|
"cost",
|
|
|
|
|
project,
|
|
|
|
|
// debouncedArea,
|
|
|
|
|
// debouncedFloor,
|
|
|
|
|
// unitTypes,
|
|
|
|
|
// view,
|
|
|
|
|
searchParams,
|
|
|
|
|
debouncedAreaChanged ? debouncedArea : undefined,
|
|
|
|
|
debouncedFloorChanged ? debouncedFloor : undefined,
|
|
|
|
|
unitTypes,
|
|
|
|
|
view,
|
|
|
|
|
],
|
|
|
|
|
enabled: !!project,
|
|
|
|
|
queryFn: () =>
|
|
|
|
@@ -139,11 +144,11 @@ function SearchFilters({
|
|
|
|
|
.map((unitType) => `&unitTypes=${unitType}`)
|
|
|
|
|
.join("")}${view !== "Any view" ? `&view=${view}` : ""}${
|
|
|
|
|
debouncedFloor[0] >= 0 && debouncedFloor[1] >= 0
|
|
|
|
|
? `&floor=${debouncedFloor.map(Math.round).join(",")}`
|
|
|
|
|
? `&floor=${debouncedFloor.map(Math.round).join()}`
|
|
|
|
|
: ""
|
|
|
|
|
}${
|
|
|
|
|
debouncedArea[0] >= 0 && debouncedArea[1] >= 0
|
|
|
|
|
? `&area=${debouncedArea.map(Math.round).join(",")}`
|
|
|
|
|
? `&area=${debouncedArea.map(Math.round).join()}`
|
|
|
|
|
: ""
|
|
|
|
|
}`
|
|
|
|
|
)
|
|
|
|
@@ -155,11 +160,10 @@ function SearchFilters({
|
|
|
|
|
"filters",
|
|
|
|
|
"floor",
|
|
|
|
|
project,
|
|
|
|
|
// debouncedArea,
|
|
|
|
|
// debouncedCost,
|
|
|
|
|
// unitTypes,
|
|
|
|
|
// view,
|
|
|
|
|
searchParams,
|
|
|
|
|
debouncedCostChanged ? debouncedCost : undefined,
|
|
|
|
|
debouncedAreaChanged ? debouncedArea : undefined,
|
|
|
|
|
unitTypes,
|
|
|
|
|
view,
|
|
|
|
|
],
|
|
|
|
|
enabled: !!project,
|
|
|
|
|
queryFn: () =>
|
|
|
|
@@ -169,11 +173,11 @@ function SearchFilters({
|
|
|
|
|
.map((unitType) => `&unitTypes=${unitType}`)
|
|
|
|
|
.join("")}${view !== "Any view" ? `&view=${view}` : ""}${
|
|
|
|
|
debouncedCost[0] >= 0 && debouncedCost[1] >= 0
|
|
|
|
|
? `&cost=${debouncedCost.map(Math.round).join(",")}`
|
|
|
|
|
? `&cost=${debouncedCost.map(Math.round).join()}`
|
|
|
|
|
: ""
|
|
|
|
|
}${
|
|
|
|
|
debouncedArea[0] >= 0 && debouncedArea[1] >= 0
|
|
|
|
|
? `&area=${debouncedArea.map(Math.round).join(",")}`
|
|
|
|
|
? `&area=${debouncedArea.map(Math.round).join()}`
|
|
|
|
|
: ""
|
|
|
|
|
}`
|
|
|
|
|
)
|
|
|
|
@@ -185,11 +189,10 @@ function SearchFilters({
|
|
|
|
|
"filters",
|
|
|
|
|
"area",
|
|
|
|
|
project,
|
|
|
|
|
// debouncedCost,
|
|
|
|
|
// debouncedFloor,
|
|
|
|
|
// unitTypes,
|
|
|
|
|
// view,
|
|
|
|
|
searchParams,
|
|
|
|
|
debouncedCostChanged ? debouncedCost : undefined,
|
|
|
|
|
debouncedFloorChanged ? debouncedFloor : undefined,
|
|
|
|
|
unitTypes,
|
|
|
|
|
view,
|
|
|
|
|
],
|
|
|
|
|
enabled: !!project,
|
|
|
|
|
queryFn: () =>
|
|
|
|
@@ -199,11 +202,11 @@ function SearchFilters({
|
|
|
|
|
.map((unitType) => `&unitTypes=${unitType}`)
|
|
|
|
|
.join("")}${view !== "Any view" ? `&view=${view}` : ""}${
|
|
|
|
|
debouncedCost[0] >= 0 && debouncedCost[1] >= 0
|
|
|
|
|
? `&cost=${debouncedCost.map(Math.round).join(",")}`
|
|
|
|
|
? `&cost=${debouncedCost.map(Math.round).join()}`
|
|
|
|
|
: ""
|
|
|
|
|
}${
|
|
|
|
|
debouncedFloor[0] >= 0 && debouncedFloor[1] >= 0
|
|
|
|
|
? `&floor=${debouncedFloor.map(Math.round).join(",")}`
|
|
|
|
|
? `&floor=${debouncedFloor.map(Math.round).join()}`
|
|
|
|
|
: ""
|
|
|
|
|
}`
|
|
|
|
|
)
|
|
|
|
@@ -226,26 +229,55 @@ function SearchFilters({
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (costInFilters && areaInFilters && floorInFilters) {
|
|
|
|
|
setCostInModal([costInFilters.min, costInFilters.max]);
|
|
|
|
|
if (areaInFilters) {
|
|
|
|
|
setAreaInModal([areaInFilters.min, areaInFilters.max]);
|
|
|
|
|
setFloorInModal([floorInFilters.min, floorInFilters.max]);
|
|
|
|
|
setAreaChanged(false);
|
|
|
|
|
}
|
|
|
|
|
}, [
|
|
|
|
|
costInFilters,
|
|
|
|
|
areaInFilters,
|
|
|
|
|
floorInFilters,
|
|
|
|
|
setAreaInModal,
|
|
|
|
|
setCostInModal,
|
|
|
|
|
setFloorInModal,
|
|
|
|
|
]);
|
|
|
|
|
}, [areaInFilters]);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (costInFilters) {
|
|
|
|
|
setCostInModal([costInFilters.min, costInFilters.max]);
|
|
|
|
|
return () => setCostChanged(false);
|
|
|
|
|
}
|
|
|
|
|
}, [costInFilters]);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (floorInFilters) {
|
|
|
|
|
setFloorInModal([floorInFilters.min, floorInFilters.max]);
|
|
|
|
|
setFloorChanged(false);
|
|
|
|
|
}
|
|
|
|
|
}, [floorInFilters]);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (inModal) return;
|
|
|
|
|
setCost(costInModal);
|
|
|
|
|
}, [costInModal, inModal]);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (inModal) return;
|
|
|
|
|
setArea(areaInModal);
|
|
|
|
|
}, [areaInModal, inModal]);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (inModal) return;
|
|
|
|
|
setFloor(floorInModal);
|
|
|
|
|
}, [setCost, costInModal, setArea, areaInModal, setFloor, floorInModal]);
|
|
|
|
|
}, [floorInModal, inModal]);
|
|
|
|
|
|
|
|
|
|
function handleCostChange([min, max]: [number, number]) {
|
|
|
|
|
setCostInModal([min, max]);
|
|
|
|
|
setCostChanged(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleFloorChange([min, max]: [number, number]) {
|
|
|
|
|
setFloorInModal([min, max]);
|
|
|
|
|
setFloorChanged(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleAreaChange([min, max]: [number, number]) {
|
|
|
|
|
setAreaInModal([min, max]);
|
|
|
|
|
setAreaChanged(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const { data: count } = useQuery({
|
|
|
|
|
queryKey: [
|
|
|
|
@@ -272,22 +304,12 @@ function SearchFilters({
|
|
|
|
|
`units/count?${project ? `project=${project}` : ""}${unitTypes
|
|
|
|
|
.map((unitType) => `&unitTypes=${unitType}`)
|
|
|
|
|
.join("")}${view !== "Any view" ? `&view=${view}` : ""}${
|
|
|
|
|
debouncedCost
|
|
|
|
|
? `&cost=${Math.round(debouncedCost[0])},${Math.round(
|
|
|
|
|
debouncedCost[1]
|
|
|
|
|
)}`
|
|
|
|
|
: ""
|
|
|
|
|
debouncedCost ? `&cost=${debouncedCost.map(Math.round).join()}` : ""
|
|
|
|
|
}${
|
|
|
|
|
debouncedArea
|
|
|
|
|
? `&area=${Math.round(debouncedArea[0])},${Math.round(
|
|
|
|
|
debouncedArea[1]
|
|
|
|
|
)}`
|
|
|
|
|
: ""
|
|
|
|
|
debouncedArea ? `&area=${debouncedArea.map(Math.round).join()}` : ""
|
|
|
|
|
}${
|
|
|
|
|
debouncedFloor
|
|
|
|
|
? `&floor=${Math.round(debouncedFloor[0])},${Math.round(
|
|
|
|
|
debouncedFloor[1]
|
|
|
|
|
)}`
|
|
|
|
|
? `&floor=${debouncedFloor.map(Math.round).join()}`
|
|
|
|
|
: ""
|
|
|
|
|
}`
|
|
|
|
|
)
|
|
|
|
@@ -315,16 +337,6 @@ function SearchFilters({
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleSelectView(view: string) {
|
|
|
|
|
setView(view);
|
|
|
|
|
if (!inModal)
|
|
|
|
|
setSearchParams((prev) => {
|
|
|
|
|
if (view !== "Any view") prev.set("view", view);
|
|
|
|
|
else prev.delete("view");
|
|
|
|
|
return prev;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleSelectUnitTypes(unitTypes: string[]) {
|
|
|
|
|
setUnitTypes(unitTypes);
|
|
|
|
|
if (!inModal)
|
|
|
|
@@ -335,6 +347,16 @@ function SearchFilters({
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleSelectView(view: string) {
|
|
|
|
|
setView(view);
|
|
|
|
|
if (!inModal)
|
|
|
|
|
setSearchParams((prev) => {
|
|
|
|
|
if (view !== "Any view") prev.set("view", view);
|
|
|
|
|
else prev.delete("view");
|
|
|
|
|
return prev;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function applyFilters() {
|
|
|
|
|
setInModal(false);
|
|
|
|
|
setSearchParams((prev) => {
|
|
|
|
@@ -351,8 +373,6 @@ function SearchFilters({
|
|
|
|
|
window.scroll({ top: 0, behavior: "smooth" });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
useEffect(() => {}, []);
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
{inModal && (
|
|
|
|
@@ -435,7 +455,7 @@ function SearchFilters({
|
|
|
|
|
currentMin={inModal ? costInModal[0] : cost[0]}
|
|
|
|
|
currentMax={inModal ? costInModal[1] : cost[1]}
|
|
|
|
|
offset={1}
|
|
|
|
|
onChange={setCostInModal}
|
|
|
|
|
onChange={handleCostChange}
|
|
|
|
|
label="Cost, AED"
|
|
|
|
|
/>
|
|
|
|
|
<MultiRangeSlider
|
|
|
|
@@ -443,7 +463,7 @@ function SearchFilters({
|
|
|
|
|
currentMin={inModal ? floorInModal[0] : floor[0]}
|
|
|
|
|
currentMax={inModal ? floorInModal[1] : floor[1]}
|
|
|
|
|
offset={1}
|
|
|
|
|
onChange={setFloorInModal}
|
|
|
|
|
onChange={handleFloorChange}
|
|
|
|
|
label="Floor"
|
|
|
|
|
/>
|
|
|
|
|
<MultiRangeSlider
|
|
|
|
@@ -451,7 +471,7 @@ function SearchFilters({
|
|
|
|
|
currentMin={inModal ? areaInModal[0] : area[0]}
|
|
|
|
|
currentMax={inModal ? areaInModal[1] : area[1]}
|
|
|
|
|
offset={1}
|
|
|
|
|
onChange={setAreaInModal}
|
|
|
|
|
onChange={handleAreaChange}
|
|
|
|
|
label="Total Area, Sqft"
|
|
|
|
|
/>
|
|
|
|
|
<Select
|
|
|
|
|