This commit is contained in:
2025-07-21 16:28:05 +05:00
parent 3a4af48d8f
commit a6286c0652
30 changed files with 292 additions and 217 deletions
+97 -75
View File
@@ -1,5 +1,7 @@
import { useEffect, useState } from "react";
import { formattedUnitTypes } from "../data/formattedUnitTypes";
import { usePopupStore } from "../stores/usePopupStore";
import getAmentiesCount, { AmentiesCount } from "../utils/getAmentiesCount";
import { FloorsData } from "./FloorSelect";
import ArrowRightIcon from "./icons/ArrowRightIcon";
import HumanIcon from "./icons/HumanIcon";
@@ -14,89 +16,109 @@ interface FloorPopupProps {
function FloorPopup({ title, complexName, data, onSelect }: FloorPopupProps) {
const { setPopup } = usePopupStore();
const [amentiesCount, setAmentiesCount] = useState<AmentiesCount | null>(
null
);
useEffect(() => {
if (Number.isNaN(+title.split(" ").at(-1)!)) {
setAmentiesCount(getAmentiesCount(complexName, title));
} else {
setAmentiesCount(null);
}
return () => setAmentiesCount(null);
}, [complexName, title]);
useEffect(() => {
console.log(amentiesCount);
}, [amentiesCount]);
return (
<div className="flex flex-col 2xl:gap-y-[0.556vw] gap-y-2">
<div className="flex 2xl:gap-[0.556vw] gap-2">
<p className="font-medium text-h5">
{Number.isNaN(+title.split(" ").at(-1)!)
? title
: `${title.split(" ").at(-1)} floor`}
{amentiesCount ? title : `${title.split(" ").at(-1)} floor`}
</p>
{complexName === "marasi-drive" &&
!Number.isNaN(+title.split(" ").at(-1)!) && (
<p className="text-[#0D1922]/40 text-s">
{title.split(" ")[0]} Wing
{complexName === "marasi-drive" && !amentiesCount && (
<p className="text-[#0D1922]/40 text-s">{title.split(" ")[0]} Wing</p>
)}
</div>
{amentiesCount !== null && (
<>
<div className="flex 2xl:gap-[0.278vw] gap-1">
<p className="2xl:px-[0.556vw] 2xl:py-[0.278vw] px-2 py-0.5 bg-[#F3F3F2] 2xl:rounded-[0.278vw] rounded text-caption-s text-[#0D1922]/70">
{amentiesCount
? `${amentiesCount?.total} Amenties`
: `${
complexName === "marasi-drive"
? data[
title.split(" ")[0] === "East"
? "East"
: title.split(" ")[0] === "West"
? "West"
: "others"
].totalUnits
: data.others.totalUnits
} apartments`}
</p>
)}
</div>
<div className="flex 2xl:gap-[0.278vw] gap-1">
<p className="2xl:px-[0.556vw] 2xl:py-[0.278vw] px-2 py-0.5 bg-[#F3F3F2] 2xl:rounded-[0.278vw] rounded text-caption-s text-[#0D1922]/70">
{title && Number.isNaN(+title!.split(" ").at(-1)!)
? "16 Amen ties"
: `${
complexName === "marasi-drive"
? data[
title.split(" ")[0] === "East"
? "East"
: title.split(" ")[0] === "West"
? "West"
: "others"
].totalUnits
: data.others.totalUnits
} apartments`}
</p>
{!Number.isNaN(+title.split(" ").at(-1)!) && (
<div className="2xl:px-[0.556vw] 2xl:py-[0.278vw] px-2 py-0.5 bg-[#30B216]/8 2xl:rounded-[0.278vw] rounded flex 2xl:gap-[0.278vw] gap-1">
<span className="2xl:size-[0.833vw] size-3 text-[#30B216]">
<HumanIcon />
</span>
<p className="text-caption-s text-[#30B216]">Virtual Tour</p>
{!amentiesCount && (
<div className="2xl:px-[0.556vw] 2xl:py-[0.278vw] px-2 py-0.5 bg-[#30B216]/8 2xl:rounded-[0.278vw] rounded flex 2xl:gap-[0.278vw] gap-1">
<span className="2xl:size-[0.833vw] size-3 text-[#30B216]">
<HumanIcon />
</span>
<p className="text-caption-s text-[#30B216]">Virtual Tour</p>
</div>
)}
</div>
)}
</div>
<hr className="border-[#E2E2DC] 2xl:h-[0.069vw] h-px" />
<div className="2xl:space-y-[0.556vw] space-y-2">
{!Number.isNaN(+title.split(" ").at(-1)!) ? (
Object.entries(
data[
title.split(" ")[0] === "East"
? "East"
: title.split(" ")[0] === "West"
? "West"
: "others"
].types
).map(([unitType, count]) => (
<div className="flex 2xl:gap-[0.556vw] gap-2" key={unitType}>
<p className="bg-[#00BED7] rounded-full flex justify-center items-center font-mono text-caption-s text-white 2xl:w-[1.111vw] 2xl:h-[1.111vw] w-4 h-4">
{count}
</p>
<p className="text-caption-m text-[#0D1922]/70">
{formattedUnitTypes.get(unitType)}
</p>
</div>
))
) : (
<>
<div className="flex 2xl:gap-[0.556vw] gap-2">
<p className="bg-[#00BED7] rounded-full flex justify-center items-center font-mono text-caption-s text-white 2xl:w-[1.111vw] 2xl:h-[1.111vw] w-4 h-4">
8
</p>
<p className="text-caption-m text-[#0D1922]/70">
Indoor Amenties
</p >
</div>
<div className="flex 2xl:gap-[0.556vw] gap-2">
<p className="bg-[#00BED7] rounded-full flex justify-center items-center font-mono text-caption-s text-white 2xl:w-[1.111vw] 2xl:h-[1.111vw] w-4 h-4">
8
</p>
<p className="text-caption-m text-[#0D1922]/70">
Outdoor Amenties
</p>
</div>
</>
)}
</div>
<hr className="border-[#E2E2DC] 2xl:h-[0.069vw] h-px" />
<div className="2xl:space-y-[0.556vw] space-y-2">
{!amentiesCount ? (
Object.entries(
data[
title.split(" ")[0] === "East"
? "East"
: title.split(" ")[0] === "West"
? "West"
: "others"
].types
).map(([unitType, count]) => (
<div className="flex 2xl:gap-[0.556vw] gap-2" key={unitType}>
<p className="bg-[#00BED7] rounded-full flex justify-center items-center font-mono text-caption-s text-white 2xl:w-[1.111vw] 2xl:h-[1.111vw] w-4 h-4">
{count}
</p>
<p className="text-caption-m text-[#0D1922]/70">
{formattedUnitTypes.get(unitType)}
</p>
</div>
))
) : (
<>
{amentiesCount?.indoor && (
<div className="flex 2xl:gap-[0.556vw] gap-2">
<p className="bg-[#00BED7] rounded-full flex justify-center items-center font-mono text-caption-s text-white 2xl:w-[1.111vw] 2xl:h-[1.111vw] w-4 h-4">
{amentiesCount.indoor}
</p>
<p className="text-caption-m text-[#0D1922]/70">
Indoor Amenties
</p>
</div>
)}
{amentiesCount?.outdoor && (
<div className="flex 2xl:gap-[0.556vw] gap-2">
<p className="bg-[#00BED7] rounded-full flex justify-center items-center font-mono text-caption-s text-white 2xl:w-[1.111vw] 2xl:h-[1.111vw] w-4 h-4">
{amentiesCount.outdoor}
</p>
<p className="text-caption-m text-[#0D1922]/70">
Outdoor Amenties
</p>
</div>
)}
</>
)}
</div>
</>
)}
<Button
variant="cta"
size="small"
+3 -3
View File
@@ -73,7 +73,7 @@ function UnitCard({ unit }: { unit: Unit }) {
</span>
</Button>
</div>
<div className="2xl:rounded-[0.556vw] rounded-xl 2xl:p-[0.556vw] p-2 bg-[#F3F3F2] overflow-hidden mx-auto">
<div className="2xl:rounded-[0.556vw] rounded-xl 2xl:p-[0.556vw] p-2 overflow-hidden mx-auto">
<img
src={`/images/unit-types/${complexSlug}/${getUnitTypeSlug(
complexSlug,
@@ -91,14 +91,14 @@ function UnitCard({ unit }: { unit: Unit }) {
maximumFractionDigits: 2,
})} Sqft`}
</p>
{(
{
<p className="text-[#00BED7] text-h4 font-medium">
{`AED ${Intl.NumberFormat("ar-AE", {
currency: "AED",
minimumFractionDigits: 0,
}).format(unit.salesPrice)}`}
</p>
)}
}
</div>
</Link>
);
+1 -1
View File
@@ -21,7 +21,7 @@ function UnitTypeCard({ project, type }: { project: Project; type: UnitType }) {
<p className="text-caption-m text-[#0D1922]/70">{type.floors}</p>
</div>
</div>
<div className="2xl:p-[1.111vw] 2xl:rounded-[0.556vw] bg-[#F3F3F2]">
<div className="2xl:p-[1.111vw] 2xl:rounded-[0.556vw]">
<img
src={`/images/unit-types/${project.slug}/${type.slug}.jpg`}
alt=""
+29 -6
View File
@@ -13,12 +13,14 @@ function Select({
className = "",
label = "",
defaultOption = "",
maxOptionsCount,
}: {
options: string[];
onSelect: (option: string) => void;
defaultOption: string;
className?: string;
label?: string;
maxOptionsCount?: number;
}) {
const [isShow, setIsShow] = useState(false);
const [selectedOption, setSelectedOption] = useState(defaultOption);
@@ -32,18 +34,39 @@ function Select({
useEffect(() => onSelect(selectedOption), [selectedOption]);
function handleScroll() {
if (dropDownRef.current)
dropDownRef.current.style.maxHeight = `calc(100vh - ${
dropDownRef.current?.getBoundingClientRect().y
}px - 0.278vw)`;
if (!dropDownRef.current) return;
dropDownRef.current.style.maxHeight = `calc(100vh - ${
dropDownRef.current?.getBoundingClientRect().y
}px - 0.278vw)`;
}
function dropdownRefCallback(el: HTMLDivElement) {
if (!el) return;
dropDownRef.current = el;
if (!maxOptionsCount) return;
const optionHeight = el.clientHeight / options.length;
el.style.maxHeight = `${optionHeight * maxOptionsCount}px`;
const scrollOffset =
(options.findIndex((option) => option === selectedOption) -
Math.floor(maxOptionsCount / 2)) *
optionHeight;
el.scrollTo({ top: scrollOffset });
}
useEffect(() => {
if (maxOptionsCount) return;
handleScroll();
document.addEventListener("scroll", handleScroll);
return () => document.removeEventListener("scroll", handleScroll);
}, [isShow]);
}, [isShow, maxOptionsCount]);
return (
<div ref={ref} className={clsx("relative", className)}>
@@ -74,7 +97,7 @@ function Select({
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.15 }}
ref={dropDownRef}
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"
>
{options.map((option, index) => (