filters
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
"@react-three/drei": "^9.105.6",
|
||||
"@react-three/fiber": "^8.16.6",
|
||||
"@types/react-router-dom": "^5.3.3",
|
||||
"@uidotdev/usehooks": "^2.4.1",
|
||||
"gsap": "^3.12.5",
|
||||
"ky": "^1.3.0",
|
||||
"react": "^18.2.0",
|
||||
|
||||
@@ -1,11 +1,56 @@
|
||||
import { apartmentsApi } from "./urls";
|
||||
import ky from "ky";
|
||||
|
||||
async function getApartments(token: string | null) {
|
||||
// const token =
|
||||
// "1000.04c54423a172cff4f2075ef60dc46403.b4a66d1663ed3b39fa86c9b28dbed2fa";
|
||||
async function getApartments(
|
||||
token: string | null,
|
||||
roveHomeFilters: string[],
|
||||
apartmentTypeFilters: string[],
|
||||
viewFilters: string[],
|
||||
totalAreaFilter: number[],
|
||||
floorFilter: number[],
|
||||
sortBy: string | undefined,
|
||||
page: number,
|
||||
perPage: number
|
||||
) {
|
||||
const roveHomeQuery =
|
||||
roveHomeFilters.length !== 0
|
||||
? `rove_home=${roveHomeFilters.join(",")}`
|
||||
: "";
|
||||
const apartmentQuery =
|
||||
apartmentTypeFilters.length !== 0
|
||||
? `apartment_type=${apartmentTypeFilters.join(",")}`
|
||||
: "";
|
||||
const viewQuery =
|
||||
viewFilters.length !== 0 ? `views=${viewFilters.join(",")}` : "";
|
||||
const totalAreaSliderQuery =
|
||||
totalAreaFilter.length !== 0
|
||||
? `total_area_between=${totalAreaFilter[0]},${totalAreaFilter[1]}`
|
||||
: "";
|
||||
const floorQuery =
|
||||
floorFilter.length !== 0
|
||||
? `floor_between=${floorFilter[0]},${floorFilter[1]}`
|
||||
: "";
|
||||
|
||||
const res = await ky.get(apartmentsApi, {
|
||||
const sortByQuery = sortBy ? `sort_by=${sortBy}` : "";
|
||||
|
||||
const pageQuery = `page=${page}`;
|
||||
const perPageQuery = `per_page=${perPage}`;
|
||||
|
||||
const query = [
|
||||
apartmentQuery,
|
||||
roveHomeQuery,
|
||||
totalAreaSliderQuery,
|
||||
floorQuery,
|
||||
viewQuery,
|
||||
sortByQuery,
|
||||
pageQuery,
|
||||
perPageQuery,
|
||||
]
|
||||
.filter((q) => q.length !== 0)
|
||||
.join("&");
|
||||
|
||||
const url = `${apartmentsApi}?${query}`;
|
||||
const res = await ky.get(url, {
|
||||
headers: {
|
||||
Authorization: `Zoho-oauthtoken ${token}`,
|
||||
},
|
||||
|
||||
@@ -6,10 +6,11 @@ async function updateAccessToken() {
|
||||
try {
|
||||
const res = await ky.get(updateAccessTokenApi);
|
||||
|
||||
res.json().then((data) => {
|
||||
return res.json().then((data) => {
|
||||
const accessToken = (data as IUpdateAccessToken).accessToken;
|
||||
|
||||
localStorage.setItem("ACCESS_TOKEN", accessToken);
|
||||
return accessToken;
|
||||
});
|
||||
} catch (error) {
|
||||
console.log("error", error);
|
||||
|
||||
@@ -10,12 +10,12 @@ import Switch from "../../Switch";
|
||||
import ResetIcon from "../../icons/ResetIcon";
|
||||
import { useSwipeable } from "react-swipeable";
|
||||
import {
|
||||
initialApartmentTypeCheckboxes,
|
||||
initialRoveHomeCheckboxes,
|
||||
initialAparmentTypeCheckboxes,
|
||||
initialSliders,
|
||||
initialSwitchers,
|
||||
} from "../../../consts/initialSearchFilters";
|
||||
import { initialViewCheckboxes } from "../../../consts/initialMasterplanFilters";
|
||||
initialViewCheckboxes,
|
||||
initialRoveHomeCheckboxes,
|
||||
} from "../../../consts/initialMasterplanFilters";
|
||||
|
||||
const SearchFiltersModal = () => {
|
||||
// const [viewCheckboxes, setViewCheckboxes] = useState<ICheckbox[]>(
|
||||
@@ -119,7 +119,7 @@ const SearchFiltersModal = () => {
|
||||
const handleOnResetClick = () => {
|
||||
setMultirangeSliders(initialSliders);
|
||||
setViewCheckboxes(initialViewCheckboxes);
|
||||
setApartmentTypeCheckboxes(initialApartmentTypeCheckboxes);
|
||||
setApartmentTypeCheckboxes(initialAparmentTypeCheckboxes);
|
||||
setRoveHomeTypeCheckboxes(initialRoveHomeCheckboxes);
|
||||
setSwitchers(initialSwitchers);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useEffect } from "react";
|
||||
import LayoutCard from "./LayoutCard";
|
||||
import SortButton from "./SortButton";
|
||||
import { initialSortList } from "../../consts/initialSearchPage";
|
||||
import SearchIcon from "../icons/SearchIcon";
|
||||
import Button from "../Button";
|
||||
import FilterIcon from "../icons/FilterIcon";
|
||||
@@ -9,19 +8,112 @@ import useModal from "../../store/useModal";
|
||||
import { MobileModalWrapper } from "../modals/mobile/MobileModalWrapper";
|
||||
import SearchFiltersModal from "../modals/mobile/SearchFiltersModal";
|
||||
import { getApartments } from "../../api/apartments";
|
||||
import { IApartmentsRes, InfoRes } from "../../types/apartmentsRes";
|
||||
import { IAparmentRes, IApartmentsRes } from "../../types/apartmentsRes";
|
||||
import { updateAccessToken } from "../../api/updateAccessToken";
|
||||
import useApartments from "../../store/useApartments";
|
||||
import useSearchFilters from "../../store/useSearchFilters";
|
||||
import { ICheckbox } from "../../types/checkbox";
|
||||
import { IMultirangeSlider } from "../../types/multirangeSlider";
|
||||
import { useDebounce } from "@uidotdev/usehooks";
|
||||
import { ISwitcher } from "../../types/switcher";
|
||||
import { initialSliders } from "../../consts/initialMasterplanFilters";
|
||||
import { ISort } from "../../types/sortType";
|
||||
|
||||
const getFilteredApartments = async (
|
||||
zohoToken: string | null,
|
||||
setApartments: (apartments: IAparmentRes[]) => void,
|
||||
roveHomeTypeCheckboxes: ICheckbox[],
|
||||
apartmentTypeCheckboxes: ICheckbox[],
|
||||
multirangeSliders: IMultirangeSlider[],
|
||||
switchers: ISwitcher[],
|
||||
viewCheckboxes: ICheckbox[],
|
||||
sortList: ISort[],
|
||||
page: number,
|
||||
perPage: number
|
||||
) => {
|
||||
const roveHomeFilters = roveHomeTypeCheckboxes
|
||||
.filter((chx) => chx.selected)
|
||||
.map((chx) => chx.value);
|
||||
|
||||
const apartmentTypeFilters = apartmentTypeCheckboxes
|
||||
.filter((chx) => chx.selected)
|
||||
.map((chx) => chx.value);
|
||||
|
||||
const viewFilters = viewCheckboxes
|
||||
.filter((chx) => chx.selected)
|
||||
.map((chx) => chx.value);
|
||||
|
||||
const sortBy = sortList.find((sortType) => sortType.isSelected)?.value;
|
||||
|
||||
const totalAreaSlider = multirangeSliders.find(
|
||||
(sld) => sld.title === "Total Area"
|
||||
);
|
||||
const totalAreaFilter = [
|
||||
totalAreaSlider?.startValue,
|
||||
totalAreaSlider?.endValue,
|
||||
] as number[];
|
||||
const isNotFirstFloor = switchers.find(
|
||||
(swch) => swch.isSwitched && swch.title === "Not the first floor"
|
||||
);
|
||||
const isNotTopFloor = switchers.find(
|
||||
(swch) => swch.isSwitched && swch.title === "Not the top floor"
|
||||
);
|
||||
const initialFloorSlider = initialSliders.find(
|
||||
(sld) => sld.title === "Floor"
|
||||
) as IMultirangeSlider;
|
||||
// если значение ввода в границах слайдера
|
||||
const maxFloor = initialFloorSlider?.maxValue;
|
||||
const minFloor = initialFloorSlider?.minValue;
|
||||
|
||||
const floorSlider = multirangeSliders.find(
|
||||
(sld) => sld.title === "Floor"
|
||||
) as IMultirangeSlider;
|
||||
|
||||
const startFloorValue = isNotFirstFloor
|
||||
? Math.max(minFloor + 1, floorSlider.startValue)
|
||||
: floorSlider.startValue;
|
||||
const endFloorValue = isNotTopFloor
|
||||
? Math.min(maxFloor - 1, floorSlider?.endValue)
|
||||
: floorSlider?.endValue;
|
||||
|
||||
const floorFilter = [startFloorValue, endFloorValue];
|
||||
|
||||
const res = await getApartments(
|
||||
zohoToken,
|
||||
roveHomeFilters,
|
||||
apartmentTypeFilters,
|
||||
viewFilters,
|
||||
totalAreaFilter,
|
||||
floorFilter,
|
||||
sortBy,
|
||||
page,
|
||||
perPage
|
||||
).then((data) => {
|
||||
const apartmentsData = (data as IApartmentsRes).apartments;
|
||||
setApartments(apartmentsData);
|
||||
});
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
const LayoutOptions = () => {
|
||||
const [sortList, setSortList] = useState(initialSortList);
|
||||
const { apartments, setApartments } = useApartments();
|
||||
const [infoRes, setInfoRes] = useState<InfoRes>(null);
|
||||
|
||||
const { setModal } = useModal();
|
||||
const { roveHomeTypeCheckboxes, apartmentTypeCheckboxes, multirangeSliders } =
|
||||
useSearchFilters();
|
||||
const {
|
||||
roveHomeTypeCheckboxes,
|
||||
apartmentTypeCheckboxes,
|
||||
multirangeSliders,
|
||||
viewCheckboxes,
|
||||
switchers,
|
||||
sortList,
|
||||
setSortList,
|
||||
page,
|
||||
setPerPage,
|
||||
setPage,
|
||||
perPage,
|
||||
} = useSearchFilters();
|
||||
const debouncedSliders = useDebounce(multirangeSliders, 300);
|
||||
|
||||
const handleOnSortClick = (sortId: string) => {
|
||||
const updatedSortList = sortList.map((sort) => {
|
||||
@@ -39,39 +131,58 @@ const LayoutOptions = () => {
|
||||
);
|
||||
};
|
||||
|
||||
function handleOnShowMoreBtnClick(): void {
|
||||
const nextPage = page + 1;
|
||||
setPage(nextPage);
|
||||
// setPerPage(nextPage);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const zohoToken = localStorage.getItem("ACCESS_TOKEN");
|
||||
|
||||
getApartments(zohoToken)
|
||||
.then((data) => {
|
||||
const apartmentsData = (data as IApartmentsRes).apartments;
|
||||
console.log("apartmentsData", apartmentsData);
|
||||
setApartments(apartmentsData);
|
||||
})
|
||||
.catch((error) => {
|
||||
const errorStatus = error.response.status;
|
||||
getFilteredApartments(
|
||||
zohoToken,
|
||||
setApartments,
|
||||
roveHomeTypeCheckboxes,
|
||||
apartmentTypeCheckboxes,
|
||||
debouncedSliders,
|
||||
switchers,
|
||||
viewCheckboxes,
|
||||
sortList,
|
||||
page,
|
||||
perPage
|
||||
).catch((error) => {
|
||||
const errorStatus = error.response.status;
|
||||
|
||||
if (errorStatus === 401) {
|
||||
updateAccessToken();
|
||||
const zohoToken = localStorage.getItem("ACCESS_TOKEN");
|
||||
|
||||
getApartments(zohoToken).then((data) => {
|
||||
const apartmentsData = (data as unknown as IApartmentsRes)
|
||||
.apartments;
|
||||
|
||||
setApartments(apartmentsData);
|
||||
});
|
||||
}
|
||||
});
|
||||
}, [setApartments]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("apartments", apartments);
|
||||
if (errorStatus === 401) {
|
||||
updateAccessToken().then((token) => {
|
||||
if (token) {
|
||||
getFilteredApartments(
|
||||
token,
|
||||
setApartments,
|
||||
roveHomeTypeCheckboxes,
|
||||
apartmentTypeCheckboxes,
|
||||
debouncedSliders,
|
||||
switchers,
|
||||
viewCheckboxes,
|
||||
sortList,
|
||||
page,
|
||||
perPage
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}, [
|
||||
setApartments,
|
||||
roveHomeTypeCheckboxes,
|
||||
apartmentTypeCheckboxes,
|
||||
multirangeSliders,
|
||||
apartments,
|
||||
debouncedSliders,
|
||||
switchers,
|
||||
viewCheckboxes,
|
||||
sortList,
|
||||
page,
|
||||
perPage,
|
||||
]);
|
||||
|
||||
return (
|
||||
@@ -101,7 +212,10 @@ const LayoutOptions = () => {
|
||||
<LayoutCard apartmentCard={apartment} key={apartment.id} />
|
||||
))}
|
||||
</div>
|
||||
<div className="bg-white rounded-lg mt-4 py-[10px] flex justify-center select-none cursor-pointer items-center gap-2">
|
||||
<div
|
||||
className="bg-white rounded-lg mt-4 py-[10px] flex justify-center select-none cursor-pointer items-center gap-2"
|
||||
onClick={handleOnShowMoreBtnClick}
|
||||
>
|
||||
<SearchIcon /> Show 12 more apartments
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -3,16 +3,33 @@ import ResetIcon from "../icons/ResetIcon";
|
||||
import Checkbox from "../Checkbox";
|
||||
import Switch from "../Switch";
|
||||
import MultiRangeSlider from "../MultiRangeSlider";
|
||||
import useSearchFilters from "../../store/useSearchFilters";
|
||||
import {
|
||||
initialApartmentTypeCheckboxes,
|
||||
initialViewCheckboxes,
|
||||
initialAparmentTypeCheckboxes,
|
||||
initialSliders,
|
||||
initialSwitchers,
|
||||
initialRoveHomeCheckboxes,
|
||||
} from "../../consts/initialSearchFilters";
|
||||
import useSearchFilters from "../../store/useSearchFilters";
|
||||
import { initialViewCheckboxes } from "../../consts/initialMasterplanFilters";
|
||||
import { useState } from "react";
|
||||
import { ICheckbox } from "../../types/checkbox";
|
||||
} from "../../consts/initialMasterplanFilters";
|
||||
// import { IMultirangeSlider } from "../../types/multirangeSlider";
|
||||
|
||||
// function updateSlider(switcherTitle: string, sliders: IMultirangeSlider[]) {
|
||||
// if(switcherTitle === 'Not the first floor'){
|
||||
// const updatedSlider = sliders.map((sld) => {
|
||||
// if(sld.title === 'Floor'){
|
||||
// const floorSlider = initialSliders.find(sld1 => sld1.title === 'Floor');
|
||||
// const minValue = floorSlider?.minValue;
|
||||
// const isValueEqualMinValue = sld.minValue === minValue;
|
||||
// //Если значение равно минимальному значение, то уменьшаем минимальное значение
|
||||
// if(isValueEqualMinValue){
|
||||
// return {...sld, startValue: minValue, minValue: minValue}
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
// return sld
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
|
||||
const SidebarFilters = () => {
|
||||
const {
|
||||
@@ -24,12 +41,10 @@ const SidebarFilters = () => {
|
||||
setApartmentTypeCheckboxes,
|
||||
roveHomeTypeCheckboxes,
|
||||
setRoveHomeTypeCheckboxes,
|
||||
viewCheckboxes,
|
||||
setViewCheckboxes,
|
||||
} = useSearchFilters();
|
||||
|
||||
const [viewCheckboxes, setViewCheckboxes] = useState<ICheckbox[]>(
|
||||
initialViewCheckboxes
|
||||
);
|
||||
|
||||
const handleOnCheckboxApartmentClick = (checkboxId: string) => {
|
||||
const updatedCheckboxes = apartmentTypeCheckboxes.map((cbox) => {
|
||||
if (checkboxId !== cbox.id) return cbox;
|
||||
@@ -89,7 +104,7 @@ const SidebarFilters = () => {
|
||||
|
||||
const handleOnResetClick = () => {
|
||||
setViewCheckboxes(initialViewCheckboxes);
|
||||
setApartmentTypeCheckboxes(initialApartmentTypeCheckboxes);
|
||||
setApartmentTypeCheckboxes(initialAparmentTypeCheckboxes);
|
||||
setRoveHomeTypeCheckboxes(initialRoveHomeCheckboxes);
|
||||
setMultirangeSliders(initialSliders);
|
||||
setSwitchers(initialSwitchers);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { initialSortList, layoutsCards } from "../../consts/initialSearchPage";
|
||||
import { layoutsCards } from "../../consts/initialSearchPage";
|
||||
import { initialSortList } from "../../consts/initialMasterplanFilters";
|
||||
import useSearchFilters from "../../store/useSearchFilters";
|
||||
import SearchIcon from "../icons/SearchIcon";
|
||||
import SortButton from "../searchPage/SortButton";
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ICheckbox } from "../types/checkbox";
|
||||
import { IMultirangeSlider } from "../types/multirangeSlider";
|
||||
import { ISort } from "../types/sortType";
|
||||
import { ISwitcher } from "../types/switcher";
|
||||
|
||||
const initialSliders: IMultirangeSlider[] = [
|
||||
@@ -15,8 +16,8 @@ const initialSliders: IMultirangeSlider[] = [
|
||||
{
|
||||
minValue: 341,
|
||||
startValue: 341,
|
||||
endValue: 891,
|
||||
maxValue: 891,
|
||||
endValue: 1058,
|
||||
maxValue: 1058,
|
||||
title: "Total Area",
|
||||
unit: "Sqrt",
|
||||
id: "2",
|
||||
@@ -24,27 +25,38 @@ const initialSliders: IMultirangeSlider[] = [
|
||||
{
|
||||
minValue: 5,
|
||||
startValue: 5,
|
||||
endValue: 81,
|
||||
maxValue: 81,
|
||||
endValue: 31,
|
||||
maxValue: 31,
|
||||
title: "Floor",
|
||||
id: "3",
|
||||
},
|
||||
];
|
||||
|
||||
const initialAparmentTypeCheckboxes: ICheckbox[] = [
|
||||
{ title: "Studio Flex", id: "1", disabled: true, selected: false },
|
||||
{ title: "Studio", id: "2", selected: false },
|
||||
{ title: "1 Bedroom", id: "3", selected: false },
|
||||
{ title: "2 Bedroom", id: "4", selected: false },
|
||||
{
|
||||
title: "Studio Flex",
|
||||
id: "1",
|
||||
disabled: false,
|
||||
selected: false,
|
||||
value: "Studio Flex",
|
||||
},
|
||||
{ title: "Studio", id: "2", selected: false, value: "Studio Squared" },
|
||||
{ title: "1 Bedroom", id: "3", selected: false, value: "1 BR Squared" },
|
||||
{ title: "2 Bedroom", id: "4", selected: false, value: "2 BR Squared" },
|
||||
];
|
||||
|
||||
const initialViewCheckboxes: ICheckbox[] = [
|
||||
{ title: "Burj Khalifa", id: "1", disabled: true, selected: false },
|
||||
{ title: "Amenties", id: "2", selected: false },
|
||||
{ title: "Downtown", id: "3", selected: false },
|
||||
{ title: "Canal", id: "4", selected: false },
|
||||
{ title: "Business Bay", id: "5", selected: false },
|
||||
{ title: "Park", id: "6", selected: false },
|
||||
{ title: "Burj Khalifa", id: "1", selected: false, value: "BK" },
|
||||
{ title: "Amenties", id: "2", selected: false, value: "Amenities" },
|
||||
{ title: "Downtown", id: "3", selected: false, value: "DT" },
|
||||
{ title: "Canal", id: "4", selected: false, value: "Canal" },
|
||||
{ title: "Business Bay", id: "5", selected: false, value: "Business Bay" },
|
||||
{
|
||||
title: "Park",
|
||||
id: "6",
|
||||
selected: false,
|
||||
value: "Partial Park,Park Facing",
|
||||
},
|
||||
];
|
||||
|
||||
const initialSwitchers: ISwitcher[] = [
|
||||
@@ -52,9 +64,60 @@ const initialSwitchers: ISwitcher[] = [
|
||||
{ id: "2", title: "Not the top floor", isSwitched: false },
|
||||
];
|
||||
|
||||
const initialRoveHomeCheckboxes: ICheckbox[] = [
|
||||
{
|
||||
title: "Downtown",
|
||||
id: "1",
|
||||
disabled: false,
|
||||
selected: false,
|
||||
value: "Rove Home Downtown",
|
||||
},
|
||||
{
|
||||
title: "Marasi Drive",
|
||||
id: "2",
|
||||
selected: false,
|
||||
value: "Rove Home Marasi Drive",
|
||||
},
|
||||
{
|
||||
title: "Dubai Marina",
|
||||
id: "3",
|
||||
selected: false,
|
||||
value: "Rove Home Dubai Marina",
|
||||
},
|
||||
];
|
||||
|
||||
const initialSortList: ISort[] = [
|
||||
{
|
||||
id: "1",
|
||||
title: "Ascending price",
|
||||
isSelected: true,
|
||||
value: "asc_price",
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "Decreasing price",
|
||||
isSelected: false,
|
||||
value: "decr_price",
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
title: "Ascending Squares",
|
||||
isSelected: false,
|
||||
value: "asc_sqr",
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
title: "Ascending Floor",
|
||||
isSelected: false,
|
||||
value: "asc_floor",
|
||||
},
|
||||
];
|
||||
|
||||
export {
|
||||
initialAparmentTypeCheckboxes,
|
||||
initialSliders,
|
||||
initialSwitchers,
|
||||
initialViewCheckboxes,
|
||||
initialRoveHomeCheckboxes,
|
||||
initialSortList,
|
||||
};
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
import { ICheckbox } from "../types/checkbox";
|
||||
import { IMultirangeSlider } from "../types/multirangeSlider";
|
||||
import { ISwitcher } from "../types/switcher";
|
||||
|
||||
const initialSliders: IMultirangeSlider[] = [
|
||||
{
|
||||
minValue: 1048888,
|
||||
startValue: 1048888,
|
||||
endValue: 2408888,
|
||||
maxValue: 2408888,
|
||||
title: "Cost",
|
||||
unit: "AED",
|
||||
id: "1",
|
||||
},
|
||||
{
|
||||
minValue: 341,
|
||||
startValue: 341,
|
||||
endValue: 891,
|
||||
maxValue: 891,
|
||||
title: "Total Area",
|
||||
unit: "Sqrt",
|
||||
id: "2",
|
||||
},
|
||||
{
|
||||
minValue: 5,
|
||||
startValue: 5,
|
||||
endValue: 81,
|
||||
maxValue: 81,
|
||||
title: "Floor",
|
||||
id: "3",
|
||||
},
|
||||
];
|
||||
|
||||
const initialApartmentTypeCheckboxes: ICheckbox[] = [
|
||||
{ title: "Studio Flex", id: "1", selected: false },
|
||||
{ title: "Studio", id: "2", selected: false },
|
||||
{ title: "1 Bedroom", id: "3", selected: false },
|
||||
{ title: "2 Bedroom", id: "4", selected: false },
|
||||
];
|
||||
|
||||
const initialRoveHomeCheckboxes: ICheckbox[] = [
|
||||
{ title: "Downtown", id: "1", disabled: false, selected: false },
|
||||
{ title: "Marasi Drive", id: "2", selected: false },
|
||||
{ title: "Dubai Marina", id: "3", selected: false },
|
||||
];
|
||||
|
||||
const initialSwitchers: ISwitcher[] = [
|
||||
{ id: "1", title: "Not the first floor", isSwitched: false },
|
||||
{ id: "2", title: "Not the top floor", isSwitched: false },
|
||||
];
|
||||
|
||||
export {
|
||||
initialApartmentTypeCheckboxes,
|
||||
initialSliders,
|
||||
initialSwitchers,
|
||||
initialRoveHomeCheckboxes,
|
||||
};
|
||||
@@ -1,5 +1,4 @@
|
||||
import { ILayoutCard } from "../types/layoutCard";
|
||||
import { ISort } from "../types/sortType";
|
||||
|
||||
const layoutsCards: ILayoutCard[] = [
|
||||
{
|
||||
@@ -136,27 +135,4 @@ const layoutsCards: ILayoutCard[] = [
|
||||
},
|
||||
];
|
||||
|
||||
const initialSortList: ISort[] = [
|
||||
{
|
||||
id: "1",
|
||||
title: "Ascending price",
|
||||
isSelected: true,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "Decreasing price",
|
||||
isSelected: false,
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
title: "Ascending Squares",
|
||||
isSelected: false,
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
title: "Ascending Floor",
|
||||
isSelected: false,
|
||||
},
|
||||
];
|
||||
|
||||
export { initialSortList, layoutsCards };
|
||||
export { layoutsCards };
|
||||
|
||||
@@ -4,7 +4,7 @@ import Button from "../components/Button";
|
||||
import Footer from "../components/Footer";
|
||||
import TrashIcon from "../components/icons/TrashIcon";
|
||||
import SortButton from "../components/searchPage/SortButton";
|
||||
import { initialSortList } from "../consts/initialSearchPage";
|
||||
import { initialSortList } from "../consts/initialMasterplanFilters";
|
||||
import { ILayoutCard } from "../types/layoutCard";
|
||||
import Switch from "../components/Switch";
|
||||
import { ISwitcher } from "../types/switcher";
|
||||
|
||||
@@ -1,18 +1,26 @@
|
||||
import { create } from "zustand";
|
||||
import { ICheckbox } from "../types/checkbox";
|
||||
import {
|
||||
initialApartmentTypeCheckboxes,
|
||||
initialRoveHomeCheckboxes,
|
||||
initialAparmentTypeCheckboxes,
|
||||
initialSliders,
|
||||
initialSwitchers,
|
||||
} from "../consts/initialSearchFilters";
|
||||
initialViewCheckboxes,
|
||||
initialRoveHomeCheckboxes,
|
||||
initialSortList,
|
||||
} from "../consts/initialMasterplanFilters";
|
||||
import { IMultirangeSlider } from "../types/multirangeSlider";
|
||||
import { ISwitcher } from "../types/switcher";
|
||||
import { initialViewCheckboxes } from "../consts/initialMasterplanFilters";
|
||||
import { ISort } from "../types/sortType";
|
||||
|
||||
interface Store {
|
||||
apartmentTypeCheckboxes: ICheckbox[];
|
||||
viewCheckboxes: ICheckbox[];
|
||||
sortList: ISort[];
|
||||
page: number;
|
||||
perPage: number;
|
||||
setPage: (page: number) => void;
|
||||
setPerPage: (perPage: number) => void;
|
||||
setSortList: (sortList: ISort[]) => void;
|
||||
setApartmentTypeCheckboxes: (typeCheckboxes: ICheckbox[]) => void;
|
||||
setViewCheckboxes: (checkboxes: ICheckbox[]) => void;
|
||||
roveHomeTypeCheckboxes: ICheckbox[];
|
||||
@@ -24,19 +32,25 @@ interface Store {
|
||||
}
|
||||
|
||||
const useSearchFilters = create<Store>((set) => ({
|
||||
apartmentTypeCheckboxes: initialApartmentTypeCheckboxes,
|
||||
apartmentTypeCheckboxes: initialAparmentTypeCheckboxes,
|
||||
viewCheckboxes: initialViewCheckboxes,
|
||||
roveHomeTypeCheckboxes: initialRoveHomeCheckboxes,
|
||||
multirangeSliders: initialSliders,
|
||||
switchers: initialSwitchers,
|
||||
sortList: initialSortList,
|
||||
page: 1,
|
||||
perPage: 12,
|
||||
setPerPage: (perPage) => set(() => ({ perPage: perPage })),
|
||||
setPage: (page) => set(() => ({ page: page })),
|
||||
setSortList: (sortList) => set(() => ({ sortList: sortList })),
|
||||
setApartmentTypeCheckboxes: (typeCheckboxes) =>
|
||||
set(() => ({ apartmentTypeCheckboxes: typeCheckboxes })),
|
||||
setViewCheckboxes: (typeCheckboxes) =>
|
||||
set(() => ({ viewCheckboxes: typeCheckboxes })),
|
||||
roveHomeTypeCheckboxes: initialRoveHomeCheckboxes,
|
||||
setRoveHomeTypeCheckboxes: (typeCheckboxes) =>
|
||||
set(() => ({ roveHomeTypeCheckboxes: typeCheckboxes })),
|
||||
multirangeSliders: initialSliders,
|
||||
setMultirangeSliders: (multirangeSliders) =>
|
||||
set(() => ({ multirangeSliders: multirangeSliders })),
|
||||
switchers: initialSwitchers,
|
||||
setSwitchers: (switchers) => set(() => ({ switchers: switchers })),
|
||||
}));
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ interface ICheckbox {
|
||||
id: string;
|
||||
disabled?: boolean;
|
||||
selected: boolean;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export type { ICheckbox };
|
||||
|
||||
@@ -2,6 +2,7 @@ interface ISort {
|
||||
id: string;
|
||||
title: string;
|
||||
isSelected: boolean;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export type { ISort };
|
||||
|
||||
@@ -884,6 +884,11 @@
|
||||
"@typescript-eslint/types" "7.6.0"
|
||||
eslint-visitor-keys "^3.4.3"
|
||||
|
||||
"@uidotdev/usehooks@^2.4.1":
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@uidotdev/usehooks/-/usehooks-2.4.1.tgz#4b733eaeae09a7be143c6c9ca158b56cc1ea75bf"
|
||||
integrity sha512-1I+RwWyS+kdv3Mv0Vmc+p0dPYH0DTRAo04HLyXReYBL9AeseDWUJyi4THuksBJcu9F0Pih69Ak150VDnqbVnXg==
|
||||
|
||||
"@ungap/structured-clone@^1.2.0":
|
||||
version "1.2.0"
|
||||
resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz"
|
||||
|
||||
@@ -24,7 +24,6 @@ app.use(json());
|
||||
app.use(morgan("combined", { stream: accessLogStream }));
|
||||
|
||||
app.use("/apartments", apartmentsRoute);
|
||||
|
||||
app.use("/updateAccessToken", updateAccessToken);
|
||||
|
||||
app.listen(port, () => {
|
||||
|
||||
+226
-82
@@ -2,12 +2,28 @@ import { Router } from "express";
|
||||
import { aparmentsApi, searchApartmentApi } from "../consts.js";
|
||||
import { logger } from "../utils/logger.js";
|
||||
|
||||
interface IApartment {
|
||||
Floor: number;
|
||||
Property_Status: string;
|
||||
Unit_Type: string;
|
||||
Project_Name: string;
|
||||
Suite_Area_Sqft: number;
|
||||
Balcony_Area_Sqft: number;
|
||||
No_Of_Bedrooms: number;
|
||||
Unit_No: string;
|
||||
id: string;
|
||||
Total_Area_Sqft: number;
|
||||
No_of_Bathrooms: number;
|
||||
Property_Name: string;
|
||||
Unit_View: string;
|
||||
}
|
||||
|
||||
const router = Router();
|
||||
|
||||
async function getAllApartments(
|
||||
page: number,
|
||||
accessToken: string,
|
||||
apartments: any[]
|
||||
apartments: IApartment[]
|
||||
) {
|
||||
const response = await fetch(`${aparmentsApi}&page=${page}&per_page=200`, {
|
||||
headers: {
|
||||
@@ -31,109 +47,237 @@ async function getAllApartments(
|
||||
return await getAllApartments(page + 1, accessToken, updatedApartment);
|
||||
}
|
||||
|
||||
function filterApartments(
|
||||
apartments: IApartment[],
|
||||
roveHome?: string[],
|
||||
apartmentType?: string[],
|
||||
costBetween?: string[],
|
||||
totalAreaBetween?: string[],
|
||||
floorBetween?: string[],
|
||||
views?: string[]
|
||||
) {
|
||||
const filteredApartments = apartments
|
||||
.filter((apart) => {
|
||||
// Rove home filter
|
||||
if (!roveHome || roveHome.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (roveHome.some((rove) => rove === apart.Project_Name)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
})
|
||||
.filter((apart) => {
|
||||
// Apartment type filter
|
||||
if (!apartmentType || apartmentType.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (apartmentType.some((rove) => rove === apart.Unit_Type)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
})
|
||||
.filter((apart) => {
|
||||
// Cost between filter еще не доступен тк нет цен
|
||||
|
||||
if (!costBetween || costBetween.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const leftCost = Number(costBetween[0]);
|
||||
const rightCost = Number(costBetween[1]);
|
||||
|
||||
return true;
|
||||
|
||||
// if (costBetween.some((rove) => rove === apart.Unit_Type)) {
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// return false;
|
||||
})
|
||||
.filter((apart) => {
|
||||
// Total area filter
|
||||
if (!totalAreaBetween || totalAreaBetween.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const leftArea = Number(totalAreaBetween[0]);
|
||||
const rightArea = Number(totalAreaBetween[1]);
|
||||
|
||||
if (
|
||||
(leftArea <= apart.Total_Area_Sqft &&
|
||||
rightArea >= apart.Total_Area_Sqft) ||
|
||||
(leftArea >= apart.Total_Area_Sqft &&
|
||||
rightArea <= apart.Total_Area_Sqft)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
})
|
||||
.filter((apart) => {
|
||||
// Views filter
|
||||
if (!views || views.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//view "Canal" "Amenities"
|
||||
// Canal / Amenities
|
||||
|
||||
// разделение по / с пробелом и без
|
||||
const apartViews = apart.Unit_View.split(" / ").join("/").split("/");
|
||||
for (let i = 0; i < apartViews.length; i++) {
|
||||
// Удаление Corner-
|
||||
const withoutCorner =
|
||||
apartViews[i].split("-").length > 1
|
||||
? apartViews[i].split("-")[1]
|
||||
: apartViews[i];
|
||||
|
||||
//удаление View
|
||||
const withoutView = withoutCorner.replace(" View", "");
|
||||
|
||||
if (views.some((view) => view === withoutView)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
})
|
||||
.filter((apart) => {
|
||||
// Floor filter
|
||||
|
||||
if (!floorBetween || floorBetween.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const leftFloor = Number(floorBetween[0]);
|
||||
const rightFloor = Number(floorBetween[1]);
|
||||
|
||||
if (
|
||||
(leftFloor <= apart.Floor && rightFloor >= apart.Floor) ||
|
||||
(leftFloor >= apart.Floor && rightFloor <= apart.Floor)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
return filteredApartments;
|
||||
}
|
||||
|
||||
router.get("/", async (req, res) => {
|
||||
const accessToken = req?.headers?.authorization;
|
||||
const {
|
||||
per_page: perPage = 20,
|
||||
page = 10,
|
||||
per_page = 20,
|
||||
page = 1,
|
||||
rove_home = "",
|
||||
apartment_type = "",
|
||||
cost_between = "",
|
||||
total_area_between = "",
|
||||
floor_between = "",
|
||||
views = "",
|
||||
sort_by = "",
|
||||
} = req.query;
|
||||
|
||||
let api = aparmentsApi;
|
||||
|
||||
if (!accessToken)
|
||||
return res
|
||||
.status(401)
|
||||
.json({ message: "Отсутсвует access token", code: 401 });
|
||||
|
||||
try {
|
||||
const allApartments = await getAllApartments(1, accessToken, []);
|
||||
const filteredApartments = allApartments.slice(
|
||||
page as number,
|
||||
perPage as number
|
||||
);
|
||||
const roveHomeFilter = (rove_home as string)
|
||||
.split(",")
|
||||
.filter((rove) => rove !== "");
|
||||
const apartmentTypeFilter = (apartment_type as string)
|
||||
.split(",")
|
||||
.filter((rove) => rove !== "");
|
||||
const costBetweenFilter = (cost_between as string)
|
||||
.split(",")
|
||||
.filter((cost) => cost !== "");
|
||||
const totalAreaBetween = (total_area_between as string)
|
||||
.split(",")
|
||||
.filter((area) => area !== "");
|
||||
const viewsFilter = (views as string)
|
||||
.split(",")
|
||||
.filter((view) => view !== "");
|
||||
const floorBetweenFilter = (floor_between as string)
|
||||
.split(",")
|
||||
.filter((floor) => floor !== "");
|
||||
|
||||
res.status(200).json({
|
||||
message: "ok",
|
||||
apartments: filteredApartments,
|
||||
code: 200,
|
||||
});
|
||||
if (!accessToken)
|
||||
return res
|
||||
.status(401)
|
||||
.json({ message: "Отсутсвует access token", code: 401 });
|
||||
|
||||
try {
|
||||
const allApartments = await getAllApartments(1, accessToken, []);
|
||||
const filteredApartments = filterApartments(
|
||||
allApartments,
|
||||
roveHomeFilter,
|
||||
apartmentTypeFilter,
|
||||
costBetweenFilter,
|
||||
totalAreaBetween,
|
||||
floorBetweenFilter,
|
||||
viewsFilter
|
||||
);
|
||||
|
||||
const sortedApartments = [...filteredApartments].sort((a, b) => {
|
||||
if (sort_by === "asc_price") {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (sort_by === "decr_price") {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (sort_by === "asc_sqr") {
|
||||
return a.Total_Area_Sqft - b.Total_Area_Sqft;
|
||||
}
|
||||
|
||||
if (sort_by === "asc_floor") {
|
||||
return a.Floor - b.Floor;
|
||||
}
|
||||
|
||||
return 1;
|
||||
});
|
||||
|
||||
const slicedApartments = sortedApartments.slice(
|
||||
((page as number) - 1) * (per_page as number),
|
||||
per_page as number
|
||||
);
|
||||
console.log("slicedApartments", slicedApartments);
|
||||
|
||||
res.status(200).json({
|
||||
message: "ok",
|
||||
apartments: slicedApartments,
|
||||
code: 200,
|
||||
});
|
||||
|
||||
return;
|
||||
} catch (error) {
|
||||
if (
|
||||
(error as Error).message === "invalid oauth token" ||
|
||||
(error as Error).message === "INVALID_TOKEN"
|
||||
) {
|
||||
console.log("error", error);
|
||||
logger.error(error);
|
||||
|
||||
return res
|
||||
.status(401)
|
||||
.json({ message: "Неправильный токен или токен устарел", code: 401 });
|
||||
}
|
||||
|
||||
return;
|
||||
} catch (error) {
|
||||
if (
|
||||
(error as Error).message === "invalid oauth token" ||
|
||||
(error as Error).message === "INVALID_TOKEN"
|
||||
) {
|
||||
console.log("error", error);
|
||||
logger.error(error);
|
||||
|
||||
return res
|
||||
.status(401)
|
||||
.json({ message: "Неправильный токен или токен устарел", code: 401 });
|
||||
return res.status(500).json({ message: "Server Error", code: 500 });
|
||||
}
|
||||
|
||||
console.log("error", error);
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
|
||||
return res.status(500).json({ message: "Server Error", code: 500 });
|
||||
console.log("error", error);
|
||||
}
|
||||
});
|
||||
|
||||
// router.get("/", async (req, res) => {
|
||||
// const accessToken = req.headers.authorization;
|
||||
// const { perPage, criteria } = req.query;
|
||||
|
||||
// let api = perPage || criteria ? searchApartmentApi : aparmentsApi;
|
||||
|
||||
// if (criteria) {
|
||||
// api = `${api}&criteria=${criteria}`;
|
||||
// }
|
||||
|
||||
// console.log("api", api);
|
||||
|
||||
// if (!accessToken)
|
||||
// return res
|
||||
// .status(401)
|
||||
// .json({ message: "Отсутсвует access token", code: 401 });
|
||||
|
||||
// try {
|
||||
// const apartments = await fetch(api, {
|
||||
// headers: {
|
||||
// Authorization: accessToken,
|
||||
// },
|
||||
// });
|
||||
|
||||
// const result = await apartments.json();
|
||||
|
||||
// if (result?.code && result?.code === "INVALID_TOKEN") {
|
||||
// return res.status(401).json({ code: 401, message: "INVALID_TOKEN" });
|
||||
// }
|
||||
|
||||
// res.status(200).json({ message: "ok", apartments: result, code: 200 });
|
||||
// return;
|
||||
// } catch (error) {
|
||||
// if ((error as Error).message === "invalid oauth token") {
|
||||
// console.log("error", error);
|
||||
// logger.error(error);
|
||||
|
||||
// return res
|
||||
// .status(401)
|
||||
// .json({ message: "Неправильный токен или токен устарел", code: 401 });
|
||||
// }
|
||||
|
||||
// console.log("error", error);
|
||||
// logger.error(error);
|
||||
|
||||
// return res.status(500).json({ message: "Server Error", code: 500 });
|
||||
// }
|
||||
// });
|
||||
|
||||
const apartmentsRoute = router;
|
||||
|
||||
export default apartmentsRoute;
|
||||
|
||||
Reference in New Issue
Block a user