diff --git a/client/src/api/apartments.ts b/client/src/api/apartments.ts index 27c9010..66bec7d 100644 --- a/client/src/api/apartments.ts +++ b/client/src/api/apartments.ts @@ -3,38 +3,40 @@ import ky from "ky"; async function getApartments( token: string | null, - roveHomeFilters: string[], - apartmentTypeFilters: string[], - viewFilters: string[], - totalAreaFilter: number[], - floorFilter: number[], - sortBy: string | undefined, - page: number, - perPage: number + roveHomeFilters?: string[], + apartmentTypeFilters?: string[], + viewFilters?: string[], + totalAreaFilter?: number[], + floorFilter?: number[], + sortBy?: string | undefined, + page?: number, + perPage?: number ) { const roveHomeQuery = - roveHomeFilters.length !== 0 + roveHomeFilters && roveHomeFilters.length !== 0 ? `rove_home=${roveHomeFilters.join(",")}` : ""; const apartmentQuery = - apartmentTypeFilters.length !== 0 + apartmentTypeFilters && apartmentTypeFilters.length !== 0 ? `apartment_type=${apartmentTypeFilters.join(",")}` : ""; const viewQuery = - viewFilters.length !== 0 ? `views=${viewFilters.join(",")}` : ""; + viewFilters && viewFilters.length !== 0 + ? `views=${viewFilters.join(",")}` + : ""; const totalAreaSliderQuery = - totalAreaFilter.length !== 0 + totalAreaFilter && totalAreaFilter.length !== 0 ? `total_area_between=${totalAreaFilter[0]},${totalAreaFilter[1]}` : ""; const floorQuery = - floorFilter.length !== 0 + floorFilter && floorFilter.length !== 0 ? `floor_between=${floorFilter[0]},${floorFilter[1]}` : ""; const sortByQuery = sortBy ? `sort_by=${sortBy}` : ""; - const pageQuery = `page=${page}`; - const perPageQuery = `per_page=${perPage}`; + const pageQuery = page ? `page=${page}` : ""; + const perPageQuery = perPage ? `per_page=${perPage}` : ""; const query = [ apartmentQuery, @@ -52,8 +54,7 @@ async function getApartments( const url = `${apartmentsApi}?${query}`; const res = await ky.get(url, { headers: { - Authorization: `Zoho-oauthtoken 1000.f2b816cab56f851da9397cfbc17254e6.8636301ca36fb659a41b050bf0237d4d`, - // Authorization: `Zoho-oauthtoken ${token}`, + Authorization: `Zoho-oauthtoken ${token}`, }, }); diff --git a/client/src/calc/getFilteredApartments.ts b/client/src/calc/getFilteredApartments.ts new file mode 100644 index 0000000..649bdd7 --- /dev/null +++ b/client/src/calc/getFilteredApartments.ts @@ -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 }; diff --git a/client/src/calc/sortCard.ts b/client/src/calc/sortCard.ts index a6d9840..a57311c 100644 --- a/client/src/calc/sortCard.ts +++ b/client/src/calc/sortCard.ts @@ -1,18 +1,18 @@ -import { ILayoutCard } from "../types/layoutCard"; +import { IAparmentRes } from "../types/apartmentsRes"; 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 sortedList = [...layoutsCards].sort((cardA, cardB) => { switch (sortType?.title) { 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; + 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: return 1; } diff --git a/client/src/components/Button.tsx b/client/src/components/Button.tsx index 352bbe4..bbc5f04 100644 --- a/client/src/components/Button.tsx +++ b/client/src/components/Button.tsx @@ -11,7 +11,9 @@ interface ButtonProps { icon?: React.ReactNode; text?: string; className?: string; - onClick?: () => void; + onClick?: ( + event: React.MouseEvent + ) => void | (() => void); disabled?: boolean; isCircleRounded?: boolean; type?: "button" | "submit" | "reset"; diff --git a/client/src/components/MultiRangeSlider.tsx b/client/src/components/MultiRangeSlider.tsx index 7fd565b..1f2dd35 100644 --- a/client/src/components/MultiRangeSlider.tsx +++ b/client/src/components/MultiRangeSlider.tsx @@ -15,6 +15,7 @@ const MultiRangeSlider = ({ }: MultiRangeSliderProps) => { const firstInputRef = useRef(null); const secondInputRef = useRef(null); + const { isDisabled } = multirangeSlider; const handleOnRangeInputChange = (e: [a: number, b: number]) => { onChange(multirangeSlider.id, e); @@ -72,14 +73,6 @@ const MultiRangeSlider = ({
- {/* */} - {/* */}
diff --git a/client/src/components/complexWingPage/FloorDescription.tsx b/client/src/components/complexWingPage/FloorDescription.tsx index 7b97f98..5d3ccc3 100644 --- a/client/src/components/complexWingPage/FloorDescription.tsx +++ b/client/src/components/complexWingPage/FloorDescription.tsx @@ -1,84 +1,19 @@ import useWingSidebar from "../../store/useWingSidebar"; +import { IAparmentRes } from "../../types/apartmentsRes"; import { IDesctiptionFloor } from "../../types/descriptionFloor"; interface FloorDescriptionProps { descriptionFloor: IDesctiptionFloor | null; + floorApartments: IAparmentRes[]; } -const FloorDescription = ({ descriptionFloor }: FloorDescriptionProps) => { +const FloorDescription = ({ + descriptionFloor, + floorApartments, +}: FloorDescriptionProps) => { const { isSidebar } = useWingSidebar(); return ( <> - {/*
-
-
-
-

- {descriptionFloor?.floor} Floor -

-

- {descriptionFloor?.wing} -

-
-
- 234 units -
-
-
-
-
-
-

21

-
-

Studio Flex

-
-

AED 1,048,888

-
-
-
-
-

- 56 -

-
-

Studio

-
-

AED 1,138,888

-
-
-
-
-

- 89 -

-
-

1 Bedroom

-
-

AED 1,668,888

-
-
-
-
-

- 10 -

-
-

2 Bedroom, Type A

-
-

AED 2,408,888

-
-
-
-
-
*/}
{

- 234 units + {floorApartments.length} units
-

21

+

+ { + floorApartments.filter( + (apart) => apart.Unit_Type === "Studio Flex" + ).length + } +

Studio Flex

-

AED 1,048,888

+

Unvailiable

- 56 + { + floorApartments.filter( + (apart) => apart.Unit_Type === "Studio Squared" + ).length + }

Studio

-

AED 1,138,888

+

Unvailiable

- 89 + { + floorApartments.filter( + (apart) => apart.Unit_Type === "1 BR Squared" + ).length + }

1 Bedroom

-

AED 1,668,888

+

Unvailiable

- 10 + { + floorApartments.filter( + (apart) => apart.Unit_Type === "2 BR Squared" + ).length + }

-

2 Bedroom, Type A

+

+ 2 Bedroom, Type A +

-

AED 2,408,888

+

Unvailiable

diff --git a/client/src/components/complexWingPage/FloorSidebar/ApartmentDescription.tsx b/client/src/components/complexWingPage/FloorSidebar/ApartmentDescription.tsx index 38031b3..557cf9c 100644 --- a/client/src/components/complexWingPage/FloorSidebar/ApartmentDescription.tsx +++ b/client/src/components/complexWingPage/FloorSidebar/ApartmentDescription.tsx @@ -1,49 +1,69 @@ +import { IAparmentRes } from "../../../types/apartmentsRes"; import VirtualTourIcon from "../../icons/VirtualTourIcon"; interface ApartmentDescriptionProps { isVisible: boolean; is3DTourAvailable: boolean; descRef: React.LegacyRef; + hoveredApartment: IAparmentRes | null; } const ApartmentDescription = ({ isVisible, is3DTourAvailable, descRef, + hoveredApartment, }: ApartmentDescriptionProps) => { + const wing = + hoveredApartment && hoveredApartment.Unit_No.split("-")[0] === "E" + ? "East Wing" + : "West Wing"; + return ( -
-
-

1 bedroom, 609 Sqft

-
-

East Wing

-
-

Floor 11

-
-

E-213

-
-
-

- AED 1,668,888 -

+ <> + {hoveredApartment && ( +
- -

- 3D-tour -

+

+ {hoveredApartment?.Unit_Type},{" "} + {hoveredApartment && + Math.round(hoveredApartment?.Total_Area_Sqft)}{" "} + Sqft +

+
+

{wing}

+
+

Floor {hoveredApartment.Floor}

+
+

{hoveredApartment.Unit_No}

+
+
+

+ Unvailiable +

+ {/*

+ AED 1,668,888 +

*/} +
+ +

+ 3D-tour +

+
+
+
-
-
-
+ )} + ); }; diff --git a/client/src/components/complexWingPage/FloorSidebar/FloorEastWingHighlighting.tsx b/client/src/components/complexWingPage/FloorSidebar/FloorEastWingHighlighting.tsx index e3e63d0..45a8667 100644 --- a/client/src/components/complexWingPage/FloorSidebar/FloorEastWingHighlighting.tsx +++ b/client/src/components/complexWingPage/FloorSidebar/FloorEastWingHighlighting.tsx @@ -1,6 +1,10 @@ interface FloorEastWingHighlightingProps { - handleOnMouseOut: () => void; - handleOnMouseOver: () => void; + handleOnMouseOut: + | (() => void) + | ((event: React.MouseEvent) => void); + handleOnMouseOver: ( + event: React.MouseEvent + ) => void | (() => void); handleOnApartmentClick: ( event: React.MouseEvent ) => void; @@ -14,6 +18,7 @@ function FloorEastWingHighlighting({ return ( <> void) + | ((event: React.MouseEvent) => void); + handleOnMouseOver: + | (() => void) + | ((event: React.MouseEvent) => void); + handleOnApartmentClick: ( + event: React.MouseEvent + ) => void; +} + +function FloorEastWingTopHighlighting({ + handleOnMouseOut, + handleOnMouseOver, + handleOnApartmentClick, +}: FloorEastWingTopHighlightingProps) { + return ( + <> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +} + +export default FloorEastWingTopHighlighting; diff --git a/client/src/components/complexWingPage/FloorSidebar/FloorEastWingTopLayout.tsx b/client/src/components/complexWingPage/FloorSidebar/FloorEastWingTopLayout.tsx new file mode 100644 index 0000000..ae23575 --- /dev/null +++ b/client/src/components/complexWingPage/FloorSidebar/FloorEastWingTopLayout.tsx @@ -0,0 +1,417 @@ +const FloorEastWingTopLayout = () => { + return ( + <> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default FloorEastWingTopLayout; diff --git a/client/src/components/complexWingPage/FloorSidebar/FloorSidebar.tsx b/client/src/components/complexWingPage/FloorSidebar/FloorSidebar.tsx index 26f63c4..9ba2bc2 100644 --- a/client/src/components/complexWingPage/FloorSidebar/FloorSidebar.tsx +++ b/client/src/components/complexWingPage/FloorSidebar/FloorSidebar.tsx @@ -7,49 +7,70 @@ import FloorEastWingHighlighting from "./FloorEastWingHighlighting"; import FloorEastWingLayout from "./FloorEastWingLayout"; import useModal from "../../../store/useModal"; import AboutComplexModal from "../../modals/AboutComplexModal"; -import _appartment from "../../../data/appartments.json"; -import { IAppartmentComplex } from "../../../types/apartmentSphere"; +import { IAparmentRes } from "../../../types/apartmentsRes"; +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 { currentFloor: IDesctiptionFloor | null; onMouseEnter: () => void; + floorApartments: IAparmentRes[]; } -const FloorSidebar = ({ currentFloor, onMouseEnter }: IFloorSidebarProps) => { +const FloorSidebar = ({ + currentFloor, + onMouseEnter, + floorApartments, +}: IFloorSidebarProps) => { const [mousePos, setMousePos] = useState([0, 0]); const [isDescVisible, setIsDescVisible] = useState(false); + const [hoveredApartment, setHoveredApartment] = useState( + null + ); const [is3DTourAvailable] = useState(true); const { setModal } = useModal(); 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( event: React.MouseEvent ) { - const apartmentId = (event.target as HTMLElement).dataset.apartment; - const apartment = appartments.find((aprt) => aprt.id === apartmentId); + const apartmentType = event.currentTarget.dataset.type; + const apartment = floorApartments.find( + (aprt) => aprt.Unit_Type === apartmentType + ); if (apartment) { setModal(); 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).width; - - // } - const x = e.clientX - window.innerWidth / 2 - 50; - - setMousePos([x, y]); - } - function handleOnMouseOut(): void { setIsDescVisible(false); } - function handleOnMouseOver(): void { + function handleOnMouseOver( + event: React.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); } @@ -67,6 +88,7 @@ const FloorSidebar = ({ currentFloor, onMouseEnter }: IFloorSidebarProps) => { style={{ top: `${mousePos[1]}px`, left: `${mousePos[0]}px` }} > {

{currentFloor?.wing}

-
234 units
+
{floorApartments.length} units
@@ -127,7 +149,7 @@ const FloorSidebar = ({ currentFloor, onMouseEnter }: IFloorSidebarProps) => { handleOnMouseOver={handleOnMouseOver} /> - ) : ( + ) : currentFloor && currentFloor.floor <= 21 ? ( { handleOnMouseOver={handleOnMouseOver} /> + ) : ( + + + + )}
diff --git a/client/src/components/complexWingPage/FloorSidebar/FloorWestWingHighlighting.tsx b/client/src/components/complexWingPage/FloorSidebar/FloorWestWingHighlighting.tsx index 4b3f9bf..3e86995 100644 --- a/client/src/components/complexWingPage/FloorSidebar/FloorWestWingHighlighting.tsx +++ b/client/src/components/complexWingPage/FloorSidebar/FloorWestWingHighlighting.tsx @@ -1,6 +1,10 @@ interface FloorWestWingHighlightingProps { - handleOnMouseOut: () => void; - handleOnMouseOver: () => void; + handleOnMouseOut: + | (() => void) + | ((event: React.MouseEvent) => void); + handleOnMouseOver: ( + event: React.MouseEvent + ) => void; handleOnApartmentClick: ( e: React.MouseEvent ) => void; @@ -21,6 +25,7 @@ const FloorWestWingHighlighting = ({ viewBox="0 0 672 280" > { const [isSkygardenSidebar, setIsSkygardenSidebar] = useState(false); const [isFloorSidebar, setIsFloorSidebar] = useState(false); const { setModal } = useModal(); + const [apartments, setApartments] = useState([]); + const [currentHoveredApartments, setCurrentHoveredApartments] = useState< + IAparmentRes[] + >([]); + const [selectedApartments, setSelectedApartments] = useState( + [] + ); function handleResize() { const screenWidth = window.innerWidth; @@ -54,7 +64,6 @@ const SequenceWing = () => { setLeft(_left); } } - const handleOnFloorMouseEnter = ( e: React.MouseEvent ) => { @@ -64,7 +73,15 @@ const SequenceWing = () => { const _currentFloor = descriptions.find((desc) => desc.id === id); if (!_currentFloor) return; 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); + setCurrentHoveredApartments(_currentHoveredApartments); }; const handleOnWingWrapperMouseEnter = ( @@ -78,8 +95,9 @@ const SequenceWing = () => { }; const handleOnFloorClick = () => { - if (!currentHoveredFloor) return; + if (!currentHoveredFloor && !currentHoveredApartments) return; const screenWidth = window.innerWidth; + setSelectedApartments(currentHoveredApartments); setCurrentFloor(currentHoveredFloor); if (screenWidth < laptopWidth) { setModal(); @@ -129,6 +147,28 @@ const SequenceWing = () => { } }, [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 (
{ style={{ right: `${isFloorSidebar ? "0" : "-50%"}` }} > @@ -193,7 +234,10 @@ const SequenceWing = () => { }`, }} > - +
{ - const { roveHome, floorEnd, floorStart, wing, apartmentType, square, cost } = - card; + const { Floor, Unit_Type, Total_Area_Sqft, Unit_No } = card; + const wing = Unit_No.split("-")[0] === "E" ? "East" : "West"; const navigate = useNavigate(); + const { setFavorites } = useFavorites(); const { setModal } = useModal(); @@ -36,62 +38,92 @@ const FavoriteAppartmentCard = ({ card }: FavoriteAppartmentCardProps) => { ); }; + const handleOnAddFavoriteClick = ( + e: React.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 ( -
-
-
-

- Rove Home {roveHome} -

-
-

{wing}

-
-

- Floor {floorStart}-{floorEnd} + <> +

+
+
+

+ Rove Home {Unit_Type}

-
-

- Floor {floorStart}-{floorEnd} +

+

+ {wing} Wing +

+
+

+ Floor {Floor} +

+
+

+ {Unit_No} +

+
+
+
+
+ +
+
+
+

+ {Unit_Type}, {Total_Area_Sqft} Sqft +

+

+ {/* AED {formatNumber(cost, ",", 3, 1)} */} + Unavailiable

+
-
-
- -
-
-
-

- {apartmentType}, {square} Sqft -

-

- AED {formatNumber(cost, ",", 3, 1)} -

-
-
-
+ ); }; diff --git a/client/src/components/favoritesPage/FavoriteCardList.tsx b/client/src/components/favoritesPage/FavoriteCardList.tsx index acd7b2a..e66679f 100644 --- a/client/src/components/favoritesPage/FavoriteCardList.tsx +++ b/client/src/components/favoritesPage/FavoriteCardList.tsx @@ -1,14 +1,11 @@ -import { ILayoutCard } from "../../types/layoutCard"; +import useFavorites from "../../store/useFavorites"; import FavoriteAppartmentCard from "./FavoriteApartmentCard"; -interface FavoriteCardListProps { - cards: ILayoutCard[]; -} - -const FavoriteCardList = ({ cards }: FavoriteCardListProps) => { +const FavoriteCardList = () => { + const { favorites } = useFavorites(); return (
- {cards.map((card) => ( + {favorites.map((card) => ( ))}
diff --git a/client/src/components/favoritesPage/FavoriteSlider.tsx b/client/src/components/favoritesPage/FavoriteSlider.tsx index d7aefb1..e1d67c1 100644 --- a/client/src/components/favoritesPage/FavoriteSlider.tsx +++ b/client/src/components/favoritesPage/FavoriteSlider.tsx @@ -1,21 +1,18 @@ import { useState, useRef, useEffect } from "react"; -import { ILayoutCard } from "../../types/layoutCard"; import FavoriteSliderCard from "./FavoriteSliderCard"; import Button from "../Button"; import RightArrowIcon from "../icons/RightArrowIcon"; import LeftArrowIcon from "../icons/LeftArrowIcon"; import { useSwipeable } from "react-swipeable"; +import useFavorites from "../../store/useFavorites"; -interface FavoritesSliderProps { - cards: ILayoutCard[]; -} - -const FavoritesSlider = ({ cards }: FavoritesSliderProps) => { +const FavoritesSlider = () => { const [offset, setOffset] = useState(0); const cardRef = useRef(null); const [cardWidth, setCardWidth] = useState(0); const [buttonTopPos, setButtonTopPos] = useState(0); const [cols, setCols] = useState(2); + const { favorites } = useFavorites(); const handlers = useSwipeable({ trackMouse: true, @@ -30,7 +27,7 @@ const FavoritesSlider = ({ cards }: FavoritesSliderProps) => { }; const handleOnRightBtnClick = () => { - if (offset > -cards.length + cols + 1) { + if (offset > -favorites.length + cols) { setOffset((prev) => prev - 1); } }; @@ -86,22 +83,25 @@ const FavoritesSlider = ({ cards }: FavoritesSliderProps) => { style={{ transform: `translateX(${offset * cardWidth}px)` }} >
- {Array.from({ length: Math.floor(cards.length / cols) }).map( + {Array.from({ length: Math.ceil(favorites.length / cols) }).map( (_, index) => { + console.log("index", index); return (
- {cards + {favorites .slice(index * cols, cols + index * cols) - .map((card) => ( - - ))} + .map((card) => { + return ( + + ); + })}
); } diff --git a/client/src/components/favoritesPage/FavoriteSliderCard.tsx b/client/src/components/favoritesPage/FavoriteSliderCard.tsx index 750c9bd..7ee01d4 100644 --- a/client/src/components/favoritesPage/FavoriteSliderCard.tsx +++ b/client/src/components/favoritesPage/FavoriteSliderCard.tsx @@ -1,15 +1,43 @@ -import { formatNumber } from "../../calc/formatNumber"; -import { ILayoutCard } from "../../types/layoutCard"; +// import { formatNumber } from "../../calc/formatNumber"; +import useFavorites from "../../store/useFavorites"; +import { IAparmentRes } from "../../types/apartmentsRes"; import Button from "../Button"; import BookingIcon from "../icons/BookingIcon"; import HeartIcon from "../icons/Heart"; interface FavoriteSliderCardProps { - card: ILayoutCard; + card: IAparmentRes; elementRef: React.MutableRefObject; } const FavoriteSliderCard = ({ card, elementRef }: FavoriteSliderCardProps) => { + const wing = card.Unit_No.split("-")[0] === "E" ? "East" : "West"; + const { setFavorites } = useFavorites(); + + const handleOnAddFavoriteClick = ( + e: React.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 (
{

- {card.apartmentType}, {card.square} Sqft + {card.Unit_Type}, {card.Total_Area_Sqft} Sqft

-
{

Price

- AED {formatNumber(card.cost, ",", 3, 1)} + Unavailable + {/* AED {formatNumber(card.cost, ",", 3, 1)} */}

Total Area

-

{card.square} Sqft

+

{card.Total_Area_Sqft} Sqft

Project

-

Rove Home {card.roveHome}

+

{card.Project_Name}

Section

-

{card.wing}

+

{wing} Wing

Floor

-

Floor 11

+

Floor {card.Floor}

Number

-

213

+

{card.Unit_No}

@@ -101,29 +139,32 @@ const AboutComplexModal = ({ apartment }: AboutComplexModalProps) => {

Complex

-

ROVE Home Marasi Drive

+

{apartment.Project_Name}

Section

-

East Wing

+

{wing} Wing

Floor

-

11

+

{apartment.Floor}

Number

-

213

+

{unitNumber}

Size

-

609 Sqft

+

+ {Math.round(apartment.Total_Area_Sqft)} Sqft +

- AED {formatNumber(1668888, ",", 3, 1)} + Unvailiable + {/* AED {formatNumber(1668888, ",", 3, 1)} */}

{sortList.map((sort) => ( diff --git a/client/src/consts/initialMasterplanFilters.ts b/client/src/consts/initialMasterplanFilters.ts index df40004..64309d1 100644 --- a/client/src/consts/initialMasterplanFilters.ts +++ b/client/src/consts/initialMasterplanFilters.ts @@ -12,6 +12,7 @@ const initialSliders: IMultirangeSlider[] = [ title: "Cost", unit: "AED", id: "1", + isDisabled: true, }, { minValue: 341, @@ -68,7 +69,7 @@ const initialRoveHomeCheckboxes: ICheckbox[] = [ { title: "Downtown", id: "1", - disabled: false, + disabled: true, selected: false, value: "Rove Home Downtown", }, @@ -82,6 +83,7 @@ const initialRoveHomeCheckboxes: ICheckbox[] = [ title: "Dubai Marina", id: "3", selected: false, + disabled: true, value: "Rove Home Dubai Marina", }, ]; @@ -113,6 +115,9 @@ const initialSortList: ISort[] = [ }, ]; +const perPageInitial = 12; +const pageInitial = 1; + export { initialAparmentTypeCheckboxes, initialSliders, @@ -120,4 +125,6 @@ export { initialViewCheckboxes, initialRoveHomeCheckboxes, initialSortList, + perPageInitial, + pageInitial, }; diff --git a/client/src/pages/Favorites.tsx b/client/src/pages/Favorites.tsx index 629b2ba..f73c2cc 100644 --- a/client/src/pages/Favorites.tsx +++ b/client/src/pages/Favorites.tsx @@ -5,146 +5,146 @@ import Footer from "../components/Footer"; import TrashIcon from "../components/icons/TrashIcon"; import SortButton from "../components/searchPage/SortButton"; import { initialSortList } from "../consts/initialMasterplanFilters"; -import { ILayoutCard } from "../types/layoutCard"; 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"; -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, - }, -]; +// 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, +// }, +// ]; const initialCollectionCompareSwitcher: ISwitcher = { id: "1", @@ -154,9 +154,8 @@ const initialCollectionCompareSwitcher: ISwitcher = { const Favorites = () => { const [sortList, setSortList] = useState(initialSortList); - // const [cards, setCards] = useState([]); - const [cards, setCards] = useState(favoriteCards); const [switcher, setSwitcher] = useState(initialCollectionCompareSwitcher); + const { favorites, setFavorites } = useFavorites(); const handleOnSortClick = (sortId: string) => { const updatedSortList = sortList.map((sort) => { @@ -174,7 +173,7 @@ const Favorites = () => { const handleOnDeleteFavoriteClick = () => { localStorage.removeItem("Favorites"); - setCards([]); + setFavorites([]); }; useEffect(() => { @@ -182,9 +181,9 @@ const Favorites = () => { if (favoriteCards) { const convertedCards = JSON.parse(favoriteCards); const sortedCards = sortCardBy(sortList, convertedCards); - setCards(sortedCards); + setFavorites(sortedCards); } - }, [sortList]); + }, [setFavorites, sortList]); return (
@@ -194,7 +193,7 @@ const Favorites = () => {

Units

-

{cards.length}

+

{favorites.length}

@@ -228,11 +227,7 @@ const Favorites = () => {
- {switcher.isSwitched ? ( - - ) : ( - - )} + {switcher.isSwitched ? : }
diff --git a/client/src/store/useFavorites.ts b/client/src/store/useFavorites.ts new file mode 100644 index 0000000..5921432 --- /dev/null +++ b/client/src/store/useFavorites.ts @@ -0,0 +1,14 @@ +import { create } from "zustand"; +import { IAparmentRes } from "../types/apartmentsRes"; + +interface ApartmentsStore { + favorites: IAparmentRes[]; + setFavorites: (favorites: IAparmentRes[]) => void; +} + +const useFavorites = create((set) => ({ + favorites: [], + setFavorites: (apartments) => set(() => ({ favorites: apartments })), +})); + +export default useFavorites; diff --git a/client/src/store/useSearchFilters.ts b/client/src/store/useSearchFilters.ts index ed49b2b..eba52ad 100644 --- a/client/src/store/useSearchFilters.ts +++ b/client/src/store/useSearchFilters.ts @@ -11,6 +11,7 @@ import { import { IMultirangeSlider } from "../types/multirangeSlider"; import { ISwitcher } from "../types/switcher"; import { ISort } from "../types/sortType"; +import { perPageInitial } from "../consts/initialMasterplanFilters"; interface Store { apartmentTypeCheckboxes: ICheckbox[]; @@ -39,7 +40,7 @@ const useSearchFilters = create((set) => ({ switchers: initialSwitchers, sortList: initialSortList, page: 1, - perPage: 12, + perPage: perPageInitial, setPerPage: (perPage) => set(() => ({ perPage: perPage })), setPage: (page) => set(() => ({ page: page })), setSortList: (sortList) => set(() => ({ sortList: sortList })), diff --git a/client/src/types/multirangeSlider.ts b/client/src/types/multirangeSlider.ts index 914cdf4..ad30aa1 100644 --- a/client/src/types/multirangeSlider.ts +++ b/client/src/types/multirangeSlider.ts @@ -6,6 +6,7 @@ interface IMultirangeSlider { title: string; unit?: string; id: string; + isDisabled?: boolean; } export type { IMultirangeSlider }; diff --git a/server/.env b/server/.env index 3f3f579..0631fdd 100644 --- a/server/.env +++ b/server/.env @@ -1,2 +1,3 @@ PORT=3000 -REFRESH_TOKEN=1000.da3146d49fa8a399f0c635e74954ff9c.e010dbb1bb605d7e1aa5bf7fc0521f8b \ No newline at end of file +REFRESH_TOKEN=1000.da3146d49fa8a399f0c635e74954ff9c.e010dbb1bb605d7e1aa5bf7fc0521f8b +URL= \ No newline at end of file diff --git a/server/package.json b/server/package.json index 17e8ac4..4efab9e 100644 --- a/server/package.json +++ b/server/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "type": "module", "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 ./", "start": "node ./dist/index.js" }, diff --git a/server/src/routes/apartments.ts b/server/src/routes/apartments.ts index fc04d57..cce7c89 100644 --- a/server/src/routes/apartments.ts +++ b/server/src/routes/apartments.ts @@ -173,7 +173,7 @@ function filterApartments( router.get("/", async (req, res) => { const accessToken = req?.headers?.authorization; const { - per_page = 20, + per_page = 1000, page = 1, rove_home = "", apartment_type = "",