favorite page

This commit is contained in:
2024-05-22 14:39:59 +05:00
parent a9fa869e4c
commit efa598f3b8
13 changed files with 512 additions and 43 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

@@ -0,0 +1,64 @@
import { ILayoutCard } from "../../types/layoutCard";
import Button from "../Button";
import BookingIcon from "../icons/BookingIcon";
import HeartIcon from "../icons/Heart";
interface FavoriteAppartmentCardProps {
card: ILayoutCard;
}
const FavoriteAppartmentCard = ({ card }: FavoriteAppartmentCardProps) => {
const {
roveHome,
floorEnd,
floorStart,
wing,
units,
apartmentType,
square,
cost,
} = card;
return (
<div className="bg-white flex flex-col p-4 rounded-lg gap-4 cursor-pointer select-none">
<div className="flex gap-4 justify-between">
<div className="flex gap-1 flex-col">
<p className="text-[#00BED7] text-s leading-5">
Rove Home {roveHome}
</p>
<div className="text-[#73787C] flex gap-2 items-center w-fit">
<p className="text-caption-m font-semibold leading-4">{wing}</p>
<div className="w-1 h-1 bg-[#E2E2DC] rounded-full"></div>
<p className="text-caption-m font-semibold leading-4">
Floor {floorStart}-{floorEnd}
</p>
<div className="w-1 h-1 bg-[#E2E2DC] rounded-full"></div>
<p className="text-caption-m font-semibold leading-4">
Floor {floorStart}-{floorEnd}
</p>
</div>
</div>
<Button buttonType="favorite" icon={<HeartIcon isFilled />} />
</div>
<div className="w-full aspect-square rounded-lg">
<img src="/images/layout-1.png" alt="" className="h-full" />
</div>
<div className="flex flex-col gap-3">
<div className="flex flex-col gap-1">
<p className="text[#0D1922] text-s">
{apartmentType}, {square} Sqft
</p>
<p className="text-[#00BED7] text-m font-bold">AED {cost}</p>
</div>
<Button
icon={<BookingIcon />}
text="Send Enquiry"
className="flex justify-center"
buttonType="cta"
/>
</div>
</div>
);
};
export default FavoriteAppartmentCard;
+20
View File
@@ -0,0 +1,20 @@
const BookingIcon = () => {
return (
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M16.6666 14.8336V8.18475C16.6666 7.87652 16.5244 7.58551 16.2813 7.39602L10.6147 2.9794C10.2532 2.6977 9.7466 2.6977 9.38518 2.9794L3.71851 7.39603C3.4754 7.58551 3.33325 7.87652 3.33325 8.18475V14.8336C3.33325 15.3859 3.78097 15.8336 4.33325 15.8336H7.99992H11.9999H15.6666C16.2189 15.8336 16.6666 15.3859 16.6666 14.8336ZM5.6077 9.83444C5.93705 9.47822 6.49174 9.45338 6.85161 9.77875L9.06456 11.7796L13.1482 8.08737C13.5081 7.762 14.0628 7.78683 14.3921 8.14306C14.7267 8.50493 14.7014 9.07035 14.3358 9.40088L9.73521 13.5604C9.3544 13.9047 8.77472 13.9047 8.3939 13.5604L5.66402 11.0923C5.29845 10.7617 5.27313 10.1963 5.6077 9.83444Z"
fill="currentColor"
/>
</svg>
);
};
export default BookingIcon;
+44
View File
@@ -0,0 +1,44 @@
const FiltersIcon = () => {
return (
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M2.5 15.4167H17.5"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
/>
<circle cx="12.0833" cy="15.4167" r="2.08333" fill="currentColor" />
<path
d="M2.5 4.58334H17.5"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
/>
<ellipse
cx="14.5833"
cy="4.58333"
rx="2.08333"
ry="2.08333"
fill="currentColor"
/>
<path
d="M2.5 10H17.5"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
/>
<path
d="M7.49992 9.99999C7.49992 11.1506 6.56718 12.0833 5.41659 12.0833C4.26599 12.0833 3.33325 11.1506 3.33325 9.99999C3.33325 8.8494 4.26599 7.91666 5.41659 7.91666C6.56718 7.91666 7.49992 8.8494 7.49992 9.99999Z"
fill="currentColor"
/>
</svg>
);
};
export default FiltersIcon;
+24
View File
@@ -0,0 +1,24 @@
const TrashIcon = () => {
return (
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M5.00008 7.08333L5.68059 15.2494C5.76697 16.286 6.6335 17.0833 7.67368 17.0833H12.3265C13.3667 17.0833 14.2332 16.286 14.3196 15.2494L15.0001 7.08333M5.00008 7.08333V7.08333C4.56897 7.08333 4.24563 6.68892 4.33018 6.26618L4.41594 5.83738C4.51332 5.35048 4.94083 5 5.43738 5H14.5628C15.0593 5 15.4868 5.35048 15.5842 5.83738L15.67 6.26618C15.7545 6.68892 15.4312 7.08333 15.0001 7.08333V7.08333M5.00008 7.08333H15.0001M11.4584 14.5833V9.58333M8.54175 9.58333V14.5833"
stroke="currentColor"
stroke-width="1.5"
/>
<path
d="M8.33325 5V3.61111C8.33325 3.4652 8.37636 3.32071 8.46012 3.18591C8.54388 3.0511 8.66664 2.92861 8.82141 2.82544C8.97617 2.72226 9.1599 2.64042 9.36211 2.58458C9.56432 2.52874 9.78105 2.5 9.99992 2.5C10.2188 2.5 10.4355 2.52874 10.6377 2.58458C10.8399 2.64042 11.0237 2.72226 11.1784 2.82544C11.3332 2.92861 11.456 3.0511 11.5397 3.18591C11.6235 3.32071 11.6666 3.4652 11.6666 3.61111V5"
stroke="currentColor"
stroke-width="1.5"
/>
</svg>
);
};
export default TrashIcon;
@@ -0,0 +1,34 @@
import { useState } from "react";
import { ISwitchLabel } from "../../types/switchLabel";
import SwitchToggle from "../SwitchToggle";
const apartmentLayouts: ISwitchLabel[] = [
{ id: "1", label: "Layout" },
{ id: "2", label: "On the floor" },
];
const ApartmentLayout = () => {
const [currentLabel, setCurrentLabel] = useState(apartmentLayouts[0]);
const handleOnSwitchClick = (label: ISwitchLabel) => {
setCurrentLabel(label);
};
return (
<div className="p-10 pt-6 rounded-lg bg-white flex flex-col items-center gap-8 relative">
<SwitchToggle
labels={apartmentLayouts}
currentLabel={currentLabel}
onClick={handleOnSwitchClick}
/>
<div className="w-full px-[304px] ">
<img className="w-full " src="/images/layout-1.png" alt="" />
</div>
<img
src="/images/compass.png"
alt=""
className="absolute right-10 bottom-10"
/>
</div>
);
};
export default ApartmentLayout;
@@ -0,0 +1,65 @@
import Button from "../Button";
const ApartmentSidebar = () => {
return (
<div className="flex flex-col gap-2 h-full">
<div className="rounded-lg overflow-clip flex-1 relative">
<p className="absolute top-[30px] left-6 font-semibold text-m text-white">
<div className="w-1/2 border-t absolute -top-[5px]"></div>
View from window
</p>
<img
src="/images/view_from_window.png"
alt=""
className="w-full h-full object-cover"
/>
</div>
<div className="flex flex-col rounded-lg bg-white p-6 gap-6 ">
<h2 className="font-semibold text-[#0D1922] text-subheadline-s">
Parameters
</h2>
<div className="flex flex-col gap-3">
<div className="flex justify-between text-m">
<p className="text-[#73787C]">Complex</p>
<p className="text-[#0D1922]">ROVE Home Marasi Drive</p>
</div>
<div className="flex justify-between text-m">
<p className="text-[#73787C]">Section</p>
<p className="text-[#0D1922]">East Wing</p>
</div>
<div className="flex justify-between text-m">
<p className="text-[#73787C]">Floor</p>
<p className="text-[#0D1922]">11</p>
</div>
<div className="flex justify-between text-m">
<p className="text-[#73787C]">Number</p>
<p className="text-[#0D1922]">213</p>
</div>
<div className="flex justify-between text-m">
<p className="text-[#73787C]">Size</p>
<p className="text-[#0D1922]">609 Sqft</p>
</div>
</div>
</div>
<div className="rounded-lg bg-white flex flex-col p-6 gap-4">
<p className="text-[#00BED7] font-semibold text-subheadline-s leading-7">
AED 1,668,888
</p>
<div className="flex gap-2">
<Button
text="3D Tour"
buttonType="secondary"
className="w-full flex justify-center"
/>
<Button
text="Send Enquiry"
buttonType="cta"
className="w-full flex justify-center"
/>
</div>
</div>
</div>
);
};
export default ApartmentSidebar;
@@ -0,0 +1,33 @@
import { useNavigate } from "react-router-dom";
import Button from "../Button";
import HeartIcon from "../icons/Heart";
import LeftArrowSliderIcon from "../icons/LeftArrowSliderIcon";
const ButtonPanel = () => {
const navigate = useNavigate();
const handleOnBackClick = () => {
navigate(-1);
};
return (
<div className="flex justify-between w-full gap-4 items-center pb-3">
<div className="flex gap-4 items-center ">
<Button
icon={<LeftArrowSliderIcon />}
buttonType="cta"
onClick={handleOnBackClick}
/>
<div className="flex flex-col">
<p className="text-[#73787C] text-caption-m font-semibold"> 213</p>
<h2 className="text-subheadline-s font-semibold text-[#0D1922]">
1 bedroom apartment
</h2>
</div>
</div>
<Button buttonType="favorite" icon={<HeartIcon />} />
</div>
);
};
export default ButtonPanel;
@@ -1,9 +1,17 @@
import Button from "../Button";
import HeartIcon from "../icons/Heart";
import { useNavigate } from "react-router-dom";
const ApartmentCard = () => {
const navigate = useNavigate();
const handleOnCardClick = () => {
navigate("1");
};
return (
<div className="bg-white flex flex-col p-4 rounded-lg gap-4 cursor-pointer select-none">
<div
className="bg-white flex flex-col p-4 rounded-lg gap-4 cursor-pointer select-none"
onClick={handleOnCardClick}
>
<div className="flex gap-4 justify-between">
<div className="flex gap-1 flex-col">
<p className="text-[#00BED7] text-s leading-5">
+5
View File
@@ -9,6 +9,7 @@ import ComplexWing from "./pages/ComplexWing";
import Search from "./pages/Search";
import SearchParticularApartments from "./pages/SearchParticularApartments";
import SearchApartment from "./pages/SearchApartment";
import Favorites from "./pages/Favorites";
const router = createBrowserRouter([
{
@@ -47,6 +48,10 @@ const router = createBrowserRouter([
path: "/search/:apartmentType/:apartmentId",
element: <SearchApartment />,
},
{
path: "/favorites",
element: <Favorites />,
},
],
},
]);
+204
View File
@@ -0,0 +1,204 @@
import { useState, useEffect } from "react";
import { sortCardBy } from "../calc/sortCard";
import Button from "../components/Button";
import Footer from "../components/Footer";
import FiltersIcon from "../components/icons/FiltersIcon";
import TrashIcon from "../components/icons/TrashIcon";
import SortButton from "../components/searchPage/SortButton";
import { initialSortList } from "../consts/initialSearchPage";
import { ILayoutCard } from "../types/layoutCard";
import FavoriteAppartmentCard from "../components/favoritesPage/FavoriteApartmentCard";
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 Favorites = () => {
const [sortList, setSortList] = useState(initialSortList);
const [cards, setCards] = useState(favoriteCards);
const handleOnSortClick = (sortId: string) => {
const updatedSortList = sortList.map((sort) => {
const isSelected = sort.id === sortId;
return { ...sort, isSelected: isSelected };
});
setSortList(updatedSortList);
};
useEffect(() => {
const sortedCards = sortCardBy(sortList, favoriteCards);
setCards(sortedCards);
}, [sortList]);
return (
<div className="overflow-scroll h-screen w-screen pt-14">
<div className="p-6">
<div className="pb-6">
<div className="flex justify-between w-full items-center border-b pb-[11px]">
<div className="flex gap-4 font-semibold text-subheadline-s leading-7 py-[6px]">
<h2 className="text-[#0D1922]">Units</h2>
<p className="text-[#73787C]">145</p>
</div>
<div className="flex items-center gap-4">
<div className="flex items-center gap-2">
<Button
buttonType="fab"
icon={<FiltersIcon />}
className="text-[#73787C]"
text={"Compare"}
/>
<Button
buttonType="fab"
icon={<TrashIcon />}
className="text-[#73787C]"
text="Remove all"
/>
</div>
<SortButton sortList={sortList} onClick={handleOnSortClick} />
</div>
</div>
</div>
<div className="grid grid-cols-4 gap-4">
{cards.map((card) => (
<FavoriteAppartmentCard card={card} key={card.id} />
))}
</div>
</div>
<Footer />
</div>
);
};
export default Favorites;
+10 -42
View File
@@ -1,51 +1,19 @@
import { useState } from "react";
import Button from "../components/Button";
import Footer from "../components/Footer";
import SwitchToggle from "../components/SwitchToggle";
import HeartIcon from "../components/icons/Heart";
import LeftArrowSliderIcon from "../components/icons/LeftArrowSliderIcon";
import { ISwitchLabel } from "../types/switchLabel";
const apartmentLayouts: ISwitchLabel[] = [
{ id: "1", label: "Layout" },
{ id: "2", label: "On the floor" },
];
import ButtonPanel from "../components/searchApartment/ButtonPanel";
import ApartmentLayout from "../components/searchApartment/ApartmentLayout";
import ApartmentSidebar from "../components/searchApartment/ApartmentSidebar";
const SearchApartment = () => {
const [currentLabel, setCurrentLabel] = useState(apartmentLayouts[0]);
const handleOnSwitchClick = (label: ISwitchLabel) => {
setCurrentLabel(label);
};
return (
<div className="overflow-scroll h-screen w-screen pt-14">
<div className="grid grid-cols-4 border px-4 pt-6 pb-4 gap-4">
<div className="flex flex-col col-span-3">
<div className="flex justify-between w-full gap-4 items-center pb-3">
<div className="flex gap-4 items-center ">
<Button icon={<LeftArrowSliderIcon />} buttonType="cta" />
<div className="flex flex-col">
<p className="text-[#73787C] text-caption-m font-semibold">
213
</p>
<h2 className="text-subheadline-s font-semibold text-[#0D1922]">
1 bedroom apartment
</h2>
</div>
</div>
<Button buttonType="favorite" icon={<HeartIcon />} />
</div>
<div className="p-10 pt-6 rounded-lg bg-white flex flex-col items-center gap-8">
<SwitchToggle
labels={apartmentLayouts}
currentLabel={currentLabel}
onClick={handleOnSwitchClick}
/>
<div className="w-full px-[304px] ">
<img className="w-full" src="/images/layout-1.png" alt="" />
</div>
</div>
<div className="grid grid-cols-9 border px-4 pt-6 pb-4 gap-4">
<div className="flex flex-col col-span-7">
<ButtonPanel />
<ApartmentLayout />
</div>
<div className="col-span-2 rounded-lg">
<ApartmentSidebar />
</div>
<div className="col-span-1 bg-white rounded-lg"></div>
</div>
<Footer />
</div>