This commit is contained in:
2026-02-11 18:32:29 +05:00
parent 13f7ac4dc0
commit 96ddfc6e4a
27 changed files with 1100 additions and 597 deletions
+3 -3
View File
@@ -1,5 +1,5 @@
# VITE_API_URL=http://localhost:4002
VITE_API_URL=http://192.168.1.35:4002
# VITE_API_URL=http://192.168.1.224:4002
# VITE_API_URL=http://192.168.1.35: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
+1
View File
@@ -11,6 +11,7 @@ lerna-debug.log*
node_modules
dist
dist-ssr
dist.zip
*.local
public/virtual-tours
Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 385 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 284 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 334 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 385 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 287 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 284 KiB

Binary file not shown.
+83 -83
View File
@@ -32,7 +32,7 @@ const constrainPosition = (
position: Position,
containerSize: Size,
imageSize: Size,
zoom: number,
zoom: number
): Position => {
const scaledWidth = imageSize.width * zoom;
const scaledHeight = imageSize.height * zoom;
@@ -58,7 +58,7 @@ const constrainPosition = (
};
const getEventPosition = (
e: MouseEvent | TouchEvent | React.MouseEvent | React.TouchEvent,
e: MouseEvent | TouchEvent | React.MouseEvent | React.TouchEvent
): Position => {
if ("touches" in e)
return {
@@ -83,7 +83,7 @@ const calculateMinZoom = (containerSize: Size, imageSize: Size): number => {
const calculateCenterPosition = (
containerSize: Size,
imageSize: Size,
zoom: number,
zoom: number
): Position => {
const scaledWidth = imageSize.width * zoom;
const scaledHeight = imageSize.height * zoom;
@@ -161,7 +161,7 @@ function FloorSelect({
newPosition,
{ width: containerRect.width, height: containerRect.height },
originalSize,
newZoom,
newZoom
);
setImagePosition(constrainedPosition);
@@ -194,7 +194,7 @@ function FloorSelect({
// Check if we've moved beyond the threshold
const distanceMoved = Math.hypot(
x - dragStartPosition.current.x,
y - dragStartPosition.current.y,
y - dragStartPosition.current.y
);
if (distanceMoved > dragThreshold) {
@@ -251,7 +251,7 @@ function FloorSelect({
const touch2 = e.touches[1];
const distance = Math.hypot(
touch1.clientX - touch2.clientX,
touch1.clientY - touch2.clientY,
touch1.clientY - touch2.clientY
);
initialTouchDistance.current = distance;
previousTouchDistance.current = distance;
@@ -285,7 +285,7 @@ function FloorSelect({
const touch2 = e.touches[1];
const distance = Math.hypot(
touch1.clientX - touch2.clientX,
touch1.clientY - touch2.clientY,
touch1.clientY - touch2.clientY
);
if (initialTouchDistance.current === null) {
@@ -311,7 +311,7 @@ function FloorSelect({
const newZoom = Math.min(
maxZoomRef.current,
Math.max(minZoomRef.current, zoom * zoomFactor),
Math.max(minZoomRef.current, zoom * zoomFactor)
);
// Prevent zoom if at limits or change is too small
@@ -353,7 +353,7 @@ function FloorSelect({
// Check if we've moved beyond the threshold
const distanceMoved = Math.hypot(
x - dragStartPosition.current.x,
y - dragStartPosition.current.y,
y - dragStartPosition.current.y
);
if (distanceMoved > dragThreshold) {
@@ -426,7 +426,7 @@ function FloorSelect({
const newZoom = Math.min(
maxZoomRef.current,
Math.max(minZoomRef.current, zoom * zoomFactor),
Math.max(minZoomRef.current, zoom * zoomFactor)
);
// Prevent zoom if at limits or change is too small
@@ -459,7 +459,7 @@ function FloorSelect({
const centerPosition = calculateCenterPosition(
{ width, height },
originalSize,
newMinZoom, // Сбрасываем к минимальному зуму (изображение на всю высоту)
newMinZoom // Сбрасываем к минимальному зуму (изображение на всю высоту)
);
setZoom(newMinZoom);
@@ -493,7 +493,7 @@ function FloorSelect({
const centerPosition = calculateCenterPosition(
{ width, height },
originalSize,
newMinZoom, // Используем вычисленный минимальный зум
newMinZoom // Используем вычисленный минимальный зум
);
setZoom(newMinZoom);
setImagePosition(centerPosition);
@@ -583,11 +583,7 @@ function FloorSelect({
const { data } = useQuery({
queryKey: ["floors-data", complexName],
queryFn: () =>
api
.get(
`units/get-floors-data/${complexName}`,
)
.json<FloorsData[]>(),
api.get(`units/get-floors-data/${complexName}`).json<FloorsData[]>(),
});
function handleFloorClick(floor: string) {
@@ -606,7 +602,7 @@ function FloorSelect({
data.some(
(floorData) =>
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)
)
@@ -618,11 +614,11 @@ function FloorSelect({
data.find(
(floorData) =>
floorData.floor === +floor!.split(" ").at(-1)! ||
floorData.floor === +floor!.split(" ").at(-1)!.split("-")[0],
floorData.floor === +floor!.split(" ").at(-1)!.split("-")[0]
)!
}
onSelect={handleFloorClick}
/>,
/>
);
}
@@ -647,7 +643,7 @@ function FloorSelect({
<div
className={clsx(
"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}
>
@@ -661,7 +657,7 @@ function FloorSelect({
"touch-none absolute inset-0 select-none will-change-[opacity,scale,transform] transition-opacity duration-300",
isImageLoaded && originalSize.width !== 0
? "opacity-100"
: "opacity-0",
: "opacity-0"
)}
style={{
cursor: isMobile ? (isDragging ? "grabbing" : "grab") : "default",
@@ -702,60 +698,64 @@ function FloorSelect({
/>
<g ref={ref}>
{Object.entries(enumerationMasks[complexName]).map(
([floorTitle, { x, y, width, height, d }]) =>
Array.isArray(d) && Array.isArray(x) ? (
<Fragment key={floorTitle}>
<rect
x={x[0]}
y={y}
width={width}
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[0]} className="pointer-events-none fill-white" />
<rect
x={x[1]}
y={y}
width={width}
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>
([floorTitle, mask]) =>
Array.isArray(mask) ? (
mask.map(({ x, y, width, height, d }) => (
<Fragment
key={`${floorTitle}-${x}-${y}-${width}-${height}-${d}`}
>
<rect
x={x}
y={y}
width={width}
height={height}
rx={height / 2}
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} className="fill-white pointer-events-none" />
</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}>
<rect
x={Array.isArray(x) ? x[0] : x}
y={y}
width={width}
height={height}
rx={complexName === "marasi-drive" ? 14.2 : 10}
x={mask.x}
y={mask.y}
width={mask.width}
height={mask.height}
rx={mask.height / 2}
fillOpacity={0.4}
className={clsx(
"transition-[fill] pointer-events-none",
@@ -767,18 +767,18 @@ function FloorSelect({
? hoveredFloor
: hoveredFloor.split(" ").at(-1)!)) ||
selectedFloor?.split(" ").at(-1) === floorTitle) &&
"fill-[#00BED7]",
"fill-[#00BED7]"
)}
/>
<path
d={d as string}
className="pointer-events-none fill-white"
d={mask.d}
className="fill-white pointer-events-none"
/>
</Fragment>
),
)
)}
{Object.entries(
floorsMasks[complexName as keyof typeof floorsMasks],
floorsMasks[complexName as keyof typeof floorsMasks]
).map(([floorTitle, d]) => (
<path
onMouseMove={!isMobile ? handleFloorMouseMove : undefined}
@@ -802,7 +802,7 @@ function FloorSelect({
SPECIAL_FLOORS.includes(floorTitle) ||
complexName === "marasi-drive"
? floorTitle
: floorTitle.split(" ").at(-1)!,
: floorTitle.split(" ").at(-1)!
);
openPopup(
@@ -810,7 +810,7 @@ function FloorSelect({
!SPECIAL_FLOORS.includes(floorTitle) &&
complexName === "marasi-drive"
? (floorTitle.split(" ")[0] as "West" | "East")
: undefined,
: undefined
);
}
}}
@@ -819,7 +819,7 @@ function FloorSelect({
SPECIAL_FLOORS.includes(floorTitle) ||
complexName === "marasi-drive"
? floorTitle
: floorTitle.split(" ").at(-1)!,
: floorTitle.split(" ").at(-1)!
);
if (!isMobile)
openPopup(
@@ -827,7 +827,7 @@ function FloorSelect({
!SPECIAL_FLOORS.includes(floorTitle) &&
complexName === "marasi-drive"
? (floorTitle.split(" ")[0] as "West" | "East")
: undefined,
: undefined
);
}}
onMouseLeave={() => {
@@ -851,7 +851,7 @@ function FloorSelect({
? floorTitle
: floorTitle.split(" ").at(-1)!)
? "opacity-60"
: "opacity-20",
: "opacity-20"
)}
/>
))}
+988 -507
View File
File diff suppressed because it is too large Load Diff
+24 -3
View File
@@ -25,9 +25,7 @@ function UnitPage() {
queryKey: ["unit", params.complexName, params.unitNumber],
queryFn: () =>
api
.get(
`units/${params.unitNumber}?project=${params.complexName}`
)
.get(`units/${params.unitNumber}?project=${params.complexName}`)
.json<Unit>(),
});
@@ -270,6 +268,29 @@ function UnitPage() {
{/* <Button disabled variant="cta" size="large">
Book
</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>