search page in process
This commit is contained in:
@@ -11,7 +11,7 @@ function FlatCard({
|
||||
salesPrice,
|
||||
}: IUnit) {
|
||||
return (
|
||||
<div className="2xl:p-[1.111vw] p-4 2xl:rounded-[1.111vw] rounded-2xl flex flex-col 2xl:gap-[1.111vw] gap-4 bg-white">
|
||||
<div className="2xl:p-[1.111vw] p-4 2xl:rounded-[1.111vw] rounded-2xl flex flex-col justify-between 2xl:gap-[1.111vw] gap-4 bg-white 2xl:aspect-[332/396] md:max-2xl:aspect-[352/396] aspect-[328/396]">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="2xl:space-y-[0.278vw] space-y-1">
|
||||
<p>{project}</p>
|
||||
|
||||
@@ -12,10 +12,10 @@ function Header() {
|
||||
}
|
||||
|
||||
return (
|
||||
<header className="sticky top-0 left-0 w-full h-16 md:max-2xl:h-18 2xl:h-[4.444vw] flex items-center justify-center bg-white outline outline-[#E2E2DC]">
|
||||
<header className="sticky top-0 left-0 z-1 w-full h-16 md:max-2xl:h-18 2xl:h-[4.444vw] flex items-center justify-center bg-white outline outline-[#E2E2DC]">
|
||||
<div className="flex 2xl:gap-[1.111vw] gap-4 flex-1">
|
||||
<div
|
||||
className="2xl:px-[1.667vw] 2xl:py-[1.111vw] md:max-2xl:p-4 max-md:px-4 max-md:py-5 cursor-pointer"
|
||||
className="2xl:px-[2.222vw] 2xl:py-[1.111vw] md:max-2xl:p-4 max-md:px-4 max-md:py-5 cursor-pointer"
|
||||
onClick={handleLogoClick}
|
||||
>
|
||||
<img
|
||||
@@ -84,7 +84,7 @@ function NavItem({ href, title }: { href: string; title: string }) {
|
||||
|
||||
function ProfileBar() {
|
||||
return (
|
||||
<Button className="!bg-[#F3F3F2] 2xl:mr-[1.667vw] mr-4" variant="secondary">
|
||||
<Button className="!bg-[#F3F3F2] 2xl:mr-[2.222vw] mr-4" variant="secondary">
|
||||
Login
|
||||
</Button>
|
||||
);
|
||||
|
||||
@@ -51,7 +51,7 @@ function ModalContainer() {
|
||||
>
|
||||
<div
|
||||
ref={popoverRef}
|
||||
className="fixed inset-0 flex flex-col items-center justify-center overflow-y-auto bg-black/70"
|
||||
className="z-1 bg-black/70 fixed inset-0 flex flex-col items-center justify-center overflow-y-auto"
|
||||
>
|
||||
<div className="max-h-full">
|
||||
<div ref={divRef} className="p-[1.08vw]">
|
||||
|
||||
@@ -9,6 +9,7 @@ import { useNavigate, useSearchParams } from "react-router";
|
||||
import UnitTypesFilter from "./UnitTypesFilter";
|
||||
import { projects } from "../data/projects";
|
||||
import { useDebounce } from "../hooks/useDebounce";
|
||||
import clsx from "clsx";
|
||||
|
||||
interface Filters {
|
||||
unitTypes: string[];
|
||||
@@ -23,7 +24,7 @@ function SearchFilters({
|
||||
ref,
|
||||
}: {
|
||||
inModal?: boolean;
|
||||
ref: RefObject<HTMLDivElement | null>;
|
||||
ref?: RefObject<HTMLDivElement | null>;
|
||||
}) {
|
||||
const [project, setProject] = useState<string>();
|
||||
const [unitTypes, setUnitTypes] = useState<string[]>([]);
|
||||
@@ -171,7 +172,10 @@ function SearchFilters({
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className="2xl:p-[2.222vw] md:max-2xl:p-6 p-4 2xl:-mx-[2.222vw] md:max-2xl:-mx-6 -mx-4 bg-white 2xl:rounded-b-[1.667vw] rounded-b-3xl 2xl:space-y-[2.222vw] md:max-2xl:space-y-8 space-y-4"
|
||||
className={clsx(
|
||||
"2xl:p-[2.222vw] md:max-2xl:p-6 p-4 2xl:-mx-[2.222vw] md:max-2xl:-mx-6 -mx-4 bg-white 2xl:rounded-b-[1.667vw] rounded-b-3xl 2xl:space-y-[2.222vw] md:max-2xl:space-y-8 space-y-4",
|
||||
inModal && "fixed top-[7.222vw] w-[calc(100vw-4.444vw)]"
|
||||
)}
|
||||
>
|
||||
<div className="2xl:space-y-[1.111vw] space-y-4">
|
||||
<p className="2xl:text-[2.222vw] md:max-2xl:text-[32px] text-2xl font-semibold leading-[135%]">
|
||||
@@ -204,7 +208,7 @@ function SearchFilters({
|
||||
max={filters?.cost[1]}
|
||||
currentMin={currentMinCost!}
|
||||
currentMax={currentMaxCost!}
|
||||
step={1}
|
||||
offset={1}
|
||||
onChangeMin={setCurrentMinCost}
|
||||
onChangeMax={setCurrentMaxCost}
|
||||
label="Cost, AED"
|
||||
@@ -214,7 +218,7 @@ function SearchFilters({
|
||||
max={filters?.floor[1]}
|
||||
currentMin={currentMinFloor!}
|
||||
currentMax={currentMaxFloor!}
|
||||
step={1}
|
||||
offset={1}
|
||||
onChangeMin={setCurrentMinFloor}
|
||||
onChangeMax={setCurrentMaxFloor}
|
||||
label="Floor"
|
||||
@@ -224,7 +228,7 @@ function SearchFilters({
|
||||
max={filters?.area[1]}
|
||||
currentMin={currentMinArea!}
|
||||
currentMax={currentMaxArea!}
|
||||
step={1}
|
||||
offset={1}
|
||||
onChangeMin={setCurrentMinArea}
|
||||
onChangeMax={setCurrentMaxArea}
|
||||
label="Total Area, Sqft"
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import SearchFilters from "../SearchFilters";
|
||||
|
||||
function UnitFiltersModal() {
|
||||
return <SearchFilters inModal />;
|
||||
}
|
||||
|
||||
export default UnitFiltersModal;
|
||||
@@ -13,7 +13,7 @@ interface IMultiRangeSlider {
|
||||
max: number;
|
||||
currentMin: number;
|
||||
currentMax: number;
|
||||
step: number;
|
||||
offset: number;
|
||||
disabled?: boolean;
|
||||
label: string;
|
||||
onChangeMin: (min: number) => void;
|
||||
@@ -27,7 +27,7 @@ function MultiRangeSlider({
|
||||
min,
|
||||
onChangeMin,
|
||||
onChangeMax,
|
||||
step,
|
||||
offset,
|
||||
label,
|
||||
disabled = false,
|
||||
}: IMultiRangeSlider) {
|
||||
@@ -41,11 +41,9 @@ function MultiRangeSlider({
|
||||
const percentage = (clientX - rect.x) / rect.width;
|
||||
const value = min + percentage * (max - min);
|
||||
|
||||
if (isMin) {
|
||||
return Math.max(Math.min(value, currentMax - step), min);
|
||||
}
|
||||
|
||||
return Math.min(Math.max(value, currentMin + step), max);
|
||||
return isMin
|
||||
? Math.max(Math.min(value, currentMax - offset), min)
|
||||
: Math.min(Math.max(value, currentMin + offset), max);
|
||||
}
|
||||
|
||||
function handleChange(
|
||||
@@ -57,11 +55,8 @@ function MultiRangeSlider({
|
||||
const value = calculateValue(clientX, current === "min");
|
||||
|
||||
if (value !== undefined) {
|
||||
if (current === "min") {
|
||||
onChangeMin(value);
|
||||
} else {
|
||||
onChangeMax(value);
|
||||
}
|
||||
if (current === "min") onChangeMin(value);
|
||||
else onChangeMax(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import { useNavigate, useSearchParams } from "react-router";
|
||||
import Button from "../components/ui/Button";
|
||||
import FiltersIcon from "../components/icons/FiltersIcon";
|
||||
import RestartIcon from "../components/icons/RestartIcon";
|
||||
import clsx from "clsx";
|
||||
|
||||
const STEP = 12;
|
||||
|
||||
@@ -44,6 +45,8 @@ function SearchPage() {
|
||||
const filtersRef = useRef<HTMLDivElement>(null);
|
||||
const observerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const [filtersInModal, setFiltersInModal] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasNextPage || isFetchingNextPage) return;
|
||||
const observerElement = observerRef.current;
|
||||
@@ -74,18 +77,38 @@ function SearchPage() {
|
||||
};
|
||||
}, []);
|
||||
|
||||
const [footerReached, setFooterReached] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const footer = document.querySelector("footer");
|
||||
const observer = new IntersectionObserver((entries) =>
|
||||
setFooterReached(entries[0].isIntersecting)
|
||||
);
|
||||
if (footer) observer.observe(footer);
|
||||
|
||||
return () => {
|
||||
if (footer) observer.unobserve(footer);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="2xl:pb-[2.222vw] md:max-2xl:pb-6 pb-4 relative">
|
||||
<SearchFilters ref={filtersRef} />
|
||||
<SearchFilters ref={filtersRef} inModal={filtersInModal} />
|
||||
<div className="2xl:grid-cols-4 md:max-2xl:grid-cols-2 grid 2xl:gap-[1.111vw] gap-4 2xl:pt-[1.111vw] pt-4">
|
||||
{data?.pages.flat().map((unit) => (
|
||||
<FlatCard key={unit.id} {...unit} />
|
||||
))}
|
||||
</div>
|
||||
<div ref={observerRef} />
|
||||
{showButtons && (
|
||||
<div className="fixed 2xl:bottom-[2.222vw] left-1/2 -translate-x-1/2 flex 2xl:gap-[0.278vw] gap-2">
|
||||
<Button>
|
||||
<div
|
||||
className={clsx(
|
||||
"fixed left-1/2 -translate-x-1/2 flex justify-center 2xl:gap-[0.278vw] gap-2 transition-all",
|
||||
footerReached && !hasNextPage
|
||||
? "top-[calc(100dvh-17.222vw)] translate-y-0"
|
||||
: "top-[calc(100dvh-2.222vw)] -translate-y-full"
|
||||
)}
|
||||
>
|
||||
<Button onClick={() => setFiltersInModal(true)}>
|
||||
<span className="2xl:w-[1.111vw] 2xl:h-[1.111vw] w-4 h-4 text-white">
|
||||
<FiltersIcon />
|
||||
</span>
|
||||
@@ -103,6 +126,7 @@ function SearchPage() {
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
<div ref={observerRef} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user