diff --git a/.env b/.env index 67c1687..e9e9623 100644 --- a/.env +++ b/.env @@ -1,5 +1,5 @@ -# VITE_API_URL=http://localhost:4002 +VITE_API_URL=http://localhost:4002 # VITE_API_URL=http://192.168.1.144:4002 # VITE_API_URL=http://194.26.138.94:4002 # VITE_API_URL=https://irthtest.online/api -VITE_API_URL=https://irth.graff.estate/api \ No newline at end of file +# VITE_API_URL=https://irth.graff.estate/api \ No newline at end of file diff --git a/src/components/NewUnitSlider.tsx b/src/components/NewUnitSlider.tsx new file mode 100644 index 0000000..f70739d --- /dev/null +++ b/src/components/NewUnitSlider.tsx @@ -0,0 +1,93 @@ +import React, { type PropsWithChildren, useState } from "react"; +import Button from "./ui/Button"; +import { useSwipeable } from "react-swipeable"; +import { motion } from "motion/react"; + +interface SliderItemProps { + text: string; +} + +function flattenChildren(children: React.ReactNode): React.ReactElement[] { + const result: React.ReactElement[] = []; + + React.Children.forEach(children, (child) => { + if (React.isValidElement(child)) { + if (child.type === React.Fragment) { + result.push( + ...flattenChildren( + (child.props as { children?: React.ReactNode }).children + ) + ); + } else { + result.push(child); + } + } + }); + + return result; +} + +function NewUnitSlider({ children }: PropsWithChildren) { + const [currentSlide, setCurrentSlide] = useState(0); + + const flattenedChildren = flattenChildren(children); + const slides = flattenedChildren.map((child, index) => { + if (React.isValidElement(child) && child.props.text) { + return { + index, + text: child.props.text, + element: child, + }; + } + return { + index, + text: `Slide ${index + 1}`, + element: child, + }; + }); + + const handlers = useSwipeable({ + onSwipedLeft: () => + setCurrentSlide(Math.min(currentSlide + 1, slides.length - 1)), + onSwipedRight: () => setCurrentSlide(Math.max(currentSlide - 1, 0)), + preventScrollOnSwipe: true, + touchEventOptions: { + passive: false, + }, + trackMouse: true, + }); + + return ( +
+ + {slides.map((slide) => slide.element)} + +
+ {slides.map((slide, index) => ( + + ))} +
+
+ ); +} + +export default NewUnitSlider; diff --git a/src/components/PopupContainer.tsx b/src/components/PopupContainer.tsx index 33c5dec..3e2987c 100644 --- a/src/components/PopupContainer.tsx +++ b/src/components/PopupContainer.tsx @@ -65,9 +65,9 @@ function PopupContainer() { side === "right" && "top-1/2 [y:-50%] right-full [x:1px] [rotate:180deg]", side === "top" && - "left-1/2 [x:100%] top-full [y:1px] [rotate:90deg] origin-top-left", + "left-1/2 [x:100%] absolute top-full [y:1px] [rotate:90deg] origin-top-left", side === "bottom" && - "left-1/2 [x:100%] bottom-full [y:1px] [rotate:-90deg] origin-bottom-left" + "left-1/2 [x:100%] absolute bottom-full [y:1px] [rotate:-90deg] origin-bottom-left" )} /> diff --git a/src/components/UnitCard.tsx b/src/components/UnitCard.tsx index e907717..b8da569 100644 --- a/src/components/UnitCard.tsx +++ b/src/components/UnitCard.tsx @@ -43,9 +43,9 @@ function UnitCard({ unit }: { unit: Unit }) { -
+

{unit.project || } diff --git a/src/components/UnitImageWithSides.tsx b/src/components/UnitImageWithSides.tsx new file mode 100644 index 0000000..dd99c8e --- /dev/null +++ b/src/components/UnitImageWithSides.tsx @@ -0,0 +1,19 @@ +import UnitTypeImageWithMarkers from "./UnitTypeImageWithMarkers"; + +interface UnitImageWithSidesProps { + unitTypeVariant: string; +} + +function UnitImageWithSides({ unitTypeVariant }: UnitImageWithSidesProps) { + return ( +

+ +
+ ); +} + +export default UnitImageWithSides; diff --git a/src/components/UnitSlider.tsx b/src/components/UnitSlider.tsx index 0a32895..7a65378 100644 --- a/src/components/UnitSlider.tsx +++ b/src/components/UnitSlider.tsx @@ -69,7 +69,7 @@ function UnitSlider({ unitTypeVariant, complexName, unit }: UnitSliderProps) { duration: 0.5, ease: "easeInOut", }} - className="flex h-full w-full relative top-0" + className="flex relative top-0 w-full h-full" > {isLoft ? ( <> diff --git a/src/components/UnitSliderItem.tsx b/src/components/UnitSliderItem.tsx new file mode 100644 index 0000000..11d38af --- /dev/null +++ b/src/components/UnitSliderItem.tsx @@ -0,0 +1,11 @@ +import { PropsWithChildren } from "react"; + +interface UnitSliderItemProps { + text: string; +} + +function UnitSliderItem({ children }: PropsWithChildren) { + return
{children}
; +} + +export default UnitSliderItem; diff --git a/src/components/UnitTypeImageWithMarkers.tsx b/src/components/UnitTypeImageWithMarkers.tsx index 88386f9..19a5ba7 100644 --- a/src/components/UnitTypeImageWithMarkers.tsx +++ b/src/components/UnitTypeImageWithMarkers.tsx @@ -5,8 +5,7 @@ function UnitTypeImageWithMarkers({ legend, floor, unitTypeVariant, -}: // unitNumber, -{ +}: { complexName: string; legend: { name: string; @@ -16,29 +15,15 @@ function UnitTypeImageWithMarkers({ }[]; floor?: "lower" | "upper"; unitTypeVariant: string; - // unitNumber: string; }) { const refRect = useRef(null); const [hoveredIndex, setHoveredIndex] = useState(null); - // Фильтруем legend по floor const filteredLegend = legend.filter((item) => { - // Если у элемента нет поля floor, показываем всегда if (!item.floor) return true; - // Если у элемента есть поле floor, показываем только если оно совпадает с переданным floor return item.floor === floor; }); - // const [unitTypeVariant, setUnitTypeVariant] = useState(); - - // useEffect(() => { - // setUnitTypeVariant( - // complexName === "dubai-marina" - // ? getUnitTypeVariantDubaiMarina(unitNumber, floor) - // : getUnitTypeVariantMarasiDrive(unitNumber) - // ); - // }, [complexName, unitNumber, floor]); - return ( - {/* Рендерим сначала все маркеры */} {filteredLegend.map((item, index) => ( setHoveredIndex(null)} /> ))} - {/* Затем рендерим все тултипы поверх маркеров */} {filteredLegend.map((item, index) => ( - + + {type.slug.includes("-loft") ? ( + <> + + + + + + + + ) : ( + + + + )} + + + +
diff --git a/src/components/ui/Select.tsx b/src/components/ui/Select.tsx index 726d6d5..94ea2bf 100644 --- a/src/components/ui/Select.tsx +++ b/src/components/ui/Select.tsx @@ -98,7 +98,7 @@ function Select({ exit={{ opacity: 0 }} transition={{ duration: 0.15 }} ref={dropdownRefCallback} - className="absolute 2xl:mt-[0.278vw] 2xl:pt-[0.278vw] mt-1 p-1 2xl:space-y-[0.139vw] space-y-0.5 shadow-[0px_2px_8px_rgba(0,0,0,0.15)] overflow-auto rounded-xl bg-white w-full z-1" + className="absolute 2xl:mt-[0.278vw] 2xl:pt-[0.278vw] mt-1 p-1 2xl:space-y-[0.139vw] space-y-0.5 shadow-[0px_2px_8px_rgba(0,0,0,0.15)] overflow-auto rounded-xl bg-white w-full z-[1]" > {options.map((option, index) => (
{(!removeSimilar || - filteredFavoriteUnits.some( - ({ salesPrice }) => salesPrice !== unit.salesPrice - )) && ( - + filteredFavoriteUnits.some( + ({ salesPrice }) => salesPrice !== unit.salesPrice + )) && ( + )} {(!removeSimilar || @@ -407,7 +409,7 @@ function UnitParameter({ : `translateX(calc((50% + clamp(8px, 2.222vw, 12px)) * ${current}))`, }} > -

{paramName}

+

{paramName}


(); - // const navigate = useNavigate(); const { data: unit } = useQuery({ queryKey: ["unit", params.complexName, params.unitNumber], @@ -36,29 +35,6 @@ function UnitPage() { .json(), }); - const [selectedFloor, setSelectedFloor] = useState<"lower" | "upper">(); - - useEffect(() => { - if ( - getUnitTypeSlug(params.complexName!, unit?.unitType || "").includes( - "loft" - ) - ) { - setSelectedFloor("lower"); - } - - // if (unit && params.complexName === "marasi-drive") {} - // <<<<<<< HEAD - - // // if (unit) { - // // console.log("Unit number:", unit.unitNo); - // // console.log("Is combinable:", isUnitCombinable(unit)); - // // console.log("Unit type:", unit.unitType); - // // } - // ======= - // >>>>>>> 964167e863ddf4416c0e747dc4d25c185dff4505 - }, [unit]); - const { favoriteUnits, setFavoriteUnits } = useFavoritesUnitsStore(); function handleFavorite() { @@ -81,6 +57,8 @@ function UnitPage() { }); } + if (!unit) return

Loading...
; + return ( @@ -88,23 +66,77 @@ function UnitPage() {
- - + + {unit.isLoft ? ( + <> + + project.slug === unit.projectSlug) + ?.types.find( + (type) => type.slug === unit.unitTypeVariantSlug + )?.legend || [] + } + /> + + + project.slug === unit.projectSlug) + ?.types.find( + (type) => type.slug === unit.unitTypeVariantSlug + )?.legend || [] + } + /> + + + ) : ( + + project.slug === unit.projectSlug) + ?.types.find( + (type) => type.slug === unit.unitTypeVariantSlug + )?.legend || [] + } + /> + + )} + + + + + + + + +
diff --git a/src/types/IUnit.ts b/src/types/IUnit.ts index 312269b..12c5c75 100644 --- a/src/types/IUnit.ts +++ b/src/types/IUnit.ts @@ -2,6 +2,7 @@ export interface Unit { id: string; unitNo: string; project: string; + projectSlug: string; floor: number; unitType: string; unitView: string; @@ -13,4 +14,7 @@ export interface Unit { salesPrice: number; balconyArea: number; wing?: string; + unitTypeVariantSlug: string; + side?: "left" | "right" + isLoft: boolean } diff --git a/src/utils/getUnitTypeVariantDubaiMarina.ts b/src/utils/getUnitTypeVariantDubaiMarina.ts index 327e3bb..856c7d7 100644 --- a/src/utils/getUnitTypeVariantDubaiMarina.ts +++ b/src/utils/getUnitTypeVariantDubaiMarina.ts @@ -4,7 +4,6 @@ export function getUnitTypeVariantDubaiMarina( ) { const isCombinable = unitNumber.endsWith('C') const formattedUnitNumber = isCombinable ? +unitNumber.slice(-4, -2) : +unitNumber.slice(-2); - // const floor = +unitNumber.slice(0, isCombinable ? -4 : -2) if (loftFloor) { if ([1, 7, 8, 14].includes(formattedUnitNumber)) return `1-bedroom-loft-c-${loftFloor}-${formattedUnitNumber % 7 === 0 ? 'left' : "right"}`