diff --git a/client/src/components/complexWingPage/SkygardenSidebar/SkyGardenSlider.tsx b/client/src/components/complexWingPage/SkygardenSidebar/SkyGardenSlider.tsx index 26e95df..5ba75f2 100644 --- a/client/src/components/complexWingPage/SkygardenSidebar/SkyGardenSlider.tsx +++ b/client/src/components/complexWingPage/SkygardenSidebar/SkyGardenSlider.tsx @@ -49,8 +49,8 @@ function SkyGardenSlider() { }px + ${currentSlideIndex * 32}px))`, }} > - {images.map((image) => ( - + {images.map((image, index) => ( + ))} )} diff --git a/client/src/main.tsx b/client/src/main.tsx index fb18761..22c0339 100644 --- a/client/src/main.tsx +++ b/client/src/main.tsx @@ -5,18 +5,14 @@ import DefaultLayout from "./layouts/DefaultLayout"; import MasterplanPage from "./pages/MasterplanPage"; import ComplexPage from "./pages/ComplexPage"; import ComplexWingPage from "./pages/ComplexWingPage"; -// import AboutProjectsPage from "./pages/AboutProjectsPage"; import UnitTypesPage from "./pages/UnitTypesPage"; import AboutPage from "./pages/AboutPage"; -// import ApartmentPage from "./pages/ApartmentPage"; import VirtualTourPage from "./pages/VirtualTourPage"; import UnitTypesItemPage from "./pages/UnitTypesItemPage"; -import SearchPage2 from "./pages/SearchPage2"; -import FavoritesPage2 from "./pages/FavoritesPage2"; import WithFooterLayout from "./layouts/WithFooterLayout"; -// import AboutProjectsPage from "./pages/AboutProjectsPage"; -import AboutProjects2Page from "./pages/AboutProjects2Page"; -import TestPage from "./pages/TestPage"; +import AboutProjectsPage from "./pages/AboutProjectsPage"; +import SearchPage from "./pages/SearchPage"; +import FavoritesPage from "./pages/FavoritesPage"; const router = createBrowserRouter([ { @@ -43,10 +39,6 @@ const router = createBrowserRouter([ path: "virtual-tour/:unitType", element: , }, - { - path: "test", - element: , - }, ], }, { @@ -55,7 +47,7 @@ const router = createBrowserRouter([ children: [ { path: "about-projects", - element: , + element: , }, { path: "about", @@ -63,16 +55,12 @@ const router = createBrowserRouter([ }, { path: "favorites", - element: , + element: , }, { path: "search", - element: , + element: , }, - // { - // path: "search/:id", - // element: , - // }, { path: "unit-types", children: [ diff --git a/client/src/pages/AboutPage.tsx b/client/src/pages/AboutPage.tsx index c719ae8..f14ea87 100644 --- a/client/src/pages/AboutPage.tsx +++ b/client/src/pages/AboutPage.tsx @@ -30,7 +30,7 @@ const AboutPage = () => { -
+

@@ -60,7 +60,11 @@ const AboutPage = () => {

- +
diff --git a/client/src/pages/AboutProjects2Page.tsx b/client/src/pages/AboutProjects2Page.tsx deleted file mode 100644 index e8940f6..0000000 --- a/client/src/pages/AboutProjects2Page.tsx +++ /dev/null @@ -1,312 +0,0 @@ -import { useNavigate } from "react-router-dom"; -import AdvantageCard from "../components/AboutProject/AdvantageCard"; -import PlaceCard from "../components/AboutProject/PlaceCard"; -import UnitCard from "../components/AboutProject/UnitCard"; -import Button2 from "../components/Button2"; -import ArrowLeftIcon from "../components/icons/ArrowLeftIcon"; -import Logo2Icon from "../components/icons/Logo2Icon"; -import ConsultantCard from "../components/AboutProject/ConsultantCard"; -import Slider from "../components/AboutProject/Slider"; - -function AboutProjects2Page() { - const navigate = useNavigate(); - - return ( -
-
-

- Rove Home this residence a complete ecosystem that has everything - you’ll ever need. This isn’t just where you’ll live. -
- It’s where you’ll thrive. -

-
-
-
-

- ABOUT ROVE HOME -

-

- Embrace Rove’s forever-young spirit at Rove Home, where - inspiring design and vibrant art installations converge with an - exceptional location and an extended playlist of life-enhancing{" "} -

-
- } - onClick={() => navigate("/masterplan/1/wing")} - > - Masterplan - -
-
- -
-
-
- -
- -
- -
-
-
-

- ROVE AROUND THE CITY -

-
- - - - - - - - - - - - -
-
-
- -
-
-
-
-

ADVANTAGES

-
- - - - - -
-
-
-

- Live in the future, today. Designed to embody Rove’s unique look and - feel, the interiors will feature intelligent and modular living - solutions by ORI, never seen before in UAE and the region. -

-
-

- ORI introduces a revolutionary solution to apartment living, where - space is not just a constraint but an opportunity. -

-
-
-
-

Simple

-
-
-
-

Safe

-
-
-
-

Effortless

-
-
-
- - - -
-
-
-
-

- UNITS DESCRIPTION -

-
- - - - -
-
-
-

- Founded under Alshamsi family, IRTH is a real estate investment - platform - based on the philosophy of value creation, innovation and - building world-class living experiences. -

-
-

- ABOUT THE DEVELOPER -

-
-
-
- -
-

- IRTH’s vision is long-term, supported with a proactive - approach, swift actions, strong financial backing, and - high-quality projects - bridging the gap between ambition - and success. IRTH continues seeking new opportunities and - broadening horizons – thriving in any market situation - through an extensive land bank and strategic partnerships. -

-

- At IRTH, we take pride in offering the best-inclass - locations and properties for value-based investment - opportunities - setting new standards in the real estate - market in the region. We are IRTH – The Future of Real - Estate. -

-
-
- Learn more -
-
- -
-
-
-
-
-

- MAIN CONSULTANTS -

-
- - -
- -
- - -
-
-
-
- ); -} - -export default AboutProjects2Page; diff --git a/client/src/pages/AboutProjectsPage.tsx b/client/src/pages/AboutProjectsPage.tsx index 2d98a50..3a3e949 100644 --- a/client/src/pages/AboutProjectsPage.tsx +++ b/client/src/pages/AboutProjectsPage.tsx @@ -1,490 +1,310 @@ -import { isMobile } from "react-device-detect"; -import Button from "../components/Button"; -import LeftArrowIcon from "../components/icons/LeftArrowIcon"; -import LivingSolutionSlider from "../components/aboutComplex/LivingSolutionSlider"; -import RoveHomeSlider from "../components/aboutComplex/RoveHomeSlider"; import { useNavigate } from "react-router-dom"; - -interface ICityItem { - time: number; - title: string; - id: string; - image: string; -} - -const roveAroundTheCity: ICityItem[] = [ - { - id: "1", - title: "Burj Khalifa", - time: 10, - image: "/images/aboutCompany/roveAroundTheCity/1.png", - }, - { - id: "2", - title: "The Dubai Fountain", - time: 10, - image: "/images/aboutCompany/roveAroundTheCity/2.png", - }, - { - id: "3", - title: "Dubai Mall", - time: 8, - image: "/images/aboutCompany/roveAroundTheCity/3.png", - }, - { - id: "4", - title: "Dubai Opera", - time: 11, - image: "/images/aboutCompany/roveAroundTheCity/4.png", - }, - { - id: "5", - title: "Marasi Promenade", - time: 4, - image: "/images/aboutCompany/roveAroundTheCity/5.png", - }, - { - id: "6", - title: "Rove Downtown Hotel", - time: 10, - image: "/images/aboutCompany/roveAroundTheCity/6.png", - }, - { - id: "7", - title: "Rove City Walk Hotel", - time: 12, - image: "/images/aboutCompany/roveAroundTheCity/7.png", - }, - { - id: "8", - title: "City Walk", - time: 12, - image: "/images/aboutCompany/roveAroundTheCity/8.png", - }, - { - id: "9", - title: "Coca Cola arena", - time: 14, - image: "/images/aboutCompany/roveAroundTheCity/9.png", - }, - { - id: "10", - title: " Dubai International Airport", - time: 10, - image: "/images/aboutCompany/roveAroundTheCity/10.png", - }, -]; - -interface IAdvantages { - title: string; - image: string; - id: string; -} - -const advantages: IAdvantages[] = [ - { - title: "Community", - image: "/images/aboutCompany/advantages/1.jpg", - id: "1", - }, - { - title: "Rove-Inspired design", - image: "/images/aboutCompany/advantages/2.jpg", - id: "2", - }, - { - title: "Fully loaded amenities", - image: "/images/aboutCompany/advantages/3.jpg", - id: "3", - }, - { - title: "Add-on services", - image: "/images/aboutCompany/advantages/4.jpg", - id: "4", - }, - { - title: "Central urban location", - image: "/images/aboutCompany/advantages/5.jpg", - id: "5", - }, -]; - -const advStyles = [ - "xl:col-start-3 xl:col-end-7", - "xl:col-span-4", - "xl:col-start-5 xl:col-end-9", - "xl:col-span-4", - "xl:col-start-3 xl:col-span-4", -]; +import AdvantageCard from "../components/AboutProject/AdvantageCard"; +import PlaceCard from "../components/AboutProject/PlaceCard"; +import UnitCard from "../components/AboutProject/UnitCard"; +import Button2 from "../components/Button2"; +import ArrowLeftIcon from "../components/icons/ArrowLeftIcon"; +import Logo2Icon from "../components/icons/Logo2Icon"; +import ConsultantCard from "../components/AboutProject/ConsultantCard"; +import Slider from "../components/AboutProject/Slider"; function AboutProjectsPage() { const navigate = useNavigate(); - const handleOnBackClick = () => { - navigate(-1); - }; - return ( -
-
-
-
-
-
- {/* About Rove Home */} -

+
+
+

Rove Home this residence a complete ecosystem that has everything - you’ll ever need. This isn’t just where you’ll live. It’s where you’ll - thrive. -

- -
-
- About rove home + you’ll ever need. This isn’t just where you’ll live. +
+ It’s where you’ll thrive. +

+
+
+
+

+ ABOUT ROVE HOME +

+

+ Embrace Rove’s forever-young spirit at Rove Home, where + inspiring design and vibrant art installations converge with an + exceptional location and an extended playlist of life-enhancing{" "} +

+
+ } + onClick={() => navigate("/masterplan/1/wing")} + > + Masterplan +
-
+
-
- Embrace Rove’s forever-young spirit at Rove Home, where inspiring - design and vibrant art installations converge with an exceptional - location and an extended playlist of life-enhancing{" "} -
- {/* RoveHome roof */} - - {/* Rove around the city */} -
-
- ROVE AROUND THE CITY -
-
-
- {roveAroundTheCity.map((item) => ( -
-
-
-
{item.title}
-
-

{item.time} mins

- -
- ))} -
-
- + +
+ +
+ +
+
+
+

+ ROVE AROUND THE CITY +

+
+ + + + + + + + + + + + -
-
- {/* Advantages */} -
-
- ADVANTAGES +
+ +
-

- What makes a rove home? +

+
+

ADVANTAGES

+
+ + + + + +
+
+
+

+ Live in the future, today. Designed to embody Rove’s unique look and + feel, the interiors will feature intelligent and modular living + solutions by ORI, never seen before in UAE and the region.

- {advantages.map((adv, index) => { - const styles = `${advStyles[index]} ${ - index === advantages.length - 1 ? "" : "xl:pb-14 pb-6" - }`; - - return ( -
- {adv.title} -
-
-
{adv.title}
-
-
- ); - })} -
- {/* EXPANDABLE LIVING SOLUTIONS */} -

- Live in the future, today. Designed to embody Rove’s unique look and - feel, the interiors will feature intelligent and modular living - solutions by ORI, never seen before in UAE and the region. -

-
-
- EXPANDABLE LIVING SOLUTIONS -
-
-
+
+

ORI introduces a revolutionary solution to apartment living, where - space is not just a constraint but an opportunity.{" "} -

-
-
-
-

Simple

+ space is not just a constraint but an opportunity. +

+
+
+
+

Simple

-
-
-

Safe

+
+
+

Safe

-
-
-

Effortless

+
+
+

Effortless

-
-
- +
+ + + +
- {/* Units description */} -
-
+
+

UNITS DESCRIPTION -

-
-
-
-
-

- Studio flex -

-

- Live in the future, today. In Studio Flex explore the ORI - Cloud Bed, optimizing your living space with functionality - and smart living. -

-

- Every inch is designed to provide more space for comfort and - convenience. This feature increase your unit size by 33% -

-
-
-

341 Sqft

-

Unavailable

-
-
- -
-
-
-
-

- Studio2 -

-

- In Studio 2 experience the Flexibed, a smart innovation for - modern living. When folded, it unveils a spacious living - room creating a cohesive space that blends both style and - functionality. -

-
-
-

390 Sqft

-

- AED 1,138,888 -

-
-
- -
-
-
-
-

- 1 Bedroom2 -

-

- In 1 Bedroom 2 double up your space with next generation - features that enhance smart living. -

-

- With pocket walls that disappear and a Flexibed that - seamlessly converts, you can transform your living room into - an extra bedroom, anytime you want! -

-
-
-

609 Sqft

-

Unvailiable

-
-
- -
-
-
-
-

- 2 Bedroom2 -

-

- In 2 Bedroom 2 discover extra functionality with added space - and maximum value. -

-

- Whether you want to add a multipurpose spare room or double - up your living space as a bedroom - every inch of space - feels larger and works exactly how you want. -

-
-
-

891 Sqft

-

- AED 2,408,888 -

-
-
- -
-
-
- {/* About the developer */} -

- Founded under Alshamsi family, IRTH is a real estate investment - platform - based on the philosophy of value creation, innovation and - building world-class living experiences. -

-
-
- ABOUT THE DEVELOPER -
-
-
-

- IRTH’s vision is long-term, supported with a proactive approach, - swift actions, strong financial backing, and high-quality - projects - bridging the gap between ambition and success. IRTH - continues seeking new opportunities and broadening horizons – - thriving in any market situation through an extensive land bank - and strategic partnerships. -

-

- At IRTH, we take pride in offering the best-inclass locations - and properties for value-based investment opportunities - - setting new standards in the real estate market in the region. - We are IRTH – The Future of Real Estate. -

-
-
- {/* MAIN CONSULTANTS */} -
-
+
+

+ Founded under Alshamsi family, IRTH is a real estate investment + platform - based on the philosophy of value creation, innovation and + building world-class living experiences. +

+
+

+ ABOUT THE DEVELOPER +

+
+
+
+ +
+

+ IRTH’s vision is long-term, supported with a proactive + approach, swift actions, strong financial backing, and + high-quality projects - bridging the gap between ambition + and success. IRTH continues seeking new opportunities and + broadening horizons – thriving in any market situation + through an extensive land bank and strategic partnerships. +

+

+ At IRTH, we take pride in offering the best-inclass + locations and properties for value-based investment + opportunities - setting new standards in the real estate + market in the region. We are IRTH – The Future of Real + Estate. +

+
+
+ Learn more +
+
+ +
+
+
+
+
+

MAIN CONSULTANTS -

-
-
-
-
-

Architect

-
- -
-
-
-
-

Landscape architect

-
- -
-
-
-
-

Art team

-
- -
-
-
-
-

Id team

-
- -
-
-
-
-

Sales and marketing

-
- -
+

+
+ + +
+ +
+ +
-
+
); } diff --git a/client/src/pages/FavoritesPage.tsx b/client/src/pages/FavoritesPage.tsx index cede359..e1a6ed1 100644 --- a/client/src/pages/FavoritesPage.tsx +++ b/client/src/pages/FavoritesPage.tsx @@ -1,237 +1,325 @@ -import { useState, useEffect } from "react"; -import { sortCardBy } from "../calc/sortCard"; +// import { useState } from "react"; +// import ChevronDownIcon from "../components/icons/ChevronDownIcon"; +import useFavoritesStore from "../store/useFavoritesStore"; +import useModal from "../store/useModal"; +import HeartIcon from "../components/icons/HeartIcon"; +import UnitModalForSearchPage from "../components/modals/UnitModalForSearchPage"; +import unitTypes from "../data/unitTypes.json"; +import HeartFilledIcon from "../components/icons/HeartFilledIcon"; import Button from "../components/Button"; -import Footer from "../components/Footer"; -import TrashIcon from "../components/icons/TrashIcon"; -import SortButton from "../components/searchPage/SortButton"; -import { initialSortList } from "../consts/initialMasterplanFilters"; -import Switch from "../components/Switch"; -import { ISwitcher } from "../types/switcher"; -import FavoritesSlider from "../components/favoritesPage/FavoriteSlider"; -import FavoriteCardList from "../components/favoritesPage/FavoriteCardList"; -import useFavorites from "../store/useFavorites"; +import BookingIcon from "../components/icons/BookingIcon"; +import IUnit from "../types/IUnit"; -// const favoriteCards: ILayoutCard[] = [ -// { -// id: "1", -// roveHome: "Marasi Drive", -// apartmentType: "Studio Flex", -// wing: "East Wing", -// floorStart: 11, -// floorEnd: 35, -// units: 234, -// cost: 10488888, -// square: 619, -// }, -// { -// id: "2", -// roveHome: "Marasi Drive", -// apartmentType: "1 Bedroom", -// wing: "East Wing", -// floorStart: 11, -// floorEnd: 35, -// units: 234, -// cost: 1668888, -// square: 619, -// }, -// { -// id: "3", -// roveHome: "Marasi Drive", -// apartmentType: "1 Bedroom", -// wing: "East Wing", -// floorStart: 11, -// floorEnd: 35, -// units: 234, -// cost: 1668888, -// square: 609, -// }, -// { -// id: "4", -// roveHome: "Marasi Drive", -// apartmentType: "1 Bedroom", -// wing: "East Wing", -// floorStart: 11, -// floorEnd: 35, -// units: 234, -// cost: 1138888, -// square: 609, -// }, -// { -// id: "5", -// roveHome: "Marasi Drive", -// apartmentType: "Studio Flex", -// wing: "East Wing", -// floorStart: 11, -// floorEnd: 35, -// units: 234, -// cost: 10488888, -// square: 609, -// }, -// { -// id: "6", -// roveHome: "Marasi Drive", -// apartmentType: "1 Bedroom", -// wing: "East Wing", -// floorStart: 11, -// floorEnd: 35, -// units: 234, -// cost: 1668888, -// square: 609, -// }, -// { -// id: "7", -// roveHome: "Marasi Drive", -// apartmentType: "1 Bedroom", -// wing: "East Wing", -// floorStart: 11, -// floorEnd: 35, -// units: 234, -// cost: 1668888, -// square: 609, -// }, -// { -// id: "8", -// roveHome: "Marasi Drive", -// apartmentType: "1 Bedroom", -// wing: "East Wing", -// floorStart: 11, -// floorEnd: 35, -// units: 234, -// cost: 1138888, -// square: 609, -// }, -// { -// id: "9", -// roveHome: "Marasi Drive", -// apartmentType: "Studio Flex", -// wing: "East Wing", -// floorStart: 11, -// floorEnd: 35, -// units: 234, -// cost: 10488888, -// square: 609, -// }, -// { -// id: "10", -// roveHome: "Marasi Drive", -// apartmentType: "1 Bedroom", -// wing: "East Wing", -// floorStart: 11, -// floorEnd: 35, -// units: 234, -// cost: 1668888, -// square: 609, -// }, -// { -// id: "11", -// roveHome: "Marasi Drive", -// apartmentType: "1 Bedroom", -// wing: "East Wing", -// floorStart: 11, -// floorEnd: 35, -// units: 234, -// cost: 1668888, -// square: 609, -// }, -// { -// id: "12", -// roveHome: "Marasi Drive", -// apartmentType: "1 Bedroom", -// wing: "East Wing", -// floorStart: 11, -// floorEnd: 35, -// units: 234, -// cost: 1138888, -// square: 609, -// }, -// ]; +function FavoritesPage() { + const { favoriteUnits, setFavoriteUnits } = useFavoritesStore(); + // const [isSortPriceAsc, setIsSortPriceAsc] = useState(false); + const { setModal } = useModal(); -const initialCollectionCompareSwitcher: ISwitcher = { - id: "1", - title: "collection/compare", - isSwitched: false, -}; + function getTypeByUnitNo(unitNo: string) { + const side = unitNo[0] === "E" ? "East" : "West"; + const floor = Number(unitNo.split("-")[1].slice(0, -2)); + const number = Number(unitNo.split("-")[1].slice(-2)); -const FavoritesPage = () => { - const [sortList, setSortList] = useState(initialSortList); - const [switcher, setSwitcher] = useState(initialCollectionCompareSwitcher); - const { favorites, setFavorites } = useFavorites(); + console.log(side, floor, number); - const handleOnSortClick = (sortId: string) => { - const updatedSortList = sortList.map((sort) => { - const isSelected = sort.id === sortId; - return { ...sort, isSelected: isSelected }; - }); - setSortList(updatedSortList); - }; - - const handleOnSwitchClick = () => { - setSwitcher((prev) => { - return { ...prev, isSwitched: !prev.isSwitched }; - }); - }; - - const handleOnDeleteFavoriteClick = () => { - localStorage.removeItem("Favorites"); - setFavorites([]); - }; - - useEffect(() => { - const favoriteCards = localStorage.getItem("Favorites"); - if (favoriteCards) { - const convertedCards = JSON.parse(favoriteCards); - const sortedCards = sortCardBy(sortList, convertedCards); - setFavorites(sortedCards); + if (side === "East") { + if ([1].includes(number)) { + return "2br-type-a"; + } else if ([2, 4, 5, 11, 12, 13, 14].includes(number)) { + return "studio-2"; + } else if ([3].includes(number)) { + return "1br-type-d"; + } else if ([6, 7, 10, 15, 16].includes(number)) { + return "1br-type-c"; + } else if ([8, 9].includes(number)) { + return "1br-type-b"; + } + } else if (side === "West") { + if (floor <= 21) { + // Floors 5-21 + if ([1].includes(number)) { + return "2br-type-a"; + } else if ([2, 4, 5].includes(number)) { + return "studio-2"; + } else if ([3, 6].includes(number)) { + return "1br-type-d"; + } else if ([7, 8].includes(number)) { + return "1br-type-a"; + } else if ([9, 10, 11, 12, 13, 14].includes(number)) { + return "studio-flex"; + } else if ([15, 16].includes(number)) { + return "1br-type-c"; + } else if ([17].includes(number)) { + return "2br-type-b"; + } + } else { + // Floors 24-31 + if ([1].includes(number)) { + return "2br-type-a"; + } else if ([2, 4, 5, 10, 11].includes(number)) { + return "studio-2"; + } else if ([3, 6, 9, 12].includes(number)) { + return "1br-type-d"; + } else if ([7, 8].includes(number)) { + return "1br-type-a"; + } else if ([13, 14].includes(number)) { + return "1br-type-c"; + } else if ([15].includes(number)) { + return "2br-type-b"; + } + } } - }, [setFavorites, sortList]); + + // TODO Connect to DB + + return ""; + } + + function getImageSrc(unitNo: string): string { + const side = unitNo[0]; + const floor = Number(unitNo.split("-")[1].slice(0, -2)); + const unitNumber = Number(unitNo.split("-")[1].slice(-2)); + + if (side === "W") { + // Side "W" + if (floor < 24) { + switch (unitNumber) { + case 1: + return "/images/layouts/2br_a_left.png"; + case 2: + return "/images/layouts/studio_left.png"; + case 3: + return "/images/layouts/1br_d_left.png"; + case 4: + return "/images/layouts/studio_left.png"; + case 5: + return "/images/layouts/studio_left.png"; + case 6: + return "/images/layouts/1br_d_left.png"; + case 7: + return "/images/layouts/1br_a_left.png"; + case 8: + return "/images/layouts/1br_a_left.png"; + case 9: + return "/images/layouts/studio_flex_left.png"; + case 10: + return "/images/layouts/studio_flex_left.png"; + case 11: + return "/images/layouts/studio_flex_left.png"; + case 12: + return "/images/layouts/studio_flex_left.png"; + case 13: + return "/images/layouts/studio_flex_left.png"; + case 14: + return "/images/layouts/studio_flex_left.png"; + case 15: + return "/images/layouts/1br_c_left.png"; + case 16: + return "/images/layouts/1br_c_left.png"; + case 17: + return "/images/layouts/2br_b_left.png"; + } + } else { + switch (unitNumber) { + case 1: + return "/images/layouts/2br_a_left.png"; + case 2: + return "/images/layouts/studio_left.png"; + case 3: + return "/images/layouts/1br_d_left.png"; + case 4: + return "/images/layouts/studio_left.png"; + case 5: + return "/images/layouts/studio_left.png"; + case 6: + return "/images/layouts/1br_d_left.png"; + case 7: + return "/images/layouts/1br_a_left.png"; + case 8: + return "/images/layouts/1br_a_left.png"; + case 9: + return "/images/layouts/1br_d_left.png"; + case 10: + return "/images/layouts/studio_left.png"; + case 11: + return "/images/layouts/studio_left.png"; + case 12: + return "/images/layouts/1br_d_left.png"; + case 13: + return "/images/layouts/1br_c_left.png"; + case 14: + return "/images/layouts/1br_c_left.png"; + case 15: + return "/images/layouts/2br_b_left.png"; + } + } + } else { + // Side "E" + switch (unitNumber) { + case 1: + return "/images/layouts/2br_a_left.png"; + case 2: + return "/images/layouts/studio_left.png"; + case 3: + return "/images/layouts/1br_d_left.png"; + case 4: + return "/images/layouts/studio_left.png"; + case 5: + return "/images/layouts/studio_left.png"; + case 6: + return "/images/layouts/1br_c_left.png"; + case 7: + return "/images/layouts/1br_c_left.png"; + case 8: + return "/images/layouts/1br_b_left.png"; + case 9: + return "/images/layouts/1br_b_left.png"; + case 10: + return "/images/layouts/1br_c_left.png"; + case 11: + return "/images/layouts/studio_left.png"; + case 12: + return "/images/layouts/studio_left.png"; + case 13: + return "/images/layouts/studio_left.png"; + case 14: + return "/images/layouts/studio_left.png"; + case 15: + return "/images/layouts/1br_c_left.png"; + case 16: + return "/images/layouts/1br_c_left.png"; + } + } + + console.log(side, floor, unitNumber); + + return ""; + } + + function addOrRemoveFromFavorites(unit: IUnit) { + if (!favoriteUnits.some((favoriteUnit) => favoriteUnit.id === unit.id)) { + setFavoriteUnits([...favoriteUnits, unit]); + } else { + setFavoriteUnits( + favoriteUnits.filter((favoriteUnit) => favoriteUnit.id !== unit.id) + ); + } + } return ( -
-
-
-
-
-
-

Units

-

{favorites.length}

-
- -
-
-
-
-
-
+
+
+
+

+ Favorites{" "} + {favoriteUnits.length} +

+ {/* */} +
+
+ {favoriteUnits.map((unit) => ( +
+
+
+

{unit.projectName}

+
+

+ {unit.unitNo[0] === "E" ? "East" : "West"} Wing +

+
+

{unit.floor}

+
+

{unit.unitNo}

+
+
+ +
+
+ setModal( + + unitType.type === getTypeByUnitNo(unit.unitNo) + )?.type || "" + } + /> + ) + } + > + +
+
+ setModal( + + unitType.type === getTypeByUnitNo(unit.unitNo) + )?.type || "" + } + /> + ) + } + > +

+ {unit.unitType}, {unit.totalArea} Sqft +

+

+ {(unit.unitPrice && + `AED ${unit.unitPrice.toLocaleString()}`) || + "Unavailable"} +

+
+
+
+
+ ))}
- {switcher.isSwitched ? : }
-
); -}; +} export default FavoritesPage; diff --git a/client/src/pages/FavoritesPage2.tsx b/client/src/pages/FavoritesPage2.tsx deleted file mode 100644 index a456a1a..0000000 --- a/client/src/pages/FavoritesPage2.tsx +++ /dev/null @@ -1,325 +0,0 @@ -// import { useState } from "react"; -// import ChevronDownIcon from "../components/icons/ChevronDownIcon"; -import useFavoritesStore from "../store/useFavoritesStore"; -import useModal from "../store/useModal"; -import HeartIcon from "../components/icons/HeartIcon"; -import UnitModalForSearchPage from "../components/modals/UnitModalForSearchPage"; -import unitTypes from "../data/unitTypes.json"; -import HeartFilledIcon from "../components/icons/HeartFilledIcon"; -import Button from "../components/Button"; -import BookingIcon from "../components/icons/BookingIcon"; -import IUnit from "../types/IUnit"; - -function FavoritesPage2() { - const { favoriteUnits, setFavoriteUnits } = useFavoritesStore(); - // const [isSortPriceAsc, setIsSortPriceAsc] = useState(false); - const { setModal } = useModal(); - - function getTypeByUnitNo(unitNo: string) { - const side = unitNo[0] === "E" ? "East" : "West"; - const floor = Number(unitNo.split("-")[1].slice(0, -2)); - const number = Number(unitNo.split("-")[1].slice(-2)); - - console.log(side, floor, number); - - if (side === "East") { - if ([1].includes(number)) { - return "2br-type-a"; - } else if ([2, 4, 5, 11, 12, 13, 14].includes(number)) { - return "studio-2"; - } else if ([3].includes(number)) { - return "1br-type-d"; - } else if ([6, 7, 10, 15, 16].includes(number)) { - return "1br-type-c"; - } else if ([8, 9].includes(number)) { - return "1br-type-b"; - } - } else if (side === "West") { - if (floor <= 21) { - // Floors 5-21 - if ([1].includes(number)) { - return "2br-type-a"; - } else if ([2, 4, 5].includes(number)) { - return "studio-2"; - } else if ([3, 6].includes(number)) { - return "1br-type-d"; - } else if ([7, 8].includes(number)) { - return "1br-type-a"; - } else if ([9, 10, 11, 12, 13, 14].includes(number)) { - return "studio-flex"; - } else if ([15, 16].includes(number)) { - return "1br-type-c"; - } else if ([17].includes(number)) { - return "2br-type-b"; - } - } else { - // Floors 24-31 - if ([1].includes(number)) { - return "2br-type-a"; - } else if ([2, 4, 5, 10, 11].includes(number)) { - return "studio-2"; - } else if ([3, 6, 9, 12].includes(number)) { - return "1br-type-d"; - } else if ([7, 8].includes(number)) { - return "1br-type-a"; - } else if ([13, 14].includes(number)) { - return "1br-type-c"; - } else if ([15].includes(number)) { - return "2br-type-b"; - } - } - } - - // TODO Connect to DB - - return ""; - } - - function getImageSrc(unitNo: string): string { - const side = unitNo[0]; - const floor = Number(unitNo.split("-")[1].slice(0, -2)); - const unitNumber = Number(unitNo.split("-")[1].slice(-2)); - - if (side === "W") { - // Side "W" - if (floor < 24) { - switch (unitNumber) { - case 1: - return "/images/layouts/2br_a_left.png"; - case 2: - return "/images/layouts/studio_left.png"; - case 3: - return "/images/layouts/1br_d_left.png"; - case 4: - return "/images/layouts/studio_left.png"; - case 5: - return "/images/layouts/studio_left.png"; - case 6: - return "/images/layouts/1br_d_left.png"; - case 7: - return "/images/layouts/1br_a_left.png"; - case 8: - return "/images/layouts/1br_a_left.png"; - case 9: - return "/images/layouts/studio_flex_left.png"; - case 10: - return "/images/layouts/studio_flex_left.png"; - case 11: - return "/images/layouts/studio_flex_left.png"; - case 12: - return "/images/layouts/studio_flex_left.png"; - case 13: - return "/images/layouts/studio_flex_left.png"; - case 14: - return "/images/layouts/studio_flex_left.png"; - case 15: - return "/images/layouts/1br_c_left.png"; - case 16: - return "/images/layouts/1br_c_left.png"; - case 17: - return "/images/layouts/2br_b_left.png"; - } - } else { - switch (unitNumber) { - case 1: - return "/images/layouts/2br_a_left.png"; - case 2: - return "/images/layouts/studio_left.png"; - case 3: - return "/images/layouts/1br_d_left.png"; - case 4: - return "/images/layouts/studio_left.png"; - case 5: - return "/images/layouts/studio_left.png"; - case 6: - return "/images/layouts/1br_d_left.png"; - case 7: - return "/images/layouts/1br_a_left.png"; - case 8: - return "/images/layouts/1br_a_left.png"; - case 9: - return "/images/layouts/1br_d_left.png"; - case 10: - return "/images/layouts/studio_left.png"; - case 11: - return "/images/layouts/studio_left.png"; - case 12: - return "/images/layouts/1br_d_left.png"; - case 13: - return "/images/layouts/1br_c_left.png"; - case 14: - return "/images/layouts/1br_c_left.png"; - case 15: - return "/images/layouts/2br_b_left.png"; - } - } - } else { - // Side "E" - switch (unitNumber) { - case 1: - return "/images/layouts/2br_a_left.png"; - case 2: - return "/images/layouts/studio_left.png"; - case 3: - return "/images/layouts/1br_d_left.png"; - case 4: - return "/images/layouts/studio_left.png"; - case 5: - return "/images/layouts/studio_left.png"; - case 6: - return "/images/layouts/1br_c_left.png"; - case 7: - return "/images/layouts/1br_c_left.png"; - case 8: - return "/images/layouts/1br_b_left.png"; - case 9: - return "/images/layouts/1br_b_left.png"; - case 10: - return "/images/layouts/1br_c_left.png"; - case 11: - return "/images/layouts/studio_left.png"; - case 12: - return "/images/layouts/studio_left.png"; - case 13: - return "/images/layouts/studio_left.png"; - case 14: - return "/images/layouts/studio_left.png"; - case 15: - return "/images/layouts/1br_c_left.png"; - case 16: - return "/images/layouts/1br_c_left.png"; - } - } - - console.log(side, floor, unitNumber); - - return ""; - } - - function addOrRemoveFromFavorites(unit: IUnit) { - if (!favoriteUnits.some((favoriteUnit) => favoriteUnit.id === unit.id)) { - setFavoriteUnits([...favoriteUnits, unit]); - } else { - setFavoriteUnits( - favoriteUnits.filter((favoriteUnit) => favoriteUnit.id !== unit.id) - ); - } - } - - return ( -
-
-
-

- Favorites{" "} - {favoriteUnits.length} -

- {/* */} -
-
- {favoriteUnits.map((unit) => ( -
-
-
-

{unit.projectName}

-
-

- {unit.unitNo[0] === "E" ? "East" : "West"} Wing -

-
-

{unit.floor}

-
-

{unit.unitNo}

-
-
- -
-
- setModal( - - unitType.type === getTypeByUnitNo(unit.unitNo) - )?.type || "" - } - /> - ) - } - > - -
-
- setModal( - - unitType.type === getTypeByUnitNo(unit.unitNo) - )?.type || "" - } - /> - ) - } - > -

- {unit.unitType}, {unit.totalArea} Sqft -

-

- {(unit.unitPrice && - `AED ${unit.unitPrice.toLocaleString()}`) || - "Unavailable"} -

-
-
-
-
- ))} -
-
-
- ); -} - -export default FavoritesPage2; diff --git a/client/src/pages/SearchPage.tsx b/client/src/pages/SearchPage.tsx index b4735e8..645caaa 100644 --- a/client/src/pages/SearchPage.tsx +++ b/client/src/pages/SearchPage.tsx @@ -1,17 +1,896 @@ -import Footer from "../components/Footer"; -import LayoutOptions from "../components/searchPage/LayoutOptions"; -import SidebarFilters from "../components/searchPage/SidebarFilters"; +/* eslint-disable react-hooks/exhaustive-deps */ +import { useEffect, useState } from "react"; +import RestartIcon from "../components/icons/RestartIcon"; +import api from "../utils/api"; +import IUnit from "../types/IUnit"; +import Checkbox2 from "../components/Checkbox2"; +import HeartIcon from "../components/icons/HeartIcon"; +import RangeSlider from "react-range-slider-input"; +import Input from "../components/Input"; +import ChevronDownIcon from "../components/icons/ChevronDownIcon"; +import useModal from "../store/useModal"; +import unitTypes from "../data/unitTypes.json"; +import UnitModalForSearchPage from "../components/modals/UnitModalForSearchPage"; +import useFavoritesStore from "../store/useFavoritesStore"; +import HeartFilledIcon from "../components/icons/HeartFilledIcon"; +import { useSearchParams } from "react-router-dom"; + +function SearchPage() { + const [units, setUnits] = useState([]); + const [filteredUnits, setFilteredUnits] = useState([]); + const [unitTypeFilters, setUnitTypeFilters] = useState([]); + const [unitViewFilters, setUnitViewFilters] = useState([]); + const [minCost, setMinCost] = useState(0); + const [maxCost, setMaxCost] = useState(1000000); + const [cost, setCost] = useState([minCost, maxCost]); + const [minTotalArea] = useState(341); + const [maxTotalArea] = useState(1058); + const [totalArea, setTotalArea] = useState([ + minTotalArea, + maxTotalArea, + ]); + const [minFloor] = useState(5); + const [maxFloor] = useState(31); + const [floor, setFloor] = useState([minFloor, maxFloor]); + const [isSortPriceAsc, setIsSortPriceAsc] = useState(); + const { setModal } = useModal(); + const { favoriteUnits, setFavoriteUnits } = useFavoritesStore(); + const [searchParams, setSearchParams] = useSearchParams(); + + async function getUnits() { + try { + const result: IUnit[] = await api.get("units").json(); + + setUnits(result); + } catch (error) { + // + } + } + + function getImageSrc(unitNo: string): string { + const side = unitNo[0]; + const floor = Number(unitNo.split("-")[1].slice(0, -2)); + const unitNumber = Number(unitNo.split("-")[1].slice(-2)); + + if (side === "W") { + // Side "W" + if (floor < 24) { + switch (unitNumber) { + case 1: + return "/images/layouts/2br_a_left.png"; + case 2: + return "/images/layouts/studio_left.png"; + case 3: + return "/images/layouts/1br_d_left.png"; + case 4: + return "/images/layouts/studio_left.png"; + case 5: + return "/images/layouts/studio_left.png"; + case 6: + return "/images/layouts/1br_d_left.png"; + case 7: + return "/images/layouts/1br_a_left.png"; + case 8: + return "/images/layouts/1br_a_left.png"; + case 9: + return "/images/layouts/studio_flex_left.png"; + case 10: + return "/images/layouts/studio_flex_left.png"; + case 11: + return "/images/layouts/studio_flex_left.png"; + case 12: + return "/images/layouts/studio_flex_left.png"; + case 13: + return "/images/layouts/studio_flex_left.png"; + case 14: + return "/images/layouts/studio_flex_left.png"; + case 15: + return "/images/layouts/1br_c_left.png"; + case 16: + return "/images/layouts/1br_c_left.png"; + case 17: + return "/images/layouts/2br_b_left.png"; + } + } else { + switch (unitNumber) { + case 1: + return "/images/layouts/2br_a_left.png"; + case 2: + return "/images/layouts/studio_left.png"; + case 3: + return "/images/layouts/1br_d_left.png"; + case 4: + return "/images/layouts/studio_left.png"; + case 5: + return "/images/layouts/studio_left.png"; + case 6: + return "/images/layouts/1br_d_left.png"; + case 7: + return "/images/layouts/1br_a_left.png"; + case 8: + return "/images/layouts/1br_a_left.png"; + case 9: + return "/images/layouts/1br_d_left.png"; + case 10: + return "/images/layouts/studio_left.png"; + case 11: + return "/images/layouts/studio_left.png"; + case 12: + return "/images/layouts/1br_d_left.png"; + case 13: + return "/images/layouts/1br_c_left.png"; + case 14: + return "/images/layouts/1br_c_left.png"; + case 15: + return "/images/layouts/2br_b_left.png"; + } + } + } else { + // Side "E" + switch (unitNumber) { + case 1: + return "/images/layouts/2br_a_left.png"; + case 2: + return "/images/layouts/studio_left.png"; + case 3: + return "/images/layouts/1br_d_left.png"; + case 4: + return "/images/layouts/studio_left.png"; + case 5: + return "/images/layouts/studio_left.png"; + case 6: + return "/images/layouts/1br_c_left.png"; + case 7: + return "/images/layouts/1br_c_left.png"; + case 8: + return "/images/layouts/1br_b_left.png"; + case 9: + return "/images/layouts/1br_b_left.png"; + case 10: + return "/images/layouts/1br_c_left.png"; + case 11: + return "/images/layouts/studio_left.png"; + case 12: + return "/images/layouts/studio_left.png"; + case 13: + return "/images/layouts/studio_left.png"; + case 14: + return "/images/layouts/studio_left.png"; + case 15: + return "/images/layouts/1br_c_left.png"; + case 16: + return "/images/layouts/1br_c_left.png"; + } + } + + console.log(side, floor, unitNumber); + + return ""; + } + + function refreshFilters() { + console.log("call func refreshFilters"); + setUnitTypeFilters([]); + setUnitViewFilters([]); + setCost([minCost, maxCost]); + setTotalArea([minTotalArea, maxTotalArea]); + setFloor([minFloor, maxFloor]); + } + + function getTypeByUnitNo(unitNo: string) { + const side = unitNo[0] === "E" ? "East" : "West"; + const floor = Number(unitNo.split("-")[1].slice(0, -2)); + const number = Number(unitNo.split("-")[1].slice(-2)); + + console.log(side, floor, number); + + if (side === "East") { + if ([1].includes(number)) { + return "2br-type-a"; + } else if ([2, 4, 5, 11, 12, 13, 14].includes(number)) { + return "studio-2"; + } else if ([3].includes(number)) { + return "1br-type-d"; + } else if ([6, 7, 10, 15, 16].includes(number)) { + return "1br-type-c"; + } else if ([8, 9].includes(number)) { + return "1br-type-b"; + } + } else if (side === "West") { + if (floor <= 21) { + // Floors 5-21 + if ([1].includes(number)) { + return "2br-type-a"; + } else if ([2, 4, 5].includes(number)) { + return "studio-2"; + } else if ([3, 6].includes(number)) { + return "1br-type-d"; + } else if ([7, 8].includes(number)) { + return "1br-type-a"; + } else if ([9, 10, 11, 12, 13, 14].includes(number)) { + return "studio-flex"; + } else if ([15, 16].includes(number)) { + return "1br-type-c"; + } else if ([17].includes(number)) { + return "2br-type-b"; + } + } else { + // Floors 24-31 + if ([1].includes(number)) { + return "2br-type-a"; + } else if ([2, 4, 5, 10, 11].includes(number)) { + return "studio-2"; + } else if ([3, 6, 9, 12].includes(number)) { + return "1br-type-d"; + } else if ([7, 8].includes(number)) { + return "1br-type-a"; + } else if ([13, 14].includes(number)) { + return "1br-type-c"; + } else if ([15].includes(number)) { + return "2br-type-b"; + } + } + } + + // TODO Connect to DB + + return ""; + } + + function addOrRemoveFromFavorites(unit: IUnit) { + if (!favoriteUnits.some((favoriteUnit) => favoriteUnit.id === unit.id)) { + setFavoriteUnits([...favoriteUnits, unit]); + } else { + setFavoriteUnits( + favoriteUnits.filter((favoriteUnit) => favoriteUnit.id !== unit.id) + ); + } + } + + function handleClickCard(unit: IUnit) { + setModal( + unitType.type === getTypeByUnitNo(unit.unitNo) + )?.type || "" + } + /> + ); + + searchParams.set("unitNo", unit.unitNo); + setSearchParams(searchParams); + } + + useEffect(() => { + let newFilteredUnits = units + .filter((unit) => + unitTypeFilters.length ? unitTypeFilters.includes(unit.unitType) : unit + ) + .filter((unit) => + unitViewFilters.length + ? unitViewFilters.some((unitViewFilter) => + unit.unitView.includes(unitViewFilter) + ) + : unit + ) + .filter( + (unit) => + unit.totalArea >= totalArea[0] && unit.totalArea <= totalArea[1] + ) + .filter((unit) => unit.floor >= floor[0] && unit.floor <= floor[1]); + + console.log("isSortPriceAsc", isSortPriceAsc); + + if (isSortPriceAsc !== undefined) { + if (isSortPriceAsc) { + newFilteredUnits = newFilteredUnits.sort( + (a, b) => (b.unitPrice || 0) - (a.unitPrice || 0) + ); + } else { + newFilteredUnits = newFilteredUnits.sort( + (a, b) => (a.unitPrice || 0) - (b.unitPrice || 0) + ); + } + } + + setFilteredUnits(newFilteredUnits); + + setMinCost( + Math.min( + ...newFilteredUnits.map((unit) => unit.unitPrice!).filter(Boolean) + ) + ); + setMaxCost( + Math.max( + ...newFilteredUnits.map((unit) => unit.unitPrice!).filter(Boolean) + ) + ); + setCost([ + Math.min( + ...newFilteredUnits.map((unit) => unit.unitPrice!).filter(Boolean) + ), + Math.max( + ...newFilteredUnits.map((unit) => unit.unitPrice!).filter(Boolean) + ), + ]); + + // setMinTotalArea( + // Math.round( + // Math.min( + // ...newFilteredUnits.map((unit) => unit.totalArea).filter(Boolean) + // ) + // ) + // ); + // setMaxTotalArea( + // Math.round( + // Math.max( + // ...newFilteredUnits.map((unit) => unit.totalArea).filter(Boolean) + // ) + // ) + // ); + // setTotalArea([ + // Math.round( + // Math.min( + // ...newFilteredUnits.map((unit) => unit.totalArea).filter(Boolean) + // ) + // ), + // Math.round( + // Math.max( + // ...newFilteredUnits.map((unit) => unit.totalArea).filter(Boolean) + // ) + // ), + // ]); + + // setMinFloor( + // Math.min(...newFilteredUnits.map((unit) => unit.floor).filter(Boolean)) + // ); + // setMaxFloor( + // Math.max(...newFilteredUnits.map((unit) => unit.floor).filter(Boolean)) + // ); + // setFloor([ + // Math.min(...newFilteredUnits.map((unit) => unit.floor).filter(Boolean)), + // Math.max(...newFilteredUnits.map((unit) => unit.floor).filter(Boolean)), + // ]); + }, [ + units, + unitTypeFilters, + unitViewFilters, + totalArea, + floor, + isSortPriceAsc, + ]); + + // useEffect(() => { + // if (!units.length) return; + + // setMinCost( + // Math.min(...units.map((unit) => unit.unitPrice!).filter(Boolean)) + // ); + // setMaxCost( + // Math.max(...units.map((unit) => unit.unitPrice!).filter(Boolean)) + // ); + // setCost([ + // Math.min(...units.map((unit) => unit.unitPrice!).filter(Boolean)), + // Math.max(...units.map((unit) => unit.unitPrice!).filter(Boolean)), + // ]); + // }, [units]); + + useEffect(() => { + getUnits(); + }, []); + + useEffect(() => { + if (searchParams.has("unitNo")) { + const unitNo = searchParams.get("unitNo"); + + if (!unitNo) return; + + const type = getTypeByUnitNo(unitNo); + const unit = units.find((unit) => unit.unitNo === unitNo); + + if (!unit) return; + + setModal(); + } + }, [units]); -const SearchPage = () => { return ( -
-
- - +
+
+
+

Filters

+ +
+
+

Apartment type

+
+
+
+ unitTypeFilter === "Studio Flex" + )} + onChange={(isChecked, filterName) => { + if (isChecked) { + setUnitTypeFilters((prev) => [...prev, filterName]); + } else { + setUnitTypeFilters( + unitTypeFilters.filter( + (unitTypeFilter) => unitTypeFilter !== filterName + ) + ); + } + }} + /> +

Studio Flex

+
+
+

+ { + units.filter((unit) => unit.unitType === "Studio Flex") + .length + } +

+
+
+
+
+ unitTypeFilter === "Studio Squared" + )} + onChange={(isChecked, filterName) => { + if (isChecked) { + setUnitTypeFilters((prev) => [...prev, filterName]); + } else { + setUnitTypeFilters( + unitTypeFilters.filter( + (unitTypeFilter) => unitTypeFilter !== filterName + ) + ); + } + }} + /> +

Studio²

+
+
+

+ { + units.filter((unit) => unit.unitType === "Studio Squared") + .length + } +

+
+
+
+
+ unitTypeFilter === "1 BR Squared" + )} + onChange={(isChecked, filterName) => { + if (isChecked) { + setUnitTypeFilters((prev) => [...prev, filterName]); + } else { + setUnitTypeFilters( + unitTypeFilters.filter( + (unitTypeFilter) => unitTypeFilter !== filterName + ) + ); + } + }} + /> +

1 Bedroom²

+
+
+

+ { + units.filter((unit) => unit.unitType === "1 BR Squared") + .length + } +

+
+
+
+
+ unitTypeFilter === "2 BR Squared" + )} + onChange={(isChecked, filterName) => { + if (isChecked) { + setUnitTypeFilters((prev) => [...prev, filterName]); + } else { + setUnitTypeFilters( + unitTypeFilters.filter( + (unitTypeFilter) => unitTypeFilter !== filterName + ) + ); + } + }} + /> +

2 Bedroom²

+
+
+

+ { + units.filter((unit) => unit.unitType === "2 BR Squared") + .length + } +

+
+
+
+
+
+
+

Cost

+

AED

+
+
+
+ setCost([value as number, cost[1]])} + /> + setCost([cost[0], value as number])} + /> +
+
+ setCost(value)} + disabled + /> +
+
+
+
+
+

Total Area

+

Sqft

+
+
+
+ + setTotalArea([value as number, totalArea[1]]) + } + /> + + setTotalArea([totalArea[0], value as number]) + } + /> +
+
+ setTotalArea(value)} + /> +
+
+
+
+
+

Floor

+
+
+
+ setFloor([value as number, floor[1]])} + /> + setFloor([floor[0], value as number])} + /> +
+
+ setFloor(value)} + /> +
+
+
+
+

View

+
+
+
+ unitViewFilter === "BK/DT" + )} + onChange={(isChecked, filterName) => { + if (isChecked) { + setUnitViewFilters((prev) => [...prev, filterName]); + } else { + setUnitViewFilters( + unitViewFilters.filter( + (unitViewFilter) => unitViewFilter !== filterName + ) + ); + } + }} + /> +

Burj Khalifa / Downtown

+
+
+

+ { + units.filter((unit) => unit.unitView.includes("BK/DT")) + .length + } +

+
+
+
+
+ unitViewFilter === "Business Bay" + )} + onChange={(isChecked, filterName) => { + if (isChecked) { + setUnitViewFilters((prev) => [...prev, filterName]); + } else { + setUnitViewFilters( + unitViewFilters.filter( + (unitViewFilter) => unitViewFilter !== filterName + ) + ); + } + }} + /> +

Business Bay

+
+
+

+ { + units.filter((unit) => unit.unitView === "Business Bay") + .length + } +

+
+
+
+
+ unitViewFilter === "Amenities" + )} + onChange={(isChecked, filterName) => { + if (isChecked) { + setUnitViewFilters((prev) => [...prev, filterName]); + } else { + setUnitViewFilters( + unitViewFilters.filter( + (unitViewFilter) => unitViewFilter !== filterName + ) + ); + } + }} + /> +

Amenities

+
+
+

+ { + units.filter((unit) => unit.unitView.includes("Amenities")) + .length + } +

+
+
+
+
+ unitViewFilter === "Canal" + )} + onChange={(isChecked, filterName) => { + if (isChecked) { + setUnitViewFilters((prev) => [...prev, filterName]); + } else { + setUnitViewFilters( + unitViewFilters.filter( + (unitViewFilter) => unitViewFilter !== filterName + ) + ); + } + }} + /> +

Canal

+
+
+

+ { + units.filter((unit) => unit.unitView.includes("Canal")) + .length + } +

+
+
+
+
+ unitViewFilter === "Park" + )} + onChange={(isChecked, filterName) => { + if (isChecked) { + setUnitViewFilters((prev) => [...prev, filterName]); + } else { + setUnitViewFilters( + unitViewFilters.filter( + (unitViewFilter) => unitViewFilter !== filterName + ) + ); + } + }} + /> +

Park

+
+
+

+ { + units.filter((unit) => unit.unitView.includes("Park")) + .length + } +

+
+
+
+
+
+
+
+
+

+ Units{" "} + {filteredUnits.length} +

+ +
+
+ {filteredUnits.map((unit) => ( +
+
+
+

{unit.projectName}

+
+

+ {unit.unitNo[0] === "E" ? "East" : "West"} Wing +

+
+

{unit.floor}

+
+

{unit.unitNo}

+
+
+ +
+
handleClickCard(unit)} + > + +
+
handleClickCard(unit)} + > +

+ {unit.unitName}, {unit.totalArea} Sqft +

+

+ {(unit.unitPrice && + `AED ${unit.unitPrice.toLocaleString()}`) || + "Unavailable"} +

+
+
+ ))} +
+
-
); -}; +} export default SearchPage; diff --git a/client/src/pages/SearchPage2.tsx b/client/src/pages/SearchPage2.tsx deleted file mode 100644 index 73f6aa6..0000000 --- a/client/src/pages/SearchPage2.tsx +++ /dev/null @@ -1,896 +0,0 @@ -/* eslint-disable react-hooks/exhaustive-deps */ -import { useEffect, useState } from "react"; -import RestartIcon from "../components/icons/RestartIcon"; -import api from "../utils/api"; -import IUnit from "../types/IUnit"; -import Checkbox2 from "../components/Checkbox2"; -import HeartIcon from "../components/icons/HeartIcon"; -import RangeSlider from "react-range-slider-input"; -import Input from "../components/Input"; -import ChevronDownIcon from "../components/icons/ChevronDownIcon"; -import useModal from "../store/useModal"; -import unitTypes from "../data/unitTypes.json"; -import UnitModalForSearchPage from "../components/modals/UnitModalForSearchPage"; -import useFavoritesStore from "../store/useFavoritesStore"; -import HeartFilledIcon from "../components/icons/HeartFilledIcon"; -import { useSearchParams } from "react-router-dom"; - -function SearchPage2() { - const [units, setUnits] = useState([]); - const [filteredUnits, setFilteredUnits] = useState([]); - const [unitTypeFilters, setUnitTypeFilters] = useState([]); - const [unitViewFilters, setUnitViewFilters] = useState([]); - const [minCost, setMinCost] = useState(0); - const [maxCost, setMaxCost] = useState(1000000); - const [cost, setCost] = useState([minCost, maxCost]); - const [minTotalArea] = useState(341); - const [maxTotalArea] = useState(1058); - const [totalArea, setTotalArea] = useState([ - minTotalArea, - maxTotalArea, - ]); - const [minFloor] = useState(5); - const [maxFloor] = useState(31); - const [floor, setFloor] = useState([minFloor, maxFloor]); - const [isSortPriceAsc, setIsSortPriceAsc] = useState(); - const { setModal } = useModal(); - const { favoriteUnits, setFavoriteUnits } = useFavoritesStore(); - const [searchParams, setSearchParams] = useSearchParams(); - - async function getUnits() { - try { - const result: IUnit[] = await api.get("units").json(); - - setUnits(result); - } catch (error) { - // - } - } - - function getImageSrc(unitNo: string): string { - const side = unitNo[0]; - const floor = Number(unitNo.split("-")[1].slice(0, -2)); - const unitNumber = Number(unitNo.split("-")[1].slice(-2)); - - if (side === "W") { - // Side "W" - if (floor < 24) { - switch (unitNumber) { - case 1: - return "/images/layouts/2br_a_left.png"; - case 2: - return "/images/layouts/studio_left.png"; - case 3: - return "/images/layouts/1br_d_left.png"; - case 4: - return "/images/layouts/studio_left.png"; - case 5: - return "/images/layouts/studio_left.png"; - case 6: - return "/images/layouts/1br_d_left.png"; - case 7: - return "/images/layouts/1br_a_left.png"; - case 8: - return "/images/layouts/1br_a_left.png"; - case 9: - return "/images/layouts/studio_flex_left.png"; - case 10: - return "/images/layouts/studio_flex_left.png"; - case 11: - return "/images/layouts/studio_flex_left.png"; - case 12: - return "/images/layouts/studio_flex_left.png"; - case 13: - return "/images/layouts/studio_flex_left.png"; - case 14: - return "/images/layouts/studio_flex_left.png"; - case 15: - return "/images/layouts/1br_c_left.png"; - case 16: - return "/images/layouts/1br_c_left.png"; - case 17: - return "/images/layouts/2br_b_left.png"; - } - } else { - switch (unitNumber) { - case 1: - return "/images/layouts/2br_a_left.png"; - case 2: - return "/images/layouts/studio_left.png"; - case 3: - return "/images/layouts/1br_d_left.png"; - case 4: - return "/images/layouts/studio_left.png"; - case 5: - return "/images/layouts/studio_left.png"; - case 6: - return "/images/layouts/1br_d_left.png"; - case 7: - return "/images/layouts/1br_a_left.png"; - case 8: - return "/images/layouts/1br_a_left.png"; - case 9: - return "/images/layouts/1br_d_left.png"; - case 10: - return "/images/layouts/studio_left.png"; - case 11: - return "/images/layouts/studio_left.png"; - case 12: - return "/images/layouts/1br_d_left.png"; - case 13: - return "/images/layouts/1br_c_left.png"; - case 14: - return "/images/layouts/1br_c_left.png"; - case 15: - return "/images/layouts/2br_b_left.png"; - } - } - } else { - // Side "E" - switch (unitNumber) { - case 1: - return "/images/layouts/2br_a_left.png"; - case 2: - return "/images/layouts/studio_left.png"; - case 3: - return "/images/layouts/1br_d_left.png"; - case 4: - return "/images/layouts/studio_left.png"; - case 5: - return "/images/layouts/studio_left.png"; - case 6: - return "/images/layouts/1br_c_left.png"; - case 7: - return "/images/layouts/1br_c_left.png"; - case 8: - return "/images/layouts/1br_b_left.png"; - case 9: - return "/images/layouts/1br_b_left.png"; - case 10: - return "/images/layouts/1br_c_left.png"; - case 11: - return "/images/layouts/studio_left.png"; - case 12: - return "/images/layouts/studio_left.png"; - case 13: - return "/images/layouts/studio_left.png"; - case 14: - return "/images/layouts/studio_left.png"; - case 15: - return "/images/layouts/1br_c_left.png"; - case 16: - return "/images/layouts/1br_c_left.png"; - } - } - - console.log(side, floor, unitNumber); - - return ""; - } - - function refreshFilters() { - console.log("call func refreshFilters"); - setUnitTypeFilters([]); - setUnitViewFilters([]); - setCost([minCost, maxCost]); - setTotalArea([minTotalArea, maxTotalArea]); - setFloor([minFloor, maxFloor]); - } - - function getTypeByUnitNo(unitNo: string) { - const side = unitNo[0] === "E" ? "East" : "West"; - const floor = Number(unitNo.split("-")[1].slice(0, -2)); - const number = Number(unitNo.split("-")[1].slice(-2)); - - console.log(side, floor, number); - - if (side === "East") { - if ([1].includes(number)) { - return "2br-type-a"; - } else if ([2, 4, 5, 11, 12, 13, 14].includes(number)) { - return "studio-2"; - } else if ([3].includes(number)) { - return "1br-type-d"; - } else if ([6, 7, 10, 15, 16].includes(number)) { - return "1br-type-c"; - } else if ([8, 9].includes(number)) { - return "1br-type-b"; - } - } else if (side === "West") { - if (floor <= 21) { - // Floors 5-21 - if ([1].includes(number)) { - return "2br-type-a"; - } else if ([2, 4, 5].includes(number)) { - return "studio-2"; - } else if ([3, 6].includes(number)) { - return "1br-type-d"; - } else if ([7, 8].includes(number)) { - return "1br-type-a"; - } else if ([9, 10, 11, 12, 13, 14].includes(number)) { - return "studio-flex"; - } else if ([15, 16].includes(number)) { - return "1br-type-c"; - } else if ([17].includes(number)) { - return "2br-type-b"; - } - } else { - // Floors 24-31 - if ([1].includes(number)) { - return "2br-type-a"; - } else if ([2, 4, 5, 10, 11].includes(number)) { - return "studio-2"; - } else if ([3, 6, 9, 12].includes(number)) { - return "1br-type-d"; - } else if ([7, 8].includes(number)) { - return "1br-type-a"; - } else if ([13, 14].includes(number)) { - return "1br-type-c"; - } else if ([15].includes(number)) { - return "2br-type-b"; - } - } - } - - // TODO Connect to DB - - return ""; - } - - function addOrRemoveFromFavorites(unit: IUnit) { - if (!favoriteUnits.some((favoriteUnit) => favoriteUnit.id === unit.id)) { - setFavoriteUnits([...favoriteUnits, unit]); - } else { - setFavoriteUnits( - favoriteUnits.filter((favoriteUnit) => favoriteUnit.id !== unit.id) - ); - } - } - - function handleClickCard(unit: IUnit) { - setModal( - unitType.type === getTypeByUnitNo(unit.unitNo) - )?.type || "" - } - /> - ); - - searchParams.set("unitNo", unit.unitNo); - setSearchParams(searchParams); - } - - useEffect(() => { - let newFilteredUnits = units - .filter((unit) => - unitTypeFilters.length ? unitTypeFilters.includes(unit.unitType) : unit - ) - .filter((unit) => - unitViewFilters.length - ? unitViewFilters.some((unitViewFilter) => - unit.unitView.includes(unitViewFilter) - ) - : unit - ) - .filter( - (unit) => - unit.totalArea >= totalArea[0] && unit.totalArea <= totalArea[1] - ) - .filter((unit) => unit.floor >= floor[0] && unit.floor <= floor[1]); - - console.log("isSortPriceAsc", isSortPriceAsc); - - if (isSortPriceAsc !== undefined) { - if (isSortPriceAsc) { - newFilteredUnits = newFilteredUnits.sort( - (a, b) => (b.unitPrice || 0) - (a.unitPrice || 0) - ); - } else { - newFilteredUnits = newFilteredUnits.sort( - (a, b) => (a.unitPrice || 0) - (b.unitPrice || 0) - ); - } - } - - setFilteredUnits(newFilteredUnits); - - setMinCost( - Math.min( - ...newFilteredUnits.map((unit) => unit.unitPrice!).filter(Boolean) - ) - ); - setMaxCost( - Math.max( - ...newFilteredUnits.map((unit) => unit.unitPrice!).filter(Boolean) - ) - ); - setCost([ - Math.min( - ...newFilteredUnits.map((unit) => unit.unitPrice!).filter(Boolean) - ), - Math.max( - ...newFilteredUnits.map((unit) => unit.unitPrice!).filter(Boolean) - ), - ]); - - // setMinTotalArea( - // Math.round( - // Math.min( - // ...newFilteredUnits.map((unit) => unit.totalArea).filter(Boolean) - // ) - // ) - // ); - // setMaxTotalArea( - // Math.round( - // Math.max( - // ...newFilteredUnits.map((unit) => unit.totalArea).filter(Boolean) - // ) - // ) - // ); - // setTotalArea([ - // Math.round( - // Math.min( - // ...newFilteredUnits.map((unit) => unit.totalArea).filter(Boolean) - // ) - // ), - // Math.round( - // Math.max( - // ...newFilteredUnits.map((unit) => unit.totalArea).filter(Boolean) - // ) - // ), - // ]); - - // setMinFloor( - // Math.min(...newFilteredUnits.map((unit) => unit.floor).filter(Boolean)) - // ); - // setMaxFloor( - // Math.max(...newFilteredUnits.map((unit) => unit.floor).filter(Boolean)) - // ); - // setFloor([ - // Math.min(...newFilteredUnits.map((unit) => unit.floor).filter(Boolean)), - // Math.max(...newFilteredUnits.map((unit) => unit.floor).filter(Boolean)), - // ]); - }, [ - units, - unitTypeFilters, - unitViewFilters, - totalArea, - floor, - isSortPriceAsc, - ]); - - // useEffect(() => { - // if (!units.length) return; - - // setMinCost( - // Math.min(...units.map((unit) => unit.unitPrice!).filter(Boolean)) - // ); - // setMaxCost( - // Math.max(...units.map((unit) => unit.unitPrice!).filter(Boolean)) - // ); - // setCost([ - // Math.min(...units.map((unit) => unit.unitPrice!).filter(Boolean)), - // Math.max(...units.map((unit) => unit.unitPrice!).filter(Boolean)), - // ]); - // }, [units]); - - useEffect(() => { - getUnits(); - }, []); - - useEffect(() => { - if (searchParams.has("unitNo")) { - const unitNo = searchParams.get("unitNo"); - - if (!unitNo) return; - - const type = getTypeByUnitNo(unitNo); - const unit = units.find((unit) => unit.unitNo === unitNo); - - if (!unit) return; - - setModal(); - } - }, [units]); - - return ( -
-
-
-

Filters

- -
-
-

Apartment type

-
-
-
- unitTypeFilter === "Studio Flex" - )} - onChange={(isChecked, filterName) => { - if (isChecked) { - setUnitTypeFilters((prev) => [...prev, filterName]); - } else { - setUnitTypeFilters( - unitTypeFilters.filter( - (unitTypeFilter) => unitTypeFilter !== filterName - ) - ); - } - }} - /> -

Studio Flex

-
-
-

- { - units.filter((unit) => unit.unitType === "Studio Flex") - .length - } -

-
-
-
-
- unitTypeFilter === "Studio Squared" - )} - onChange={(isChecked, filterName) => { - if (isChecked) { - setUnitTypeFilters((prev) => [...prev, filterName]); - } else { - setUnitTypeFilters( - unitTypeFilters.filter( - (unitTypeFilter) => unitTypeFilter !== filterName - ) - ); - } - }} - /> -

Studio²

-
-
-

- { - units.filter((unit) => unit.unitType === "Studio Squared") - .length - } -

-
-
-
-
- unitTypeFilter === "1 BR Squared" - )} - onChange={(isChecked, filterName) => { - if (isChecked) { - setUnitTypeFilters((prev) => [...prev, filterName]); - } else { - setUnitTypeFilters( - unitTypeFilters.filter( - (unitTypeFilter) => unitTypeFilter !== filterName - ) - ); - } - }} - /> -

1 Bedroom²

-
-
-

- { - units.filter((unit) => unit.unitType === "1 BR Squared") - .length - } -

-
-
-
-
- unitTypeFilter === "2 BR Squared" - )} - onChange={(isChecked, filterName) => { - if (isChecked) { - setUnitTypeFilters((prev) => [...prev, filterName]); - } else { - setUnitTypeFilters( - unitTypeFilters.filter( - (unitTypeFilter) => unitTypeFilter !== filterName - ) - ); - } - }} - /> -

2 Bedroom²

-
-
-

- { - units.filter((unit) => unit.unitType === "2 BR Squared") - .length - } -

-
-
-
-
-
-
-

Cost

-

AED

-
-
-
- setCost([value as number, cost[1]])} - /> - setCost([cost[0], value as number])} - /> -
-
- setCost(value)} - disabled - /> -
-
-
-
-
-

Total Area

-

Sqft

-
-
-
- - setTotalArea([value as number, totalArea[1]]) - } - /> - - setTotalArea([totalArea[0], value as number]) - } - /> -
-
- setTotalArea(value)} - /> -
-
-
-
-
-

Floor

-
-
-
- setFloor([value as number, floor[1]])} - /> - setFloor([floor[0], value as number])} - /> -
-
- setFloor(value)} - /> -
-
-
-
-

View

-
-
-
- unitViewFilter === "BK/DT" - )} - onChange={(isChecked, filterName) => { - if (isChecked) { - setUnitViewFilters((prev) => [...prev, filterName]); - } else { - setUnitViewFilters( - unitViewFilters.filter( - (unitViewFilter) => unitViewFilter !== filterName - ) - ); - } - }} - /> -

Burj Khalifa / Downtown

-
-
-

- { - units.filter((unit) => unit.unitView.includes("BK/DT")) - .length - } -

-
-
-
-
- unitViewFilter === "Business Bay" - )} - onChange={(isChecked, filterName) => { - if (isChecked) { - setUnitViewFilters((prev) => [...prev, filterName]); - } else { - setUnitViewFilters( - unitViewFilters.filter( - (unitViewFilter) => unitViewFilter !== filterName - ) - ); - } - }} - /> -

Business Bay

-
-
-

- { - units.filter((unit) => unit.unitView === "Business Bay") - .length - } -

-
-
-
-
- unitViewFilter === "Amenities" - )} - onChange={(isChecked, filterName) => { - if (isChecked) { - setUnitViewFilters((prev) => [...prev, filterName]); - } else { - setUnitViewFilters( - unitViewFilters.filter( - (unitViewFilter) => unitViewFilter !== filterName - ) - ); - } - }} - /> -

Amenities

-
-
-

- { - units.filter((unit) => unit.unitView.includes("Amenities")) - .length - } -

-
-
-
-
- unitViewFilter === "Canal" - )} - onChange={(isChecked, filterName) => { - if (isChecked) { - setUnitViewFilters((prev) => [...prev, filterName]); - } else { - setUnitViewFilters( - unitViewFilters.filter( - (unitViewFilter) => unitViewFilter !== filterName - ) - ); - } - }} - /> -

Canal

-
-
-

- { - units.filter((unit) => unit.unitView.includes("Canal")) - .length - } -

-
-
-
-
- unitViewFilter === "Park" - )} - onChange={(isChecked, filterName) => { - if (isChecked) { - setUnitViewFilters((prev) => [...prev, filterName]); - } else { - setUnitViewFilters( - unitViewFilters.filter( - (unitViewFilter) => unitViewFilter !== filterName - ) - ); - } - }} - /> -

Park

-
-
-

- { - units.filter((unit) => unit.unitView.includes("Park")) - .length - } -

-
-
-
-
-
-
-
-
-

- Units{" "} - {filteredUnits.length} -

- -
-
- {filteredUnits.map((unit) => ( -
-
-
-

{unit.projectName}

-
-

- {unit.unitNo[0] === "E" ? "East" : "West"} Wing -

-
-

{unit.floor}

-
-

{unit.unitNo}

-
-
- -
-
handleClickCard(unit)} - > - -
-
handleClickCard(unit)} - > -

- {unit.unitName}, {unit.totalArea} Sqft -

-

- {(unit.unitPrice && - `AED ${unit.unitPrice.toLocaleString()}`) || - "Unavailable"} -

-
-
- ))} -
-
-
-
- ); -} - -export default SearchPage2; diff --git a/client/src/pages/TestPage.tsx b/client/src/pages/TestPage.tsx deleted file mode 100644 index 169a56b..0000000 --- a/client/src/pages/TestPage.tsx +++ /dev/null @@ -1,5 +0,0 @@ -function TestPage() { - return
TestPage
; -} - -export default TestPage; diff --git a/client/src/pages/UnitTypesItemPage.tsx b/client/src/pages/UnitTypesItemPage.tsx index 81e4f8a..84339c9 100644 --- a/client/src/pages/UnitTypesItemPage.tsx +++ b/client/src/pages/UnitTypesItemPage.tsx @@ -13,7 +13,7 @@ function UnitTypesItemPage() { const [selectedUniTypePos, setSelectedUniTypePos] = useState("left"); return ( -
+