server
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 184 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import Button from "../Button";
|
||||
import { formatNumber } from "../../calc/formatNumber";
|
||||
import Button from "./Button";
|
||||
import { formatNumber } from "../calc/formatNumber";
|
||||
|
||||
const ApartmentSidebar = () => {
|
||||
const navigate = useNavigate();
|
||||
@@ -0,0 +1,457 @@
|
||||
interface FloorEastWingHighlightingProps {
|
||||
handleOnMouseOut: () => void;
|
||||
handleOnMouseOver: () => void;
|
||||
handleOnApartmentClick: (
|
||||
event: React.MouseEvent<SVGSVGElement, MouseEvent>
|
||||
) => void;
|
||||
}
|
||||
|
||||
function FloorEastWingHighlighting({
|
||||
handleOnMouseOut,
|
||||
handleOnMouseOver,
|
||||
handleOnApartmentClick,
|
||||
}: FloorEastWingHighlightingProps) {
|
||||
return (
|
||||
<>
|
||||
<svg
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
|
||||
x={40}
|
||||
y={1}
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M43.2341 36.4771L32.7082 58.1869L29.3319 56.2506L39.8082 34.7023L43.2341 36.4771Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M28.5005 74.2294L42.5381 81.1479L50.4314 84.8972L51.9701 85.6403L59.349 70.188L58.1451 69.527L72.3281 41.1009L19.0886 15.0072L8.86602 35.7266L9.918 36.2984L0.275391 55.8072L30.2844 70.6783L28.5005 74.2294ZM43.2341 36.4771L32.7082 58.1869L29.3319 56.2506L39.8082 34.7023L43.2341 36.4771Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
<path
|
||||
d="M10.0694 32.4059L18.7878 14.1246L63.8107 36.2118L66.1586 31.4119C66.8459 30.0068 66.3551 28.3095 65.0241 27.488L21.9939 0.930965C20.4626 -0.0141451 18.45 0.569992 17.6626 2.1881L5.64879 26.8762C4.91348 28.3873 5.54323 30.2083 7.05493 30.9423L10.0694 32.4059Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
|
||||
x={92}
|
||||
y={41}
|
||||
width="88"
|
||||
height="70"
|
||||
viewBox="0 0 88 70"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M37.4333 47.3867L33.7376 45.5513L44.3549 23.5337L47.9879 25.4442L37.4333 47.3867Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
<path
|
||||
d="M68.3198 47.3867L77.2296 29.0916L31.8335 7.26571C31.9227 7.16484 32.9092 5.19457 34.1722 2.63713C34.8571 1.25035 36.4724 0.59442 37.9286 1.11561L85.5011 18.1418C87.1993 18.7496 87.9983 20.6935 87.2183 22.3198L75.1849 47.4108C74.4431 48.9575 72.5695 49.5849 71.0459 48.7968L68.3198 47.3867Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M0.257812 47.2912L1.7471 48.074L9.88156 52.0272L23.6313 58.775L25.5512 55.0764L55.5352 69.7014L65.1629 49.7968L66.264 50.3332L76.2737 29.4883L22.9254 3.71262L8.73526 32.4366L7.68019 31.8754L0.257812 47.2912ZM37.4333 47.3867L33.7376 45.5513L44.3549 23.5337L47.9879 25.4442L37.4333 47.3867Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
|
||||
x={99}
|
||||
y={126}
|
||||
width="78"
|
||||
height="58"
|
||||
viewBox="0 0 78 58"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M0.847656 29.9186V31.905V40.8977V52.7401H4.09539V57.6346H57.5094V0.815186H26.4511V4.85119H13.8386V29.9186H0.847656Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
<path
|
||||
d="M57.8461 9.22863H77.4339V47.9344H57.8461V9.22863Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
|
||||
x={99}
|
||||
y={184}
|
||||
width="78"
|
||||
height="32"
|
||||
viewBox="0 0 78 32"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M77.4339 4.21582H59.9175V31.7744H77.4339V4.21582Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
<path
|
||||
d="M0.847656 3.83763V5.30536V14.3033V24.9006H6.11339V31.7744H19.2304V30.5131H59.4959V0.116943H4.09539V3.83763H0.847656Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
|
||||
x={99}
|
||||
y={217}
|
||||
width="78"
|
||||
height="33"
|
||||
viewBox="0 0 78 33"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M0.847656 7.23569V17.9161V26.8653V28.5971H4.09539V32.0826H59.4959V1.50751H19.2304V0.423796H6.11339V7.23569H0.847656Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
<path
|
||||
d="M77.4339 0.398926H59.9175V28.0973H77.4339V0.398926Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
|
||||
x={99}
|
||||
y={251}
|
||||
width="78"
|
||||
height="58"
|
||||
viewBox="0 0 78 58"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M77.4328 10.4467H57.8326V48.5921H77.4328V10.4467Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
<path
|
||||
d="M0.882812 5.72498V17.467V26.4419V28.6878H13.7973V53.2329H26.3883V57.2601H57.4322V0.816895H4.09427V5.72498H0.882812Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
|
||||
x={99}
|
||||
y={310}
|
||||
width="78"
|
||||
height="32"
|
||||
viewBox="0 0 78 32"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M59.9425 5.4146H77.4328V31.695H59.9425V5.4146Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
<path
|
||||
d="M0.882812 5.03001V6.47548V15.4165V26.1621H6.11227V31.695H59.5172V1.32728H19.1782V0.162598H4.09427V5.03001H0.882812Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
|
||||
x={99}
|
||||
y={343}
|
||||
width="99"
|
||||
height="85"
|
||||
viewBox="0 0 99 85"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M50.6968 62.4116L47.8478 59.5627L69.0706 38.3812L72.0021 41.2714L50.6968 62.4116Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M0.882812 21.6152V22.9085V31.96V33.1601H6.50805L55.9408 82.5928L59.9338 78.5999L65.3813 84.0474L94.655 54.7737L76.6019 36.6138L72.5931 40.56L54.5146 22.6064V0.348877H8.54341V2.76417H6.11227V21.6152H0.882812ZM50.6968 62.4116L47.8478 59.5627L69.0706 38.3812L72.0021 41.2714L50.6968 62.4116Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
<path
|
||||
d="M55.0253 0.348877H77.4328V2.84703C77.4328 10.9119 80.6365 18.6464 86.3392 24.3491L98.8228 36.8326L88.1845 47.4709L76.7404 36.0268L72.5931 40.1742L55.0253 22.6064V0.348877Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
|
||||
x={4.66}
|
||||
y={492}
|
||||
width="90"
|
||||
height="97"
|
||||
viewBox="0 0 90 97"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M18.1036 5.09509H0.662109V46.8361H18.1036V5.09509Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
<path
|
||||
d="M89.5155 19.6333H88.0078H78.9667H77.2382V5.79173H73.8163V0.916504H18.4757V50.221H48.9767V54.6804H55.5607V78.7987H89.5155V19.6333Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
<path
|
||||
d="M59.227 79.2319V96.211H85.7186V79.2319H59.227Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
|
||||
x={4.63}
|
||||
y={439}
|
||||
width="78"
|
||||
height="52"
|
||||
viewBox="0 0 78 52"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M18.1034 4.49092H0.628906V47.2577H18.1034V4.49092Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
<path
|
||||
d="M77.238 27.2949V25.1743H70.5371V0.437012H50.6172V1.66582H18.4755V51.3945H73.8161V46.4628H77.1584V36.2871L77.238 27.2949Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
|
||||
x={4.63}
|
||||
y={387}
|
||||
width="78"
|
||||
height="52"
|
||||
viewBox="0 0 78 52"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M0.628906 47.7823H18.1034V4.83478H0.628906V47.7823Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
<path
|
||||
d="M73.8161 0.840332H18.4755V50.7118H50.6172V51.8273H70.5371V26.9096H77.238V24.869V15.8135V5.80208H73.8161V0.840332Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
data-apartment="apartments-studio-1"
|
||||
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
|
||||
x={9.06}
|
||||
y={279}
|
||||
width="73"
|
||||
height="29"
|
||||
viewBox="0 0 73 29"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M16.8529 0.00878906H0.0644531V24.141H16.8529V0.00878906Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
<path
|
||||
d="M72.2048 24.5692V23.078L72.2363 14.2041V3.60853H66.9374V0.00878906H17.238V28.1512H68.8053V24.5692H72.2048Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
data-apartment="apartments-studio-1"
|
||||
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
|
||||
x={9.06}
|
||||
y={249}
|
||||
width="73"
|
||||
height="30"
|
||||
viewBox="0 0 73 30"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M16.8529 4.74607H0.0644531V29.3672H16.8529V4.74607Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
<path
|
||||
d="M17.238 0.731445V29.3672H66.9374V25.8529H72.2363V15.0391V5.94945V4.34722H68.7814V0.731445H17.238Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
data-apartment="apartments-studio-1"
|
||||
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
|
||||
x={9.06}
|
||||
y={217}
|
||||
width="73"
|
||||
height="31"
|
||||
viewBox="0 0 73 31"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M17.238 1.41691V30.2271H68.7814V26.5346H72.2363V24.9657V15.9437V3.98155H66.9374V0.365723H49.2652V1.41691H17.238Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
<path
|
||||
d="M16.8529 0.431123H0.0644531V26.2567H16.8529V1.41691V0.431123Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
data-apartment="apartments-studio-1"
|
||||
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
|
||||
x={9.06}
|
||||
y={186}
|
||||
width="73"
|
||||
height="30"
|
||||
viewBox="0 0 73 30"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M16.8529 4.13203H0.0644531V29.8606H16.8529V28.5874V4.13203Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
<path
|
||||
d="M17.238 0.0864258V28.5874H49.2652V29.8341H66.9374V26.2549H72.2363V14.2384V5.51238V3.67383H68.7814V0.0864258H17.238Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
data-apartment="apartments-studio-1"
|
||||
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
|
||||
x={9.06}
|
||||
y={156}
|
||||
width="73"
|
||||
height="30"
|
||||
viewBox="0 0 73 30"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M16.8529 1.05846H0.0644531V25.5008H16.8529V1.05846Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
<path
|
||||
d="M17.238 0.952393V29.4774H68.7814V26.0328H72.2363V24.4149V15.368V4.84596H66.9374V0.952393H17.238Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
</svg>
|
||||
<svg
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
data-apartment="apartments-studio-1"
|
||||
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
|
||||
x={9.06}
|
||||
y={126}
|
||||
width="73"
|
||||
height="30"
|
||||
viewBox="0 0 73 30"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M68.7814 0.799072H17.238V29.6647H66.9374V25.8007H72.2363V15.0942V6.11895V4.4029H68.7814V0.799072Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
<path
|
||||
d="M16.8529 4.83698V29.5578H0.0644531V4.83698H16.8529Z"
|
||||
fill="#00BED7"
|
||||
fillOpacity="0.2"
|
||||
/>
|
||||
</svg>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default FloorEastWingHighlighting;
|
||||
File diff suppressed because one or more lines are too long
@@ -5,6 +5,14 @@ import FloorWestWingHighlighting from "./FloorWestWingHighlighting";
|
||||
import FloorWestWingLayout from "./FloorWestWingLayout";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import useWingSidebar from "../../../store/useWingSidebar";
|
||||
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";
|
||||
|
||||
const appartments = _appartment as IAppartmentComplex[];
|
||||
|
||||
interface IFloorSidebarProps {
|
||||
currentFloor: IDesctiptionFloor | null;
|
||||
@@ -16,13 +24,20 @@ const FloorSidebar = ({ currentFloor, onMouseEnter }: IFloorSidebarProps) => {
|
||||
const [isDescVisible, setIsDescVisible] = useState(false);
|
||||
const [is3DTourAvailable] = useState(true);
|
||||
const { setIsSidebar } = useWingSidebar();
|
||||
const { setModal } = useModal();
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
function handleOnApartmentClick() {
|
||||
navigate("../virtual-tour/apartments-studio-1");
|
||||
function handleOnApartmentClick(
|
||||
event: React.MouseEvent<SVGSVGElement, MouseEvent>
|
||||
) {
|
||||
const apartmentId = (event.target as HTMLElement).dataset.apartment;
|
||||
const apartment = appartments.find((aprt) => aprt.id === apartmentId);
|
||||
if (apartment) {
|
||||
setModal(<AboutComplexModal apartment={apartment} />);
|
||||
setIsDescVisible(false);
|
||||
setIsSidebar(false);
|
||||
}
|
||||
// console.log("e", apartments);
|
||||
}
|
||||
|
||||
function handleMouseMove(e: MouseEvent) {
|
||||
@@ -95,10 +110,13 @@ const FloorSidebar = ({ currentFloor, onMouseEnter }: IFloorSidebarProps) => {
|
||||
</div>
|
||||
|
||||
<div className="px-10 bg-white flex gap-6 font-semibold text-caption-m rounded-2xl justify-center items-center flex-1 py-4">
|
||||
{currentFloor?.wing === "West Wing" ? (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 645 269"
|
||||
width="672"
|
||||
height="280"
|
||||
viewBox="0 0 672 280"
|
||||
>
|
||||
<FloorWestWingLayout />
|
||||
<FloorWestWingHighlighting
|
||||
@@ -107,6 +125,22 @@ const FloorSidebar = ({ currentFloor, onMouseEnter }: IFloorSidebarProps) => {
|
||||
handleOnMouseOver={handleOnMouseOver}
|
||||
/>
|
||||
</svg>
|
||||
) : (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="204"
|
||||
height="588"
|
||||
fill="none"
|
||||
viewBox="0 0 204 588"
|
||||
>
|
||||
<FloorEastWingLayout />
|
||||
<FloorEastWingHighlighting
|
||||
handleOnApartmentClick={handleOnApartmentClick}
|
||||
handleOnMouseOut={handleOnMouseOut}
|
||||
handleOnMouseOver={handleOnMouseOver}
|
||||
/>
|
||||
</svg>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
interface FloorWestWingHighlightingProps {
|
||||
handleOnMouseOut: () => void;
|
||||
handleOnMouseOver: () => void;
|
||||
handleOnApartmentClick: () => void;
|
||||
handleOnApartmentClick: (
|
||||
e: React.MouseEvent<SVGSVGElement, MouseEvent>
|
||||
) => void;
|
||||
}
|
||||
|
||||
const FloorWestWingHighlighting = ({
|
||||
@@ -13,18 +15,18 @@ const FloorWestWingHighlighting = ({
|
||||
<>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="645"
|
||||
height="269"
|
||||
width="672"
|
||||
height="280"
|
||||
fill="none"
|
||||
viewBox="0 0 645 269"
|
||||
viewBox="0 0 672 280"
|
||||
>
|
||||
<svg
|
||||
className="opacity-0 hover:opacity-100 ease-in-out duration-300 transition-opacity cursor-pointer"
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
y={36}
|
||||
x={205}
|
||||
y={38}
|
||||
x={215}
|
||||
width="44"
|
||||
height="106"
|
||||
viewBox="0 0 44 106"
|
||||
@@ -48,8 +50,8 @@ const FloorWestWingHighlighting = ({
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
y={36}
|
||||
x={250}
|
||||
y={38}
|
||||
x={260}
|
||||
width="79"
|
||||
height="106"
|
||||
viewBox="0 0 79 106"
|
||||
@@ -73,8 +75,8 @@ const FloorWestWingHighlighting = ({
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
y={36}
|
||||
x={328}
|
||||
y={40}
|
||||
x={342}
|
||||
width="45"
|
||||
height="106"
|
||||
viewBox="0 0 45 106"
|
||||
@@ -98,8 +100,8 @@ const FloorWestWingHighlighting = ({
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
y={36}
|
||||
x={371}
|
||||
y={40}
|
||||
x={388}
|
||||
width="44"
|
||||
height="106"
|
||||
viewBox="0 0 44 106"
|
||||
@@ -123,8 +125,8 @@ const FloorWestWingHighlighting = ({
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
y={36}
|
||||
x={415}
|
||||
y={40}
|
||||
x={432}
|
||||
width="71"
|
||||
height="106"
|
||||
viewBox="0 0 71 106"
|
||||
@@ -148,8 +150,8 @@ const FloorWestWingHighlighting = ({
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
y={36}
|
||||
x={484}
|
||||
y={40}
|
||||
x={505}
|
||||
width="73"
|
||||
height="106"
|
||||
viewBox="0 0 73 106"
|
||||
@@ -173,8 +175,8 @@ const FloorWestWingHighlighting = ({
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
y={159}
|
||||
x={415}
|
||||
y={168}
|
||||
x={435}
|
||||
width="71"
|
||||
height="106"
|
||||
viewBox="0 0 71 106"
|
||||
@@ -198,8 +200,8 @@ const FloorWestWingHighlighting = ({
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
y={158}
|
||||
x={370}
|
||||
y={168}
|
||||
x={387}
|
||||
width="44"
|
||||
height="106"
|
||||
viewBox="0 0 44 106"
|
||||
@@ -223,8 +225,8 @@ const FloorWestWingHighlighting = ({
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
y={158}
|
||||
x={328}
|
||||
y={170}
|
||||
x={342}
|
||||
width="45"
|
||||
height="106"
|
||||
viewBox="0 0 45 106"
|
||||
@@ -248,8 +250,8 @@ const FloorWestWingHighlighting = ({
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
y={158}
|
||||
x={285}
|
||||
y={169}
|
||||
x={298}
|
||||
width="43"
|
||||
height="106"
|
||||
viewBox="0 0 43 106"
|
||||
@@ -273,8 +275,8 @@ const FloorWestWingHighlighting = ({
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
y={158}
|
||||
x={242}
|
||||
y={169}
|
||||
x={255}
|
||||
width="42"
|
||||
height="106"
|
||||
viewBox="0 0 42 106"
|
||||
@@ -298,8 +300,8 @@ const FloorWestWingHighlighting = ({
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
x={70}
|
||||
y={157}
|
||||
x={75}
|
||||
y={168}
|
||||
width="71"
|
||||
height="106"
|
||||
viewBox="0 0 71 106"
|
||||
@@ -324,7 +326,7 @@ const FloorWestWingHighlighting = ({
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
y={157}
|
||||
y={168}
|
||||
x={2}
|
||||
width="71"
|
||||
height="106"
|
||||
@@ -343,8 +345,8 @@ const FloorWestWingHighlighting = ({
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
y={4.94}
|
||||
x={92.12}
|
||||
y={8.94}
|
||||
x={100.12}
|
||||
width="116"
|
||||
height="136"
|
||||
fill="none"
|
||||
@@ -373,8 +375,8 @@ const FloorWestWingHighlighting = ({
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
y={35.26}
|
||||
x={555.27}
|
||||
y={40.26}
|
||||
x={580.27}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="91"
|
||||
height="106"
|
||||
@@ -397,8 +399,8 @@ const FloorWestWingHighlighting = ({
|
||||
onMouseOut={handleOnMouseOut}
|
||||
onMouseOver={handleOnMouseOver}
|
||||
onClick={handleOnApartmentClick}
|
||||
y={158.26}
|
||||
x={556}
|
||||
y={168.26}
|
||||
x={580}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="89"
|
||||
height="106"
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,150 @@
|
||||
import { useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { apartmentLayouts } from "../../consts/apartmentsLayout";
|
||||
import useModal from "../../store/useModal";
|
||||
import { ISwitchLabel } from "../../types/switchLabel";
|
||||
import Button from "../Button";
|
||||
import SwitchToggle from "../SwitchToggle";
|
||||
import HeartIcon from "../icons/Heart";
|
||||
import LeftArrowSliderIcon from "../icons/LeftArrowSliderIcon";
|
||||
import { formatNumber } from "../../calc/formatNumber";
|
||||
import { IAppartmentComplex } from "../../types/apartmentSphere";
|
||||
|
||||
interface AboutComplexModalProps {
|
||||
apartment: IAppartmentComplex;
|
||||
}
|
||||
|
||||
const AboutComplexModal = ({ apartment }: AboutComplexModalProps) => {
|
||||
const { setModal } = useModal();
|
||||
const [currentLabel, setCurrentLabel] = useState(apartmentLayouts[0]);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleOnBackClick = () => {
|
||||
setModal(false);
|
||||
};
|
||||
|
||||
const handleOnSwitchClick = (label: ISwitchLabel) => {
|
||||
setCurrentLabel(label);
|
||||
};
|
||||
|
||||
const handleOn3DTourClick = () => {
|
||||
setModal(null);
|
||||
navigate(`../virtual-tour/${apartment.id}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="absolute z-[99999998] top-0 left-0 w-screen bg-[#0D192266] h-screen backdrop-blur-[6px] grid grid-cols-12 items-center">
|
||||
<div className="col-span-9 col-start-4 bg-[#F3F3F2] grid grid-cols-9 gap-4 max-h-screen px-6">
|
||||
<div className="flex flex-col col-span-6 max-h-screen h-screen py-6">
|
||||
{/* Button pannel */}
|
||||
<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 />}
|
||||
isCircleRounded
|
||||
/>
|
||||
</div>
|
||||
{/* Layout */}
|
||||
<div className="p-10 rounded-2xl bg-white flex flex-col items-center gap-8 relative justify-center h-full">
|
||||
<div className="w-full flex justify-center h-full">
|
||||
<img
|
||||
className="object-cover h-full"
|
||||
src="/images/layout-1.png"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
<img
|
||||
src="/images/compass.png"
|
||||
alt=""
|
||||
className="absolute right-10 bottom-10"
|
||||
/>
|
||||
<SwitchToggle
|
||||
labels={apartmentLayouts}
|
||||
currentLabel={currentLabel}
|
||||
onClick={handleOnSwitchClick}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{/* Sidebar */}
|
||||
<div className="col-span-3 rounded-lg h-screen py-6">
|
||||
<div className="flex lg:flex-col gap-2 h-full">
|
||||
<div className="rounded-2xl overflow-clip lg:flex-1 flex-none relative">
|
||||
<p className="absolute top-[30px] left-6 font-semibold text-m text-white">
|
||||
View from window
|
||||
</p>
|
||||
<img
|
||||
src="/images/view_from_window.png"
|
||||
alt=""
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex gap-2 flex-col flex-1 lg:flex-none">
|
||||
<div className="flex flex-col rounded-2xl 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-2xl bg-white flex flex-col p-6 gap-4 flex-1 lg:flex-none justify-between">
|
||||
<p className="text-[#00BED7] font-semibold text-subheadline-s leading-7">
|
||||
AED {formatNumber(1668888, ",", 3, 1)}
|
||||
</p>
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
onClick={handleOn3DTourClick}
|
||||
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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AboutComplexModal;
|
||||
@@ -12,6 +12,7 @@ const ApartmentLayout = () => {
|
||||
const handleOnSwitchClick = (label: ISwitchLabel) => {
|
||||
setCurrentLabel(label);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="p-10 pt-6 rounded-2xl bg-white flex flex-col items-center gap-8 relative h-full">
|
||||
<div className="w-full xl:px-[304px] sm:px-24 h-full">
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Html } from "@react-three/drei";
|
||||
import { IAppartmentSphere, ISphereLink } from "../../types/apartmentSphere";
|
||||
import { IAppartmentComplex, ISphereLink } from "../../types/apartmentSphere";
|
||||
import WalkHereIcon from "../icons/WalkHereIcon";
|
||||
import useSphere from "../../store/useSphere";
|
||||
|
||||
interface LaberlMarkerProps {
|
||||
sphereLink: ISphereLink;
|
||||
apartment: IAppartmentSphere;
|
||||
apartment: IAppartmentComplex;
|
||||
}
|
||||
|
||||
const LabelMarker = ({ sphereLink, apartment }: LaberlMarkerProps) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState } from "react";
|
||||
import useSphere from "../../store/useSphere";
|
||||
import { IAppartmentSphere, ISphere } from "../../types/apartmentSphere";
|
||||
import { IAppartmentComplex, ISphere } from "../../types/apartmentSphere";
|
||||
import Button from "../Button";
|
||||
import BookingIcon from "../icons/BookingIcon";
|
||||
import ChevronDownIcon from "../icons/ChevronDownIcon";
|
||||
@@ -14,7 +14,7 @@ import useModal from "../../store/useModal";
|
||||
import { SendEnquiryModal } from "../modals/SendEnquryModal";
|
||||
|
||||
interface VirtualTourSidebarProps {
|
||||
currentAppartment: null | IAppartmentSphere;
|
||||
currentAppartment: null | IAppartmentComplex;
|
||||
}
|
||||
|
||||
const VirtualTourSidebar = ({ currentAppartment }: VirtualTourSidebarProps) => {
|
||||
|
||||
@@ -3,12 +3,12 @@ import { Suspense, useEffect, useRef } from "react";
|
||||
import { OrbitControls as OrbitControlsImpl } from "three-stdlib";
|
||||
import useCompass from "../../store/useCompass";
|
||||
import SphereTour from "./SphereTour";
|
||||
import { IAppartmentSphere } from "../../types/apartmentSphere";
|
||||
import { IAppartmentComplex } from "../../types/apartmentSphere";
|
||||
import useSphere from "../../store/useSphere";
|
||||
import LabelMarker from "./LabelMarker";
|
||||
|
||||
interface VirtualTourWrapperProps {
|
||||
appartment: IAppartmentSphere;
|
||||
appartment: IAppartmentComplex;
|
||||
}
|
||||
|
||||
const VirtualTourWrapper = ({ appartment }: VirtualTourWrapperProps) => {
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { ISwitchLabel } from "../types/switchLabel";
|
||||
|
||||
const apartmentLayouts: ISwitchLabel[] = [
|
||||
{ id: "1", label: "Layout" },
|
||||
{ id: "2", label: "On the floor" },
|
||||
];
|
||||
|
||||
export { apartmentLayouts };
|
||||
@@ -1,7 +1,7 @@
|
||||
import Footer from "../components/Footer";
|
||||
import ButtonPanel from "../components/searchApartment/ButtonPanel";
|
||||
import ApartmentLayout from "../components/searchApartment/ApartmentLayout";
|
||||
import ApartmentSidebar from "../components/searchApartment/ApartmentSidebar";
|
||||
import ApartmentSidebar from "../components/ApartmentSidebar";
|
||||
import SimilarSlider from "../components/searchApartment/SimilarSlider";
|
||||
import StudioDescriptionSection from "../components/searchApartment/StudioDescriptionSection";
|
||||
|
||||
|
||||
@@ -2,17 +2,17 @@ import { useEffect, useState } from "react";
|
||||
import { Canvas } from "@react-three/fiber";
|
||||
import { useParams } from "react-router-dom";
|
||||
import VirtualTourWrapper from "../components/virtualTour/VirtualTourWrapper";
|
||||
import { IAppartmentSphere } from "../types/apartmentSphere";
|
||||
import _appartment from "../data/appartments.json";
|
||||
import { IAppartmentComplex } from "../types/apartmentSphere";
|
||||
import VirtualTourTopPanel from "../components/virtualTour/VirtualTourTopPanel";
|
||||
import ButtomPanelCompassVirtualTour from "../components/virtualTour/ButtomPanelCompassVirualTour";
|
||||
import VirtualTourSidebar from "../components/virtualTour/VirtualTourSidebar";
|
||||
import _appartment from "../data/appartments.json";
|
||||
|
||||
const appartments = _appartment as IAppartmentSphere[];
|
||||
const appartments = _appartment as IAppartmentComplex[];
|
||||
|
||||
const VirtualTour = () => {
|
||||
const [currentAppartment, setCurrentAppartment] =
|
||||
useState<null | IAppartmentSphere>(null);
|
||||
useState<null | IAppartmentComplex>(null);
|
||||
|
||||
const { appartmentTypeId } = useParams();
|
||||
|
||||
|
||||
@@ -13,10 +13,10 @@ interface ISphere {
|
||||
links: ISphereLink[];
|
||||
}
|
||||
|
||||
interface IAppartmentSphere {
|
||||
interface IAppartmentComplex {
|
||||
id: string;
|
||||
map: string;
|
||||
spheres: ISphere[];
|
||||
}
|
||||
|
||||
export type { ISphere, IAppartmentSphere, ISphereLink };
|
||||
export type { ISphere, IAppartmentComplex, ISphereLink };
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
PORT=3000
|
||||
REFRESH_TOKEN=1000.da3146d49fa8a399f0c635e74954ff9c.e010dbb1bb605d7e1aa5bf7fc0521f8b
|
||||
@@ -0,0 +1,24 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "client",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "nodemon --exec node --import=./register.js ./src/index.ts",
|
||||
"build": "npx tsc --project ./",
|
||||
"start": "node ./dist/index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.4.5",
|
||||
"express": "^4.19.2",
|
||||
"morgan": "^1.10.0",
|
||||
"winston": "^3.13.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/cors": "^2.8.17",
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/morgan": "^1.9.9",
|
||||
"@types/node": "^20.14.2",
|
||||
"nodemon": "^3.1.3",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.4.5"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
import { register } from "module";
|
||||
import { pathToFileURL } from "url";
|
||||
|
||||
register("ts-node/esm", pathToFileURL("./"));
|
||||
@@ -0,0 +1,18 @@
|
||||
const refreshToken =
|
||||
"1000.da3146d49fa8a399f0c635e74954ff9c.e010dbb1bb605d7e1aa5bf7fc0521f8b";
|
||||
const clientId = "1000.6ZV07WFOC7PQOY3X109UN55Q9BMBBY";
|
||||
const clientSecret = "595f5262886a6e81475b533350a81e46fecda57fb5";
|
||||
const grantType = "refresh_token";
|
||||
|
||||
const updateAccessTokenApi = `https://accounts.zoho.com/oauth/v2/token`;
|
||||
const aparmentsApi =
|
||||
"https://www.zohoapis.com/crm/v2/Apartments?fields=Floor,Property_Status,Project_Name,Balcony_Area_Sqft,Unit_Type,Suite_Area_Sqft,No_Of_Bedrooms,Total_Area_Sqft,No_of_Bathrooms,Property_Name,Unit_View,Balcony_Area_Sqft,Unit_No,Suite_Area_Sqft";
|
||||
|
||||
export {
|
||||
aparmentsApi,
|
||||
updateAccessTokenApi,
|
||||
refreshToken,
|
||||
clientId,
|
||||
clientSecret,
|
||||
grantType,
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
import "dotenv/config";
|
||||
import express, { json } from "express";
|
||||
import cors from "cors";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import morgan from "morgan";
|
||||
import apartmentsRoute from "./routes/aparments.js";
|
||||
import accessTokenMiddleware from "./middlewares/accessTokenMiddleware.js";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const app = express();
|
||||
const port = process.env.PORT || 3000;
|
||||
|
||||
const accessLogStream = fs.createWriteStream(
|
||||
path.join(__dirname, "../logs/access.log"),
|
||||
{ flags: "a" }
|
||||
);
|
||||
|
||||
app.use(cors());
|
||||
app.use(json());
|
||||
app.use(morgan("combined", { stream: accessLogStream }));
|
||||
|
||||
app.use("/aparments", accessTokenMiddleware, apartmentsRoute);
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`Server is listening on port ${port}`);
|
||||
});
|
||||
@@ -0,0 +1,47 @@
|
||||
import { Request, Response, NextFunction } from "express";
|
||||
import { aparmentsApi } from "../consts.js";
|
||||
import { logger } from "../utils/logger.js";
|
||||
|
||||
var checkAccessToken = async function (
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: NextFunction
|
||||
) {
|
||||
const accessToken = req.headers.authorization;
|
||||
|
||||
if (!accessToken)
|
||||
return res.status(401).json({ error: "Not found access token" });
|
||||
|
||||
try {
|
||||
const respose = await fetch(aparmentsApi, {
|
||||
headers: {
|
||||
Authorization: accessToken,
|
||||
},
|
||||
});
|
||||
|
||||
if (respose.status === 401) {
|
||||
try {
|
||||
const response2 = await fetch(
|
||||
`https://accounts.zoho.com/oauth/v2/token?refresh_token=1000.da3146d49fa8a399f0c635e74954ff9c.e010dbb1bb605d7e1aa5bf7fc0521f8b&client_id=1000.6ZV07WFOC7PQOY3X109UN55Q9BMBBY&client_secret=595f5262886a6e81475b533350a81e46fecda57fb5&grant_type=refresh_token`,
|
||||
{
|
||||
method: "post",
|
||||
}
|
||||
);
|
||||
const { access_token } = await response2.json();
|
||||
return res.json({ accessToken: access_token });
|
||||
} catch (error) {
|
||||
console.log("error", (error as Error).message);
|
||||
logger.error(error);
|
||||
return res.json({ error: (error as Error).message });
|
||||
}
|
||||
}
|
||||
|
||||
next();
|
||||
} catch (error) {
|
||||
console.log("error", (error as Error).message);
|
||||
logger.error(error);
|
||||
return res.json({ error: (error as Error).message });
|
||||
}
|
||||
};
|
||||
|
||||
export default checkAccessToken;
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Router } from "express";
|
||||
import { aparmentsApi } from "../consts.js";
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get("/", async (req, res) => {
|
||||
const accessToken = req.headers.authorization;
|
||||
|
||||
if (!accessToken) return;
|
||||
|
||||
console.log("accessToken", `[${accessToken}]`);
|
||||
|
||||
const apartments = await fetch(aparmentsApi, {
|
||||
headers: {
|
||||
Authorization: accessToken,
|
||||
},
|
||||
});
|
||||
|
||||
const result = await apartments.json();
|
||||
|
||||
res.json({ ok: 1, apartments: result });
|
||||
});
|
||||
|
||||
const apartmentsRoute = router;
|
||||
|
||||
export default apartmentsRoute;
|
||||
@@ -0,0 +1,27 @@
|
||||
import * as winston from "winston";
|
||||
|
||||
const { combine, timestamp, json } = winston.format;
|
||||
|
||||
export const logger = winston.createLogger({
|
||||
level: "info",
|
||||
format: combine(
|
||||
timestamp({
|
||||
format: "YYYY-MM-DD hh:mm:ss.SSS A",
|
||||
}),
|
||||
json()
|
||||
),
|
||||
transports: [
|
||||
//
|
||||
// - Write to all logs with level `debug` and below to `all.log`
|
||||
// - Write all logs error (and below) to `error.log`.
|
||||
//
|
||||
new winston.transports.File({
|
||||
filename: "logs/error.log",
|
||||
level: "error",
|
||||
}),
|
||||
new winston.transports.File({
|
||||
filename: "logs/all.log",
|
||||
level: "debug",
|
||||
}),
|
||||
],
|
||||
});
|
||||
@@ -0,0 +1,111 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
/* Visit https://aka.ms/tsconfig to read more about this file */
|
||||
|
||||
/* Projects */
|
||||
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
|
||||
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
|
||||
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
|
||||
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
||||
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||
|
||||
/* Language and Environment */
|
||||
"target": "ESNext" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
|
||||
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
|
||||
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
||||
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
|
||||
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
|
||||
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
||||
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
||||
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
|
||||
|
||||
/* Modules */
|
||||
"module": "NodeNext" /* Specify what module code is generated. */,
|
||||
// "rootDir": "./", /* Specify the root folder within your source files. */
|
||||
"moduleResolution": "NodeNext" /* Specify how TypeScript looks up a file from a given module specifier. */,
|
||||
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
||||
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
|
||||
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
|
||||
// "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
|
||||
// "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
|
||||
// "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
|
||||
// "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
|
||||
// "resolveJsonModule": true, /* Enable importing .json files. */
|
||||
// "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
|
||||
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
|
||||
|
||||
/* JavaScript Support */
|
||||
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
|
||||
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
|
||||
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
|
||||
|
||||
/* Emit */
|
||||
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
|
||||
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
|
||||
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
||||
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
||||
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
||||
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
|
||||
"outDir": "./dist" /* Specify an output folder for all emitted files. */,
|
||||
// "removeComments": true, /* Disable emitting comments. */
|
||||
// "noEmit": true, /* Disable emitting files from a compilation. */
|
||||
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|
||||
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
|
||||
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
|
||||
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
|
||||
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
|
||||
// "newLine": "crlf", /* Set the newline character for emitting files. */
|
||||
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
|
||||
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
|
||||
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
|
||||
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
|
||||
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
|
||||
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
|
||||
|
||||
/* Interop Constraints */
|
||||
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
|
||||
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
|
||||
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
|
||||
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
||||
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
|
||||
|
||||
/* Type Checking */
|
||||
"strict": true /* Enable all strict type-checking options. */,
|
||||
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
|
||||
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
||||
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
|
||||
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
|
||||
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
|
||||
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
|
||||
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
|
||||
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
|
||||
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
|
||||
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
|
||||
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
|
||||
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
|
||||
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
|
||||
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
|
||||
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
|
||||
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
||||
|
||||
/* Completeness */
|
||||
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||
},
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
+1112
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user