+ );
+};
+
+export default SearchLoader;
diff --git a/client/src/components/virtualTour/VideoMarker.tsx b/client/src/components/virtualTour/VideoMarker.tsx
index 45d92ac..3be26d5 100644
--- a/client/src/components/virtualTour/VideoMarker.tsx
+++ b/client/src/components/virtualTour/VideoMarker.tsx
@@ -1,16 +1,25 @@
+import useModal from "../../store/useModal";
import { ISphereLink } from "../../types/apartmentSphere";
import VideoIcon from "../icons/VideoIcon";
+import VirtualTourVideoModal from "../modals/VirtualTourVideoModal";
interface VideoMarkerProps {
sphereLink: ISphereLink;
}
const VideoMarker = ({ sphereLink }: VideoMarkerProps) => {
+ const { setModal } = useModal();
+
+ const handleOnClick = () => {
+ sphereLink.video &&
+ setModal(
diff --git a/client/src/consts/apartmentsRoutes.ts b/client/src/consts/apartmentsRoutes.ts
new file mode 100644
index 0000000..79cfbe3
--- /dev/null
+++ b/client/src/consts/apartmentsRoutes.ts
@@ -0,0 +1,30 @@
+import { IApartmentRoute } from "../types/apartmentRoute";
+
+const apartmentRoutes: IApartmentRoute[] = [
+ {
+ type: "1 BR Squared",
+ virtualTour: "apartments-studio-3",
+ id: "1",
+ layout: "/images/layouts/layout-2.jpg",
+ },
+ {
+ type: "Studio Squared",
+ virtualTour: "apartments-studio-2",
+ id: "2",
+ layout: "/images/layouts/layout-4.jpg",
+ },
+ {
+ type: "2 BR Squared",
+ virtualTour: "apartments-studio-4",
+ id: "3",
+ layout: "/images/layouts/layout-3.jpg",
+ },
+ {
+ type: "Studio Flex",
+ virtualTour: "apartments-studio-1",
+ id: "4",
+ layout: "/images/layouts/layout-1.jpg",
+ },
+];
+
+export { apartmentRoutes };
diff --git a/client/src/consts/apartmentsWithoutVirtualTour.ts b/client/src/consts/apartmentsWithoutVirtualTour.ts
new file mode 100644
index 0000000..1034171
--- /dev/null
+++ b/client/src/consts/apartmentsWithoutVirtualTour.ts
@@ -0,0 +1,14 @@
+interface IApartmentWithoutVirtualTour {
+ type: string;
+ layout: string;
+ id: string;
+}
+
+const apartmentsWithoutVirtualTour: IApartmentWithoutVirtualTour[] = [
+ { type: "1 BR U1 Left", layout: "/images/layouts/layout-5.jpg", id: "1" },
+ { type: "1 BR U1 Right", layout: "/images/layouts/layout-6.jpg", id: "2" },
+ { type: "1 BR U2 Left", layout: "/images/layouts/layout-7.jpg", id: "3" },
+ { type: "1 BR U2 Right", layout: "/images/layouts/layout-8.jpg", id: "4" },
+];
+
+export { apartmentsWithoutVirtualTour };
diff --git a/client/src/consts/initialSearchPage.ts b/client/src/consts/initialSearchPage.ts
index dc6f461..d8a20fb 100644
--- a/client/src/consts/initialSearchPage.ts
+++ b/client/src/consts/initialSearchPage.ts
@@ -1,137 +1,108 @@
-import { ILayoutCard } from "../types/layoutCard";
+import { IAparmentRes } from "../types/apartmentsRes";
-const layoutsCards: ILayoutCard[] = [
+// Property_Status: string;
+// Unit_Type: string;
+// Project_Name: string;
+// Suite_Area_Sqft: number;
+// Balcony_Area_Sqft: number;
+// No_Of_Bedrooms: number;
+// Unit_No: string;
+// id: string;
+// Total_Area_Sqft: number;
+// No_of_Bathrooms: number;
+// Property_Name: string;
+// Unit_View: string;
+
+const layoutsCards: IAparmentRes[] = [
{
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,
+ Property_Status: "",
+ Unit_Type: "",
+ Project_Name: "Rove Home Marasi Drive",
+ Floor: 5,
+ Balcony_Area_Sqft: 77.5,
+ No_of_Bathrooms: 1,
+ No_Of_Bedrooms: 1,
+ Total_Area_Sqft: 402,
+ Property_Name: "",
+ Unit_View: "Canal / Amenities",
+ Suite_Area_Sqft: 0,
+ Unit_No: "W-502",
},
{
id: "6",
- roveHome: "Marasi Drive",
- apartmentType: "1 Bedroom",
- wing: "East Wing",
- floorStart: 11,
- floorEnd: 35,
- units: 234,
- cost: 1668888,
- square: 609,
+ Property_Status: "",
+ Unit_Type: "",
+ Project_Name: "Rove Home Marasi Drive",
+ Floor: 5,
+ Balcony_Area_Sqft: 77.5,
+ No_of_Bathrooms: 1,
+ No_Of_Bedrooms: 1,
+ Total_Area_Sqft: 402,
+ Property_Name: "",
+ Unit_View: "Canal / Amenities",
+ Suite_Area_Sqft: 0,
+ Unit_No: "W-502",
},
{
- id: "7",
- roveHome: "Marasi Drive",
- apartmentType: "1 Bedroom",
- wing: "East Wing",
- floorStart: 11,
- floorEnd: 35,
- units: 234,
- cost: 1668888,
- square: 609,
+ id: "2",
+ Property_Status: "",
+ Unit_Type: "",
+ Project_Name: "Rove Home Marasi Drive",
+ Floor: 5,
+ Balcony_Area_Sqft: 77.5,
+ No_of_Bathrooms: 1,
+ No_Of_Bedrooms: 1,
+ Total_Area_Sqft: 402,
+ Property_Name: "",
+ Unit_View: "Canal / Amenities",
+ Suite_Area_Sqft: 0,
+ Unit_No: "W-502",
},
{
- id: "8",
- roveHome: "Marasi Drive",
- apartmentType: "1 Bedroom",
- wing: "East Wing",
- floorStart: 11,
- floorEnd: 35,
- units: 234,
- cost: 1138888,
- square: 609,
+ id: "3",
+ Property_Status: "",
+ Unit_Type: "",
+ Project_Name: "Rove Home Marasi Drive",
+ Floor: 5,
+ Balcony_Area_Sqft: 77.5,
+ No_of_Bathrooms: 1,
+ No_Of_Bedrooms: 1,
+ Total_Area_Sqft: 402,
+ Property_Name: "",
+ Unit_View: "Canal / Amenities",
+ Suite_Area_Sqft: 0,
+ Unit_No: "W-502",
},
{
- id: "9",
- roveHome: "Marasi Drive",
- apartmentType: "Studio Flex",
- wing: "East Wing",
- floorStart: 11,
- floorEnd: 35,
- units: 234,
- cost: 10488888,
- square: 609,
+ id: "4",
+ Property_Status: "",
+ Unit_Type: "",
+ Project_Name: "Rove Home Marasi Drive",
+ Floor: 5,
+ Balcony_Area_Sqft: 77.5,
+ No_of_Bathrooms: 1,
+ No_Of_Bedrooms: 1,
+ Total_Area_Sqft: 402,
+ Property_Name: "",
+ Unit_View: "Canal / Amenities",
+ Suite_Area_Sqft: 0,
+ Unit_No: "W-502",
},
{
- 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,
+ id: "5",
+ Property_Status: "",
+ Unit_Type: "",
+ Project_Name: "Rove Home Marasi Drive",
+ Floor: 5,
+ Balcony_Area_Sqft: 77.5,
+ No_of_Bathrooms: 1,
+ No_Of_Bedrooms: 1,
+ Total_Area_Sqft: 402,
+ Property_Name: "",
+ Unit_View: "Canal / Amenities",
+ Suite_Area_Sqft: 0,
+ Unit_No: "W-502",
},
];
diff --git a/client/src/data/appartments.json b/client/src/data/appartments.json
index 8bad13e..8fd9b55 100644
--- a/client/src/data/appartments.json
+++ b/client/src/data/appartments.json
@@ -56,7 +56,7 @@
{
"id": "studio-1_video-1",
"type": "video",
- "video": "",
+ "video": "/videos/studio_flex_bed.mp4",
"videoTitle": "Cloud Bed",
"labelPosition": [-5, 0, 36.11]
}
diff --git a/client/src/main.tsx b/client/src/main.tsx
index 87ffa6c..0a68c3d 100644
--- a/client/src/main.tsx
+++ b/client/src/main.tsx
@@ -46,7 +46,7 @@ const router = createBrowserRouter([
element:
,
},
{
- path: "/search/:apartmentType",
+ path: "/search/:id",
element:
,
},
// {
diff --git a/client/src/pages/SearchApartment.tsx b/client/src/pages/SearchApartment.tsx
index a2ee0a4..b8e3572 100644
--- a/client/src/pages/SearchApartment.tsx
+++ b/client/src/pages/SearchApartment.tsx
@@ -2,26 +2,94 @@ import Footer from "../components/Footer";
import ButtonPanel from "../components/searchApartment/ButtonPanel";
import ApartmentLayout from "../components/searchApartment/ApartmentLayout";
import ApartmentSidebar from "../components/ApartmentSidebar";
-import SimilarSlider from "../components/searchApartment/SimilarSlider";
+// import SimilarSlider from "../components/searchApartment/SimilarSlider";
import StudioDescriptionSection from "../components/searchApartment/StudioDescriptionSection";
+import { useEffect, useState } from "react";
+import { getApartments } from "../api/apartments";
+import { updateAccessToken } from "../api/updateAccessToken";
+import { IAparmentRes, IApartmentsRes } from "../types/apartmentsRes";
+import { useNavigate, useParams } from "react-router-dom";
+import useModal from "../store/useModal";
+import SearchLoaderModal from "../components/modals/SearchLoaderModal";
const SearchApartment = () => {
+ const { id } = useParams();
+ const [currentApartment, setCurrentApartment] = useState
();
+ const [isLoading, setIsLoading] = useState(true);
+ const { setModal } = useModal();
+
+ const navigate = useNavigate();
+
+ useEffect(() => {
+ setIsLoading(true);
+ const zohoToken = localStorage.getItem("ACCESS_TOKEN");
+
+ getApartments(zohoToken)
+ .then((data) => {
+ const apartmentsData = (data as IApartmentsRes).apartments;
+ const _currentApartment = apartmentsData.find((aprt) => aprt.id === id);
+ if (_currentApartment) {
+ setCurrentApartment(_currentApartment);
+ } else {
+ navigate(-1);
+ }
+ })
+ .catch((error) => {
+ const errorStatus = error.response.status;
+
+ if (errorStatus === 401) {
+ updateAccessToken().then((token) => {
+ if (token) {
+ getApartments(zohoToken).then((data) => {
+ const apartmentsData = (data as IApartmentsRes).apartments;
+ const _currentApartment = apartmentsData.find(
+ (aprt) => aprt.id === id
+ );
+ if (_currentApartment) {
+ setCurrentApartment(_currentApartment);
+ } else {
+ navigate(-1);
+ }
+ });
+ }
+ });
+ }
+ })
+ .finally(() => {
+ setIsLoading(false);
+ });
+ }, [id, navigate]);
+
+ useEffect(() => {
+ if (isLoading) {
+ setModal();
+ } else {
+ setModal(null);
+ }
+ }, [isLoading, setModal]);
+
return (
-
-
+ {currentApartment && (
+
+ )}
+ {currentApartment && (
+
+ )}
+ {currentApartment && (
+
+ )}
-
*/}
diff --git a/client/src/store/useMasterplanFilters.ts b/client/src/store/useMasterplanFilters.ts
new file mode 100644
index 0000000..d7d10e3
--- /dev/null
+++ b/client/src/store/useMasterplanFilters.ts
@@ -0,0 +1,58 @@
+import { create } from "zustand";
+import { ICheckbox } from "../types/checkbox";
+import {
+ initialAparmentTypeCheckboxes,
+ initialSliders,
+ initialSwitchers,
+ initialViewCheckboxes,
+ initialRoveHomeCheckboxes,
+ initialSortList,
+} from "../consts/initialMasterplanFilters";
+import { IMultirangeSlider } from "../types/multirangeSlider";
+import { ISwitcher } from "../types/switcher";
+import { ISort } from "../types/sortType";
+import { perPageInitial } from "../consts/initialMasterplanFilters";
+
+interface Store {
+ apartmentTypeCheckboxes: ICheckbox[];
+ viewCheckboxes: ICheckbox[];
+ sortList: ISort[];
+ page: number;
+ perPage: number;
+ setPage: (page: number) => void;
+ setPerPage: (perPage: number) => void;
+ setSortList: (sortList: ISort[]) => void;
+ setApartmentTypeCheckboxes: (typeCheckboxes: ICheckbox[]) => void;
+ setViewCheckboxes: (checkboxes: ICheckbox[]) => void;
+ roveHomeTypeCheckboxes: ICheckbox[];
+ setRoveHomeTypeCheckboxes: (typeCheckboxes: ICheckbox[]) => void;
+ multirangeSliders: IMultirangeSlider[];
+ setMultirangeSliders: (multirangeSliders: IMultirangeSlider[]) => void;
+ switchers: ISwitcher[];
+ setSwitchers: (switchers: ISwitcher[]) => void;
+}
+
+const useMasterplanFilters = create((set) => ({
+ apartmentTypeCheckboxes: initialAparmentTypeCheckboxes,
+ viewCheckboxes: initialViewCheckboxes,
+ roveHomeTypeCheckboxes: initialRoveHomeCheckboxes,
+ multirangeSliders: initialSliders,
+ switchers: initialSwitchers,
+ sortList: initialSortList,
+ page: 1,
+ perPage: perPageInitial,
+ setPerPage: (perPage) => set(() => ({ perPage: perPage })),
+ setPage: (page) => set(() => ({ page: page })),
+ setSortList: (sortList) => set(() => ({ sortList: sortList })),
+ setApartmentTypeCheckboxes: (typeCheckboxes) =>
+ set(() => ({ apartmentTypeCheckboxes: typeCheckboxes })),
+ setViewCheckboxes: (typeCheckboxes) =>
+ set(() => ({ viewCheckboxes: typeCheckboxes })),
+ setRoveHomeTypeCheckboxes: (typeCheckboxes) =>
+ set(() => ({ roveHomeTypeCheckboxes: typeCheckboxes })),
+ setMultirangeSliders: (multirangeSliders) =>
+ set(() => ({ multirangeSliders: multirangeSliders })),
+ setSwitchers: (switchers) => set(() => ({ switchers: switchers })),
+}));
+
+export default useMasterplanFilters;
diff --git a/client/src/types/apartmentRoute.ts b/client/src/types/apartmentRoute.ts
new file mode 100644
index 0000000..d2919c7
--- /dev/null
+++ b/client/src/types/apartmentRoute.ts
@@ -0,0 +1,8 @@
+interface IApartmentRoute {
+ type: string;
+ virtualTour: string;
+ id: string;
+ layout: string;
+}
+
+export type { IApartmentRoute };
diff --git a/server/src/index.ts b/server/src/index.ts
index bea89e3..ccf1731 100644
--- a/server/src/index.ts
+++ b/server/src/index.ts
@@ -24,6 +24,7 @@ app.use(json());
app.use(morgan("combined", { stream: accessLogStream }));
app.use("/apartments", apartmentsRoute);
+app.use("/apartments/:id", apartmentsRoute);
app.use("/updateAccessToken", updateAccessToken);
app.listen(port, () => {
diff --git a/server/src/routes/apartments.ts b/server/src/routes/apartments.ts
index cce7c89..da25e57 100644
--- a/server/src/routes/apartments.ts
+++ b/server/src/routes/apartments.ts
@@ -276,6 +276,54 @@ router.get("/", async (req, res) => {
console.log("error", error);
}
});
+// router.get("/:id", async (req, res) => {
+// const accessToken = req?.headers?.authorization;
+// const {id} = req.params;
+
+// try {
+// const response = await fetch(`${aparmentsApi}&page=${page}&per_page=200`, {
+// headers: {
+// Authorization: accessToken,
+// },
+// });
+
+// if (!accessToken)
+// return res
+// .status(401)
+// .json({ message: "Отсутсвует access token", code: 401 });
+
+// try {
+
+// res.status(200).json({
+// message: "ok",
+// apartments: slicedApartments,
+// code: 200,
+// });
+
+// return;
+// } catch (error) {
+// if (
+// (error as Error).message === "invalid oauth token" ||
+// (error as Error).message === "INVALID_TOKEN"
+// ) {
+// console.log("error", error);
+// logger.error(error);
+
+// return res
+// .status(401)
+// .json({ message: "Неправильный токен или токен устарел", code: 401 });
+// }
+
+// console.log("error", error);
+// logger.error(error);
+
+// return res.status(500).json({ message: "Server Error", code: 500 });
+// }
+// } catch (error) {
+// logger.error(error);
+// console.log("error", error);
+// }
+// });
const apartmentsRoute = router;