virtual tour page

This commit is contained in:
2024-05-24 18:12:02 +05:00
parent a9cde50016
commit f4cf8a98ab
29 changed files with 965 additions and 96 deletions
+2 -2
View File
@@ -14,12 +14,12 @@ const ButtomPanel = () => {
<div className="flex gap-2 pb-6 pl-6">
<Button
text="Disclaimer"
buttonType="tertiary"
buttonType="special"
className="pl-2"
icon={<DisclaimerIcon />}
onClick={handleOnDisclaimerClick}
/>
<Button text="Privacy Policy" buttonType="tertiary" />
<Button text="Privacy Policy" buttonType="special" />
</div>
</div>
<div className="p-6">
+2 -2
View File
@@ -18,12 +18,12 @@ const ComplexButtomPanel = () => {
<div className="flex gap-2 pb-6 pl-6">
<Button
text="Disclaimer"
buttonType="tertiary"
buttonType="special"
className="pl-2"
icon={<DisclaimerIcon />}
onClick={handleOnDisclaimerClick}
/>
<Button text="Privacy Policy" buttonType="tertiary" />
<Button text="Privacy Policy" buttonType="special" />
</div>
</div>
<div className="p-6">
+10 -2
View File
@@ -50,12 +50,20 @@ const MultiRangeSlider = ({
};
useEffect(() => {
if (!firstInputRef.current) return;
if (
!firstInputRef.current ||
multirangeSlider.startValue === multirangeSlider.minValue
)
return;
(firstInputRef.current as HTMLInputElement).focus();
}, [multirangeSlider.startValue]);
useEffect(() => {
if (!secondInputRef.current) return;
if (
!secondInputRef.current ||
multirangeSlider.maxValue === multirangeSlider.endValue
)
return;
(secondInputRef.current as HTMLInputElement).focus();
}, [multirangeSlider.endValue]);
+3 -4
View File
@@ -2,7 +2,7 @@ import { ISwitcher } from "../types/switcher";
interface ISwitchProps {
switcher: ISwitcher;
onClick: (id: string) => void;
onClick: ((id: string) => void) | (() => void);
}
const Switch = ({ switcher, onClick }: ISwitchProps) => {
@@ -18,9 +18,8 @@ const Switch = ({ switcher, onClick }: ISwitchProps) => {
onClick={handleOnClick}
>
<div
className={`w-5 h-5 bg-[#fff] rounded-full absolute transition-all duration-300 ease-in-out top-[2px] ${
switcher.isSwitched ? "left-[18px]" : "left-[2px]"
}`}
className={`w-5 h-5 bg-[#fff] rounded-full absolute transition-all duration-300 ease-in-out top-[2px]
${switcher.isSwitched ? "left-[18px]" : "left-[2px]"}`}
></div>
</div>
);
@@ -148,7 +148,7 @@ const SequenceWing = () => {
}, [isSidebar]);
return (
<div className="absolute left-0 overflow-hidden h-screen w-screen select-none pointer-events-none">
<div className="absolute left-0 overflow-hidden h-screen w-screen select-none ">
<div
className=" absolute h-[calc(100vh-56px)] right-0 w-1/2 duration-300 transition-all "
style={{ right: `${isFloorSidebar ? "0" : "-50%"}` }}
@@ -1,6 +1,8 @@
import useModal from "../../store/useModal";
import { ILayoutCard } from "../../types/layoutCard";
import Button from "../Button";
import BookingIcon from "../icons/BookingIcon";
import CrossIcon from "../icons/CrossIcon";
import HeartIcon from "../icons/Heart";
interface FavoriteAppartmentCardProps {
@@ -8,17 +10,14 @@ interface FavoriteAppartmentCardProps {
}
const FavoriteAppartmentCard = ({ card }: FavoriteAppartmentCardProps) => {
const {
roveHome,
floorEnd,
floorStart,
wing,
units,
apartmentType,
square,
cost,
} = card;
const { roveHome, floorEnd, floorStart, wing, apartmentType, square, cost } =
card;
const { setModal } = useModal();
const handleOnSendEquiryClick = () => {
setModal(<SendEnquiryModal />);
};
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">
@@ -55,10 +54,65 @@ const FavoriteAppartmentCard = ({ card }: FavoriteAppartmentCardProps) => {
text="Send Enquiry"
className="flex justify-center"
buttonType="cta"
onClick={handleOnSendEquiryClick}
/>
</div>
</div>
);
};
const SendEnquiryModal = () => {
const { setModal } = useModal();
const handleOnModalClick = () => {
setModal(null);
};
return (
<div className="absolute z-50 top-0 left-0 w-screen bg-[#0D192266] h-screen backdrop-blur-[6px] grid grid-cols-12 items-center">
<div className="h-full col-span-3 col-start-10 bg-[#F3F3F2] py-6 px-6 flex flex-col justify-between items-center">
<div className="flex flex-col gap-8 w-full">
<div className="flex justify-between pb-4 border-b border-[#E2E2DC] ">
<h2 className="text-subheadline-m font-semibold">
Apartment purchase enquiry
</h2>
<Button
buttonType="tertiary"
icon={<CrossIcon />}
onClick={handleOnModalClick}
/>
</div>
<div className="rounded-lg bg-white p-4 flex flex-col gap-4">
<div className="flex flex-col gap-1">
<p className="text-subheadline-s font-semibold text-[#0D1922]">
1 bedroom, 609 Sqft{" "}
</p>
<p className="text-subheadline-s font-semibold text-[#0D192266]">
AED 1,668,888
</p>
</div>
<div className="flex flex-col gap-1">
<p className="text-[#00BED7] text-s">1 bedroom, 609 Sqft </p>
<div className="flex gap-1 flex-col">
<div className="text-[#73787C] flex gap-2 items-center w-fit">
<p className="text-caption-m font-semibold leading-4">
East Wing
</p>
<div className="w-1 h-1 bg-[#E2E2DC] rounded-full"></div>
<p className="text-caption-m font-semibold leading-4">
Floor 11
</p>
<div className="w-1 h-1 bg-[#E2E2DC] rounded-full"></div>
<p className="text-caption-m font-semibold leading-4">
213
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default FavoriteAppartmentCard;
@@ -0,0 +1,18 @@
import { ILayoutCard } from "../../types/layoutCard";
import FavoriteAppartmentCard from "./FavoriteApartmentCard";
interface FavoriteCardListProps {
cards: ILayoutCard[];
}
const FavoriteCardList = ({ cards }: FavoriteCardListProps) => {
return (
<div className="grid grid-cols-4 gap-4">
{cards.map((card) => (
<FavoriteAppartmentCard card={card} key={card.id} />
))}
</div>
);
};
export default FavoriteCardList;
@@ -0,0 +1,99 @@
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";
interface FavoritesSliderProps {
cards: ILayoutCard[];
}
const cols = 4;
const FavoritesSlider = ({ cards }: FavoritesSliderProps) => {
const [offset, setOffset] = useState(0);
const cardRef = useRef<HTMLDivElement | null>(null);
const [cardWidth, setCardWidth] = useState(0);
const [buttonTopPos, setButtonTopPos] = useState(0);
useEffect(() => {
const cardElement = cardRef.current;
if (cardElement) {
const gap = 16;
const width = cardElement.clientWidth + gap;
const buttonHeight = cardElement.clientHeight;
const _buttonTopPos = buttonHeight / 2 + 20;
setCardWidth(width);
setButtonTopPos(_buttonTopPos);
}
}, []);
const handleOnLeftBtnClick = () => {
if (0 > offset) {
setOffset((prev) => prev + 1);
}
};
const handleOnRightBtnClick = () => {
if (offset > -cards.length + cols) {
setOffset((prev) => prev - 1);
}
};
return (
<div className="w-[calc(100vw - 48px)] relative">
<div
className="absolute -left-2 z-30"
style={{ top: `${buttonTopPos}px` }}
>
<Button
buttonType="fab"
icon={<LeftArrowIcon />}
onClick={handleOnLeftBtnClick}
/>
</div>
<div
className="absolute -right-2 z-30"
style={{ top: `${buttonTopPos}px` }}
>
<Button
buttonType="fab"
icon={<RightArrowIcon />}
onClick={handleOnRightBtnClick}
/>
</div>
<div className="w-full overflow-hidden">
<div
className="transition-all ease-in-out duration-300"
style={{ transform: `translateX(${offset * cardWidth}px)` }}
>
<div className="flex w-fit gap-4">
{Array.from({ length: Math.floor(cards.length / cols) }).map(
(_, index) => {
return (
<div
className="grid grid-cols-4 gap-4 w-[calc(100vw-48px)] h-fit"
key={index}
>
{cards
.slice(index * cols, cols + index * cols)
.map((card) => (
<FavoriteSliderCard
elementRef={cardRef}
card={card}
key={card.id}
/>
))}
</div>
);
}
)}
</div>
</div>
</div>
</div>
);
};
export default FavoritesSlider;
@@ -0,0 +1,59 @@
import { ILayoutCard } from "../../types/layoutCard";
import Button from "../Button";
import BookingIcon from "../icons/BookingIcon";
import HeartIcon from "../icons/Heart";
interface FavoriteSliderCardProps {
card: ILayoutCard;
elementRef: React.MutableRefObject<HTMLDivElement | null>;
}
const FavoriteSliderCard = ({ card, elementRef }: FavoriteSliderCardProps) => {
return (
<div className="rounded-lg flex flex-col overflow-clip gap-6">
<div className="flex flex-col gap-4 bg-white p-4" ref={elementRef}>
<div className="flex justify-between">
<div className="flex text-subheadline-s font-semibold text-[#0D1922]">
<h2>
{card.apartmentType}, {card.square} Sqft
</h2>
</div>
<Button buttonType="favorite" icon={<HeartIcon isFilled />} />
</div>
<img src="/images/layout-1.png" alt="" className="w-full" />
</div>
<div className="flex flex-col gap-1 pb-6 border-b">
<p className="text-s text-[#73787C]">Price</p>
<p className="text-[#0D1922] text-m">AED {card.cost}</p>
</div>
<div className="flex flex-col gap-1 pb-6 border-b">
<p className="text-s text-[#73787C]">Total Area</p>
<p className="text-[#0D1922] text-m">{card.square} Sqft</p>
</div>
<div className="flex flex-col gap-1 pb-6 border-b">
<p className="text-s text-[#73787C]">Project</p>
<p className="text-[#00BED7] text-m">Rove Home {card.roveHome}</p>
</div>
<div className="flex flex-col gap-1 pb-6 border-b">
<p className="text-s text-[#73787C]">Section</p>
<p className="text-[#0D1922] text-m">{card.wing}</p>
</div>
<div className="flex flex-col gap-1 pb-6 border-b">
<p className="text-s text-[#73787C]">Floor</p>
<p className="text-[#0D1922] text-m">Floor 11</p>
</div>
<div className="flex flex-col gap-1 pb-6 border-b">
<p className="text-s text-[#73787C]">Number</p>
<p className="text-[#0D1922] text-m">213</p>
</div>
<Button
icon={<BookingIcon />}
text="Send Enquiry"
className="flex justify-center"
buttonType="cta"
/>
</div>
);
};
export default FavoriteSliderCard;
+21
View File
@@ -0,0 +1,21 @@
const LeftArrowIcon = () => {
return (
<svg
width="20"
height="21"
viewBox="0 0 20 21"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12.5001 16.3334L6.66675 10.5001L12.5001 4.66675"
stroke="currentColor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
};
export default LeftArrowIcon;
@@ -14,11 +14,6 @@ const ApartmentLayout = () => {
};
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>
@@ -27,6 +22,11 @@ const ApartmentLayout = () => {
alt=""
className="absolute right-10 bottom-10"
/>
<SwitchToggle
labels={apartmentLayouts}
currentLabel={currentLabel}
onClick={handleOnSwitchClick}
/>
</div>
);
};
@@ -1,24 +1,19 @@
import { useEffect, useLayoutEffect, useRef, useState } from "react";
/* eslint-disable @typescript-eslint/no-unused-vars */
import { useLayoutEffect, useRef, useState } from "react";
import { layoutsCards } from "../../consts/initialSearchPage";
import LayoutCard from "../searchPage/LayoutCard";
import SimilarAppartmentCard from "./SimilarAppartmentCard";
import Button from "../Button";
import RightArrowIcon from "../icons/RightArrowIcon";
const cols = 4;
const SimilarSlider = () => {
const [cards, setCards] = useState(layoutsCards.slice(0, 4));
const [cards, setCards] = useState(layoutsCards);
const [offset, setOffset] = useState(0);
const sliderRef = useRef<HTMLDivElement | null>(null);
const cardRef = useRef<HTMLDivElement | null>(null);
const [sliderHeight, setSliderHeight] = useState(0);
const [cardWidth, setCardWidth] = useState(0);
useLayoutEffect(() => {
const sliderElement = sliderRef.current;
if (sliderElement) {
const height = sliderElement.clientHeight;
setSliderHeight(height);
}
const cardElement = cardRef.current;
if (cardElement) {
const gap = 16;
@@ -27,21 +22,20 @@ const SimilarSlider = () => {
}
}, []);
useEffect(() => {
console.log("offset", offset);
return () => {};
}, [offset]);
const handleOnLeftBtnClick = () => {
if (0 < offset) {
if (0 > offset) {
setOffset((prev) => prev + 1);
}
};
const handleOnRightBtnClick = () => {
// if (0 > offset) {
setOffset((prev) => prev - 1);
if (offset > -cards.length + cols) {
setOffset((prev) => prev - 1);
}
// if (offset === -cards.length + cols) {
// const updatedCards = [...cards, ...cards.slice(0, 4)];
// setCards(updatedCards);
// setOffset((prev) => prev - 1);
// }
};
@@ -68,32 +62,32 @@ const SimilarSlider = () => {
<div className="border-t border-b py-4">
<div className="w-[100vw-16px] overflow-hidden">
<div
className={` relative transition-transform duration-300 ease-in-out`}
className={`transition-transform duration-300 ease-in-out`}
style={{
height: sliderHeight,
transform: `translateX(${offset * cardWidth}px)`,
}}
>
<div className="flex w-fit gap-4 absolute left-0 top-0">
<div
className="grid grid-cols-4 gap-4 w-[calc(100vw-32px)] h-fit"
ref={sliderRef}
>
{cards.map((layoutsCard) => (
<SimilarAppartmentCard
elementRef={cardRef}
layoutCard={layoutsCard}
/>
))}
</div>
<div className="grid grid-cols-4 gap-4 w-[calc(100vw-32px)]">
{cards.map((layoutsCard) => (
<SimilarAppartmentCard
elementRef={cardRef}
layoutCard={layoutsCard}
/>
))}
</div>
<div className="flex w-fit gap-4">
{Array.from({ length: Math.floor(cards.length / cols) }).map(
(_, index) => {
return (
<div
className="grid grid-cols-4 gap-4 w-[calc(100vw-48px)] h-fit"
key={index}
>
{cards
.slice(index * cols, cols + index * cols)
.map((card) => (
<SimilarAppartmentCard
elementRef={cardRef}
layoutCard={card}
key={card.id}
/>
))}
</div>
);
}
)}
</div>
</div>
</div>
+1 -1
View File
@@ -34,7 +34,7 @@ const SortButton = ({ sortList, onClick }: SortButtonProps) => {
</div>
</button>
<div
className={`absolute flex flex-col bg-white p-2 text-[#0D1922] rounded-lg w-full shadow-lg transition-opacity duration-300 ease-in-out ${
className={`absolute z-20 flex flex-col bg-white p-2 text-[#0D1922] rounded-lg w-full shadow-lg transition-opacity duration-300 ease-in-out ${
isSelected ? "opacity-100" : "opacity-0"
}`}
>
@@ -0,0 +1,43 @@
import { BackSide, MeshBasicMaterial } from "three";
import { OrbitControls, Html, Sphere, useTexture } from "@react-three/drei";
import { Suspense, useRef } from "react";
import { OrbitControls as OrbitControlsImpl } from "three-stdlib";
import { useParams } from "react-router-dom";
const VirtualTourWrapper = () => {
const orbitRef = useRef<OrbitControlsImpl>(null);
const materialRef = useRef<MeshBasicMaterial>(null);
const texture = useTexture(
"/images/virtual-tour/studio1/Studio1_w-12_13_sp-01.webp"
);
const { id } = useParams();
return (
<Suspense fallback={<div>Loading ...</div>}>
<Sphere
args={[1, 64, 64]}
position={[-14.16, 0, 24.11]}
scale={[-1, 1, 1]}
rotation={[0, Math.PI, 0]}
>
<meshBasicMaterial
ref={materialRef}
map={texture}
side={BackSide}
transparent
/>
</Sphere>
<OrbitControls
ref={orbitRef}
maxDistance={0.001}
enableZoom={false}
rotateSpeed={0.5}
reverseOrbit
onChange={() => console.log("e", orbitRef.current?.getAzimuthalAngle())}
target={[-14.16, 0, 24.11]}
/>
</Suspense>
);
};
export default VirtualTourWrapper;
+8 -4
View File
@@ -4,27 +4,30 @@ const backgroundColors: ButtonStyle = {
cta: "bg-[#00BED7] hover:bg-[#00A8BE]",
primary: "bg-[#ffffff] hover:bg-[#F3F3F2] active:bg-[#fff]",
secondary: "bg-[#ffffff] hover:bg-[#F3F3F2] active:bg-[#fff]",
tertiary: "bg-[#0D192266] hover:bg-[#0D1922B2]",
tertiary: "",
fab: "bg-[#ffffff] hover:bg-[#F3F3F2]",
favorite: "bg-[#FFFFFF] hover:bg-[#F3F3F2]",
special: "bg-[#0D192266] hover:bg-[#0D1922B2]",
};
const textColors: ButtonStyle = {
cta: "text-[#ffffff]",
primary: "text-[#0D1922]",
secondary: "text-[#0D1922]",
tertiary: "text-[#ffffff]",
tertiary: "text-[#73787C] hover:text-[#0D1922] active:text-[#00BED7]",
fab: "text-[#0D1922]",
favorite: "text-[#F3F3F2]",
special: "text-[#ffffff]",
};
const borders: ButtonStyle = {
cta: "rounded-lg",
primary: "rounded-lg border border-[#ffffff] active:border-[#00BED7]",
secondary: "rounded-lg border border-[#E2E2DC] active:border-[#00BED7]",
tertiary: "rounded-full",
tertiary: "",
fab: "rounded-full",
favorite: "rounded-lg border border-[#E2E2DC]",
favorite: "rounded-full border border-[#E2E2DC]",
special: "rounded-full",
};
const paddings: ButtonStyle = {
@@ -34,6 +37,7 @@ const paddings: ButtonStyle = {
tertiary: "py-1 px-3",
fab: "py-3 px-6",
favorite: "p-[10px]",
special: "py-1 px-3",
};
export { textColors, backgroundColors, borders, paddings };
+77
View File
@@ -0,0 +1,77 @@
[
{
"id": "studio-1-sp-01",
"src": "/images/virtual-tour/studio1/Studio1_w-12_13_sp-01.webp",
"position": [-23.12, 0, -13.4],
"mapPosition": [97.61, 281.92],
"links": [
{ "toId": "Dvor_16", "label": "" },
{ "toId": "Dvor_17", "label": "Детская площадка" }
]
},
{
"id": "studio-1-sp-02",
"src": "/images/virtual-tour/studio1/Studio1_w-12_13_sp-02.webp",
"position": [-14.16, 0, 24.11],
"mapPosition": [39.57, 347.47],
"links": [
{ "toId": "Dvor_16", "label": "" },
{ "toId": "Dvor_2", "label": "" },
{ "toId": "Hall_1", "label": "Лобби" }
]
},
{
"id": "studio-1-sp-03",
"src": "/images/virtual-tour/studio1/Studio1_w-12_13_sp-03.webp",
"position": [-22.27, 0, 19.69],
"mapPosition": [36.26, 327.64],
"links": [
{ "toId": "Dvor_1", "label": "" },
{ "toId": "Dvor_14", "label": "" }
]
},
{
"id": "studio-1-sp-04",
"src": "/images/virtual-tour/studio1/Studio1_w-12_13_sp-04.webp",
"position": [-52.03, 0, -3.63],
"mapPosition": [41.11, 241.29],
"links": [
{ "toId": "Dvor_15", "label": "" },
{ "toId": "Dvor_4", "label": "" },
{ "toId": "Dvor_9", "label": "Детская площадка" }
]
},
{
"id": "studio-1-sp-05",
"src": "/images/virtual-tour/studio1/Studio1_w-12_13_sp-05.webp",
"position": [-50.6, 0, -15.06],
"mapPosition": [64.39, 228.91],
"links": [
{ "toId": "Dvor_9", "label": "Детская площадка" },
{ "toId": "Dvor_5", "label": "" },
{ "toId": "Dvor_3", "label": "" },
{ "toId": "Dvor_6", "label": "Детская площадка" }
]
},
{
"id": "studio-1-sp-06",
"src": "/images/virtual-tour/studio1/Studio1_w-12_13_sp-06.webp",
"position": [-34.36, 0, -4.72],
"mapPosition": [66.41, 273.23],
"links": [
{ "toId": "Dvor_4", "label": "" },
{ "toId": "Dvor_17", "label": "Детская площадка" }
]
},
{
"id": "studio-1-sp-07",
"src": "/images/virtual-tour/studio1/Studio1_w-12_13_sp-07.webp",
"position": [-40.94, 0, -23.93],
"mapPosition": [93.88, 235.03],
"links": [
{ "toId": "Dvor_17", "label": "Детская площадка" },
{ "toId": "Dvor_7", "label": "" },
{ "toId": "Dvor_4", "label": "" }
]
}
]
+5
View File
@@ -10,6 +10,7 @@ import Search from "./pages/Search";
import SearchParticularApartments from "./pages/SearchParticularApartments";
import SearchApartment from "./pages/SearchApartment";
import Favorites from "./pages/Favorites";
import VirtualTour from "./pages/VirtualTour";
const router = createBrowserRouter([
{
@@ -52,6 +53,10 @@ const router = createBrowserRouter([
path: "/favorites",
element: <Favorites />,
},
{
path: "virtual-tour/:appartmentTypeId",
element: <VirtualTour />,
},
],
},
]);
+47 -19
View File
@@ -2,12 +2,14 @@ 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";
import Switch from "../components/Switch";
import { ISwitcher } from "../types/switcher";
import FavoritesSlider from "../components/favoritesPage/FavoriteSlider";
import FavoriteCardList from "../components/favoritesPage/FavoriteCardList";
const favoriteCards: ILayoutCard[] = [
{
@@ -144,9 +146,16 @@ const favoriteCards: ILayoutCard[] = [
},
];
const initialCollectionCompareSwitcher: ISwitcher = {
id: "1",
title: "collection/compare",
isSwitched: false,
};
const Favorites = () => {
const [sortList, setSortList] = useState(initialSortList);
const [cards, setCards] = useState(favoriteCards);
const [switcher, setSwitcher] = useState(initialCollectionCompareSwitcher);
const handleOnSortClick = (sortId: string) => {
const updatedSortList = sortList.map((sort) => {
@@ -156,6 +165,12 @@ const Favorites = () => {
setSortList(updatedSortList);
};
const handleOnSwitchClick = () => {
setSwitcher((prev) => {
return { ...prev, isSwitched: !prev.isSwitched };
});
};
useEffect(() => {
const sortedCards = sortCardBy(sortList, favoriteCards);
@@ -164,37 +179,50 @@ const Favorites = () => {
return (
<div className="overflow-scroll h-screen w-screen pt-14">
<div className="p-6">
<div className="p-6 pb-16">
<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 className="flex items-center gap-8">
<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>
<SortButton sortList={sortList} onClick={handleOnSortClick} />
</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"
buttonType="tertiary"
icon={<TrashIcon />}
className="text-[#73787C]"
text="Remove all"
/>
<div className="flex gap-2 items-center text-s">
<p
className={`transition-all duration-300 ease-in-out ${
!switcher.isSwitched ? "text-[#0D1922]" : "text-[#73787C]"
}`}
>
Collection
</p>
<Switch switcher={switcher} onClick={handleOnSwitchClick} />
<p
className={`transition-all duration-300 ease-in-out ${
switcher.isSwitched ? "text-[#0D1922]" : "text-[#73787C]"
}`}
>
Compare
</p>
</div>
</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>
{switcher.isSwitched ? (
<FavoritesSlider cards={cards} />
) : (
<FavoriteCardList cards={cards} />
)}
</div>
<Footer />
</div>
+39
View File
@@ -0,0 +1,39 @@
import { Canvas } from "@react-three/fiber";
import ButtomPanel from "../components/ButtomPanel";
import VirtualTourWrapper from "../components/virtualTour/VirtualTourWrapper";
const VirtualTour = () => {
return (
<div className="overflow-hidden h-screen w-screen">
{/* <TopPanel /> */}
<div className="absolute w-screen h-screen grid grid-cols-12 z-30 pointer-events-none">
<div className="col-span-3 h-screen py-[68px] px-3">
<div className="bg-white w-full rounded-lg p-4 flex flex-col">
<div className="flex flex-col gap-1 pb-[18px] border-b">
<p className="text-[#00BED7] text-caption-m font-medium">
Rove Home Marasi Drive{" "}
</p>
<div className="text-[#73787C] flex gap-2 items-center w-fit">
<p className="text-caption-m font-semibold leading-4">
East Wing
</p>
<div className="w-1 h-1 bg-[#E2E2DC] rounded-full"></div>
<p className="text-caption-m font-semibold leading-4">
Floor 11
</p>
<div className="w-1 h-1 bg-[#E2E2DC] rounded-full"></div>
<p className="text-caption-m font-semibold leading-4"> 213</p>
</div>
</div>
</div>
</div>
</div>
<Canvas>
<VirtualTourWrapper />
</Canvas>
<ButtomPanel />
</div>
);
};
export default VirtualTour;
+2 -1
View File
@@ -4,7 +4,8 @@ type ButtonType =
| "cta"
| "fab"
| "secondary"
| "favorite";
| "favorite"
| "special";
type ButtonStyle = {
[key in ButtonType]: string;
};