wing + filter

This commit is contained in:
2024-06-24 19:18:39 +05:00
parent b1bd436ab7
commit a651ab552e
31 changed files with 1572 additions and 528 deletions
+18 -17
View File
@@ -3,38 +3,40 @@ import ky from "ky";
async function getApartments( async function getApartments(
token: string | null, token: string | null,
roveHomeFilters: string[], roveHomeFilters?: string[],
apartmentTypeFilters: string[], apartmentTypeFilters?: string[],
viewFilters: string[], viewFilters?: string[],
totalAreaFilter: number[], totalAreaFilter?: number[],
floorFilter: number[], floorFilter?: number[],
sortBy: string | undefined, sortBy?: string | undefined,
page: number, page?: number,
perPage: number perPage?: number
) { ) {
const roveHomeQuery = const roveHomeQuery =
roveHomeFilters.length !== 0 roveHomeFilters && roveHomeFilters.length !== 0
? `rove_home=${roveHomeFilters.join(",")}` ? `rove_home=${roveHomeFilters.join(",")}`
: ""; : "";
const apartmentQuery = const apartmentQuery =
apartmentTypeFilters.length !== 0 apartmentTypeFilters && apartmentTypeFilters.length !== 0
? `apartment_type=${apartmentTypeFilters.join(",")}` ? `apartment_type=${apartmentTypeFilters.join(",")}`
: ""; : "";
const viewQuery = const viewQuery =
viewFilters.length !== 0 ? `views=${viewFilters.join(",")}` : ""; viewFilters && viewFilters.length !== 0
? `views=${viewFilters.join(",")}`
: "";
const totalAreaSliderQuery = const totalAreaSliderQuery =
totalAreaFilter.length !== 0 totalAreaFilter && totalAreaFilter.length !== 0
? `total_area_between=${totalAreaFilter[0]},${totalAreaFilter[1]}` ? `total_area_between=${totalAreaFilter[0]},${totalAreaFilter[1]}`
: ""; : "";
const floorQuery = const floorQuery =
floorFilter.length !== 0 floorFilter && floorFilter.length !== 0
? `floor_between=${floorFilter[0]},${floorFilter[1]}` ? `floor_between=${floorFilter[0]},${floorFilter[1]}`
: ""; : "";
const sortByQuery = sortBy ? `sort_by=${sortBy}` : ""; const sortByQuery = sortBy ? `sort_by=${sortBy}` : "";
const pageQuery = `page=${page}`; const pageQuery = page ? `page=${page}` : "";
const perPageQuery = `per_page=${perPage}`; const perPageQuery = perPage ? `per_page=${perPage}` : "";
const query = [ const query = [
apartmentQuery, apartmentQuery,
@@ -52,8 +54,7 @@ async function getApartments(
const url = `${apartmentsApi}?${query}`; const url = `${apartmentsApi}?${query}`;
const res = await ky.get(url, { const res = await ky.get(url, {
headers: { headers: {
Authorization: `Zoho-oauthtoken 1000.f2b816cab56f851da9397cfbc17254e6.8636301ca36fb659a41b050bf0237d4d`, Authorization: `Zoho-oauthtoken ${token}`,
// Authorization: `Zoho-oauthtoken ${token}`,
}, },
}); });
+87
View File
@@ -0,0 +1,87 @@
import { getApartments } from "../api/apartments";
import { initialSliders } from "../consts/initialMasterplanFilters";
import { IAparmentRes, IApartmentsRes } from "../types/apartmentsRes";
import { ICheckbox } from "../types/checkbox";
import { IMultirangeSlider } from "../types/multirangeSlider";
import { ISort } from "../types/sortType";
import { ISwitcher } from "../types/switcher";
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;
const updatedApartments = [...apartmentsData];
setApartments(updatedApartments);
});
return res;
};
export { getFilteredApartments };
+8 -8
View File
@@ -1,18 +1,18 @@
import { ILayoutCard } from "../types/layoutCard"; import { IAparmentRes } from "../types/apartmentsRes";
import { ISort } from "../types/sortType"; import { ISort } from "../types/sortType";
const sortCardBy = (sortTypeList: ISort[], layoutsCards: ILayoutCard[]) => { const sortCardBy = (sortTypeList: ISort[], layoutsCards: IAparmentRes[]) => {
const sortType = sortTypeList.find((sort) => sort.isSelected); const sortType = sortTypeList.find((sort) => sort.isSelected);
const sortedList = [...layoutsCards].sort((cardA, cardB) => { const sortedList = [...layoutsCards].sort((cardA, cardB) => {
switch (sortType?.title) { switch (sortType?.title) {
case "Ascending price": case "Ascending price":
return cardA.cost - cardB.cost;
case "Decreasing price":
return cardB.cost - cardA.cost;
case "Ascending Squares":
return cardA.square - cardB.square;
case "Ascending Floor":
return 1; return 1;
case "Decreasing price":
return 2;
case "Ascending Squares":
return cardA.Total_Area_Sqft - cardB.Total_Area_Sqft;
case "Ascending Floor":
return cardA.Floor - cardB.Floor;
default: default:
return 1; return 1;
} }
+3 -1
View File
@@ -11,7 +11,9 @@ interface ButtonProps {
icon?: React.ReactNode; icon?: React.ReactNode;
text?: string; text?: string;
className?: string; className?: string;
onClick?: () => void; onClick?: (
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => void | (() => void);
disabled?: boolean; disabled?: boolean;
isCircleRounded?: boolean; isCircleRounded?: boolean;
type?: "button" | "submit" | "reset"; type?: "button" | "submit" | "reset";
+4 -17
View File
@@ -15,6 +15,7 @@ const MultiRangeSlider = ({
}: MultiRangeSliderProps) => { }: MultiRangeSliderProps) => {
const firstInputRef = useRef(null); const firstInputRef = useRef(null);
const secondInputRef = useRef(null); const secondInputRef = useRef(null);
const { isDisabled } = multirangeSlider;
const handleOnRangeInputChange = (e: [a: number, b: number]) => { const handleOnRangeInputChange = (e: [a: number, b: number]) => {
onChange(multirangeSlider.id, e); onChange(multirangeSlider.id, e);
@@ -72,14 +73,6 @@ const MultiRangeSlider = ({
<div className=""> <div className="">
<div className="flex justify-between p-3 bg-white rounded-lg relative flex-col"> <div className="flex justify-between p-3 bg-white rounded-lg relative flex-col">
<div className="flex justify-between"> <div className="flex justify-between">
{/* <input
ref={firstInputRef}
key={multirangeSlider.startValue}
type="string"
onChange={handleOnFirstInputChange}
defaultValue={formatNumber(multirangeSlider.startValue, ",", 3, 1)}
className="focus:outline-none input_number w-1/2"
/> */}
<NumericFormat <NumericFormat
thousandSeparator="," thousandSeparator=","
key={multirangeSlider.startValue} key={multirangeSlider.startValue}
@@ -94,20 +87,14 @@ const MultiRangeSlider = ({
defaultValue={multirangeSlider.endValue} defaultValue={multirangeSlider.endValue}
className="focus:outline-none input_number w-1/2 text-right" className="focus:outline-none input_number w-1/2 text-right"
/> />
{/* <input
ref={secondInputRef}
onChange={handleOnSecondInputChange}
key={multirangeSlider.endValue}
type="string"
defaultValue={formatNumber(multirangeSlider.endValue, ",", 3, 1)}
className="focus:outline-none appearance-none input_number text-right w-1/2"
/> */}
</div> </div>
<RangeSlider <RangeSlider
min={multirangeSlider.minValue} min={multirangeSlider.minValue}
max={multirangeSlider.maxValue} max={multirangeSlider.maxValue}
value={[multirangeSlider.startValue, multirangeSlider.endValue]} value={[multirangeSlider.startValue, multirangeSlider.endValue]}
className="absolute -bottom-3 left-0 w-[calc(100%-16px)] z-20" className={`${
isDisabled ? "pointer-events-none text" : ""
} absolute -bottom-3 left-0 w-[calc(100%-16px)] z-20`}
onInput={handleOnRangeInputChange} onInput={handleOnRangeInputChange}
/> />
</div> </div>
@@ -1,84 +1,19 @@
import useWingSidebar from "../../store/useWingSidebar"; import useWingSidebar from "../../store/useWingSidebar";
import { IAparmentRes } from "../../types/apartmentsRes";
import { IDesctiptionFloor } from "../../types/descriptionFloor"; import { IDesctiptionFloor } from "../../types/descriptionFloor";
interface FloorDescriptionProps { interface FloorDescriptionProps {
descriptionFloor: IDesctiptionFloor | null; descriptionFloor: IDesctiptionFloor | null;
floorApartments: IAparmentRes[];
} }
const FloorDescription = ({ descriptionFloor }: FloorDescriptionProps) => { const FloorDescription = ({
descriptionFloor,
floorApartments,
}: FloorDescriptionProps) => {
const { isSidebar } = useWingSidebar(); const { isSidebar } = useWingSidebar();
return ( return (
<> <>
{/* <div
className={`bg-white rounded-lg p-6 flex flex-col gap-4 w-[364px] absolute transition-opacity duration-300 delay-100 ${
isSidebar && descriptionFloor?.wing === "West Wing"
? "opacity-0"
: "opacity-0"
}`}
>
<div className="relative">
<div className="flex justify-between border-b pb-4">
<div className="flex flex-col">
<p
className={`text-[#0D1922] font-semibold text-[20px] duration-300 ease-in-out`}
>
{descriptionFloor?.floor} Floor
</p>
<p className="text-[#73787C] font-semibold text-caption-m">
{descriptionFloor?.wing}
</p>
</div>
<div className="py-[3px] px-2 rounded-full bg-[#00BED7] text-white justify-start self-start">
234 units
</div>
</div>
<div className="flex flex-col gap-4 pt-4">
<div className="flex items-center justify-between gap-8">
<div className="flex gap-2 items-center">
<div className="min-w-6 min-h-6 rounded-full bg-[#00BED7] text-white text-xs font-semibold">
<p className="p-1 flex justify-center items-center">21</p>
</div>
<p className="text-s text-[#73787C] w-full">Studio Flex</p>
</div>
<p className="text-s text-[#0D1922]">AED 1,048,888</p>
</div>
<div className="flex items-center justify-between gap-8">
<div className="flex gap-2 items-center">
<div className="min-w-6 min-h-6 p-1 rounded-full bg-[#00BED7] text-white text-xs font-semibold">
<p className="h-full w-full flex justify-center items-center">
56
</p>
</div>
<p className="text-s text-[#73787C]">Studio</p>
</div>
<p className="text-s text-[#0D1922]">AED 1,138,888</p>
</div>
<div className="flex items-center justify-between gap-8">
<div className="flex gap-2 items-center">
<div className="min-w-6 min-h-6 p-1 rounded-full bg-[#00BED7] text-white text-xs font-semibold">
<p className="h-full w-full flex justify-center items-center">
89
</p>
</div>
<p className="text-s text-[#73787C]">1 Bedroom</p>
</div>
<p className="text-s text-[#0D1922]">AED 1,668,888</p>
</div>
<div className="flex items-center justify-between gap-8">
<div className="flex gap-2 items-center">
<div className="min-w-6 min-h-6 p-1 rounded-full bg-[#00BED7] text-white text-xs font-semibold">
<p className="h-full w-full flex justify-center items-center">
10
</p>
</div>
<p className="text-s text-[#73787C]">2 Bedroom, Type A</p>
</div>
<p className="text-s text-[#0D1922]">AED 2,408,888</p>
</div>
</div>
<div className="w-0 h-0 border-t-0 border-r-[7px] border-b-[12px] border-l-[7px] border-transparent border-b-white rotate-90 absolute top-0 -right-[35px]"></div>
</div>
</div> */}
<div <div
className={`bg-white rounded-2xl p-6 flex flex-col gap-4 w-[364px] absolute left-[414px] transition-opacity duration-300 desc-shadow ${ className={`bg-white rounded-2xl p-6 flex flex-col gap-4 w-[364px] absolute left-[414px] transition-opacity duration-300 desc-shadow ${
isSidebar && descriptionFloor?.wing === "West Wing" isSidebar && descriptionFloor?.wing === "West Wing"
@@ -99,51 +34,71 @@ const FloorDescription = ({ descriptionFloor }: FloorDescriptionProps) => {
</p> </p>
</div> </div>
<div className="py-[3px] px-2 rounded-full bg-[#00BED7] text-white justify-start self-start"> <div className="py-[3px] px-2 rounded-full bg-[#00BED7] text-white justify-start self-start">
234 units {floorApartments.length} units
</div> </div>
</div> </div>
<div className="flex flex-col gap-4 pt-4"> <div className="flex flex-col gap-4 pt-4">
<div className="flex items-center justify-between gap-8"> <div className="flex items-center justify-between gap-8">
<div className="flex gap-2 items-center"> <div className="flex gap-2 items-center">
<div className="min-w-6 min-h-6 rounded-full bg-[#00BED7] text-white text-xs font-semibold"> <div className="min-w-6 min-h-6 rounded-full bg-[#00BED7] text-white text-xs font-semibold">
<p className="p-1 flex justify-center items-center">21</p> <p className="p-1 flex justify-center items-center">
{
floorApartments.filter(
(apart) => apart.Unit_Type === "Studio Flex"
).length
}
</p>
</div> </div>
<p className="text-s text-[#73787C] w-full">Studio Flex</p> <p className="text-s text-[#73787C] w-full">Studio Flex</p>
</div> </div>
<p className="text-s text-[#0D1922]">AED 1,048,888</p> <p className="text-s text-[#0D1922] text-nowrap">Unvailiable</p>
</div> </div>
<div className="flex items-center justify-between gap-8"> <div className="flex items-center justify-between gap-8">
<div className="flex gap-2 items-center"> <div className="flex gap-2 items-center">
<div className="min-w-6 min-h-6 p-1 rounded-full bg-[#00BED7] text-white text-xs font-semibold"> <div className="min-w-6 min-h-6 p-1 rounded-full bg-[#00BED7] text-white text-xs font-semibold">
<p className="h-full w-full flex justify-center items-center"> <p className="h-full w-full flex justify-center items-center">
56 {
floorApartments.filter(
(apart) => apart.Unit_Type === "Studio Squared"
).length
}
</p> </p>
</div> </div>
<p className="text-s text-[#73787C]">Studio</p> <p className="text-s text-[#73787C]">Studio</p>
</div> </div>
<p className="text-s text-[#0D1922]">AED 1,138,888</p> <p className="text-s text-[#0D1922] text-nowrap">Unvailiable</p>
</div> </div>
<div className="flex items-center justify-between gap-8"> <div className="flex items-center justify-between gap-8">
<div className="flex gap-2 items-center"> <div className="flex gap-2 items-center">
<div className="min-w-6 min-h-6 p-1 rounded-full bg-[#00BED7] text-white text-xs font-semibold"> <div className="min-w-6 min-h-6 p-1 rounded-full bg-[#00BED7] text-white text-xs font-semibold">
<p className="h-full w-full flex justify-center items-center"> <p className="h-full w-full flex justify-center items-center">
89 {
floorApartments.filter(
(apart) => apart.Unit_Type === "1 BR Squared"
).length
}
</p> </p>
</div> </div>
<p className="text-s text-[#73787C]">1 Bedroom</p> <p className="text-s text-[#73787C]">1 Bedroom</p>
</div> </div>
<p className="text-s text-[#0D1922]">AED 1,668,888</p> <p className="text-s text-[#0D1922] text-nowrap">Unvailiable</p>
</div> </div>
<div className="flex items-center justify-between gap-8"> <div className="flex items-center justify-between gap-8">
<div className="flex gap-2 items-center"> <div className="flex gap-2 items-center">
<div className="min-w-6 min-h-6 p-1 rounded-full bg-[#00BED7] text-white text-xs font-semibold"> <div className="min-w-6 min-h-6 p-1 rounded-full bg-[#00BED7] text-white text-xs font-semibold">
<p className="h-full w-full flex justify-center items-center"> <p className="h-full w-full flex justify-center items-center">
10 {
floorApartments.filter(
(apart) => apart.Unit_Type === "2 BR Squared"
).length
}
</p> </p>
</div> </div>
<p className="text-s text-[#73787C]">2 Bedroom, Type A</p> <p className="text-s text-[#73787C] text-nowrap">
2 Bedroom, Type A
</p>
</div> </div>
<p className="text-s text-[#0D1922]">AED 2,408,888</p> <p className="text-s text-[#0D1922] text-nowrap">Unvailiable</p>
</div> </div>
</div> </div>
<div className="w-0 h-0 border-t-0 border-r-[7px] border-b-[12px] border-l-[7px] border-transparent border-b-white -rotate-90 absolute top-0 -left-[35px]"></div> <div className="w-0 h-0 border-t-0 border-r-[7px] border-b-[12px] border-l-[7px] border-transparent border-b-white -rotate-90 absolute top-0 -left-[35px]"></div>
@@ -1,49 +1,69 @@
import { IAparmentRes } from "../../../types/apartmentsRes";
import VirtualTourIcon from "../../icons/VirtualTourIcon"; import VirtualTourIcon from "../../icons/VirtualTourIcon";
interface ApartmentDescriptionProps { interface ApartmentDescriptionProps {
isVisible: boolean; isVisible: boolean;
is3DTourAvailable: boolean; is3DTourAvailable: boolean;
descRef: React.LegacyRef<HTMLDivElement>; descRef: React.LegacyRef<HTMLDivElement>;
hoveredApartment: IAparmentRes | null;
} }
const ApartmentDescription = ({ const ApartmentDescription = ({
isVisible, isVisible,
is3DTourAvailable, is3DTourAvailable,
descRef, descRef,
hoveredApartment,
}: ApartmentDescriptionProps) => { }: ApartmentDescriptionProps) => {
const wing =
hoveredApartment && hoveredApartment.Unit_No.split("-")[0] === "E"
? "East Wing"
: "West Wing";
return ( return (
<div className="p-6 py-3" ref={descRef}> <>
<div {hoveredApartment && (
className={`bg-white rounded-2xl p-6 flex flex-col text-subheadline-s relative text-nowrap desc-shadow py-2 ${ <div className="p-6 py-3" ref={descRef}>
isVisible ? "opacity-100" : "opacity-0"
} duration-300 ease-in-out transition-opacity`}
>
<h2 className="text-[#0D1922] font-semibold">1 bedroom, 609 Sqft</h2>
<div className="flex gap-2 items-center text-caption-m font-semibold pt-1 border-b pb-4 justify-start">
<p className="text-[#0D1922B2]">East Wing</p>
<div className="w-1 h-1 bg-[#E2E2DC] rounded-full"></div>
<p className="text-[#0D1922B2]">Floor 11</p>
<div className="w-1 h-1 bg-[#E2E2DC] rounded-full"></div>
<p className="text-[#0D1922B2]">E-213</p>
</div>
<div className="flex justify-between items-center pt-4 gap-14">
<p className="font-semibold text-[#00BED7] text-subheadline-s">
AED 1,668,888
</p>
<div <div
className={`bg-[#30B21614] text-[#30B216] px-2 py-[6px] flex gap-1 items-center rounded-lg ${ className={`bg-white rounded-2xl p-6 flex flex-col text-subheadline-s relative text-nowrap desc-shadow py-2 ${
is3DTourAvailable ? "opacity-100" : "opacity-0" isVisible ? "opacity-100" : "opacity-0"
}`} } duration-300 ease-in-out transition-opacity`}
> >
<VirtualTourIcon /> <h2 className="text-[#0D1922] font-semibold">
<p className="text-caption-m font-semibold text-[#30B216]"> {hoveredApartment?.Unit_Type},{" "}
3D-tour {hoveredApartment &&
</p> Math.round(hoveredApartment?.Total_Area_Sqft)}{" "}
Sqft
</h2>
<div className="flex gap-2 items-center text-caption-m font-semibold pt-1 border-b pb-4 justify-start">
<p className="text-[#0D1922B2]">{wing}</p>
<div className="w-1 h-1 bg-[#E2E2DC] rounded-full"></div>
<p className="text-[#0D1922B2]">Floor {hoveredApartment.Floor}</p>
<div className="w-1 h-1 bg-[#E2E2DC] rounded-full"></div>
<p className="text-[#0D1922B2]">{hoveredApartment.Unit_No}</p>
</div>
<div className="flex justify-between items-center pt-4 gap-14">
<p className="font-semibold text-[#00BED7] text-subheadline-s">
Unvailiable
</p>
{/* <p className="font-semibold text-[#00BED7] text-subheadline-s">
AED 1,668,888
</p> */}
<div
className={`bg-[#30B21614] text-[#30B216] px-2 py-[6px] flex gap-1 items-center rounded-lg ${
is3DTourAvailable ? "opacity-100" : "opacity-0"
}`}
>
<VirtualTourIcon />
<p className="text-caption-m font-semibold text-[#30B216]">
3D-tour
</p>
</div>
</div>
<div className="w-0 h-0 border-transparent border-t-[14px] border-x-[6px] border-b-0 absolute left-6 -bottom-[13px] border-t-white"></div>
</div> </div>
</div> </div>
<div className="w-0 h-0 border-transparent border-t-[14px] border-x-[6px] border-b-0 absolute left-6 -bottom-[13px] border-t-white"></div> )}
</div> </>
</div>
); );
}; };
@@ -1,6 +1,10 @@
interface FloorEastWingHighlightingProps { interface FloorEastWingHighlightingProps {
handleOnMouseOut: () => void; handleOnMouseOut:
handleOnMouseOver: () => void; | (() => void)
| ((event: React.MouseEvent<SVGSVGElement, MouseEvent>) => void);
handleOnMouseOver: (
event: React.MouseEvent<SVGSVGElement, MouseEvent>
) => void | (() => void);
handleOnApartmentClick: ( handleOnApartmentClick: (
event: React.MouseEvent<SVGSVGElement, MouseEvent> event: React.MouseEvent<SVGSVGElement, MouseEvent>
) => void; ) => void;
@@ -14,6 +18,7 @@ function FloorEastWingHighlighting({
return ( return (
<> <>
<svg <svg
data-type="1 BR Squared"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick} onClick={handleOnApartmentClick}
@@ -42,6 +47,7 @@ function FloorEastWingHighlighting({
/> />
</svg> </svg>
<svg <svg
data-type="1 BR Squared"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick} onClick={handleOnApartmentClick}
@@ -97,6 +103,7 @@ function FloorEastWingHighlighting({
/> />
</svg> </svg>
<svg <svg
data-type="Studio Squared"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick} onClick={handleOnApartmentClick}
@@ -121,6 +128,7 @@ function FloorEastWingHighlighting({
/> />
</svg> </svg>
<svg <svg
data-type="Studio Squared"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick} onClick={handleOnApartmentClick}
@@ -169,6 +177,7 @@ function FloorEastWingHighlighting({
/> />
</svg> </svg>
<svg <svg
data-type="Studio Squared"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick} onClick={handleOnApartmentClick}
@@ -193,6 +202,7 @@ function FloorEastWingHighlighting({
/> />
</svg> </svg>
<svg <svg
data-type="2 BR Squared"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick} onClick={handleOnApartmentClick}
@@ -224,6 +234,7 @@ function FloorEastWingHighlighting({
/> />
</svg> </svg>
<svg <svg
data-type="2 BR Squared"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick} onClick={handleOnApartmentClick}
@@ -253,6 +264,7 @@ function FloorEastWingHighlighting({
/> />
</svg> </svg>
<svg <svg
data-type="1 BR Squared"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick} onClick={handleOnApartmentClick}
@@ -277,6 +289,7 @@ function FloorEastWingHighlighting({
/> />
</svg> </svg>
<svg <svg
data-type="1 BR Squared"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick} onClick={handleOnApartmentClick}
@@ -301,6 +314,7 @@ function FloorEastWingHighlighting({
/> />
</svg> </svg>
<svg <svg
data-type="Studio Flex"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick} onClick={handleOnApartmentClick}
@@ -326,6 +340,7 @@ function FloorEastWingHighlighting({
/> />
</svg> </svg>
<svg <svg
data-type="Studio Flex"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick} onClick={handleOnApartmentClick}
@@ -351,6 +366,7 @@ function FloorEastWingHighlighting({
/> />
</svg> </svg>
<svg <svg
data-type="Studio Flex"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick} onClick={handleOnApartmentClick}
@@ -376,6 +392,7 @@ function FloorEastWingHighlighting({
/> />
</svg> </svg>
<svg <svg
data-type="Studio Flex"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick} onClick={handleOnApartmentClick}
@@ -401,6 +418,7 @@ function FloorEastWingHighlighting({
/> />
</svg> </svg>
<svg <svg
data-type="Studio Flex"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick} onClick={handleOnApartmentClick}
@@ -426,6 +444,7 @@ function FloorEastWingHighlighting({
/> />
</svg> </svg>
<svg <svg
data-type="Studio Flex"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick} onClick={handleOnApartmentClick}
@@ -0,0 +1,386 @@
interface FloorEastWingTopHighlightingProps {
handleOnMouseOut:
| (() => void)
| ((event: React.MouseEvent<SVGSVGElement, MouseEvent>) => void);
handleOnMouseOver:
| (() => void)
| ((event: React.MouseEvent<SVGSVGElement, MouseEvent>) => void);
handleOnApartmentClick: (
event: React.MouseEvent<SVGSVGElement, MouseEvent>
) => void;
}
function FloorEastWingTopHighlighting({
handleOnMouseOut,
handleOnMouseOver,
handleOnApartmentClick,
}: FloorEastWingTopHighlightingProps) {
return (
<>
<svg
data-type="1 BR Squared"
onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick}
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
width="88"
height="70"
viewBox="0 0 88 70"
x={94.26}
y={39.61}
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M37.4416 47.1579L33.6245 45.3636L44.3253 23.4401L48.0444 25.2018L37.4416 47.1579Z"
fill="#00BED7"
fillOpacity="0.2"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M23.5133 58.544L25.5672 54.8287L55.5142 69.3691L65.2604 49.4993L66.359 50.057L67.937 46.9297L71.0509 48.5517C72.5722 49.3441 74.4475 48.7248 75.1976 47.1822L87.3465 22.1984C88.1364 20.5742 87.3476 18.6233 85.6507 18.0045L37.7803 0.547369C36.3212 0.015281 34.6954 0.666085 34.0066 2.05802L31.5133 7.09591L22.8819 2.98319L8.58992 32.2338L7.57561 31.7343L0.0341797 47.0746L1.58678 47.833L9.67981 51.7864L23.5133 58.544ZM37.4416 47.1579L33.6245 45.3636L44.3253 23.4401L48.0444 25.2018L37.4416 47.1579Z"
fill="#00BED7"
fillOpacity="0.2"
/>
</svg>
<svg
data-type="1 BR Squared"
onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick}
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
width="73"
height="87"
viewBox="0 0 73 87"
x={41}
y={0}
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M32.5912 58.5005L28.7741 56.7062L39.4749 34.7827L43.194 36.5444L32.5912 58.5005Z"
fill="#00BED7"
fillOpacity="0.2"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M28.2063 74.5399L42.2919 81.4206L50.3853 85.3742L51.8093 86.0698L59.1424 70.6884L57.9507 70.033L72.2416 40.9286L63.3587 36.7142L66.0572 31.6615C66.8135 30.2455 66.3411 28.4857 64.9774 27.6387L21.7582 0.796817C20.2225 -0.156957 18.1988 0.428848 17.4101 2.0555L5.33356 26.9622C4.61199 28.4504 5.20971 30.2424 6.68015 30.9995L10.161 32.7916L8.74124 35.8939L9.7403 36.3409L0.101562 56.2952L30.07 71.0002L28.2063 74.5399ZM32.5912 58.5005L28.7741 56.7062L39.4749 34.7827L43.194 36.5444L32.5912 58.5005Z"
fill="#00BED7"
fillOpacity="0.2"
/>
</svg>
<svg
onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick}
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
y={125}
x={9}
width="73"
height="57"
viewBox="0 0 73 57"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M17.3466 0.0617676H16.1783V56.5067H69.7002V51.5572H72.9689V39.5828V30.825H72.963V28.6804H59.9008V4.03219H47.0893V0.0617676H17.3466Z"
fill="#00BED7"
fillOpacity="0.2"
/>
<path
d="M15.6667 3.84307H0.666016V52.4613H15.6667V3.84307Z"
fill="#00BED7"
fillOpacity="0.2"
/>
</svg>
<svg
onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick}
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
x={99}
y={125}
width="78"
height="57"
viewBox="0 0 78 57"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M0.662109 39.7869V51.5515H4.03768V56.4767H57.5102V0.0410156H26.5681V4.05196H13.6902V28.6231H0.662109V30.8402V39.7869Z"
fill="#00BED7"
fillOpacity="0.2"
/>
<path
d="M57.9663 8.36376H77.5586V46.6439H57.9663V8.36376Z"
fill="#00BED7"
fillOpacity="0.2"
/>
</svg>
<svg
data-type="Studio Squared"
onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick}
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
x={4.46}
y={183}
width="77"
height="32"
viewBox="0 0 77 32"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M76.9691 5.32577V3.55554H73.7004V0.162842H18.1451V31.8098H21.5662V30.5281H53.9992V31.8224H71.6254V24.8243H76.9691V13.8638V5.32577Z"
fill="#00BED7"
fillOpacity="0.2"
/>
<path
d="M0.242188 4.14775V31.8098H17.7145V4.14775H0.242188Z"
fill="#00BED7"
fillOpacity="0.2"
/>
</svg>
<svg
data-type="Studio Squared"
onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick}
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
x={99}
y={183}
width="78"
height="32"
viewBox="0 0 78 32"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M0.662109 14.3096V24.8356H5.8425V31.9174H19.0689V30.5738H59.6759V0.113281H4.03768V3.5896H0.662109V5.22047V14.3096Z"
fill="#00BED7"
fillOpacity="0.2"
/>
<path
d="M60.0319 4.01643H77.5586V31.9174H60.0319V4.01643Z"
fill="#00BED7"
fillOpacity="0.2"
/>
</svg>
<svg
data-type="Studio Squared"
onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick}
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
x={4.46}
y={216}
width="77"
height="33"
viewBox="0 0 77 33"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M73.7448 32.5354V28.6863H76.9691V27.0022V18.4757V7.36456H71.6254V0.278274H53.9992V1.69553H21.5662V0.254639H18.1451V32.5354H73.7448Z"
fill="#00BED7"
fillOpacity="0.2"
/>
<path
d="M0.242188 0.254639V28.34H17.7145V0.254639H0.242188Z"
fill="#00BED7"
fillOpacity="0.2"
/>
</svg>
<svg
data-type="Studio Squared"
onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick}
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
x={99}
y={216.3}
width="78"
height="33"
viewBox="0 0 78 33"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M4.12126 28.5608V32.5681H59.6759V1.73959H19.0689V0.337321H5.8425V7.27978H0.662109V18.0732V27.0198V28.5608H4.12126Z"
fill="#00BED7"
fillOpacity="0.2"
/>
<path
d="M60.0319 0.289307H77.5586V28.4344H60.0319V0.289307Z"
fill="#00BED7"
fillOpacity="0.2"
/>
</svg>
<svg
onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick}
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
x={9}
y={250}
width="73"
height="57"
viewBox="0 0 73 57"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M72.9719 16.7399V4.98665H69.7446V0.0654297H16.1078V56.6636H47.167V52.6935H59.9591V27.8975H72.9719V25.7104V16.7399Z"
fill="#00BED7"
fillOpacity="0.2"
/>
<path
d="M15.5797 4.03601H0.666016V52.6572H15.5797V4.03601Z"
fill="#00BED7"
fillOpacity="0.2"
/>
</svg>
<svg
onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick}
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
x={99}
y={250}
width="78"
height="57"
viewBox="0 0 78 57"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M0.662109 25.804V27.9046H13.7708V52.7081H26.5361V56.6677H57.4948V0.0319824H4.12126V5.02312H0.662109V16.6865V25.804Z"
fill="#00BED7"
fillOpacity="0.2"
/>
<path
d="M77.4068 48.2411V9.79336H57.9888V48.2411H77.4068Z"
fill="#00BED7"
fillOpacity="0.2"
/>
</svg>
<svg
data-type="2 BR Squared"
onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick}
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
x={99}
y={343}
width="100"
height="84"
viewBox="0 0 100 84"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M69.1864 38.0339L72.0786 40.9467L50.681 62.2016L47.8587 59.2904L69.1864 38.0339Z"
fill="#00BED7"
fillOpacity="0.2"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M0.624023 31.6515V32.9749H6.40788L55.9138 82.4318L59.884 78.3635L65.4718 83.6572L94.9315 54.4612L76.7449 36.347L72.69 40.3426L54.5099 22.2023V0.268311H8.55087V2.78348H5.93509V21.4964H0.624023V22.6533V31.6515ZM69.1864 38.0339L72.0786 40.9467L50.681 62.2016L47.8587 59.2904L69.1864 38.0339Z"
fill="#00BED7"
fillOpacity="0.2"
/>
<path
d="M99.0468 36.5627L86.9001 24.5394C80.831 18.532 77.4163 10.3472 77.4163 1.80777V0.268311H55.2076V22.2023L72.69 39.7317L76.7449 35.6995L88.3716 47.2062L99.0468 36.5627Z"
fill="#00BED7"
fillOpacity="0.2"
/>
</svg>
<svg
data-type="1 BR Squared"
onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick}
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
x={4.46}
y={386.57}
width="77"
height="52"
viewBox="0 0 77 52"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M73.7537 5.51381V0.574219H18.2338V50.4153H50.4802V51.6531H70.4037V26.6998H76.9721V24.7513V15.56V5.51381H73.7537Z"
fill="#00BED7"
fillOpacity="0.2"
/>
<path
d="M17.7952 47.5694V4.83612H0.238281V47.5694H17.7952Z"
fill="#00BED7"
fillOpacity="0.2"
/>
</svg>
<svg
data-type="1 BR Squared"
onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick}
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
x={4.46}
y={439}
width="77"
height="52"
viewBox="0 0 77 52"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M50.4802 1.63666H18.2338V51.222H73.7027V46.2792H76.9721V36.0496V27.0335V25.1328H70.4037V0.324219H50.4802V1.63666Z"
fill="#00BED7"
fillOpacity="0.2"
/>
<path
d="M17.7952 4.45175H0.238281V47.0947H17.7952V4.45175Z"
fill="#00BED7"
fillOpacity="0.2"
/>
</svg>
<svg
data-type="2 BR Squared"
onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver}
onClick={handleOnApartmentClick}
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
x={4.45}
y={491.64}
width="90"
height="97"
viewBox="0 0 90 97"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M0.224609 47.0658H17.7949V4.80184H0.224609V47.0658Z"
fill="#00BED7"
fillOpacity="0.2"
/>
<path
d="M85.7376 96.2551V78.9278H58.9691V96.2551H85.7376Z"
fill="#00BED7"
fillOpacity="0.2"
/>
<path
d="M78.6838 19.4997H76.9718V5.51494H73.7024V0.63501H18.2335V50.2799H48.7934V54.433H55.3024V78.6627H89.0398H89.4037V19.4997H87.8314H78.6838Z"
fill="#00BED7"
fillOpacity="0.2"
/>
</svg>
</>
);
}
export default FloorEastWingTopHighlighting;
@@ -0,0 +1,417 @@
const FloorEastWingTopLayout = () => {
return (
<>
<path
fill="#F0F0E9"
d="M9.276 359.836v-26.089H81.69V98.61l-6.98-4.613 5.428-11.231.811.394 1.963-3.37 22.908 11.537-1.647 3.122 1.647.8-6.66 14.467.598 46.051v338.325H98.21l-2.31 4.617v11.842H81.388V359.836H9.277z"
></path>
<path
fill="#DAE0E6"
d="M79.124 485.687V496.159h3.773v-10.472h-3.773zM75.899 413.335v50.094h7.22v-50.094H75.9zM79.228 385.481v5.699h3.67v-5.699h-3.67zM5.149 381.446h73.784l.342-21.881H5.149v21.881zM4.316 333.942h78.542v-55.689h-13.3v24.921h-12.81v6.72H4.315v24.048zM83.111 244.95h-3.999v9.664h3.999v-9.664zM82.852 222.846h-5.776v-14.589h5.776v14.589zM79.15 176.97v9.22h3.665v-9.22h-3.666zM82.926 122.172v31.102H69.393v-24.592H56.625v-4.732l-27.262-1.277v-26.06H74.65l8.961 3.98v19.601l-.685 1.978zM39.355 57.334l-2.268 4.093 30.201 14.215 1.77-3.706-29.703-14.602zM118.69 96.088l-1.986 3.741-10.437-4.941-7.25 14.593v43.793h12.977v-24.592h13.023v-6.51h22.028v-6.503l-.231-1.016 2.032-4.156-30.156-14.409zM102.715 176.97H98.77v9.22h3.945v-9.22zM104.416 222.846h-5.578v-14.589h5.578v14.589zM102.712 244.777h-3.843v9.837h3.843v-9.837zM112.018 278.253H98.946l-.317 36.031h4.087v-5.356h16.702v-1.304h5.532v-4.686h-12.932v-24.685zM104.298 336.283h-5.53v27.775h5.53v-18.752h2.911v-2.952h-2.911v-6.071zM105.248 376.421h-6.48l-.448.887V493.45h50.965v-72.679l-44.037-44.35z"
></path>
<path
stroke="#0D1922"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M112.708 453.528v21.03m2.513 0v-21.03m2.415 21.03v-21.03m2.611 21.03v-21.03m2.342 0v21.03m2.512 0v-21.03m2.416 21.03v-21.03m2.366 21.03v-21.03m2.537 21.03v-21.03m2.513 21.03v-11.222m0-9.808v9.808m0 0h2.391v-9.808M47.74 98.763v21.144m2.513 0V98.763m2.415 21.144V98.763m2.61 21.144V98.763m2.343 0v21.144m2.513 0V98.763m2.415 21.144V98.763m2.366 21.144V98.763m2.538 21.144V98.763m2.295 21.144V98.764M57.074 306.688l11.857-3.226m0 3.226l-11.857-3.368M99.4 313.752c.056-.041 1.933-2.707 2.865-4.034m-2.865 0l2.865 4.034m10.462-6.951l11.808-3.284m0 3.179l-11.808-3.179m-33.237-49.259l2.907-4.156m-2.907 0l2.907 4.156m-2.907-5.72l2.907-3.223m-2.907 0l2.907 3.223m17.05 5.72l2.907-4.156m-2.908 0l2.908 4.156m-2.908-5.72l2.908-3.223m-2.908 0l2.908 3.223m-24.937-25.966l4.971-14.034m-4.971 0l4.971 14.034m17.036 0l4.818-13.92h-4.818l4.818 13.92M79.375 185.77l3.001-2.586m-3 0l3 2.586m-3-4.278l3-4.071m-3 0l3 4.071m17.061 4.278l3.001-2.586m-3 0l3 2.586m-3-4.278l3-4.071m-3 0l3 4.071M57.185 128.33l11.692-3.226m-11.692 0l11.692 3.226m43.833.039l11.886-3.324m0 3.324l-11.886-3.324m-81.427-5.026l5.014-21.249m-5.014 0l5.014 21.249m1.722-58.946l30.304 11.012m-28.835-14.03l27.57 16.967m50.555 24.849l30.303 11.012m-28.835-14.03l27.571 16.966M82.4 386.618l-2.836 4.222m0-4.222l2.836 4.222m17.678-8.437l3.774-5.626m-4.202 0l3.679 5.626m-20.956 31.508l-5.752 23.791m0-23.791l5.752 23.791m0 1.61l-5.752 23.791m0-23.791l5.752 23.791m-2.931 22.847l3.01 4.382v-4.382l-3.01 4.382m0 1.191l3.01 4.382m0-4.382l-3.01 4.382"
></path>
<path
fill="#fff"
d="M11.664 360.093v.49h5.752v-.49h-5.752zM23.168 360.583v-.49h-5.752v.49h5.752z"
></path>
<path
stroke="#0D1922"
strokeWidth="0.152"
d="M11.45 361.972h-.424v14.136h12.565v-14.136h-.423m-11.719 0v-1.389h.215m-.215 1.389h11.72m0-1.389v1.389m0-1.389v-.49h-5.753m5.752.49h-5.752m-5.752 0v-.49h5.752m-5.752.49h5.752m0-.49v.49"
></path>
<path
fill="#fff"
d="M11.664 333.339v-.491h5.752v.491h-5.752zM23.168 332.848v.491h-5.752v-.491h5.752z"
></path>
<path
stroke="#0D1922"
strokeWidth="0.152"
d="M11.45 331.459h-.424v-14.135h12.565v14.135h-.423m-11.719 0v1.389h.215m-.215-1.389h11.72m0 1.389v-1.389m0 1.389v.491h-5.753m5.752-.491h-5.752m-5.752 0v.491h5.752m-5.752-.491h5.752m0 .491v-.491"
></path>
<path
fill="#fff"
d="M36.55 360.093v.49h5.752v-.49H36.55zM48.054 360.583v-.49h-5.752v.49h5.752z"
></path>
<path
stroke="#0D1922"
strokeWidth="0.152"
d="M36.335 361.973h-.423v14.135h12.565v-14.135h-.423m-11.719 0v-1.39h.215m-.215 1.39h11.719m0-1.39v1.39m0-1.39v-.49h-5.752m5.752.49h-5.752m-5.752 0v-.49h5.752m-5.752.49h5.752m0-.49v.49"
></path>
<path
fill="#fff"
d="M36.55 333.339v-.491h5.752v.491H36.55zM48.054 332.848v.491h-5.752v-.491h5.752z"
></path>
<path
stroke="#0D1922"
strokeWidth="0.152"
d="M36.335 331.459h-.423v-14.135h12.565v14.135h-.423m-11.719 0v1.389h.215m-.215-1.389h11.719m0 1.389v-1.389m0 1.389v.491h-5.752m5.752-.491h-5.752m-5.752 0v.491h5.752m-5.752-.491h5.752m0 .491v-.491"
></path>
<path
fill="#fff"
d="M61.18 333.339v-.491h5.752v.491H61.18zM72.684 332.848v.491h-5.752v-.491h5.752z"
></path>
<path
stroke="#0D1922"
strokeWidth="0.152"
d="M60.965 331.459h-.423v-14.135h12.565v14.135h-.423m-11.719 0v1.389h.215m-.215-1.389h11.719m0 1.389v-1.389m0 1.389v.491h-5.752m5.752-.491h-5.752m-5.752 0v.491h5.752m-5.752-.491h5.752m0 .491v-.491"
></path>
<path
fill="#fff"
d="M121.423 431.529h.49v5.336h-.49v-5.336zM121.913 442.2h-.49v-5.335h.49v5.335z"
></path>
<path
stroke="#0D1922"
strokeWidth="0.152"
d="M123.302 431.529h18.106V442.2h-18.106m0-10.671h-1.389m1.389 0V442.2m0 0h-1.389m0-10.671h-.49v5.336m.49-5.336v5.336m0 5.335h-.49v-5.335m.49 5.335v-5.335m-.49 0h.49"
></path>
<path
fill="#F3F3F2"
d="M81.97 188.326v-1.77H78.7v-3.393H23.145v31.647h3.421v-1.282H59v1.294h17.626v-6.998h5.344v-19.498zM5.242 187.148v27.662h17.473v-27.662H5.242z"
></path>
<path
fill="#fff"
d="M78.745 248.535v-3.849h3.224V223.365h-5.344v-7.087H59v1.418H26.566v-1.441h-3.42v32.28h55.599zM5.242 216.255v28.085h17.473v-28.085H5.242zM99.662 197.31v10.526h5.181v7.081h13.226v-1.343h40.607v-30.461h-55.638v3.477h-3.376V197.31zM159.032 187.016h17.527v27.901h-17.527v-27.901z"
></path>
<path
fill="#F3F3F2"
d="M103.121 244.561v4.007h55.555V217.74h-40.607v-1.403h-13.226v6.943h-5.18v21.281h3.458zM159.032 216.289h17.527v28.145h-17.527v-28.145zM104.935 341.593h53.775v-30.691h-40.646v-1.244H103.01v4.88h-3.386v21.418h5.311v5.637zM176.416 341.593v-26.575h-17.374v26.575h17.374z"
></path>
<path
fill="#fff"
d="M26.347 125.062h-1.169v56.445H78.7v-4.95h3.269v-20.732h-.006v-2.145H68.901v-24.648H56.089v-3.97H26.347zM24.667 128.843H9.666v48.618h15v-48.618z"
></path>
<path
fill="#F3F3F2"
d="M81.972 266.74v-11.753h-3.227v-4.922H25.108v56.599h31.059v-3.97h12.792v-24.796h13.013V266.74zM24.58 254.036H9.666v48.621H24.58v-48.621z"
></path>
<path
fill="#fff"
d="M78.754 391.514v-4.94h-55.52v49.841H55.48v1.238h19.924V412.7h6.568v-21.186h-3.218zM22.795 433.569v-42.733H5.238v42.733h17.557z"
></path>
<path
fill="#F3F3F2"
d="M55.48 440.637H23.234v49.585h55.469v-4.943h3.27V464.133h-6.57v-24.809H55.48v1.313zM22.795 443.452H5.238v42.643h17.557v-42.643z"
></path>
<path
fill="#fff"
d="M5.225 538.066h17.57v-42.264H5.225v42.264zM90.738 587.255v-17.327H63.969v17.327h26.769zM83.684 510.5h-1.712v-13.985h-3.27v-4.88H23.234v49.645h30.56v4.153h6.508v24.23h34.102V510.5h-10.72z"
></path>
<path
fill="#fff"
fillRule="evenodd"
d="M99.624 374.651v1.324h5.784l49.506 49.457 3.97-4.069 5.588 5.294 29.459-29.196-18.186-18.114-4.055 3.996-18.18-18.141v-21.934h-45.959v2.515h-2.616v18.713h-5.311v10.155zm68.562 6.383l2.893 2.913-21.398 21.255-2.822-2.912 21.327-21.256z"
clipRule="evenodd"
></path>
<path
fill="#fff"
d="M198.047 379.563L185.9 367.539a31.983 31.983 0 01-9.484-22.731v-1.54h-22.208v21.934l17.482 17.53 4.055-4.032 11.627 11.506 10.675-10.643zM99.662 275.804v2.101h13.109v24.803h12.765v3.96h30.959v-56.636h-53.374v4.991h-3.459v20.781zM176.407 298.241v-38.448h-19.418v38.448h19.418z"
></path>
<path
fill="#F3F3F2"
d="M99.662 164.787v11.764h3.376v4.926h53.472v-56.436h-30.942v4.011H112.69v24.571H99.662v11.164zM156.966 133.364h19.593v38.28h-19.593v-38.28zM72.591 59.5l-3.817-1.794 10.7-21.923 3.72 1.761-10.603 21.957z"
></path>
<path
fill="#F3F3F2"
fillRule="evenodd"
d="M68.206 75.54l14.086 6.88 8.093 3.954 1.424.696 7.333-15.382-1.191-.655 14.291-29.104-8.883-4.215 2.698-5.053a3.046 3.046 0 00-1.08-4.022L61.758 1.797a3.046 3.046 0 00-4.348 1.258L45.334 27.962A3.046 3.046 0 0046.68 32l3.481 1.792-1.42 3.102 1 .447-9.64 19.954L70.07 72l-1.864 3.54zm4.385-16.04l-3.817-1.794 10.7-21.923 3.72 1.761-10.603 21.957z"
clipRule="evenodd"
></path>
<path
fill="#fff"
d="M130.442 87.158l-3.817-1.794 10.7-21.924 3.719 1.762-10.602 21.956z"
></path>
<path
fill="#fff"
fillRule="evenodd"
d="M116.513 98.544l2.054-3.715 29.947 14.54 9.746-19.87 1.099.558 1.578-3.127 3.114 1.622a3.047 3.047 0 004.147-1.37l12.149-24.984a3.047 3.047 0 00-1.696-4.194L130.78 40.547a3.045 3.045 0 00-3.773 1.511l-2.494 5.038-8.631-4.113-14.292 29.25-1.014-.499-7.542 15.34 1.553.759 8.093 3.953 13.833 6.758zm13.929-11.386l-3.817-1.794 10.7-21.924 3.719 1.762-10.602 21.956z"
clipRule="evenodd"
></path>
<path fill="#fff" d="M81.967 156.227h-8.194v.481h8.194v-.481z"></path>
<path
stroke="#0D1922"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M81.967 156.227v-.401h1.664v.401h-1.664zm0 0h-8.194v.481h8.194v-.481zm0 8.374v-.38h1.664v.38h-1.664z"
></path>
<path
stroke="#0D1922"
strokeDasharray="0.76 0.76"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M73.773 156.698c0 2.028.862 3.972 2.397 5.406 1.534 1.434 3.615 2.239 5.785 2.239"
></path>
<path
fill="#fff"
d="M89.906 85.806l3.691-7.315-.429-.216-3.692 7.315.43.216z"
></path>
<path
stroke="#0D1922"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M89.906 85.806l.357.181-.75 1.485-.357-.18.75-1.486zm0 0l3.691-7.315-.429-.216-3.692 7.315.43.216zm-7.477-3.773l.34.172-.75 1.485-.34-.172.75-1.485z"
></path>
<path
stroke="#0D1922"
strokeDasharray="0.76 0.76"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M93.177 78.279c-1.81-.914-3.935-1.02-5.906-.296-1.971.724-3.628 2.219-4.606 4.156"
></path>
<path
fill="#fff"
d="M95.055 88.192l3.596-7.362.435.212-3.596 7.363-.435-.213z"
></path>
<path
stroke="#0D1922"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M95.055 88.192l-.363-.177-.73 1.495.362.177.73-1.495zm0 0l3.596-7.362.435.212-3.596 7.363-.435-.213zm7.577 3.701l-.345-.168-.73 1.494.344.169.731-1.495z"
></path>
<path
stroke="#0D1922"
strokeDasharray="0.76 0.76"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M99.078 81.038c1.835.896 3.216 2.53 3.839 4.542.624 2.012.439 4.238-.513 6.188"
></path>
<path fill="#fff" d="M99.854 156.227h8.194v.481h-8.194v-.481z"></path>
<path
stroke="#0D1922"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M99.854 156.227v-.401H98.19v.401h1.663zm0 0h8.194v.481h-8.194v-.481zm0 8.374v-.38H98.19v.38h1.663z"
></path>
<path
stroke="#0D1922"
strokeDasharray="0.76 0.76"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M108.048 156.698c0 2.028-.862 3.972-2.397 5.406-1.534 1.434-3.615 2.239-5.785 2.239"
></path>
<path fill="#fff" d="M81.967 196.625h-8.194v-.481h8.194v.481z"></path>
<path
stroke="#0D1922"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M81.967 196.625v.401h1.664v-.401h-1.664zm0 0h-8.194v-.481h8.194v.481zm0-8.375v.381h1.664v-.381h-1.664z"
></path>
<path
stroke="#0D1922"
strokeDasharray="0.76 0.76"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M73.773 196.154c0-2.028.862-3.973 2.397-5.406 1.534-1.434 3.615-2.24 5.785-2.24"
></path>
<path fill="#fff" d="M99.854 196.624h8.194v-.48h-8.194v.48z"></path>
<path
stroke="#0D1922"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M99.854 196.624v.401H98.19v-.401h1.663zm0 0h8.194v-.48h-8.194v.48zm0-8.374v.38H98.19v-.38h1.663z"
></path>
<path
stroke="#0D1922"
strokeDasharray="0.76 0.76"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M108.048 196.153c0-2.028-.862-3.972-2.397-5.406-1.534-1.434-3.615-2.239-5.785-2.239"
></path>
<path fill="#fff" d="M81.967 234.688h-8.194v.481h8.194v-.481z"></path>
<path
stroke="#0D1922"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M81.967 234.688v-.401h1.664v.401h-1.664zm0 0h-8.194v.481h8.194v-.481zm0 8.375v-.381h1.664v.381h-1.664z"
></path>
<path
stroke="#0D1922"
strokeDasharray="0.76 0.76"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M73.773 235.159c0 2.028.862 3.972 2.397 5.406 1.534 1.434 3.615 2.239 5.785 2.239"
></path>
<path fill="#fff" d="M99.854 234.688h8.194v.481h-8.194v-.481z"></path>
<path
stroke="#0D1922"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M99.854 234.688v-.401H98.19v.401h1.663zm0 0h8.194v.481h-8.194v-.481zm0 8.375v-.381H98.19v.381h1.663z"
></path>
<path
stroke="#0D1922"
strokeDasharray="0.76 0.76"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M108.048 235.159c0 2.028-.862 3.972-2.397 5.406-1.534 1.434-3.615 2.239-5.785 2.239"
></path>
<path fill="#fff" d="M81.967 275.265h-8.194v-.481h8.194v.481z"></path>
<path
stroke="#0D1922"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M81.967 275.265v.401h1.664v-.401h-1.664zm0 0h-8.194v-.481h8.194v.481zm0-8.375v.381h1.664v-.381h-1.664z"
></path>
<path
stroke="#0D1922"
strokeDasharray="0.76 0.76"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M73.773 274.794c0-2.028.862-3.972 2.397-5.406 1.534-1.434 3.615-2.239 5.785-2.239"
></path>
<path fill="#fff" d="M99.854 275.265h8.194v-.481h-8.194v.481z"></path>
<path
stroke="#0D1922"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M99.854 275.265v.401H98.19v-.401h1.663zm0 0h8.194v-.481h-8.194v.481zm0-8.375v.381H98.19v-.381h1.663z"
></path>
<path
stroke="#0D1922"
strokeDasharray="0.76 0.76"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M108.048 274.794c0-2.028-.862-3.972-2.397-5.406-1.534-1.434-3.615-2.239-5.785-2.239"
></path>
<path fill="#fff" d="M99.854 324.66h8.194v-.481h-8.194v.481z"></path>
<path
stroke="#0D1922"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M99.854 324.66v.401H98.19v-.401h1.663zm0 0h8.194v-.481h-8.194v.481zm0-8.375v.381H98.19v-.381h1.663z"
></path>
<path
stroke="#0D1922"
strokeDasharray="0.76 0.76"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M108.048 324.189c0-2.028-.862-3.972-2.397-5.406-1.534-1.434-3.615-2.239-5.785-2.239"
></path>
<path fill="#fff" d="M99.854 374.188h8.194v-.481h-8.194v.481z"></path>
<path
stroke="#0D1922"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M99.854 374.188v.4H98.19v-.4h1.663zm0 0h8.194v-.481h-8.194v.481zm0-8.375v.38H98.19v-.38h1.663z"
></path>
<path
stroke="#0D1922"
strokeDasharray="0.76 0.76"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M108.048 373.716c0-2.027-.862-3.972-2.397-5.406-1.534-1.433-3.615-2.239-5.785-2.239"
></path>
<path fill="#fff" d="M99.854 445.343h8.194v-.48h-8.194v.48z"></path>
<path
stroke="#0D1922"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M99.854 445.343v.401H98.19v-.401h1.663zm0 0h8.194v-.48h-8.194v.48zm0-8.374v.38H98.19v-.38h1.663z"
></path>
<path
stroke="#0D1922"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M108.048 444.872c0-2.028-.862-3.972-2.397-5.406-1.534-1.434-3.615-2.239-5.785-2.239"
></path>
<path fill="#fff" d="M81.891 119.494h-8.194v-.495h8.194v.495z"></path>
<path
stroke="#0D1922"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M81.891 119.494v.413h1.664v-.413H81.89zm0 0h-8.194v-.495h8.194v.495zm0-8.63v.392h1.664v-.392H81.89z"
></path>
<path
stroke="#0D1922"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M73.697 119.009c0-2.09.862-4.094 2.397-5.571a8.348 8.348 0 015.785-2.308"
></path>
<path fill="#fff" d="M99.854 454.011h8.194v.481h-8.194v-.481z"></path>
<path
stroke="#0D1922"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M99.854 454.011v-.4H98.19v.4h1.663zm0 0h8.194v.481h-8.194v-.481zm0 8.375v-.381H98.19v.381h1.663z"
></path>
<path
stroke="#0D1922"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M108.048 454.483c0 2.027-.862 3.972-2.397 5.406-1.534 1.433-3.615 2.239-5.785 2.239"
></path>
<path fill="#fff" d="M81.967 410.098h-8.194v-.481h8.194v.481z"></path>
<path
stroke="#0D1922"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M81.967 410.098v.401h1.664v-.401h-1.664zm0 0h-8.194v-.481h8.194v.481zm0-8.375v.381h1.664v-.381h-1.664z"
></path>
<path
stroke="#0D1922"
strokeDasharray="0.76 0.76"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M73.773 409.626c0-2.027.862-3.972 2.397-5.405 1.534-1.434 3.615-2.24 5.785-2.24"
></path>
<path fill="#fff" d="M81.967 466.447h-8.194v.481h8.194v-.481z"></path>
<path
stroke="#0D1922"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M81.967 466.447v-.401h1.664v.401h-1.664zm0 0h-8.194v.481h8.194v-.481zm0 8.375v-.381h1.664v.381h-1.664z"
></path>
<path
stroke="#0D1922"
strokeDasharray="0.76 0.76"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M73.773 466.918c0 2.028.862 3.972 2.397 5.406 1.534 1.434 3.615 2.239 5.785 2.239"
></path>
<path fill="#fff" d="M92.31 510.661v8.193h-.48v-8.193h.48z"></path>
<path
stroke="#0D1922"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M92.31 510.661h.4v-1.664h-.4v1.664zm0 0v8.193h-.48v-8.193h.48zm-8.375 0h.381v-1.664h-.38v1.664z"
></path>
<path
stroke="#0D1922"
strokeDasharray="0.76 0.76"
strokeOpacity="0.7"
strokeWidth="0.152"
d="M91.84 518.854c-2.028 0-3.972-.862-5.406-2.396-1.434-1.534-2.24-3.616-2.24-5.786"
></path>
<path
fill="#81878C"
d="M168.185 381.035l2.892 2.913-21.397 21.255-2.823-2.912 21.328-21.256zM72.59 59.134l-3.817-1.795 10.7-21.923 3.72 1.762L72.59 59.134zM130.441 87.385l-3.817-1.794 10.701-21.924 3.719 1.762-10.603 21.956zM112.821 464.975v-1.6h22.012v1.6h-22.012z"
></path>
<path
fill="#81878C"
fillRule="evenodd"
d="M130.441 87.385l-3.817-1.794 10.701-21.924 3.719 1.762-10.603 21.956zM8.896 128.318h15.77v-4.137h.511v57.327H78.7v-4.95h3.269v-11.974h1.715v23.743h-1.715v-1.771h-3.27v-3.392H23.145v31.647h3.42v-1.282h32.434v1.294h17.626v-6.998h5.344v-10.96h1.715v37.612h-1.715v-11.111h-5.344v-7.087H58.998v1.418H26.565v-1.441h-3.421v32.28h55.6v-3.849h3.224v-1.684h1.715v23.738H81.97v-11.753h-3.228v-4.922H25.107v56.599h31.059v-3.97h12.792v-24.796H81.97v-2.188h1.712v59.549H71.829v-1.366h6.923v-21.439H55.127v21.439h6.924v1.366H47.08v-1.366h6.57v-21.439H30.767v21.439h6.505v1.366H22.119v-1.366h7.105v-21.439H5.543v21.439h6.838v1.366H.777v-28.595h23.801v-3.248H8.865V253.26h15.713v-3.194h-1.865v.391H9.932l-.366-.366v-.437h.366v-.836h-.366v-.497l.366-.367h12.781v-2.857H4.4v-58.929h18.314v-2.705H9.865l-.3-.299v-.421h.3v-.825h-.3v-.41l.367-.367h12.781v.367h1.968v-3.251H8.896v-49.939zm17.45-3.255V93.907h48.619l8.718 4.28v12.621h-4.067v-10.182l-3.773-1.854H37.848v21.21h45.835v35.844h-1.721v-2.145H68.899v-24.648H56.089v-3.97H26.345zm42.612 181.602v-3.248h-11.86v3.248h11.86zm1.11-28.086h12.434v28.086H70.07v-28.086zm-45.49-24.542H9.665v48.621h14.913v-48.621zm-19.337-9.696v-28.085h17.472v28.085H5.241zm0-57.193v27.663h17.472v-27.663H5.241zm77.16 21.397h-5.007v14.009H82.4v-14.009zm0 36.744v3.247h-2.888v-3.247h2.888zm0 8.938v-4.161h-2.888v4.161h2.888zm-3.004-71.063h3.004v2.6h-3.004v-2.6zm3.004-5.768h-3.004v4.112h3.004v-4.112zm-12.344-24.603h12.42v-27.73h-12.42v27.73zm-1.157-27.73v3.285H57.142v-3.285H68.9zm-44.235 3.781h-15v48.618h15v-48.618zm6.618-8.862h4.998v-21.21h-4.998v21.21zM83.683 358.039H47.08v1.551h6.556v21.455H30.875V359.59h6.397v-1.551H22.119v1.551h7.105v21.455H5.543V359.59h6.838v-1.551H.777v28.536h22.017v3.216H4.432v44.71h18.362v2.716H7.168l-.423.422v.48h.211v.818h-.21c.004.151.01.455 0 .465-.011.011.277.287.422.423h15.626V489.78H7.168l-.423.422v.404h.233v.688h-.233v.465l.423.422h15.626v2.914H4.376v43.644h18.418v7.067H59.964v24.123h3.128V588h28.241v-18.071h2.706v15.285l.299.299h.512v-.299h.656v.299h.356l.498-.498v-15.351h-.374v-60.662H92.83v1.499h1.573v59.163H60.3v-24.23h-6.509v-4.153h-30.56v-49.645h55.47v4.88h3.269v13.985h1.712V475.05H81.97v10.23H78.7v4.943H23.232v-49.586H55.48v-1.312h19.923v24.809h6.569v1.9h1.712v-55.281H81.97v1.948h-6.569v24.953H55.48v-1.238H23.232v-49.841h55.52v4.94h3.219v10.046h1.712v-43.522zm-60.89 180.028H5.224v-42.264h17.57v42.264zm67.944 49.189v-17.327h-26.77v17.327h26.77zM82.4 439.325h-5.78v23.583h5.78v-23.583zm0-25.42v23.749h-5.78v-23.749h5.78zm0 72.176h-2.853v4.142H82.4v-4.142zm-2.853 5.555H82.4v4.142h-2.853v-4.142zM22.794 390.837v42.734H5.237v-42.734h17.557zm32.403-31.247h23.555v21.455H55.197V359.59zm24.316 31.227h2.888v-4.242h-2.888v4.242z"
clipRule="evenodd"
></path>
<path
fill="#81878C"
d="M47.799 108.704v1.463h21.934v-1.463H47.799zM4.432 486.775h18.362v-.679H5.237v-42.643h17.557v-.768H4.432v44.09zM25.177 125.063h1.168v-.441h-1.168v.441zM9.389 358.039V335.26h-.297v22.779h.297zM74.965 93.907l5.26-11.04-.324-.157-5.35 11.197h.414z"
></path>
<path
fill="#81878C"
fillRule="evenodd"
d="M80.224 82.868l1.33.647.737-1.461-14.086-6.881 1.864-3.54L40.1 56.928l9.64-19.954-1-.447 1.42-3.102-.61-.314-2.87-1.478a3.046 3.046 0 01-1.347-4.038L57.409 2.69a3.046 3.046 0 014.348-1.259l43.219 26.842a3.046 3.046 0 011.08 4.023l-2.415 4.522-.283.53 8.882 4.215-14.29 29.104 1.191.656-7.333 15.38-1.424-.695c-.259.474-.769 1.425-.739 1.44l4.214 2.048.727-1.435-1.552-.758 7.541-15.34 1.014.499 14.292-29.25 8.632 4.112.299-.604 2.194-4.434a3.047 3.047 0 013.774-1.51l47.87 17.456a3.046 3.046 0 011.696 4.194L168.197 87.41a3.046 3.046 0 01-4.147 1.37l-2.911-1.517-.202-.105-1.579 3.127-.224-.114-.874-.444-9.746 19.87-29.947-14.54-2.054 3.715-13.834-6.758-.718 1.42 3.34 1.623-7.098 14.377v46.409h1.457v-2.217h13.028v-24.572h12.878v-4.01h30.942v56.435h-53.472v-4.925H99.66v-11.765h-1.457v23.433h1.457v-1.63h3.376v-3.477h55.638v30.461h-40.607v1.343h-13.226v-7.081h-5.18v-10.526h-1.458v36.763h1.457v-10.793h5.181v-6.943h13.226v1.402h40.607v30.829h-55.555v-4.007H99.66v-1.541h-1.457v23.667h1.457v-11.664h3.459v-4.991h53.374v56.636h-30.959v-3.96h-12.765v-24.803H99.66v-2.101h-1.457v40.259h1.42v-1.525h3.385v-4.88h15.054v1.244h40.647v30.691h-53.775v-5.637h-5.311v-10.799h-1.42v40.496h1.42v-1.157h5.311v-18.712h2.615v-2.516h45.959v21.934l18.181 18.141 4.054-3.996 18.187 18.114-29.46 29.196-5.587-5.293-3.971 4.068-49.506-49.457h-5.784v-1.324h-1.42v62.152h1.42v-14.41h14.852v8.921h5.539v-4.657h24.753v21.175h-24.753v-5.637h-5.539v5.637H99.622v-1.961h-1.42v7.598h46.564v21.109h-41.787v-11.928h-4.776v31.519h52.062v-71.049l8.757 8.75 1.322 1.321 5.267-5.074 29.87-29.914.254.26 9.095-9.261v-.531l-.275-.275-.366.275-.569-.587.294-.37-.294-.254-.699.254-8.795 9.122-6.095-6.136 11.123-11.137-13.272-13.25a29.698 29.698 0 01-8.717-21.019v-31.17H159.04v-4.149h15.595l.42-.42v-.341h-.42v-.833h.42v-.43l-.42-.42H159.04v-.863h-2.053v-7.719h20.178v-39.921h-20.2v-8.996h2.075v.342h15.595l.42-.42v-.341h-.42v-.833h.42v-.429l-.42-.421H159.04v-2.887h18.125v-58.853H159.03v-2.654h15.605l.42-.42v-.333h-.42v-.834h.42v-.472l-.42-.42H159.03v.42h-2.066v-8.927h20.201v-39.806h-20.201v-7.702h1.961v-4.342h-11.308v-5.496l13.437-27.028c.155.087 1.007.554 2.279 1.25a4.188 4.188 0 005.781-1.858l12.043-25.006a3.807 3.807 0 00-2.143-5.236l-48.005-17.244A3.807 3.807 0 00126.298 42l-2.209 4.54-8.683-4.176 4.135-8.373v-.558l-.538-.29-.33.29-.455-.29.103-.434-.289-.165-.74.304-4.137 8.486-8.68-3.987c.066-.114 1.057-2.158 2.353-4.839a3.808 3.808 0 00-1.407-4.883L62.226.581a3.808 3.808 0 00-5.451 1.575L44.628 27.374a3.808 3.808 0 001.701 5.045l2.957 1.508L35.911 61.3 79.9 82.71l.323.157zm19.436 39.309v-12.376l7.046-14.063 39.205 19.053v5.91h-27.745v1.476H99.66zm-.219 30.702h12.14v-29.155h-12.14v29.155zm13.247-29.155v4.646h11.938v-3.327h-6.46v-1.319h-5.478zm44.276 9.641h19.593v38.28h-19.593v-38.28zm19.593 53.652H159.03v27.901h17.527v-27.901zM159.03 216.29h17.527v28.145H159.03V216.29zm-54.828 6.211h-4.76v-13.867h4.76v13.867zm-4.76-36.75v-2.637h2.95v2.637h-2.95zm0-8.388v4.115h2.95v-4.115h-2.95zm0 71.206h2.875v-3.198h-2.876v3.198zm2.875 5.671h-2.876v-4.207h2.876v4.207zm9.264 53.79v-29.386h-12.14v29.386h12.14zm64.824-48.235v38.447h-19.418v-38.447h19.418zm-58.343 48.235h-5.293v-4.553h11.776v3.192h-6.483v1.361zm-15.781 1.629h-2.84v4.116h2.84v-4.116zm74.134 31.935V315.02H159.04v26.574h17.375zm9.484 25.946l12.146 12.024-10.675 10.643-11.627-11.506-4.054 4.032-17.483-17.53v-21.934h22.209v1.54a31.983 31.983 0 009.484 22.731zm-82.025 9.224h-4.251v5.587h9.842l-5.591-5.587zm-4.251 7.184h11.44l36.819 36.791h-48.26v-36.791zm.067 108.68v-12.137h49.037v12.137H99.69zm4.058-129.077h-4.307v-26.917h4.307v26.917zM39.466 58.089l-1.432 2.927 28.982 13.998 1.368-2.927-28.918-13.998zm79.524 38.815l-1.401 2.696 28.994 14.217 1.47-3.047-29.063-13.866zm-14.056 247.912v-1.547h1.8v1.547h-1.8z"
clipRule="evenodd"
></path>
<path
fill="#81878C"
d="M50.16 33.425l8.384-17.776 44.814 21.698.283-.53L58.345 14.68l-8.794 18.43.609.314zM159.358 90.284l1.579-3.127.202.105 8.881-18.253-45.208-22.29-.299.604 44.588 22.102-9.967 20.745.224.114z"
></path>
</>
);
};
export default FloorEastWingTopLayout;
@@ -7,49 +7,70 @@ import FloorEastWingHighlighting from "./FloorEastWingHighlighting";
import FloorEastWingLayout from "./FloorEastWingLayout"; import FloorEastWingLayout from "./FloorEastWingLayout";
import useModal from "../../../store/useModal"; import useModal from "../../../store/useModal";
import AboutComplexModal from "../../modals/AboutComplexModal"; import AboutComplexModal from "../../modals/AboutComplexModal";
import _appartment from "../../../data/appartments.json"; import { IAparmentRes } from "../../../types/apartmentsRes";
import { IAppartmentComplex } from "../../../types/apartmentSphere"; import FloorEastWingTopLayout from "./FloorEastWingTopLayout";
import FloorEastWingTopHighlighting from "./FloorEastWingTopHighlighting";
const appartments = _appartment as IAppartmentComplex[]; // import _appartment from "../../../data/appartments.json";
// import { IAppartmentComplex } from "../../../types/apartmentSphere";
// const appartments = _appartment as IAppartmentComplex[];
interface IFloorSidebarProps { interface IFloorSidebarProps {
currentFloor: IDesctiptionFloor | null; currentFloor: IDesctiptionFloor | null;
onMouseEnter: () => void; onMouseEnter: () => void;
floorApartments: IAparmentRes[];
} }
const FloorSidebar = ({ currentFloor, onMouseEnter }: IFloorSidebarProps) => { const FloorSidebar = ({
currentFloor,
onMouseEnter,
floorApartments,
}: IFloorSidebarProps) => {
const [mousePos, setMousePos] = useState<number[]>([0, 0]); const [mousePos, setMousePos] = useState<number[]>([0, 0]);
const [isDescVisible, setIsDescVisible] = useState(false); const [isDescVisible, setIsDescVisible] = useState(false);
const [hoveredApartment, setHoveredApartment] = useState<IAparmentRes | null>(
null
);
const [is3DTourAvailable] = useState(true); const [is3DTourAvailable] = useState(true);
const { setModal } = useModal(); const { setModal } = useModal();
const descRef = useRef(null); const descRef = useRef(null);
function handleMouseMove(e: MouseEvent) {
const y = e.clientY - 175;
const x = e.clientX - window.innerWidth / 2 - 50;
setMousePos([x, y]);
}
function handleOnApartmentClick( function handleOnApartmentClick(
event: React.MouseEvent<SVGSVGElement, MouseEvent> event: React.MouseEvent<SVGSVGElement, MouseEvent>
) { ) {
const apartmentId = (event.target as HTMLElement).dataset.apartment; const apartmentType = event.currentTarget.dataset.type;
const apartment = appartments.find((aprt) => aprt.id === apartmentId); const apartment = floorApartments.find(
(aprt) => aprt.Unit_Type === apartmentType
);
if (apartment) { if (apartment) {
setModal(<AboutComplexModal apartment={apartment} />); setModal(<AboutComplexModal apartment={apartment} />);
setIsDescVisible(false); setIsDescVisible(false);
} }
} }
function handleMouseMove(e: MouseEvent) {
const y = e.clientY - 170;
// if(!descRef && !descRef?.current){
// const x = window.innerWidth / 2 - 54 - (descRef.current as React.LegacyRef<HTMLDivElement>).width;
// }
const x = e.clientX - window.innerWidth / 2 - 50;
setMousePos([x, y]);
}
function handleOnMouseOut(): void { function handleOnMouseOut(): void {
setIsDescVisible(false); setIsDescVisible(false);
} }
function handleOnMouseOver(): void { function handleOnMouseOver(
event: React.MouseEvent<SVGSVGElement, MouseEvent>
): void {
const apartmentType = event.currentTarget.dataset.type;
const _hoveredApartment = floorApartments.find(
(apart) => apart.Unit_Type === apartmentType
);
if (_hoveredApartment) {
setHoveredApartment(_hoveredApartment);
} else {
setHoveredApartment(null);
}
setIsDescVisible(true); setIsDescVisible(true);
} }
@@ -67,6 +88,7 @@ const FloorSidebar = ({ currentFloor, onMouseEnter }: IFloorSidebarProps) => {
style={{ top: `${mousePos[1]}px`, left: `${mousePos[0]}px` }} style={{ top: `${mousePos[1]}px`, left: `${mousePos[0]}px` }}
> >
<ApartmentDescription <ApartmentDescription
hoveredApartment={hoveredApartment}
descRef={descRef} descRef={descRef}
isVisible={isDescVisible} isVisible={isDescVisible}
is3DTourAvailable={is3DTourAvailable} is3DTourAvailable={is3DTourAvailable}
@@ -85,7 +107,7 @@ const FloorSidebar = ({ currentFloor, onMouseEnter }: IFloorSidebarProps) => {
<p className="text-s text-[#73787C]">{currentFloor?.wing}</p> <p className="text-s text-[#73787C]">{currentFloor?.wing}</p>
</div> </div>
<div className="bg-[#00BED7] text-white text-s px-2 py-[3px] rounded-3xl flex h-fit"> <div className="bg-[#00BED7] text-white text-s px-2 py-[3px] rounded-3xl flex h-fit">
<div className="leading-5">234 units</div> <div className="leading-5">{floorApartments.length} units</div>
</div> </div>
</div> </div>
<div className="px-4 py-[18px] bg-white flex gap-6 text-[#73787C] font-semibold text-caption-m rounded-2xl mb-2"> <div className="px-4 py-[18px] bg-white flex gap-6 text-[#73787C] font-semibold text-caption-m rounded-2xl mb-2">
@@ -127,7 +149,7 @@ const FloorSidebar = ({ currentFloor, onMouseEnter }: IFloorSidebarProps) => {
handleOnMouseOver={handleOnMouseOver} handleOnMouseOver={handleOnMouseOver}
/> />
</svg> </svg>
) : ( ) : currentFloor && currentFloor.floor <= 21 ? (
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
width="204" width="204"
@@ -142,6 +164,21 @@ const FloorSidebar = ({ currentFloor, onMouseEnter }: IFloorSidebarProps) => {
handleOnMouseOver={handleOnMouseOver} handleOnMouseOver={handleOnMouseOver}
/> />
</svg> </svg>
) : (
<svg
xmlns="http://www.w3.org/2000/svg"
width="205"
height="588"
fill="none"
viewBox="0 0 205 588"
>
<FloorEastWingTopLayout />
<FloorEastWingTopHighlighting
handleOnApartmentClick={handleOnApartmentClick}
handleOnMouseOut={handleOnMouseOut}
handleOnMouseOver={handleOnMouseOver}
/>
</svg>
)} )}
</div> </div>
</div> </div>
@@ -1,6 +1,10 @@
interface FloorWestWingHighlightingProps { interface FloorWestWingHighlightingProps {
handleOnMouseOut: () => void; handleOnMouseOut:
handleOnMouseOver: () => void; | (() => void)
| ((event: React.MouseEvent<SVGSVGElement, MouseEvent>) => void);
handleOnMouseOver: (
event: React.MouseEvent<SVGSVGElement, MouseEvent>
) => void;
handleOnApartmentClick: ( handleOnApartmentClick: (
e: React.MouseEvent<SVGSVGElement, MouseEvent> e: React.MouseEvent<SVGSVGElement, MouseEvent>
) => void; ) => void;
@@ -21,6 +25,7 @@ const FloorWestWingHighlighting = ({
viewBox="0 0 672 280" viewBox="0 0 672 280"
> >
<svg <svg
data-type="Studio Squared"
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer" className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
@@ -71,6 +76,7 @@ const FloorWestWingHighlighting = ({
</svg> </svg>
<svg <svg
data-type="Studio Squared"
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer" className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
@@ -96,6 +102,7 @@ const FloorWestWingHighlighting = ({
</svg> </svg>
<svg <svg
data-type="Studio Squared"
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer" className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
@@ -121,6 +128,7 @@ const FloorWestWingHighlighting = ({
</svg> </svg>
<svg <svg
data-type="1 BR Squared"
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer" className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
@@ -146,6 +154,7 @@ const FloorWestWingHighlighting = ({
</svg> </svg>
<svg <svg
data-type="1 BR Squared"
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer" className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
@@ -171,6 +180,7 @@ const FloorWestWingHighlighting = ({
</svg> </svg>
<svg <svg
data-type="1 BR Squared"
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer" className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
@@ -196,6 +206,7 @@ const FloorWestWingHighlighting = ({
</svg> </svg>
<svg <svg
data-type="Studio Squared"
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer" className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
@@ -221,6 +232,7 @@ const FloorWestWingHighlighting = ({
</svg> </svg>
<svg <svg
data-type="Studio Squared"
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer" className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
@@ -246,6 +258,7 @@ const FloorWestWingHighlighting = ({
</svg> </svg>
<svg <svg
data-type="Studio Squared"
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer" className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
@@ -271,6 +284,7 @@ const FloorWestWingHighlighting = ({
</svg> </svg>
<svg <svg
data-type="Studio Squared"
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer" className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
@@ -296,6 +310,7 @@ const FloorWestWingHighlighting = ({
</svg> </svg>
<svg <svg
data-type="1 BR Squared"
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer" className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
@@ -321,6 +336,7 @@ const FloorWestWingHighlighting = ({
</svg> </svg>
<svg <svg
data-type="1 BR Squared"
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer" className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
@@ -340,6 +356,7 @@ const FloorWestWingHighlighting = ({
></path> ></path>
</svg> </svg>
<svg <svg
data-type="2 BR Squared"
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer" className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
onMouseOut={handleOnMouseOut} onMouseOut={handleOnMouseOut}
onMouseOver={handleOnMouseOver} onMouseOver={handleOnMouseOver}
@@ -12,6 +12,9 @@ import {
mobileWidht, mobileWidht,
descriptions, descriptions,
} from "../../consts/masterplan"; } from "../../consts/masterplan";
import { getApartments } from "../../api/apartments";
import { updateAccessToken } from "../../api/updateAccessToken";
import { IAparmentRes, IApartmentsRes } from "../../types/apartmentsRes";
const skyGardenFloor = 22; const skyGardenFloor = 22;
@@ -31,6 +34,13 @@ const SequenceWing = () => {
const [isSkygardenSidebar, setIsSkygardenSidebar] = useState(false); const [isSkygardenSidebar, setIsSkygardenSidebar] = useState(false);
const [isFloorSidebar, setIsFloorSidebar] = useState(false); const [isFloorSidebar, setIsFloorSidebar] = useState(false);
const { setModal } = useModal(); const { setModal } = useModal();
const [apartments, setApartments] = useState<IAparmentRes[]>([]);
const [currentHoveredApartments, setCurrentHoveredApartments] = useState<
IAparmentRes[]
>([]);
const [selectedApartments, setSelectedApartments] = useState<IAparmentRes[]>(
[]
);
function handleResize() { function handleResize() {
const screenWidth = window.innerWidth; const screenWidth = window.innerWidth;
@@ -54,7 +64,6 @@ const SequenceWing = () => {
setLeft(_left); setLeft(_left);
} }
} }
const handleOnFloorMouseEnter = ( const handleOnFloorMouseEnter = (
e: React.MouseEvent<SVGPathElement, MouseEvent> e: React.MouseEvent<SVGPathElement, MouseEvent>
) => { ) => {
@@ -64,7 +73,15 @@ const SequenceWing = () => {
const _currentFloor = descriptions.find((desc) => desc.id === id); const _currentFloor = descriptions.find((desc) => desc.id === id);
if (!_currentFloor) return; if (!_currentFloor) return;
setHoverCurrentFloor(_currentFloor); setHoverCurrentFloor(_currentFloor);
const _currentHoveredApartments = apartments.filter((apartment) => {
const wing =
apartment.Unit_No.split("-")[0] === "E" ? "East Wing" : "West Wing";
return (
apartment.Floor === _currentFloor.floor && wing === _currentFloor.wing
);
});
setIsWrapperHovered(true); setIsWrapperHovered(true);
setCurrentHoveredApartments(_currentHoveredApartments);
}; };
const handleOnWingWrapperMouseEnter = ( const handleOnWingWrapperMouseEnter = (
@@ -78,8 +95,9 @@ const SequenceWing = () => {
}; };
const handleOnFloorClick = () => { const handleOnFloorClick = () => {
if (!currentHoveredFloor) return; if (!currentHoveredFloor && !currentHoveredApartments) return;
const screenWidth = window.innerWidth; const screenWidth = window.innerWidth;
setSelectedApartments(currentHoveredApartments);
setCurrentFloor(currentHoveredFloor); setCurrentFloor(currentHoveredFloor);
if (screenWidth < laptopWidth) { if (screenWidth < laptopWidth) {
setModal(<WingFloorModal />); setModal(<WingFloorModal />);
@@ -129,6 +147,28 @@ const SequenceWing = () => {
} }
}, [isSidebar]); }, [isSidebar]);
useEffect(() => {
const zohoToken = localStorage.getItem("ACCESS_TOKEN");
getApartments(zohoToken)
.catch((error) => {
const errorStatus = error.response.status;
if (errorStatus === 401) {
updateAccessToken().then((token) => {
if (token) {
getApartments(token);
}
});
}
})
.then((data) => {
const apartmentsData = (data as IApartmentsRes).apartments;
const updatedApartments = [...apartmentsData];
setApartments(updatedApartments);
});
}, []);
return ( return (
<div className="absolute left-0 overflow-hidden h-screen w-screen select-none "> <div className="absolute left-0 overflow-hidden h-screen w-screen select-none ">
<div <div
@@ -136,6 +176,7 @@ const SequenceWing = () => {
style={{ right: `${isFloorSidebar ? "0" : "-50%"}` }} style={{ right: `${isFloorSidebar ? "0" : "-50%"}` }}
> >
<FloorSidebar <FloorSidebar
floorApartments={selectedApartments}
currentFloor={currentFloor} currentFloor={currentFloor}
onMouseEnter={handleOnWingWrapperMouseLeave} onMouseEnter={handleOnWingWrapperMouseLeave}
/> />
@@ -193,7 +234,10 @@ const SequenceWing = () => {
}`, }`,
}} }}
> >
<FloorDescription descriptionFloor={currentHoveredFloor} /> <FloorDescription
descriptionFloor={currentHoveredFloor}
floorApartments={currentHoveredApartments}
/>
</div> </div>
<img <img
@@ -1,22 +1,24 @@
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { formatNumber } from "../../calc/formatNumber"; // import { formatNumber } from "../../calc/formatNumber";
import useModal from "../../store/useModal"; import useModal from "../../store/useModal";
import { ILayoutCard } from "../../types/layoutCard";
import Button from "../Button"; import Button from "../Button";
import BookingIcon from "../icons/BookingIcon"; import BookingIcon from "../icons/BookingIcon";
import HeartIcon from "../icons/Heart"; import HeartIcon from "../icons/Heart";
import { SendEnquiryModal } from "../modals/SendEnquryModal"; import { SendEnquiryModal } from "../modals/SendEnquryModal";
import { MobileModalWrapper } from "../modals/mobile/MobileModalWrapper"; import { MobileModalWrapper } from "../modals/mobile/MobileModalWrapper";
import SendEnquiryMobileModal from "../modals/mobile/SendEnquiryMobileModal"; import SendEnquiryMobileModal from "../modals/mobile/SendEnquiryMobileModal";
import { IAparmentRes } from "../../types/apartmentsRes";
import useFavorites from "../../store/useFavorites";
interface FavoriteAppartmentCardProps { interface FavoriteAppartmentCardProps {
card: ILayoutCard; card: IAparmentRes;
} }
const FavoriteAppartmentCard = ({ card }: FavoriteAppartmentCardProps) => { const FavoriteAppartmentCard = ({ card }: FavoriteAppartmentCardProps) => {
const { roveHome, floorEnd, floorStart, wing, apartmentType, square, cost } = const { Floor, Unit_Type, Total_Area_Sqft, Unit_No } = card;
card; const wing = Unit_No.split("-")[0] === "E" ? "East" : "West";
const navigate = useNavigate(); const navigate = useNavigate();
const { setFavorites } = useFavorites();
const { setModal } = useModal(); const { setModal } = useModal();
@@ -36,62 +38,92 @@ const FavoriteAppartmentCard = ({ card }: FavoriteAppartmentCardProps) => {
); );
}; };
const handleOnAddFavoriteClick = (
e: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
e.stopPropagation();
const favorites = localStorage.getItem("Favorites");
if (favorites) {
const _favorites = JSON.parse(favorites) as IAparmentRes[];
if (_favorites.some((apart) => apart.id === card.id)) {
const updatedFavorites = [..._favorites].filter(
(apart) => apart.id !== card.id
);
setFavorites(updatedFavorites);
const convertedFavorites = JSON.stringify(updatedFavorites);
localStorage.setItem("Favorites", convertedFavorites);
} else {
const updatedFavorites = [..._favorites, card];
setFavorites(updatedFavorites);
const convertedFavorites = JSON.stringify(updatedFavorites);
localStorage.setItem("Favorites", convertedFavorites);
}
}
};
return ( return (
<div <>
className="bg-white flex flex-col p-4 rounded-2xl gap-4 cursor-pointer select-none" <div
onClick={handleOnFavoriteCardClick} className="bg-white flex flex-col p-4 rounded-2xl gap-4 cursor-pointer select-none"
> onClick={handleOnFavoriteCardClick}
<div className="flex gap-4 justify-between"> >
<div className="flex gap-1 flex-col"> <div className="flex gap-4 justify-between">
<p className="text-[#00BED7] text-s leading-5"> <div className="flex gap-1 flex-col">
Rove Home {roveHome} <p className="text-[#00BED7] text-s leading-5">
</p> Rove Home {Unit_Type}
<div className="text-[#73787C] flex gap-2 items-center w-fit">
<p className="text-caption-m font-semibold leading-4">{wing}</p>
<div className="w-1 h-1 bg-[#E2E2DC] rounded-full"></div>
<p className="text-caption-m font-semibold leading-4">
Floor {floorStart}-{floorEnd}
</p> </p>
<div className="w-1 h-1 bg-[#E2E2DC] rounded-full"></div> <div className="text-[#73787C] flex gap-2 items-center w-fit">
<p className="text-caption-m font-semibold leading-4"> <p className="text-caption-m font-semibold leading-4">
Floor {floorStart}-{floorEnd} {wing} Wing
</p>
<div className="w-1 h-1 bg-[#E2E2DC] rounded-full"></div>
<p className="text-caption-m font-semibold leading-4">
Floor {Floor}
</p>
<div className="w-1 h-1 bg-[#E2E2DC] rounded-full"></div>
<p className="text-caption-m font-semibold leading-4">
{Unit_No}
</p>
</div>
</div>
<Button
onClick={handleOnAddFavoriteClick}
buttonType="favorite"
icon={<HeartIcon isFilled />}
isCircleRounded
/>
</div>
<div className="w-full aspect-square rounded-lg">
<img src="/images/layout-1.png" alt="" className="h-full" />
</div>
<div className="flex flex-col gap-3">
<div className="flex flex-col gap-1">
<p className="text[#0D1922] text-s">
{Unit_Type}, {Total_Area_Sqft} Sqft
</p>
<p className="text-[#00BED7] text-m font-bold">
{/* AED {formatNumber(cost, ",", 3, 1)} */}
Unavailiable
</p> </p>
</div> </div>
<Button
icon={<BookingIcon />}
text="Send Enquiry"
className="justify-center hidden lg:flex"
buttonType="cta"
onClick={handleOnSendEquiryClick}
/>
<Button
icon={<BookingIcon />}
text="Send Enquiry"
className="justify-center lg:hidden flex"
buttonType="cta"
onClick={handleOnMobileSendEquiryClick}
/>
</div> </div>
<Button
buttonType="favorite"
icon={<HeartIcon isFilled />}
isCircleRounded
/>
</div> </div>
<div className="w-full aspect-square rounded-lg"> </>
<img src="/images/layout-1.png" alt="" className="h-full" />
</div>
<div className="flex flex-col gap-3">
<div className="flex flex-col gap-1">
<p className="text[#0D1922] text-s">
{apartmentType}, {square} Sqft
</p>
<p className="text-[#00BED7] text-m font-bold">
AED {formatNumber(cost, ",", 3, 1)}
</p>
</div>
<Button
icon={<BookingIcon />}
text="Send Enquiry"
className="justify-center hidden lg:flex"
buttonType="cta"
onClick={handleOnSendEquiryClick}
/>
<Button
icon={<BookingIcon />}
text="Send Enquiry"
className="justify-center lg:hidden flex"
buttonType="cta"
onClick={handleOnMobileSendEquiryClick}
/>
</div>
</div>
); );
}; };
@@ -1,14 +1,11 @@
import { ILayoutCard } from "../../types/layoutCard"; import useFavorites from "../../store/useFavorites";
import FavoriteAppartmentCard from "./FavoriteApartmentCard"; import FavoriteAppartmentCard from "./FavoriteApartmentCard";
interface FavoriteCardListProps { const FavoriteCardList = () => {
cards: ILayoutCard[]; const { favorites } = useFavorites();
}
const FavoriteCardList = ({ cards }: FavoriteCardListProps) => {
return ( return (
<div className="grid lg:grid-cols-4 gap-4 grid-cols-2"> <div className="grid lg:grid-cols-4 gap-4 grid-cols-2">
{cards.map((card) => ( {favorites.map((card) => (
<FavoriteAppartmentCard card={card} key={card.id} /> <FavoriteAppartmentCard card={card} key={card.id} />
))} ))}
</div> </div>
@@ -1,21 +1,18 @@
import { useState, useRef, useEffect } from "react"; import { useState, useRef, useEffect } from "react";
import { ILayoutCard } from "../../types/layoutCard";
import FavoriteSliderCard from "./FavoriteSliderCard"; import FavoriteSliderCard from "./FavoriteSliderCard";
import Button from "../Button"; import Button from "../Button";
import RightArrowIcon from "../icons/RightArrowIcon"; import RightArrowIcon from "../icons/RightArrowIcon";
import LeftArrowIcon from "../icons/LeftArrowIcon"; import LeftArrowIcon from "../icons/LeftArrowIcon";
import { useSwipeable } from "react-swipeable"; import { useSwipeable } from "react-swipeable";
import useFavorites from "../../store/useFavorites";
interface FavoritesSliderProps { const FavoritesSlider = () => {
cards: ILayoutCard[];
}
const FavoritesSlider = ({ cards }: FavoritesSliderProps) => {
const [offset, setOffset] = useState(0); const [offset, setOffset] = useState(0);
const cardRef = useRef<HTMLDivElement | null>(null); const cardRef = useRef<HTMLDivElement | null>(null);
const [cardWidth, setCardWidth] = useState(0); const [cardWidth, setCardWidth] = useState(0);
const [buttonTopPos, setButtonTopPos] = useState(0); const [buttonTopPos, setButtonTopPos] = useState(0);
const [cols, setCols] = useState(2); const [cols, setCols] = useState(2);
const { favorites } = useFavorites();
const handlers = useSwipeable({ const handlers = useSwipeable({
trackMouse: true, trackMouse: true,
@@ -30,7 +27,7 @@ const FavoritesSlider = ({ cards }: FavoritesSliderProps) => {
}; };
const handleOnRightBtnClick = () => { const handleOnRightBtnClick = () => {
if (offset > -cards.length + cols + 1) { if (offset > -favorites.length + cols) {
setOffset((prev) => prev - 1); setOffset((prev) => prev - 1);
} }
}; };
@@ -86,22 +83,25 @@ const FavoritesSlider = ({ cards }: FavoritesSliderProps) => {
style={{ transform: `translateX(${offset * cardWidth}px)` }} style={{ transform: `translateX(${offset * cardWidth}px)` }}
> >
<div className="flex w-fit gap-4"> <div className="flex w-fit gap-4">
{Array.from({ length: Math.floor(cards.length / cols) }).map( {Array.from({ length: Math.ceil(favorites.length / cols) }).map(
(_, index) => { (_, index) => {
console.log("index", index);
return ( return (
<div <div
className="grid lg:grid-cols-4 grid-cols-2 gap-4 w-[calc(100vw-48px)] h-fit" className="grid lg:grid-cols-4 grid-cols-2 gap-4 w-[calc(100vw-48px)] h-fit"
key={index} key={index}
> >
{cards {favorites
.slice(index * cols, cols + index * cols) .slice(index * cols, cols + index * cols)
.map((card) => ( .map((card) => {
<FavoriteSliderCard return (
elementRef={cardRef} <FavoriteSliderCard
card={card} elementRef={cardRef}
key={card.id} card={card}
/> key={card.id}
))} />
);
})}
</div> </div>
); );
} }
@@ -1,15 +1,43 @@
import { formatNumber } from "../../calc/formatNumber"; // import { formatNumber } from "../../calc/formatNumber";
import { ILayoutCard } from "../../types/layoutCard"; import useFavorites from "../../store/useFavorites";
import { IAparmentRes } from "../../types/apartmentsRes";
import Button from "../Button"; import Button from "../Button";
import BookingIcon from "../icons/BookingIcon"; import BookingIcon from "../icons/BookingIcon";
import HeartIcon from "../icons/Heart"; import HeartIcon from "../icons/Heart";
interface FavoriteSliderCardProps { interface FavoriteSliderCardProps {
card: ILayoutCard; card: IAparmentRes;
elementRef: React.MutableRefObject<HTMLDivElement | null>; elementRef: React.MutableRefObject<HTMLDivElement | null>;
} }
const FavoriteSliderCard = ({ card, elementRef }: FavoriteSliderCardProps) => { const FavoriteSliderCard = ({ card, elementRef }: FavoriteSliderCardProps) => {
const wing = card.Unit_No.split("-")[0] === "E" ? "East" : "West";
const { setFavorites } = useFavorites();
const handleOnAddFavoriteClick = (
e: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
e.stopPropagation();
const favorites = localStorage.getItem("Favorites");
if (favorites) {
const _favorites = JSON.parse(favorites) as IAparmentRes[];
if (_favorites.some((apart) => apart.id === card.id)) {
const updatedFavorites = [..._favorites].filter(
(apart) => apart.id !== card.id
);
setFavorites(updatedFavorites);
const convertedFavorites = JSON.stringify(updatedFavorites);
localStorage.setItem("Favorites", convertedFavorites);
} else {
const updatedFavorites = [..._favorites, card];
setFavorites(updatedFavorites);
const convertedFavorites = JSON.stringify(updatedFavorites);
localStorage.setItem("Favorites", convertedFavorites);
}
}
};
return ( return (
<div className="rounded-ss-2xl rounded-se-2xl flex flex-col overflow-clip gap-6 select-none"> <div className="rounded-ss-2xl rounded-se-2xl flex flex-col overflow-clip gap-6 select-none">
<div <div
@@ -19,10 +47,15 @@ const FavoriteSliderCard = ({ card, elementRef }: FavoriteSliderCardProps) => {
<div className="flex justify-between"> <div className="flex justify-between">
<div className="flex text-subheadline-s font-semibold text-[#0D1922] select-none"> <div className="flex text-subheadline-s font-semibold text-[#0D1922] select-none">
<h2> <h2>
{card.apartmentType}, {card.square} Sqft {card.Unit_Type}, {card.Total_Area_Sqft} Sqft
</h2> </h2>
</div> </div>
<Button buttonType="favorite" icon={<HeartIcon isFilled />} /> <Button
buttonType="favorite"
icon={<HeartIcon isFilled />}
isCircleRounded
onClick={handleOnAddFavoriteClick}
/>
</div> </div>
<img <img
src="/images/layout-1.png" src="/images/layout-1.png"
@@ -33,28 +66,29 @@ const FavoriteSliderCard = ({ card, elementRef }: FavoriteSliderCardProps) => {
<div className="flex flex-col gap-1 pb-6 border-b"> <div className="flex flex-col gap-1 pb-6 border-b">
<p className="text-s text-[#73787C]">Price</p> <p className="text-s text-[#73787C]">Price</p>
<p className="text-[#0D1922] text-m"> <p className="text-[#0D1922] text-m">
AED {formatNumber(card.cost, ",", 3, 1)} Unavailable
{/* AED {formatNumber(card.cost, ",", 3, 1)} */}
</p> </p>
</div> </div>
<div className="flex flex-col gap-1 pb-6 border-b"> <div className="flex flex-col gap-1 pb-6 border-b">
<p className="text-s text-[#73787C]">Total Area</p> <p className="text-s text-[#73787C]">Total Area</p>
<p className="text-[#0D1922] text-m">{card.square} Sqft</p> <p className="text-[#0D1922] text-m">{card.Total_Area_Sqft} Sqft</p>
</div> </div>
<div className="flex flex-col gap-1 pb-6 border-b"> <div className="flex flex-col gap-1 pb-6 border-b">
<p className="text-s text-[#73787C]">Project</p> <p className="text-s text-[#73787C]">Project</p>
<p className="text-[#00BED7] text-m">Rove Home {card.roveHome}</p> <p className="text-[#00BED7] text-m">{card.Project_Name}</p>
</div> </div>
<div className="flex flex-col gap-1 pb-6 border-b"> <div className="flex flex-col gap-1 pb-6 border-b">
<p className="text-s text-[#73787C]">Section</p> <p className="text-s text-[#73787C]">Section</p>
<p className="text-[#0D1922] text-m">{card.wing}</p> <p className="text-[#0D1922] text-m">{wing} Wing</p>
</div> </div>
<div className="flex flex-col gap-1 pb-6 border-b"> <div className="flex flex-col gap-1 pb-6 border-b">
<p className="text-s text-[#73787C]">Floor</p> <p className="text-s text-[#73787C]">Floor</p>
<p className="text-[#0D1922] text-m">Floor 11</p> <p className="text-[#0D1922] text-m">Floor {card.Floor}</p>
</div> </div>
<div className="flex flex-col gap-1 pb-6 border-b"> <div className="flex flex-col gap-1 pb-6 border-b">
<p className="text-s text-[#73787C]">Number</p> <p className="text-s text-[#73787C]">Number</p>
<p className="text-[#0D1922] text-m">213</p> <p className="text-[#0D1922] text-m">{card.Unit_No}</p>
</div> </div>
<Button <Button
icon={<BookingIcon />} icon={<BookingIcon />}
+15 -1
View File
@@ -4,12 +4,15 @@ import { useNavigate, useLocation } from "react-router-dom";
import { Tab } from "../../../types/tab"; import { Tab } from "../../../types/tab";
import NavbarDesktop from "./NavbarDesktop"; import NavbarDesktop from "./NavbarDesktop";
import NavbarMobile from "./NavbarMobile"; import NavbarMobile from "./NavbarMobile";
import { tabs } from "../../../consts/tabs"; import { tabs as _tabs } from "../../../consts/tabs";
import useFavorites from "../../../store/useFavorites";
const Navbar = () => { const Navbar = () => {
const [selectedTab, setSelectedTab] = useState<Tab | null>(null); const [selectedTab, setSelectedTab] = useState<Tab | null>(null);
const [tabs, setTabs] = useState(_tabs);
const location = useLocation(); const location = useLocation();
const navigate = useNavigate(); const navigate = useNavigate();
const { favorites } = useFavorites();
const onTabClick = (tab: Tab) => { const onTabClick = (tab: Tab) => {
setSelectedTab(tab); setSelectedTab(tab);
@@ -27,6 +30,17 @@ const Navbar = () => {
} }
}, [location.pathname]); }, [location.pathname]);
useEffect(() => {
const updatedTabs = _tabs.map((tab) => {
if (tab.value === "Favorites") {
return { ...tab, count: favorites.length };
}
return tab;
});
setTabs(updatedTabs);
}, [favorites]);
return ( return (
<> <>
{isMobile ? ( {isMobile ? (
@@ -7,17 +7,47 @@ import Button from "../Button";
import SwitchToggle from "../SwitchToggle"; import SwitchToggle from "../SwitchToggle";
import HeartIcon from "../icons/Heart"; import HeartIcon from "../icons/Heart";
import LeftArrowSliderIcon from "../icons/LeftArrowSliderIcon"; import LeftArrowSliderIcon from "../icons/LeftArrowSliderIcon";
import { formatNumber } from "../../calc/formatNumber"; import { IAparmentRes } from "../../types/apartmentsRes";
import { IAppartmentComplex } from "../../types/apartmentSphere";
interface IApartmentRoute {
type: string;
virtualTour: string;
id: string;
}
const apartmentRoute: IApartmentRoute[] = [
{
type: "1 BR Squared",
virtualTour: "apartments-studio-3",
id: "1",
},
{
type: "Studio Squared",
virtualTour: "apartments-studio-2",
id: "2",
},
{
type: "2 BR Squared",
virtualTour: "apartments-studio-4",
id: "3",
},
{
type: "Studio Flex",
virtualTour: "apartments-studio-1",
id: "4",
},
];
interface AboutComplexModalProps { interface AboutComplexModalProps {
apartment: IAppartmentComplex; apartment: IAparmentRes;
} }
const AboutComplexModal = ({ apartment }: AboutComplexModalProps) => { const AboutComplexModal = ({ apartment }: AboutComplexModalProps) => {
const { setModal } = useModal(); const { setModal } = useModal();
const [currentLabel, setCurrentLabel] = useState(apartmentLayouts[0]); const [currentLabel, setCurrentLabel] = useState(apartmentLayouts[0]);
const navigate = useNavigate(); const navigate = useNavigate();
const unitNumber = apartment.Unit_No.split("-")[1];
const wing = apartment.Unit_No.split("-")[0] === "E" ? "East" : "West";
const handleOnBackClick = () => { const handleOnBackClick = () => {
setModal(false); setModal(false);
@@ -29,7 +59,15 @@ const AboutComplexModal = ({ apartment }: AboutComplexModalProps) => {
const handleOn3DTourClick = () => { const handleOn3DTourClick = () => {
setModal(null); setModal(null);
navigate(`../virtual-tour/${apartment.id}`); const virtualTour = apartmentRoute.find(
(route) => route.type === apartment.Unit_Type
);
const virtualRoute = virtualTour
? virtualTour.virtualTour
: "apartments-studio-1";
navigate(`../virtual-tour/${virtualRoute}`);
}; };
return ( return (
@@ -46,10 +84,10 @@ const AboutComplexModal = ({ apartment }: AboutComplexModalProps) => {
/> />
<div className="flex flex-col"> <div className="flex flex-col">
<p className="text-[#73787C] text-caption-m font-semibold"> <p className="text-[#73787C] text-caption-m font-semibold">
213 {unitNumber}
</p> </p>
<h2 className="text-subheadline-s font-semibold text-[#0D1922]"> <h2 className="text-subheadline-s font-semibold text-[#0D1922]">
1 bedroom apartment {apartment.Unit_Type}
</h2> </h2>
</div> </div>
</div> </div>
@@ -101,29 +139,32 @@ const AboutComplexModal = ({ apartment }: AboutComplexModalProps) => {
<div className="flex flex-col gap-3"> <div className="flex flex-col gap-3">
<div className="flex justify-between text-m"> <div className="flex justify-between text-m">
<p className="text-[#73787C]">Complex</p> <p className="text-[#73787C]">Complex</p>
<p className="text-[#0D1922]">ROVE Home Marasi Drive</p> <p className="text-[#0D1922]">{apartment.Project_Name}</p>
</div> </div>
<div className="flex justify-between text-m"> <div className="flex justify-between text-m">
<p className="text-[#73787C]">Section</p> <p className="text-[#73787C]">Section</p>
<p className="text-[#0D1922]">East Wing</p> <p className="text-[#0D1922]">{wing} Wing</p>
</div> </div>
<div className="flex justify-between text-m"> <div className="flex justify-between text-m">
<p className="text-[#73787C]">Floor</p> <p className="text-[#73787C]">Floor</p>
<p className="text-[#0D1922]">11</p> <p className="text-[#0D1922]">{apartment.Floor}</p>
</div> </div>
<div className="flex justify-between text-m"> <div className="flex justify-between text-m">
<p className="text-[#73787C]">Number</p> <p className="text-[#73787C]">Number</p>
<p className="text-[#0D1922]">213</p> <p className="text-[#0D1922]">{unitNumber}</p>
</div> </div>
<div className="flex justify-between text-m"> <div className="flex justify-between text-m">
<p className="text-[#73787C]">Size</p> <p className="text-[#73787C]">Size</p>
<p className="text-[#0D1922]">609 Sqft</p> <p className="text-[#0D1922]">
{Math.round(apartment.Total_Area_Sqft)} Sqft
</p>
</div> </div>
</div> </div>
</div> </div>
<div className="rounded-2xl bg-white flex flex-col p-6 gap-4 flex-1 lg:flex-none justify-between"> <div className="rounded-2xl bg-white flex flex-col p-6 gap-4 flex-1 lg:flex-none justify-between">
<p className="text-[#00BED7] font-semibold text-subheadline-s leading-7"> <p className="text-[#00BED7] font-semibold text-subheadline-s leading-7">
AED {formatNumber(1668888, ",", 3, 1)} Unvailiable
{/* AED {formatNumber(1668888, ",", 3, 1)} */}
</p> </p>
<div className="flex gap-2"> <div className="flex gap-2">
<Button <Button
@@ -3,6 +3,7 @@ import Button from "../Button";
import HeartIcon from "../icons/Heart"; import HeartIcon from "../icons/Heart";
import { IAparmentRes } from "../../types/apartmentsRes"; import { IAparmentRes } from "../../types/apartmentsRes";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import useFavorites from "../../store/useFavorites";
interface LayoutCardProps { interface LayoutCardProps {
apartmentCard: IAparmentRes; apartmentCard: IAparmentRes;
@@ -19,8 +20,10 @@ const LayoutCard = ({ apartmentCard }: LayoutCardProps) => {
} = apartmentCard; } = apartmentCard;
const wing = unit.split("-")[0] === "E" ? "East" : "West"; const wing = unit.split("-")[0] === "E" ? "East" : "West";
const unitNumber = unit.split("-")[1]; const unitNumber = unit.split("-")[1];
const totalArea = `${_totalArea}`.split(".").join(","); const totalArea = `${_totalArea}`.split(".").join(",");
const [isFavorite, setIsFavorite] = useState(false); const [isFavorite, setIsFavorite] = useState(false);
const { setFavorites } = useFavorites();
const navigate = useNavigate(); const navigate = useNavigate();
@@ -28,25 +31,32 @@ const LayoutCard = ({ apartmentCard }: LayoutCardProps) => {
navigate(`${id}`); navigate(`${id}`);
}; };
const handleOnFavoriteClick = () => { const handleOnFavoriteClick = (
e: React.MouseEvent<HTMLButtonElement, MouseEvent>
) => {
e.stopPropagation();
const favorites = localStorage.getItem("Favorites"); const favorites = localStorage.getItem("Favorites");
if (!favorites) { if (!favorites) {
setIsFavorite(true); setIsFavorite(true);
const updatedFavorites = JSON.stringify([apartmentCard]); const updatedFavorites = JSON.stringify([apartmentCard]);
localStorage.setItem("Favorites", updatedFavorites); localStorage.setItem("Favorites", updatedFavorites);
} else { } else {
const _favorites = JSON.parse(favorites) as IAparmentRes[]; const _favorites = JSON.parse(favorites) as IAparmentRes[];
if (_favorites.some((apart) => apart.id === apartmentCard.id)) { if (_favorites.some((apart) => apart.id === apartmentCard.id)) {
setIsFavorite(false); setIsFavorite(false);
const updatedFavorites = [..._favorites].filter( const updatedFavorites = [..._favorites].filter(
(apart) => apart.id !== apartmentCard.id (apart) => apart.id !== apartmentCard.id
); );
const convertedFavorites = JSON.stringify(updatedFavorites); const convertedFavorites = JSON.stringify(updatedFavorites);
setFavorites(updatedFavorites);
localStorage.setItem("Favorites", convertedFavorites); localStorage.setItem("Favorites", convertedFavorites);
} else { } else {
setIsFavorite(true); setIsFavorite(true);
const updatedFavorites = [..._favorites, apartmentCard]; const updatedFavorites = [..._favorites, apartmentCard];
setFavorites(updatedFavorites);
const convertedFavorites = JSON.stringify(updatedFavorites); const convertedFavorites = JSON.stringify(updatedFavorites);
localStorage.setItem("Favorites", convertedFavorites); localStorage.setItem("Favorites", convertedFavorites);
} }
@@ -8,96 +8,15 @@ import FilterIcon from "../icons/FilterIcon";
import useModal from "../../store/useModal"; import useModal from "../../store/useModal";
import { MobileModalWrapper } from "../modals/mobile/MobileModalWrapper"; import { MobileModalWrapper } from "../modals/mobile/MobileModalWrapper";
import SearchFiltersModal from "../modals/mobile/SearchFiltersModal"; import SearchFiltersModal from "../modals/mobile/SearchFiltersModal";
import { getApartments } from "../../api/apartments";
import { IAparmentRes, IApartmentsRes } from "../../types/apartmentsRes";
import { updateAccessToken } from "../../api/updateAccessToken"; import { updateAccessToken } from "../../api/updateAccessToken";
import useApartments from "../../store/useApartments"; import useApartments from "../../store/useApartments";
import useSearchFilters from "../../store/useSearchFilters"; import useSearchFilters from "../../store/useSearchFilters";
import { ICheckbox } from "../../types/checkbox";
import { IMultirangeSlider } from "../../types/multirangeSlider";
import { useDebounce } from "@uidotdev/usehooks"; import { useDebounce } from "@uidotdev/usehooks";
import { ISwitcher } from "../../types/switcher"; import {
import { initialSliders } from "../../consts/initialMasterplanFilters"; perPageInitial,
import { ISort } from "../../types/sortType"; pageInitial,
} from "../../consts/initialMasterplanFilters";
const getFilteredApartments = async ( import { getFilteredApartments } from "../../calc/getFilteredApartments";
zohoToken: string | null,
setApartments: (apartments: IAparmentRes[]) => void,
apartments: IAparmentRes[],
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;
const updatedApartments = [...apartments, ...apartmentsData];
setApartments(updatedApartments);
});
return res;
};
const LayoutOptions = () => { const LayoutOptions = () => {
const { apartments, setApartments } = useApartments(); const { apartments, setApartments } = useApartments();
@@ -113,6 +32,7 @@ const LayoutOptions = () => {
setSortList, setSortList,
page, page,
setPage, setPage,
setPerPage,
perPage, perPage,
} = useSearchFilters(); } = useSearchFilters();
const debouncedSliders = useDebounce(multirangeSliders, 300); const debouncedSliders = useDebounce(multirangeSliders, 300);
@@ -134,8 +54,11 @@ const LayoutOptions = () => {
}; };
function handleOnShowMoreBtnClick(): void { function handleOnShowMoreBtnClick(): void {
const nextPage = page + 1; const _page = page + 1;
setPage(nextPage); const _perPage = _page * perPageInitial;
setPage(_page);
setPerPage(_perPage);
} }
useEffect(() => { useEffect(() => {
@@ -144,17 +67,15 @@ const LayoutOptions = () => {
getFilteredApartments( getFilteredApartments(
zohoToken, zohoToken,
setApartments, setApartments,
apartments,
roveHomeTypeCheckboxes, roveHomeTypeCheckboxes,
apartmentTypeCheckboxes, apartmentTypeCheckboxes,
debouncedSliders, debouncedSliders,
switchers, switchers,
viewCheckboxes, viewCheckboxes,
sortList, sortList,
page, pageInitial,
perPage perPage
).catch((error) => { ).catch((error) => {
console.log("error", error);
const errorStatus = error.response.status; const errorStatus = error.response.status;
if (errorStatus === 401) { if (errorStatus === 401) {
@@ -163,14 +84,13 @@ const LayoutOptions = () => {
getFilteredApartments( getFilteredApartments(
token, token,
setApartments, setApartments,
apartments,
roveHomeTypeCheckboxes, roveHomeTypeCheckboxes,
apartmentTypeCheckboxes, apartmentTypeCheckboxes,
debouncedSliders, debouncedSliders,
switchers, switchers,
viewCheckboxes, viewCheckboxes,
sortList, sortList,
page, pageInitial,
perPage perPage
); );
} }
@@ -185,7 +105,6 @@ const LayoutOptions = () => {
switchers, switchers,
viewCheckboxes, viewCheckboxes,
sortList, sortList,
page,
perPage, perPage,
]); ]);
@@ -10,6 +10,8 @@ import {
initialSliders, initialSliders,
initialSwitchers, initialSwitchers,
initialRoveHomeCheckboxes, initialRoveHomeCheckboxes,
pageInitial,
perPageInitial,
} from "../../consts/initialMasterplanFilters"; } from "../../consts/initialMasterplanFilters";
const SidebarFilters = () => { const SidebarFilters = () => {
@@ -24,6 +26,8 @@ const SidebarFilters = () => {
setRoveHomeTypeCheckboxes, setRoveHomeTypeCheckboxes,
viewCheckboxes, viewCheckboxes,
setViewCheckboxes, setViewCheckboxes,
setPage,
setPerPage,
} = useSearchFilters(); } = useSearchFilters();
const handleOnCheckboxApartmentClick = (checkboxId: string) => { const handleOnCheckboxApartmentClick = (checkboxId: string) => {
@@ -89,6 +93,8 @@ const SidebarFilters = () => {
setRoveHomeTypeCheckboxes(initialRoveHomeCheckboxes); setRoveHomeTypeCheckboxes(initialRoveHomeCheckboxes);
setMultirangeSliders(initialSliders); setMultirangeSliders(initialSliders);
setSwitchers(initialSwitchers); setSwitchers(initialSwitchers);
setPage(pageInitial);
setPerPage(perPageInitial);
}; };
return ( return (
@@ -35,7 +35,7 @@ const SortButton = ({ sortList, onClick }: SortButtonProps) => {
</button> </button>
<div <div
className={`absolute z-20 flex flex-col bg-white p-2 text-[#0D1922] rounded-lg w-full shadow-lg transition-opacity duration-300 ease-in-out ${ className={`absolute z-20 flex flex-col bg-white p-2 text-[#0D1922] rounded-lg w-full shadow-lg transition-opacity duration-300 ease-in-out ${
isSelected ? "opacity-100" : "opacity-0" isSelected ? "opacity-100" : "opacity-0 pointer-events-none hidden"
}`} }`}
> >
{sortList.map((sort) => ( {sortList.map((sort) => (
@@ -12,6 +12,7 @@ const initialSliders: IMultirangeSlider[] = [
title: "Cost", title: "Cost",
unit: "AED", unit: "AED",
id: "1", id: "1",
isDisabled: true,
}, },
{ {
minValue: 341, minValue: 341,
@@ -68,7 +69,7 @@ const initialRoveHomeCheckboxes: ICheckbox[] = [
{ {
title: "Downtown", title: "Downtown",
id: "1", id: "1",
disabled: false, disabled: true,
selected: false, selected: false,
value: "Rove Home Downtown", value: "Rove Home Downtown",
}, },
@@ -82,6 +83,7 @@ const initialRoveHomeCheckboxes: ICheckbox[] = [
title: "Dubai Marina", title: "Dubai Marina",
id: "3", id: "3",
selected: false, selected: false,
disabled: true,
value: "Rove Home Dubai Marina", value: "Rove Home Dubai Marina",
}, },
]; ];
@@ -113,6 +115,9 @@ const initialSortList: ISort[] = [
}, },
]; ];
const perPageInitial = 12;
const pageInitial = 1;
export { export {
initialAparmentTypeCheckboxes, initialAparmentTypeCheckboxes,
initialSliders, initialSliders,
@@ -120,4 +125,6 @@ export {
initialViewCheckboxes, initialViewCheckboxes,
initialRoveHomeCheckboxes, initialRoveHomeCheckboxes,
initialSortList, initialSortList,
perPageInitial,
pageInitial,
}; };
+141 -146
View File
@@ -5,146 +5,146 @@ import Footer from "../components/Footer";
import TrashIcon from "../components/icons/TrashIcon"; import TrashIcon from "../components/icons/TrashIcon";
import SortButton from "../components/searchPage/SortButton"; import SortButton from "../components/searchPage/SortButton";
import { initialSortList } from "../consts/initialMasterplanFilters"; import { initialSortList } from "../consts/initialMasterplanFilters";
import { ILayoutCard } from "../types/layoutCard";
import Switch from "../components/Switch"; import Switch from "../components/Switch";
import { ISwitcher } from "../types/switcher"; import { ISwitcher } from "../types/switcher";
import FavoritesSlider from "../components/favoritesPage/FavoriteSlider"; import FavoritesSlider from "../components/favoritesPage/FavoriteSlider";
import FavoriteCardList from "../components/favoritesPage/FavoriteCardList"; import FavoriteCardList from "../components/favoritesPage/FavoriteCardList";
import useFavorites from "../store/useFavorites";
const favoriteCards: ILayoutCard[] = [ // const favoriteCards: ILayoutCard[] = [
{ // {
id: "1", // id: "1",
roveHome: "Marasi Drive", // roveHome: "Marasi Drive",
apartmentType: "Studio Flex", // apartmentType: "Studio Flex",
wing: "East Wing", // wing: "East Wing",
floorStart: 11, // floorStart: 11,
floorEnd: 35, // floorEnd: 35,
units: 234, // units: 234,
cost: 10488888, // cost: 10488888,
square: 619, // square: 619,
}, // },
{ // {
id: "2", // id: "2",
roveHome: "Marasi Drive", // roveHome: "Marasi Drive",
apartmentType: "1 Bedroom", // apartmentType: "1 Bedroom",
wing: "East Wing", // wing: "East Wing",
floorStart: 11, // floorStart: 11,
floorEnd: 35, // floorEnd: 35,
units: 234, // units: 234,
cost: 1668888, // cost: 1668888,
square: 619, // square: 619,
}, // },
{ // {
id: "3", // id: "3",
roveHome: "Marasi Drive", // roveHome: "Marasi Drive",
apartmentType: "1 Bedroom", // apartmentType: "1 Bedroom",
wing: "East Wing", // wing: "East Wing",
floorStart: 11, // floorStart: 11,
floorEnd: 35, // floorEnd: 35,
units: 234, // units: 234,
cost: 1668888, // cost: 1668888,
square: 609, // square: 609,
}, // },
{ // {
id: "4", // id: "4",
roveHome: "Marasi Drive", // roveHome: "Marasi Drive",
apartmentType: "1 Bedroom", // apartmentType: "1 Bedroom",
wing: "East Wing", // wing: "East Wing",
floorStart: 11, // floorStart: 11,
floorEnd: 35, // floorEnd: 35,
units: 234, // units: 234,
cost: 1138888, // cost: 1138888,
square: 609, // square: 609,
}, // },
{ // {
id: "5", // id: "5",
roveHome: "Marasi Drive", // roveHome: "Marasi Drive",
apartmentType: "Studio Flex", // apartmentType: "Studio Flex",
wing: "East Wing", // wing: "East Wing",
floorStart: 11, // floorStart: 11,
floorEnd: 35, // floorEnd: 35,
units: 234, // units: 234,
cost: 10488888, // cost: 10488888,
square: 609, // square: 609,
}, // },
{ // {
id: "6", // id: "6",
roveHome: "Marasi Drive", // roveHome: "Marasi Drive",
apartmentType: "1 Bedroom", // apartmentType: "1 Bedroom",
wing: "East Wing", // wing: "East Wing",
floorStart: 11, // floorStart: 11,
floorEnd: 35, // floorEnd: 35,
units: 234, // units: 234,
cost: 1668888, // cost: 1668888,
square: 609, // square: 609,
}, // },
{ // {
id: "7", // id: "7",
roveHome: "Marasi Drive", // roveHome: "Marasi Drive",
apartmentType: "1 Bedroom", // apartmentType: "1 Bedroom",
wing: "East Wing", // wing: "East Wing",
floorStart: 11, // floorStart: 11,
floorEnd: 35, // floorEnd: 35,
units: 234, // units: 234,
cost: 1668888, // cost: 1668888,
square: 609, // square: 609,
}, // },
{ // {
id: "8", // id: "8",
roveHome: "Marasi Drive", // roveHome: "Marasi Drive",
apartmentType: "1 Bedroom", // apartmentType: "1 Bedroom",
wing: "East Wing", // wing: "East Wing",
floorStart: 11, // floorStart: 11,
floorEnd: 35, // floorEnd: 35,
units: 234, // units: 234,
cost: 1138888, // cost: 1138888,
square: 609, // square: 609,
}, // },
{ // {
id: "9", // id: "9",
roveHome: "Marasi Drive", // roveHome: "Marasi Drive",
apartmentType: "Studio Flex", // apartmentType: "Studio Flex",
wing: "East Wing", // wing: "East Wing",
floorStart: 11, // floorStart: 11,
floorEnd: 35, // floorEnd: 35,
units: 234, // units: 234,
cost: 10488888, // cost: 10488888,
square: 609, // square: 609,
}, // },
{ // {
id: "10", // id: "10",
roveHome: "Marasi Drive", // roveHome: "Marasi Drive",
apartmentType: "1 Bedroom", // apartmentType: "1 Bedroom",
wing: "East Wing", // wing: "East Wing",
floorStart: 11, // floorStart: 11,
floorEnd: 35, // floorEnd: 35,
units: 234, // units: 234,
cost: 1668888, // cost: 1668888,
square: 609, // square: 609,
}, // },
{ // {
id: "11", // id: "11",
roveHome: "Marasi Drive", // roveHome: "Marasi Drive",
apartmentType: "1 Bedroom", // apartmentType: "1 Bedroom",
wing: "East Wing", // wing: "East Wing",
floorStart: 11, // floorStart: 11,
floorEnd: 35, // floorEnd: 35,
units: 234, // units: 234,
cost: 1668888, // cost: 1668888,
square: 609, // square: 609,
}, // },
{ // {
id: "12", // id: "12",
roveHome: "Marasi Drive", // roveHome: "Marasi Drive",
apartmentType: "1 Bedroom", // apartmentType: "1 Bedroom",
wing: "East Wing", // wing: "East Wing",
floorStart: 11, // floorStart: 11,
floorEnd: 35, // floorEnd: 35,
units: 234, // units: 234,
cost: 1138888, // cost: 1138888,
square: 609, // square: 609,
}, // },
]; // ];
const initialCollectionCompareSwitcher: ISwitcher = { const initialCollectionCompareSwitcher: ISwitcher = {
id: "1", id: "1",
@@ -154,9 +154,8 @@ const initialCollectionCompareSwitcher: ISwitcher = {
const Favorites = () => { const Favorites = () => {
const [sortList, setSortList] = useState(initialSortList); const [sortList, setSortList] = useState(initialSortList);
// const [cards, setCards] = useState<ILayoutCard[]>([]);
const [cards, setCards] = useState(favoriteCards);
const [switcher, setSwitcher] = useState(initialCollectionCompareSwitcher); const [switcher, setSwitcher] = useState(initialCollectionCompareSwitcher);
const { favorites, setFavorites } = useFavorites();
const handleOnSortClick = (sortId: string) => { const handleOnSortClick = (sortId: string) => {
const updatedSortList = sortList.map((sort) => { const updatedSortList = sortList.map((sort) => {
@@ -174,7 +173,7 @@ const Favorites = () => {
const handleOnDeleteFavoriteClick = () => { const handleOnDeleteFavoriteClick = () => {
localStorage.removeItem("Favorites"); localStorage.removeItem("Favorites");
setCards([]); setFavorites([]);
}; };
useEffect(() => { useEffect(() => {
@@ -182,9 +181,9 @@ const Favorites = () => {
if (favoriteCards) { if (favoriteCards) {
const convertedCards = JSON.parse(favoriteCards); const convertedCards = JSON.parse(favoriteCards);
const sortedCards = sortCardBy(sortList, convertedCards); const sortedCards = sortCardBy(sortList, convertedCards);
setCards(sortedCards); setFavorites(sortedCards);
} }
}, [sortList]); }, [setFavorites, sortList]);
return ( return (
<div className="overflow-scroll h-screen w-screen pt-14"> <div className="overflow-scroll h-screen w-screen pt-14">
@@ -194,7 +193,7 @@ const Favorites = () => {
<div className="flex items-center gap-8"> <div className="flex items-center gap-8">
<div className="flex gap-4 font-semibold text-subheadline-s leading-7 py-[6px]"> <div className="flex gap-4 font-semibold text-subheadline-s leading-7 py-[6px]">
<h2 className="text-[#0D1922]">Units</h2> <h2 className="text-[#0D1922]">Units</h2>
<p className="text-[#73787C]">{cards.length}</p> <p className="text-[#73787C]">{favorites.length}</p>
</div> </div>
<SortButton sortList={sortList} onClick={handleOnSortClick} /> <SortButton sortList={sortList} onClick={handleOnSortClick} />
</div> </div>
@@ -228,11 +227,7 @@ const Favorites = () => {
</div> </div>
</div> </div>
</div> </div>
{switcher.isSwitched ? ( {switcher.isSwitched ? <FavoritesSlider /> : <FavoriteCardList />}
<FavoritesSlider cards={cards} />
) : (
<FavoriteCardList cards={cards} />
)}
</div> </div>
<Footer /> <Footer />
</div> </div>
+14
View File
@@ -0,0 +1,14 @@
import { create } from "zustand";
import { IAparmentRes } from "../types/apartmentsRes";
interface ApartmentsStore {
favorites: IAparmentRes[];
setFavorites: (favorites: IAparmentRes[]) => void;
}
const useFavorites = create<ApartmentsStore>((set) => ({
favorites: [],
setFavorites: (apartments) => set(() => ({ favorites: apartments })),
}));
export default useFavorites;
+2 -1
View File
@@ -11,6 +11,7 @@ import {
import { IMultirangeSlider } from "../types/multirangeSlider"; import { IMultirangeSlider } from "../types/multirangeSlider";
import { ISwitcher } from "../types/switcher"; import { ISwitcher } from "../types/switcher";
import { ISort } from "../types/sortType"; import { ISort } from "../types/sortType";
import { perPageInitial } from "../consts/initialMasterplanFilters";
interface Store { interface Store {
apartmentTypeCheckboxes: ICheckbox[]; apartmentTypeCheckboxes: ICheckbox[];
@@ -39,7 +40,7 @@ const useSearchFilters = create<Store>((set) => ({
switchers: initialSwitchers, switchers: initialSwitchers,
sortList: initialSortList, sortList: initialSortList,
page: 1, page: 1,
perPage: 12, perPage: perPageInitial,
setPerPage: (perPage) => set(() => ({ perPage: perPage })), setPerPage: (perPage) => set(() => ({ perPage: perPage })),
setPage: (page) => set(() => ({ page: page })), setPage: (page) => set(() => ({ page: page })),
setSortList: (sortList) => set(() => ({ sortList: sortList })), setSortList: (sortList) => set(() => ({ sortList: sortList })),
+1
View File
@@ -6,6 +6,7 @@ interface IMultirangeSlider {
title: string; title: string;
unit?: string; unit?: string;
id: string; id: string;
isDisabled?: boolean;
} }
export type { IMultirangeSlider }; export type { IMultirangeSlider };
+2 -1
View File
@@ -1,2 +1,3 @@
PORT=3000 PORT=3000
REFRESH_TOKEN=1000.da3146d49fa8a399f0c635e74954ff9c.e010dbb1bb605d7e1aa5bf7fc0521f8b REFRESH_TOKEN=1000.da3146d49fa8a399f0c635e74954ff9c.e010dbb1bb605d7e1aa5bf7fc0521f8b
URL=
+1 -1
View File
@@ -4,7 +4,7 @@
"version": "0.0.0", "version": "0.0.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "nodemon --exec node --import=./register.js ./src/index.ts", "dev": "nodemon --exec node --inspect --import=./register.js ./src/index.ts",
"build": "npx tsc --project ./", "build": "npx tsc --project ./",
"start": "node ./dist/index.js" "start": "node ./dist/index.js"
}, },
+1 -1
View File
@@ -173,7 +173,7 @@ function filterApartments(
router.get("/", async (req, res) => { router.get("/", async (req, res) => {
const accessToken = req?.headers?.authorization; const accessToken = req?.headers?.authorization;
const { const {
per_page = 20, per_page = 1000,
page = 1, page = 1,
rove_home = "", rove_home = "",
apartment_type = "", apartment_type = "",