search page tablet version + filters modal

This commit is contained in:
2024-05-30 17:38:05 +05:00
parent 3586728262
commit def62d4215
14 changed files with 278 additions and 19 deletions
+3 -1
View File
@@ -35,7 +35,9 @@ const Checkbox = ({ onClick, checkbox }: CheckboxProps) => {
</div>
{!checkbox.disabled ? (
<div className="bg-[#00BED7] rounded-full text-white w-6 h-6 flex items-center justify-center font-semibold text-caption-s ">
<div className="h-fit align-middle text-center flex">8</div>
<div className="h-fit align-middle text-center flex items-center justify-center leading-1">
8
</div>
</div>
) : (
<div className="bg-[#E2E2DC] rounded-full text-white w-6 h-6 flex items-center justify-center font-semibold text-caption-s">
+1 -1
View File
@@ -68,7 +68,7 @@ const MultiRangeSlider = ({
}, [multirangeSlider.endValue]);
return (
<div className="px-2">
<div className="">
<div className="flex justify-between p-3 bg-white rounded-2xl relative flex-col">
<div className="flex justify-between">
<input
@@ -91,18 +91,21 @@ const ComplexTopPanel = () => {
buttonType="fab"
icon={<ActiveResizeIcon />}
onClick={handleOnFullScreenClick}
isCircleRounded
/>
) : (
<Button
buttonType="fab"
icon={<ResizeIcon />}
onClick={handleOnFullScreenClick}
isCircleRounded
/>
)}
<Button
buttonType="fab"
icon={<HintIcon />}
onClick={handleOnHelpClick}
isCircleRounded
/>
</div>
</div>
@@ -4,7 +4,7 @@ import Navbar from "../Navbar/Navbar";
import Location from "../Location";
const DesktopHeader = () => (
<header className="bg-white w-full text-white sm:grid grid-cols-6 fixed left-0 top-0 z-50 font-usual text-m">
<header className="bg-white w-full text-white sm:grid grid-cols-6 fixed left-0 top-0 z-[99999900] font-usual text-m">
<div className="flex gap-4 col-span-2">
<Logo />
<Location />
@@ -18,7 +18,7 @@ const MobileHeader = () => {
isToggled
? "rounded-ee-lg rounded-es-lg shadow-[#00000026] shadow-md"
: ""
} text-white flex flex-col text-sm items-center transition-all duration-500 ease-in-out absolute top-0 left-0 z-30 overflow-hidden font-usual ${
} text-white flex flex-col text-sm items-center transition-all duration-500 ease-in-out absolute top-0 left-0 z-[99999900] overflow-hidden font-usual ${
isToggled ? "max-h-[472px]" : "max-h-14"
}`}
>
-1
View File
@@ -26,7 +26,6 @@ const FilterIcon = () => {
rx="2.08333"
ry="2.08333"
fill="currentColor"
// fill="#0D1922"
/>
<path
d="M2.5 10H17.5"
+2 -1
View File
@@ -10,7 +10,7 @@ const HelpModal = () => {
const handleOnCloseClick = () => setModal(null);
return (
<div className="absolute z-50 top-0 left-0 w-screen bg-[#0D192266] h-screen backdrop-blur-[6px] grid grid-cols-12 items-center">
<div className="absolute z-[99999901] top-0 left-0 w-screen bg-[#0D192266] h-screen backdrop-blur-[6px] grid grid-cols-12 items-center">
<div className="h-full col-span-3 col-start-10 bg-[#F3F3F2] py-6 px-6 flex flex-col justify-between items-center">
<div className="flex flex-col gap-8">
<div className="flex justify-between pb-4 border-b border-[#E2E2DC]">
@@ -21,6 +21,7 @@ const HelpModal = () => {
icon={<CrossIcon />}
buttonType="fab"
onClick={handleOnCloseClick}
isCircleRounded
/>
</div>
<img
+1 -1
View File
@@ -65,7 +65,7 @@ const MasterplanFilters = () => {
};
return (
<div className="absolute z-50 top-0 left-0 w-screen bg-[#0D192266] h-screen backdrop-blur-[6px] items-center ">
<div className="absolute z-[99999901] top-0 left-0 w-screen bg-[#0D192266] h-screen backdrop-blur-[6px] items-center ">
<div className="h-full bg-[#F3F3F2] flex flex-col items-center justify-between w-[360px]">
<div className="w-full py-6 px-6 flex flex-col items-center">
<div className="flex justify-between border-b border-[#E2E2DC] w-full pb-4">
@@ -0,0 +1,51 @@
import {
SetStateAction,
createContext,
useEffect,
useState,
Dispatch,
} from "react";
interface MobileModalWrapperContext {
setIsAnimate: Dispatch<SetStateAction<boolean>> | null;
isAnimate: boolean | null;
}
export const MobileModalWrapperContext =
createContext<MobileModalWrapperContext>({
setIsAnimate: null,
isAnimate: null,
});
interface MobileModalWrapperProps {
children: React.ReactNode;
}
const MobileModalWrapper = ({ children }: MobileModalWrapperProps) => {
const [isAnimate, setIsAnimate] = useState(false);
useEffect(() => {
setIsAnimate(true);
}, []);
return (
<div
className={`h-screen w-screen pt-20 absolute z-[99999999] top-0 duration-300 ease-in-out ${
isAnimate ? "backdrop-blur-sm" : "backdrop-blur-none"
}`}
>
<div
className="h-full w-full transition-transform duration-300 ease-in-out"
style={{ transform: `translateY(${isAnimate ? 0 : 100}%)` }}
>
<MobileModalWrapperContext.Provider
value={{ isAnimate: isAnimate, setIsAnimate: setIsAnimate }}
>
{children}
</MobileModalWrapperContext.Provider>
</div>
</div>
);
};
export { MobileModalWrapper };
@@ -0,0 +1,182 @@
import { useContext } from "react";
import useModal from "../../../store/useModal";
import Button from "../../Button";
import CrossIcon from "../../icons/CrossIcon";
import { MobileModalWrapperContext } from "./MobileModalWrapper";
import {
initialApartmentTypeCheckboxes,
initialSliders,
initialSwitchers,
initialRoveHomeCheckboxes,
} from "../../consts/initialSearchFilters";
import useSearchFilters from "../../../store/useSearchFilters";
import Checkbox from "../../Checkbox";
import MultiRangeSlider from "../../MultiRangeSlider";
import Switch from "../../Switch";
import ResetIcon from "../../icons/ResetIcon";
const SearchFiltersModal = () => {
const { setModal } = useModal();
const { setIsAnimate } = useContext(MobileModalWrapperContext);
const {
multirangeSliders,
setMultirangeSliders,
switchers,
setSwitchers,
apartmentTypeCheckboxes,
setApartmentTypeCheckboxes,
roveHomeTypeCheckboxes,
setRoveHomeTypeCheckboxes,
} = useSearchFilters();
const handleOnCrossClick = () => {
if (setIsAnimate) {
setIsAnimate(false);
const timeout = setTimeout(() => {
setModal(null);
clearTimeout(timeout);
}, 300);
}
};
const handleOnCheckboxApartmentClick = (checkboxId: string) => {
const updatedCheckboxes = apartmentTypeCheckboxes.map((cbox) => {
if (checkboxId !== cbox.id) return cbox;
const isSelected = !cbox.selected;
return { ...cbox, selected: isSelected };
});
setApartmentTypeCheckboxes(updatedCheckboxes);
};
const handleOnCheckboxRoveHomeClick = (checkboxId: string) => {
const updatedCheckboxes = roveHomeTypeCheckboxes.map((cbox) => {
if (checkboxId !== cbox.id) return cbox;
const isSelected = !cbox.selected;
return { ...cbox, selected: isSelected };
});
setRoveHomeTypeCheckboxes(updatedCheckboxes);
};
const handleOnSwitcherClick = (switcherId: string) => {
const updatedSwitchers = switchers.map((switcher) => {
if (switcherId !== switcher.id) return switcher;
const { isSwitched } = switcher;
return { ...switcher, isSwitched: !isSwitched };
});
setSwitchers(updatedSwitchers);
};
const handleOnSliderValueChange = (
sliderId: string,
e: [a: number, b: number]
) => {
const updatedSliders = multirangeSliders.map((slider) => {
if (sliderId !== slider.id) return slider;
return { ...slider, startValue: e[0], endValue: e[1] };
});
setMultirangeSliders(updatedSliders);
};
const handleOnShowApartmentClick = () => {
if (setIsAnimate) {
setIsAnimate(false);
const timeout = setTimeout(() => {
setModal(null);
clearTimeout(timeout);
}, 300);
}
};
return (
<div className="bg-[#F3F3F2] rounded-ss-lg rounded-se-lg h-full p-6 flex flex-col gap-6">
<div className="flex justify-between pb-6 border-b">
<h2 className="text-[#0D1922] text-subheadline-m font-semibold">
Filters
</h2>
<Button
buttonType="secondary"
isCircleRounded
icon={<CrossIcon />}
className="text-[#0D1922B2]"
onClick={handleOnCrossClick}
/>
</div>
<div className="flex flex-col w-full">
<p className="text-[#0D1922] text-m font-semibold pb-4">Rove Home</p>
<div className="grid grid-cols-2 gap-2">
{roveHomeTypeCheckboxes.map((checkbox) => (
<Checkbox
checkbox={checkbox}
key={checkbox.id}
onClick={handleOnCheckboxRoveHomeClick}
/>
))}
</div>
</div>
<div className="flex flex-col w-full">
<p className="text-[#0D1922] text-m font-semibold pb-4">
Apartment type
</p>
<div className="grid grid-cols-2 gap-2">
{apartmentTypeCheckboxes.map((checkbox) => (
<Checkbox
checkbox={checkbox}
key={checkbox.id}
onClick={handleOnCheckboxApartmentClick}
/>
))}
</div>
</div>
<div className="grid grid-cols-2 gap-6 border-b pb-12">
{multirangeSliders.map((slider) => (
<div className="flex flex-col gap-3">
<div className="flex justify-between items-center">
<p className="text-[#0D1922] text-m font-semibold ">
{slider.title}
</p>
<p className="text-[#73787C] text-m font-semibold">
{slider.unit}
</p>
</div>
<MultiRangeSlider
onChange={handleOnSliderValueChange}
multirangeSlider={slider}
/>
</div>
))}
<div className="flex flex-col gap-2 pt-6">
{switchers.map((switcher) => (
<div key={switcher.id} className="flex justify-between w-full">
<p className="text-s text-[#73787C]">{switcher.title}</p>
<Switch switcher={switcher} onClick={handleOnSwitcherClick} />
</div>
))}
</div>
</div>
<div className="flex justify-between">
<p className="text-[#00BED7] text-m">195 apartments found</p>
<Button
icon={<ResetIcon />}
text="Reset filters"
buttonType="tertiary"
/>
</div>
<Button
text="Show Apartments"
buttonType="cta"
className="flex justify-center"
onClick={handleOnShowApartmentClick}
/>
</div>
);
};
export default SearchFiltersModal;
+30 -6
View File
@@ -5,10 +5,16 @@ import useSearchFilters from "../../store/useSearchFilters";
import { initialSortList, layoutsCards } from "../../consts/initialSearchPage";
import SearchIcon from "../icons/SearchIcon";
import { sortCardBy } from "../../calc/sortCard";
import Button from "../Button";
import FilterIcon from "../icons/FilterIcon";
import useModal from "../../store/useModal";
import { MobileModalWrapper } from "../modals/mobile/MobileModalWrapper";
import SearchFiltersModal from "../modals/mobile/SearchFiltersModal";
const LayoutOptions = () => {
const [sortList, setSortList] = useState(initialSortList);
const [cards, setCards] = useState(layoutsCards);
const { setModal } = useModal();
const { roveHomeTypeCheckboxes, apartmentTypeCheckboxes, multirangeSliders } =
useSearchFilters();
@@ -20,6 +26,14 @@ const LayoutOptions = () => {
setSortList(updatedSortList);
};
const handleOnFilterClick = () => {
setModal(
<MobileModalWrapper>
<SearchFiltersModal />
</MobileModalWrapper>
);
};
useEffect(() => {
const sortedCards = sortCardBy(sortList, layoutsCards);
@@ -32,14 +46,24 @@ const LayoutOptions = () => {
]);
return (
<section className="w-full p-6 flex flex-col">
<div className="flex justify-between w-full items-center border-b pb-4">
<div className="flex gap-4 font-semibold text-subheadline-s leading-7 py-[6px]">
<h2 className="text-[#0D1922]">Layout options</h2>
<p className="text-[#73787C]">145</p>
<div className="flex justify-between items-center border-b">
<div className="flex w-full justify-between pb-4 lg:flex-row lg:items-center flex-col">
<div className="flex gap-4 font-semibold text-subheadline-s leading-7 py-[6px]">
<h2 className="text-[#0D1922]">Units</h2>
<p className="text-[#73787C]">145</p>
</div>
<SortButton sortList={sortList} onClick={handleOnSortClick} />
</div>
<div className="lg:hidden block">
<Button
icon={<FilterIcon />}
text="Filters"
className="text-[#0D1922B2]"
onClick={handleOnFilterClick}
/>
</div>
<SortButton sortList={sortList} onClick={handleOnSortClick} />
</div>
<div className="grid 2xl:grid-cols-4 xl:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-4 pt-6">
<div className="grid 2xl:grid-cols-4 xl:grid-cols-3 grid-cols-2 gap-4 pt-6">
{cards.map((layoutsCard) => (
<LayoutCard layoutCard={layoutsCard} />
))}
+1 -1
View File
@@ -78,7 +78,7 @@ const SidebarFilters = () => {
return (
<div>
<div className="h-full w-[360px] bg-[#F3F3F2] flex flex-col items-center justify-between border-r">
<div className="h-full w-[360px] bg-[#F3F3F2] flex-col items-center justify-between border-r lg:flex hidden">
<div className="w-full py-6 px-6 flex flex-col items-center">
<div className="flex justify-between border-b border-[#E2E2DC] w-full pb-4">
<h2 className="text-subheadline-m font-semibold">Filters</h2>
@@ -22,7 +22,7 @@ const VirtualTourSidebar = ({ currentAppartment }: VirtualTourSidebarProps) => {
};
return (
<div className="absolute w-screen h-screen grid z-[99999999] pointer-events-none">
<div className="absolute w-screen h-screen grid z-[99999999] pointer-events-none select-none">
<div className="h-screen py-[130px] px-3 w-[360px]">
<div className="bg-white w-full rounded-lg p-5 flex flex-col relative rounded-ee-none">
<div className="flex flex-col gap-1 pb-[18px] border-b">
@@ -41,11 +41,8 @@ const VirtualTourTopPanel = () => {
return (
<>
<div className="absolute top-0 w-screen z-[99999999] select-none pointer-events-none">
<img src="../images/top_shadow.png" className="w-screen" alt="" />
</div>
<div
className={`absolute top-[62px] left-0 z-[99999999] w-full p-4 grid grid-cols-12 select-none touch-none pointer-events-none`}
className={`absolute top-[62px] left-0 z-[99999998] w-full p-4 grid grid-cols-12 select-none touch-none pointer-events-none`}
>
<div className="flex gap-2 col-span-5">
<Button