update
@@ -1,5 +1,5 @@
|
|||||||
# VITE_API_URL=http://localhost:4002
|
# VITE_API_URL=http://192.168.1.224:4002
|
||||||
VITE_API_URL=http://192.168.1.35:4002
|
# VITE_API_URL=http://192.168.1.35:4002
|
||||||
# VITE_API_URL=http://194.26.138.94:4002
|
# VITE_API_URL=http://194.26.138.94:4002
|
||||||
# VITE_API_URL=https://irthtest.online/api
|
VITE_API_URL=https://irthtest.online/api
|
||||||
# VITE_API_URL=https://irth.graff.estate/api
|
# VITE_API_URL=https://irth.graff.estate/api
|
||||||
@@ -11,6 +11,7 @@ lerna-debug.log*
|
|||||||
node_modules
|
node_modules
|
||||||
dist
|
dist
|
||||||
dist-ssr
|
dist-ssr
|
||||||
|
dist.zip
|
||||||
*.local
|
*.local
|
||||||
|
|
||||||
public/virtual-tours
|
public/virtual-tours
|
||||||
@@ -24,4 +25,4 @@ public/virtual-tours
|
|||||||
*.ntvs*
|
*.ntvs*
|
||||||
*.njsproj
|
*.njsproj
|
||||||
*.sln
|
*.sln
|
||||||
*.sw?
|
*.sw?
|
||||||
|
After Width: | Height: | Size: 225 KiB |
|
After Width: | Height: | Size: 250 KiB |
|
After Width: | Height: | Size: 334 KiB |
|
After Width: | Height: | Size: 385 KiB |
|
After Width: | Height: | Size: 287 KiB |
|
After Width: | Height: | Size: 284 KiB |
|
After Width: | Height: | Size: 334 KiB |
|
After Width: | Height: | Size: 385 KiB |
|
After Width: | Height: | Size: 287 KiB |
|
After Width: | Height: | Size: 284 KiB |
@@ -32,7 +32,7 @@ const constrainPosition = (
|
|||||||
position: Position,
|
position: Position,
|
||||||
containerSize: Size,
|
containerSize: Size,
|
||||||
imageSize: Size,
|
imageSize: Size,
|
||||||
zoom: number,
|
zoom: number
|
||||||
): Position => {
|
): Position => {
|
||||||
const scaledWidth = imageSize.width * zoom;
|
const scaledWidth = imageSize.width * zoom;
|
||||||
const scaledHeight = imageSize.height * zoom;
|
const scaledHeight = imageSize.height * zoom;
|
||||||
@@ -58,7 +58,7 @@ const constrainPosition = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getEventPosition = (
|
const getEventPosition = (
|
||||||
e: MouseEvent | TouchEvent | React.MouseEvent | React.TouchEvent,
|
e: MouseEvent | TouchEvent | React.MouseEvent | React.TouchEvent
|
||||||
): Position => {
|
): Position => {
|
||||||
if ("touches" in e)
|
if ("touches" in e)
|
||||||
return {
|
return {
|
||||||
@@ -83,7 +83,7 @@ const calculateMinZoom = (containerSize: Size, imageSize: Size): number => {
|
|||||||
const calculateCenterPosition = (
|
const calculateCenterPosition = (
|
||||||
containerSize: Size,
|
containerSize: Size,
|
||||||
imageSize: Size,
|
imageSize: Size,
|
||||||
zoom: number,
|
zoom: number
|
||||||
): Position => {
|
): Position => {
|
||||||
const scaledWidth = imageSize.width * zoom;
|
const scaledWidth = imageSize.width * zoom;
|
||||||
const scaledHeight = imageSize.height * zoom;
|
const scaledHeight = imageSize.height * zoom;
|
||||||
@@ -161,7 +161,7 @@ function FloorSelect({
|
|||||||
newPosition,
|
newPosition,
|
||||||
{ width: containerRect.width, height: containerRect.height },
|
{ width: containerRect.width, height: containerRect.height },
|
||||||
originalSize,
|
originalSize,
|
||||||
newZoom,
|
newZoom
|
||||||
);
|
);
|
||||||
|
|
||||||
setImagePosition(constrainedPosition);
|
setImagePosition(constrainedPosition);
|
||||||
@@ -194,7 +194,7 @@ function FloorSelect({
|
|||||||
// Check if we've moved beyond the threshold
|
// Check if we've moved beyond the threshold
|
||||||
const distanceMoved = Math.hypot(
|
const distanceMoved = Math.hypot(
|
||||||
x - dragStartPosition.current.x,
|
x - dragStartPosition.current.x,
|
||||||
y - dragStartPosition.current.y,
|
y - dragStartPosition.current.y
|
||||||
);
|
);
|
||||||
|
|
||||||
if (distanceMoved > dragThreshold) {
|
if (distanceMoved > dragThreshold) {
|
||||||
@@ -251,7 +251,7 @@ function FloorSelect({
|
|||||||
const touch2 = e.touches[1];
|
const touch2 = e.touches[1];
|
||||||
const distance = Math.hypot(
|
const distance = Math.hypot(
|
||||||
touch1.clientX - touch2.clientX,
|
touch1.clientX - touch2.clientX,
|
||||||
touch1.clientY - touch2.clientY,
|
touch1.clientY - touch2.clientY
|
||||||
);
|
);
|
||||||
initialTouchDistance.current = distance;
|
initialTouchDistance.current = distance;
|
||||||
previousTouchDistance.current = distance;
|
previousTouchDistance.current = distance;
|
||||||
@@ -285,7 +285,7 @@ function FloorSelect({
|
|||||||
const touch2 = e.touches[1];
|
const touch2 = e.touches[1];
|
||||||
const distance = Math.hypot(
|
const distance = Math.hypot(
|
||||||
touch1.clientX - touch2.clientX,
|
touch1.clientX - touch2.clientX,
|
||||||
touch1.clientY - touch2.clientY,
|
touch1.clientY - touch2.clientY
|
||||||
);
|
);
|
||||||
|
|
||||||
if (initialTouchDistance.current === null) {
|
if (initialTouchDistance.current === null) {
|
||||||
@@ -311,7 +311,7 @@ function FloorSelect({
|
|||||||
|
|
||||||
const newZoom = Math.min(
|
const newZoom = Math.min(
|
||||||
maxZoomRef.current,
|
maxZoomRef.current,
|
||||||
Math.max(minZoomRef.current, zoom * zoomFactor),
|
Math.max(minZoomRef.current, zoom * zoomFactor)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Prevent zoom if at limits or change is too small
|
// Prevent zoom if at limits or change is too small
|
||||||
@@ -353,7 +353,7 @@ function FloorSelect({
|
|||||||
// Check if we've moved beyond the threshold
|
// Check if we've moved beyond the threshold
|
||||||
const distanceMoved = Math.hypot(
|
const distanceMoved = Math.hypot(
|
||||||
x - dragStartPosition.current.x,
|
x - dragStartPosition.current.x,
|
||||||
y - dragStartPosition.current.y,
|
y - dragStartPosition.current.y
|
||||||
);
|
);
|
||||||
|
|
||||||
if (distanceMoved > dragThreshold) {
|
if (distanceMoved > dragThreshold) {
|
||||||
@@ -426,7 +426,7 @@ function FloorSelect({
|
|||||||
|
|
||||||
const newZoom = Math.min(
|
const newZoom = Math.min(
|
||||||
maxZoomRef.current,
|
maxZoomRef.current,
|
||||||
Math.max(minZoomRef.current, zoom * zoomFactor),
|
Math.max(minZoomRef.current, zoom * zoomFactor)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Prevent zoom if at limits or change is too small
|
// Prevent zoom if at limits or change is too small
|
||||||
@@ -459,7 +459,7 @@ function FloorSelect({
|
|||||||
const centerPosition = calculateCenterPosition(
|
const centerPosition = calculateCenterPosition(
|
||||||
{ width, height },
|
{ width, height },
|
||||||
originalSize,
|
originalSize,
|
||||||
newMinZoom, // Сбрасываем к минимальному зуму (изображение на всю высоту)
|
newMinZoom // Сбрасываем к минимальному зуму (изображение на всю высоту)
|
||||||
);
|
);
|
||||||
|
|
||||||
setZoom(newMinZoom);
|
setZoom(newMinZoom);
|
||||||
@@ -493,7 +493,7 @@ function FloorSelect({
|
|||||||
const centerPosition = calculateCenterPosition(
|
const centerPosition = calculateCenterPosition(
|
||||||
{ width, height },
|
{ width, height },
|
||||||
originalSize,
|
originalSize,
|
||||||
newMinZoom, // Используем вычисленный минимальный зум
|
newMinZoom // Используем вычисленный минимальный зум
|
||||||
);
|
);
|
||||||
setZoom(newMinZoom);
|
setZoom(newMinZoom);
|
||||||
setImagePosition(centerPosition);
|
setImagePosition(centerPosition);
|
||||||
@@ -583,11 +583,7 @@ function FloorSelect({
|
|||||||
const { data } = useQuery({
|
const { data } = useQuery({
|
||||||
queryKey: ["floors-data", complexName],
|
queryKey: ["floors-data", complexName],
|
||||||
queryFn: () =>
|
queryFn: () =>
|
||||||
api
|
api.get(`units/get-floors-data/${complexName}`).json<FloorsData[]>(),
|
||||||
.get(
|
|
||||||
`units/get-floors-data/${complexName}`,
|
|
||||||
)
|
|
||||||
.json<FloorsData[]>(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function handleFloorClick(floor: string) {
|
function handleFloorClick(floor: string) {
|
||||||
@@ -606,7 +602,7 @@ function FloorSelect({
|
|||||||
data.some(
|
data.some(
|
||||||
(floorData) =>
|
(floorData) =>
|
||||||
floorData.floor === +floor!.split(" ").at(-1)! ||
|
floorData.floor === +floor!.split(" ").at(-1)! ||
|
||||||
floorData.floor === +floor!.split(" ").at(-1)!.split("-")[0],
|
floorData.floor === +floor!.split(" ").at(-1)!.split("-")[0]
|
||||||
) ||
|
) ||
|
||||||
SPECIAL_FLOORS.includes(floor)
|
SPECIAL_FLOORS.includes(floor)
|
||||||
)
|
)
|
||||||
@@ -618,11 +614,11 @@ function FloorSelect({
|
|||||||
data.find(
|
data.find(
|
||||||
(floorData) =>
|
(floorData) =>
|
||||||
floorData.floor === +floor!.split(" ").at(-1)! ||
|
floorData.floor === +floor!.split(" ").at(-1)! ||
|
||||||
floorData.floor === +floor!.split(" ").at(-1)!.split("-")[0],
|
floorData.floor === +floor!.split(" ").at(-1)!.split("-")[0]
|
||||||
)!
|
)!
|
||||||
}
|
}
|
||||||
onSelect={handleFloorClick}
|
onSelect={handleFloorClick}
|
||||||
/>,
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -647,7 +643,7 @@ function FloorSelect({
|
|||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"overflow-hidden h-full w-full relative transition-transform duration-300",
|
"overflow-hidden h-full w-full relative transition-transform duration-300",
|
||||||
selectedFloor && "2xl:-translate-x-1/4",
|
selectedFloor && "2xl:-translate-x-1/4"
|
||||||
)}
|
)}
|
||||||
ref={rootRef}
|
ref={rootRef}
|
||||||
>
|
>
|
||||||
@@ -661,7 +657,7 @@ function FloorSelect({
|
|||||||
"touch-none absolute inset-0 select-none will-change-[opacity,scale,transform] transition-opacity duration-300",
|
"touch-none absolute inset-0 select-none will-change-[opacity,scale,transform] transition-opacity duration-300",
|
||||||
isImageLoaded && originalSize.width !== 0
|
isImageLoaded && originalSize.width !== 0
|
||||||
? "opacity-100"
|
? "opacity-100"
|
||||||
: "opacity-0",
|
: "opacity-0"
|
||||||
)}
|
)}
|
||||||
style={{
|
style={{
|
||||||
cursor: isMobile ? (isDragging ? "grabbing" : "grab") : "default",
|
cursor: isMobile ? (isDragging ? "grabbing" : "grab") : "default",
|
||||||
@@ -702,60 +698,64 @@ function FloorSelect({
|
|||||||
/>
|
/>
|
||||||
<g ref={ref}>
|
<g ref={ref}>
|
||||||
{Object.entries(enumerationMasks[complexName]).map(
|
{Object.entries(enumerationMasks[complexName]).map(
|
||||||
([floorTitle, { x, y, width, height, d }]) =>
|
([floorTitle, mask]) =>
|
||||||
Array.isArray(d) && Array.isArray(x) ? (
|
Array.isArray(mask) ? (
|
||||||
<Fragment key={floorTitle}>
|
mask.map(({ x, y, width, height, d }) => (
|
||||||
<rect
|
<Fragment
|
||||||
x={x[0]}
|
key={`${floorTitle}-${x}-${y}-${width}-${height}-${d}`}
|
||||||
y={y}
|
>
|
||||||
width={width}
|
<rect
|
||||||
height={height}
|
x={x}
|
||||||
rx={complexName === "marasi-drive" ? 14.2 : 10}
|
y={y}
|
||||||
fillOpacity={0.4}
|
width={width}
|
||||||
className={clsx(
|
height={height}
|
||||||
"transition-[fill] pointer-events-none",
|
rx={height / 2}
|
||||||
((hoveredFloor &&
|
fillOpacity={0.4}
|
||||||
floorTitle ===
|
className={clsx(
|
||||||
(complexName === "dubai-marina"
|
"transition-[fill] pointer-events-none",
|
||||||
? hoveredFloor
|
((hoveredFloor &&
|
||||||
: SPECIAL_FLOORS.includes(hoveredFloor)
|
floorTitle ===
|
||||||
? hoveredFloor
|
(complexName === "dubai-marina"
|
||||||
: hoveredFloor.split(" ").at(-1)!)) ||
|
? hoveredFloor
|
||||||
selectedFloor?.split(" ").at(-1) === floorTitle) &&
|
: SPECIAL_FLOORS.includes(hoveredFloor)
|
||||||
"fill-[#00BED7]",
|
? hoveredFloor
|
||||||
)}
|
: hoveredFloor.split(" ").at(-1)!)) ||
|
||||||
/>
|
selectedFloor?.split(" ").at(-1) === floorTitle) &&
|
||||||
<path d={d[0]} className="pointer-events-none fill-white" />
|
"fill-[#00BED7]"
|
||||||
<rect
|
)}
|
||||||
x={x[1]}
|
/>
|
||||||
y={y}
|
<path d={d} className="fill-white pointer-events-none" />
|
||||||
width={width}
|
</Fragment>
|
||||||
height={height}
|
))
|
||||||
rx={complexName === "marasi-drive" ? 14.2 : 10}
|
|
||||||
fillOpacity={0.4}
|
|
||||||
className={clsx(
|
|
||||||
"transition-[fill] pointer-events-none",
|
|
||||||
((hoveredFloor &&
|
|
||||||
floorTitle ===
|
|
||||||
(complexName === "dubai-marina"
|
|
||||||
? hoveredFloor
|
|
||||||
: SPECIAL_FLOORS.includes(hoveredFloor)
|
|
||||||
? hoveredFloor
|
|
||||||
: hoveredFloor.split(" ").at(-1)!)) ||
|
|
||||||
selectedFloor?.split(" ").at(-1) === floorTitle) &&
|
|
||||||
"fill-[#00BED7]",
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<path d={d[1]} className="pointer-events-none fill-white" />
|
|
||||||
</Fragment>
|
|
||||||
) : (
|
) : (
|
||||||
|
// <rect
|
||||||
|
// x={x[1]}
|
||||||
|
// y={y[1]}
|
||||||
|
// width={width[1]}
|
||||||
|
// height={height[1]}
|
||||||
|
// rx={complexName === "marasi-drive" ? 14.2 : 10}
|
||||||
|
// fillOpacity={0.4}
|
||||||
|
// className={clsx(
|
||||||
|
// "transition-[fill] pointer-events-none",
|
||||||
|
// ((hoveredFloor &&
|
||||||
|
// floorTitle ===
|
||||||
|
// (complexName === "dubai-marina"
|
||||||
|
// ? hoveredFloor
|
||||||
|
// : SPECIAL_FLOORS.includes(hoveredFloor)
|
||||||
|
// ? hoveredFloor
|
||||||
|
// : hoveredFloor.split(" ").at(-1)!)) ||
|
||||||
|
// selectedFloor?.split(" ").at(-1) === floorTitle) &&
|
||||||
|
// "fill-[#00BED7]"
|
||||||
|
// )}
|
||||||
|
// />
|
||||||
|
// <path d={d[1]} className="fill-white pointer-events-none" />
|
||||||
<Fragment key={floorTitle}>
|
<Fragment key={floorTitle}>
|
||||||
<rect
|
<rect
|
||||||
x={Array.isArray(x) ? x[0] : x}
|
x={mask.x}
|
||||||
y={y}
|
y={mask.y}
|
||||||
width={width}
|
width={mask.width}
|
||||||
height={height}
|
height={mask.height}
|
||||||
rx={complexName === "marasi-drive" ? 14.2 : 10}
|
rx={mask.height / 2}
|
||||||
fillOpacity={0.4}
|
fillOpacity={0.4}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"transition-[fill] pointer-events-none",
|
"transition-[fill] pointer-events-none",
|
||||||
@@ -767,18 +767,18 @@ function FloorSelect({
|
|||||||
? hoveredFloor
|
? hoveredFloor
|
||||||
: hoveredFloor.split(" ").at(-1)!)) ||
|
: hoveredFloor.split(" ").at(-1)!)) ||
|
||||||
selectedFloor?.split(" ").at(-1) === floorTitle) &&
|
selectedFloor?.split(" ").at(-1) === floorTitle) &&
|
||||||
"fill-[#00BED7]",
|
"fill-[#00BED7]"
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<path
|
<path
|
||||||
d={d as string}
|
d={mask.d}
|
||||||
className="pointer-events-none fill-white"
|
className="fill-white pointer-events-none"
|
||||||
/>
|
/>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
),
|
)
|
||||||
)}
|
)}
|
||||||
{Object.entries(
|
{Object.entries(
|
||||||
floorsMasks[complexName as keyof typeof floorsMasks],
|
floorsMasks[complexName as keyof typeof floorsMasks]
|
||||||
).map(([floorTitle, d]) => (
|
).map(([floorTitle, d]) => (
|
||||||
<path
|
<path
|
||||||
onMouseMove={!isMobile ? handleFloorMouseMove : undefined}
|
onMouseMove={!isMobile ? handleFloorMouseMove : undefined}
|
||||||
@@ -802,7 +802,7 @@ function FloorSelect({
|
|||||||
SPECIAL_FLOORS.includes(floorTitle) ||
|
SPECIAL_FLOORS.includes(floorTitle) ||
|
||||||
complexName === "marasi-drive"
|
complexName === "marasi-drive"
|
||||||
? floorTitle
|
? floorTitle
|
||||||
: floorTitle.split(" ").at(-1)!,
|
: floorTitle.split(" ").at(-1)!
|
||||||
);
|
);
|
||||||
|
|
||||||
openPopup(
|
openPopup(
|
||||||
@@ -810,7 +810,7 @@ function FloorSelect({
|
|||||||
!SPECIAL_FLOORS.includes(floorTitle) &&
|
!SPECIAL_FLOORS.includes(floorTitle) &&
|
||||||
complexName === "marasi-drive"
|
complexName === "marasi-drive"
|
||||||
? (floorTitle.split(" ")[0] as "West" | "East")
|
? (floorTitle.split(" ")[0] as "West" | "East")
|
||||||
: undefined,
|
: undefined
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@@ -819,7 +819,7 @@ function FloorSelect({
|
|||||||
SPECIAL_FLOORS.includes(floorTitle) ||
|
SPECIAL_FLOORS.includes(floorTitle) ||
|
||||||
complexName === "marasi-drive"
|
complexName === "marasi-drive"
|
||||||
? floorTitle
|
? floorTitle
|
||||||
: floorTitle.split(" ").at(-1)!,
|
: floorTitle.split(" ").at(-1)!
|
||||||
);
|
);
|
||||||
if (!isMobile)
|
if (!isMobile)
|
||||||
openPopup(
|
openPopup(
|
||||||
@@ -827,7 +827,7 @@ function FloorSelect({
|
|||||||
!SPECIAL_FLOORS.includes(floorTitle) &&
|
!SPECIAL_FLOORS.includes(floorTitle) &&
|
||||||
complexName === "marasi-drive"
|
complexName === "marasi-drive"
|
||||||
? (floorTitle.split(" ")[0] as "West" | "East")
|
? (floorTitle.split(" ")[0] as "West" | "East")
|
||||||
: undefined,
|
: undefined
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
onMouseLeave={() => {
|
onMouseLeave={() => {
|
||||||
@@ -851,7 +851,7 @@ function FloorSelect({
|
|||||||
? floorTitle
|
? floorTitle
|
||||||
: floorTitle.split(" ").at(-1)!)
|
: floorTitle.split(" ").at(-1)!)
|
||||||
? "opacity-60"
|
? "opacity-60"
|
||||||
: "opacity-20",
|
: "opacity-20"
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -25,9 +25,7 @@ function UnitPage() {
|
|||||||
queryKey: ["unit", params.complexName, params.unitNumber],
|
queryKey: ["unit", params.complexName, params.unitNumber],
|
||||||
queryFn: () =>
|
queryFn: () =>
|
||||||
api
|
api
|
||||||
.get(
|
.get(`units/${params.unitNumber}?project=${params.complexName}`)
|
||||||
`units/${params.unitNumber}?project=${params.complexName}`
|
|
||||||
)
|
|
||||||
.json<Unit>(),
|
.json<Unit>(),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -270,6 +268,29 @@ function UnitPage() {
|
|||||||
{/* <Button disabled variant="cta" size="large">
|
{/* <Button disabled variant="cta" size="large">
|
||||||
Book
|
Book
|
||||||
</Button> */}
|
</Button> */}
|
||||||
|
|
||||||
|
{/* videos for hq units */}
|
||||||
|
{unit.projectSlug === "hq" &&
|
||||||
|
[
|
||||||
|
"loft-edge",
|
||||||
|
"penthouse-loft",
|
||||||
|
"presidential-loft",
|
||||||
|
"studio",
|
||||||
|
].includes(unit.unitTypeVariantSlug) && (
|
||||||
|
<Button
|
||||||
|
variant="cta"
|
||||||
|
size="large"
|
||||||
|
onClick={() =>
|
||||||
|
setModal(
|
||||||
|
<VideoModal
|
||||||
|
src={`/videos/unit-types/hq/${unit.unitTypeVariantSlug}.mp4`}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Video tour
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||