search page
This commit is contained in:
+2
-1
@@ -10,6 +10,7 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/react-router-dom": "^5.3.3",
|
||||
"gsap": "^3.12.5",
|
||||
"react": "^18.2.0",
|
||||
"react-device-detect": "^2.2.3",
|
||||
@@ -17,7 +18,7 @@
|
||||
"react-full-screen": "^1.1.1",
|
||||
"react-image-marker": "^1.2.0",
|
||||
"react-range-slider-input": "^3.0.7",
|
||||
"react-router-dom": "^6.22.3",
|
||||
"react-router-dom": "^6.23.1",
|
||||
"react-swipeable": "^7.0.1",
|
||||
"react-transition-group": "^4.4.5",
|
||||
"react-zoom-pan-pinch": "^3.4.4",
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
@@ -0,0 +1,24 @@
|
||||
import { ILayoutCard } from "../types/layoutCard";
|
||||
import { ISort } from "../types/sortType";
|
||||
|
||||
const sortCardBy = (sortTypeList: ISort[], layoutsCards: ILayoutCard[]) => {
|
||||
const sortType = sortTypeList.find((sort) => sort.isSelected);
|
||||
const sortedList = [...layoutsCards].sort((cardA, cardB) => {
|
||||
switch (sortType?.title) {
|
||||
case "Ascending price":
|
||||
return cardA.cost - cardB.cost;
|
||||
case "Decreasing price":
|
||||
return cardB.cost - cardA.cost;
|
||||
case "Ascending Squares":
|
||||
return cardA.square - cardB.square;
|
||||
case "Ascending Floor":
|
||||
return 1;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
|
||||
return sortedList;
|
||||
};
|
||||
|
||||
export { sortCardBy };
|
||||
@@ -12,7 +12,9 @@ const Checkbox = ({ onClick, checkbox }: CheckboxProps) => {
|
||||
<div
|
||||
onClick={() => onClick(checkbox.id)}
|
||||
className={`flex justify-between bg-white p-3 rounded-2xl transition-[background] duration-300 ease-in-out select-none ${
|
||||
checkbox.disabled ? "" : "hover:bg-[#F3F3F2] cursor-pointer"
|
||||
checkbox.disabled
|
||||
? "pointer-events-none touch-none"
|
||||
: "hover:bg-[#F3F3F2] cursor-pointer"
|
||||
}`}
|
||||
>
|
||||
<div className="flex gap-3">
|
||||
|
||||
@@ -7,7 +7,6 @@ interface ISwitchProps {
|
||||
|
||||
const Switch = ({ switcher, onClick }: ISwitchProps) => {
|
||||
function handleOnClick() {
|
||||
// setIsSwitched((prev) => !prev);
|
||||
onClick(switcher.id);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
interface HeartIconProps {
|
||||
isFilled?: boolean;
|
||||
}
|
||||
|
||||
const HeartIcon = ({ isFilled = false }: HeartIconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={` stroke-[#0D1922] transition-all ${
|
||||
isFilled ? "fill-[#0D1922]" : "fill-none"
|
||||
}`}
|
||||
>
|
||||
<path
|
||||
d="M15.6832 5.96475C14.3718 4.67809 12.2455 4.67809 10.9341 5.96475L10.0002 6.88098L9.06627 5.96475C7.75482 4.67809 5.62854 4.67809 4.31708 5.96475C3.00563 7.2514 3.00563 9.33748 4.31709 10.6241L10.0002 16.6664L15.6832 10.6241C16.9947 9.33748 16.9947 7.2514 15.6832 5.96475Z"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default HeartIcon;
|
||||
@@ -1,21 +1,21 @@
|
||||
const SearchPlusIcon = () => {
|
||||
const SearchIcon = () => {
|
||||
return (
|
||||
<svg
|
||||
width="49"
|
||||
height="48"
|
||||
viewBox="0 0 49 48"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M41.5 41L33.8137 33.3137M33.8137 33.3137C36.7091 30.4183 38.5 26.4183 38.5 22C38.5 13.1634 31.3366 6 22.5 6C13.6634 6 6.5 13.1634 6.5 22C6.5 30.8366 13.6634 38 22.5 38C26.9141 38 30.9108 36.2125 33.8056 33.3219L33.8137 33.3137ZM16.5 22H28.5M22.5 16V28"
|
||||
d="M15.8332 15.8334L12.973 12.9785M12.973 12.9785C13.9084 12.0445 14.487 10.7533 14.487 9.327C14.487 6.47707 12.1767 4.16675 9.32676 4.16675C6.47683 4.16675 4.1665 6.47707 4.1665 9.327C4.1665 12.1769 6.47683 14.4873 9.32676 14.4873C10.7504 14.4873 12.0394 13.9108 12.973 12.9785Z"
|
||||
stroke="currentColor"
|
||||
strokeWidth="3"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default SearchPlusIcon;
|
||||
export default SearchIcon;
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
const SearchPlusIcon = () => {
|
||||
return (
|
||||
<svg
|
||||
width="49"
|
||||
height="48"
|
||||
viewBox="0 0 49 48"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M41.5 41L33.8137 33.3137M33.8137 33.3137C36.7091 30.4183 38.5 26.4183 38.5 22C38.5 13.1634 31.3366 6 22.5 6C13.6634 6 6.5 13.1634 6.5 22C6.5 30.8366 13.6634 38 22.5 38C26.9141 38 30.9108 36.2125 33.8056 33.3219L33.8137 33.3137ZM16.5 22H28.5M22.5 16V28"
|
||||
stroke="currentColor"
|
||||
strokeWidth="3"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default SearchPlusIcon;
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import SearchPlusIcon from "../icons/SearchIcon";
|
||||
import SearchPlusIcon from "../icons/SearchPlusIcon";
|
||||
import OpenFullscreenIcon from "../icons/OpenFullscreenIcon";
|
||||
import LineIcon from "../icons/LineIcon";
|
||||
import useModal from "../../store/useModal";
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { ILayoutCard } from "../../types/layoutCard";
|
||||
|
||||
interface LayoutCardProps {
|
||||
@@ -14,10 +15,19 @@ const LayoutCard = ({ layoutCard }: LayoutCardProps) => {
|
||||
units,
|
||||
square,
|
||||
cost,
|
||||
id,
|
||||
} = layoutCard;
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleOnClick = () => {
|
||||
navigate(`${id}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="bg-white flex flex-col p-4 rounded-lg gap-4">
|
||||
<div
|
||||
className="bg-white flex flex-col p-4 rounded-lg gap-4 cursor-pointer select-none"
|
||||
onClick={handleOnClick}
|
||||
>
|
||||
<div className="flex gap-4 justify-between">
|
||||
<div className="flex gap-1 flex-col">
|
||||
<p className="text-[#00BED7] text-s leading-5">
|
||||
@@ -35,7 +45,9 @@ const LayoutCard = ({ layoutCard }: LayoutCardProps) => {
|
||||
{units} units
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-full bg-slate-500 aspect-square rounded-lg"></div>
|
||||
<div className="w-full aspect-square rounded-lg">
|
||||
<img src="/images/layout-1.png" alt="" className="h-full" />
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<p className="text[#0D1922] text-s">
|
||||
{apartmentType}, {square} Sqft
|
||||
|
||||
@@ -1,169 +1,17 @@
|
||||
import { useState } from "react";
|
||||
import { ILayoutCard } from "../../types/layoutCard";
|
||||
import { ISort } from "../../types/sortType";
|
||||
import { useEffect, useState } from "react";
|
||||
import LayoutCard from "./LayoutCard";
|
||||
import SortButton from "./SortButton";
|
||||
|
||||
const layoutsCards: ILayoutCard[] = [
|
||||
{
|
||||
id: "1",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "Studio Flex",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 10488888,
|
||||
square: 609,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "1 Bedroom",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 1668888,
|
||||
square: 609,
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "1 Bedroom",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 1668888,
|
||||
square: 609,
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "1 Bedroom",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 1138888,
|
||||
square: 609,
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "Studio Flex",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 10488888,
|
||||
square: 609,
|
||||
},
|
||||
{
|
||||
id: "6",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "1 Bedroom",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 1668888,
|
||||
square: 609,
|
||||
},
|
||||
{
|
||||
id: "7",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "1 Bedroom",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 1668888,
|
||||
square: 609,
|
||||
},
|
||||
{
|
||||
id: "8",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "1 Bedroom",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 1138888,
|
||||
square: 609,
|
||||
},
|
||||
{
|
||||
id: "9",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "Studio Flex",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 10488888,
|
||||
square: 609,
|
||||
},
|
||||
{
|
||||
id: "10",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "1 Bedroom",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 1668888,
|
||||
square: 609,
|
||||
},
|
||||
{
|
||||
id: "11",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "1 Bedroom",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 1668888,
|
||||
square: 609,
|
||||
},
|
||||
{
|
||||
id: "12",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "1 Bedroom",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 1138888,
|
||||
square: 609,
|
||||
},
|
||||
];
|
||||
|
||||
const initialSortList: ISort[] = [
|
||||
{
|
||||
id: "1",
|
||||
title: "Ascending price",
|
||||
isSelected: true,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "Decreasing price",
|
||||
isSelected: false,
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
title: "Ascending Squares",
|
||||
isSelected: false,
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
title: "Ascending Floor",
|
||||
isSelected: false,
|
||||
},
|
||||
];
|
||||
import useSearchFilters from "../../store/useSearchFilters";
|
||||
import { initialSortList, layoutsCards } from "../../consts/initialSearchPage";
|
||||
import SearchIcon from "../icons/SearchIcon";
|
||||
import { sortCardBy } from "../../calc/sortCard";
|
||||
|
||||
const LayoutOptions = () => {
|
||||
const [sortList, setSortList] = useState(initialSortList);
|
||||
const [cards, setCards] = useState(layoutsCards);
|
||||
const { roveHomeTypeCheckboxes, apartmentTypeCheckboxes, multirangeSliders } =
|
||||
useSearchFilters();
|
||||
|
||||
const handleOnSortClick = (sortId: string) => {
|
||||
const updatedSortList = sortList.map((sort) => {
|
||||
const isSelected = sort.id === sortId;
|
||||
@@ -171,20 +19,34 @@ const LayoutOptions = () => {
|
||||
});
|
||||
setSortList(updatedSortList);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const sortedCards = sortCardBy(sortList, layoutsCards);
|
||||
|
||||
setCards(sortedCards);
|
||||
}, [
|
||||
sortList,
|
||||
roveHomeTypeCheckboxes,
|
||||
apartmentTypeCheckboxes,
|
||||
multirangeSliders,
|
||||
]);
|
||||
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">
|
||||
<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>
|
||||
<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">
|
||||
{layoutsCards.map((layoutsCard) => (
|
||||
{cards.map((layoutsCard) => (
|
||||
<LayoutCard layoutCard={layoutsCard} />
|
||||
))}
|
||||
</div>
|
||||
<div className="bg-white rounded-lg mt-4 py-[10px] flex justify-center select-none cursor-pointer items-center gap-2">
|
||||
<SearchIcon /> Show 12 more apartments
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,28 +1,27 @@
|
||||
import { useState } from "react";
|
||||
import Button from "../Button";
|
||||
import ResetIcon from "../icons/ResetIcon";
|
||||
import Checkbox from "../Checkbox";
|
||||
import Switch from "../Switch";
|
||||
import MultiRangeSlider from "../MultiRangeSlider";
|
||||
import { ICheckbox } from "../../types/checkbox";
|
||||
import { IMultirangeSlider } from "../../types/multirangeSlider";
|
||||
import { ISwitcher } from "../../types/switcher";
|
||||
import {
|
||||
initialApartmentTypeCheckboxes,
|
||||
initialSliders,
|
||||
initialSwitchers,
|
||||
initialRoveHomeCheckboxes,
|
||||
} from "../../consts/initialSearchFilters";
|
||||
import useSearchFilters from "../../store/useSearchFilters";
|
||||
|
||||
const SidebarFilters = () => {
|
||||
const [apartmentTypeCheckboxes, setApartmentTypeCheckboxes] = useState<
|
||||
ICheckbox[]
|
||||
>(initialApartmentTypeCheckboxes);
|
||||
const [roveHomeCheckboxes, setRoveHomeCheckboxes] = useState<ICheckbox[]>(
|
||||
initialRoveHomeCheckboxes
|
||||
);
|
||||
const [sliders, setSliders] = useState<IMultirangeSlider[]>(initialSliders);
|
||||
const [switchers, setSwitchers] = useState<ISwitcher[]>(initialSwitchers);
|
||||
const {
|
||||
multirangeSliders,
|
||||
setMultirangeSliders,
|
||||
switchers,
|
||||
setSwitchers,
|
||||
apartmentTypeCheckboxes,
|
||||
setApartmentTypeCheckboxes,
|
||||
roveHomeTypeCheckboxes,
|
||||
setRoveHomeTypeCheckboxes,
|
||||
} = useSearchFilters();
|
||||
|
||||
const handleOnCheckboxApartmentClick = (checkboxId: string) => {
|
||||
const updatedCheckboxes = apartmentTypeCheckboxes.map((cbox) => {
|
||||
@@ -36,27 +35,27 @@ const SidebarFilters = () => {
|
||||
};
|
||||
|
||||
const handleOnCheckboxRoveHomeClick = (checkboxId: string) => {
|
||||
const updatedCheckboxes = roveHomeCheckboxes.map((cbox) => {
|
||||
const updatedCheckboxes = roveHomeTypeCheckboxes.map((cbox) => {
|
||||
if (checkboxId !== cbox.id) return cbox;
|
||||
const isSelected = !cbox.selected;
|
||||
|
||||
return { ...cbox, selected: isSelected };
|
||||
});
|
||||
|
||||
setRoveHomeCheckboxes(updatedCheckboxes);
|
||||
setRoveHomeTypeCheckboxes(updatedCheckboxes);
|
||||
};
|
||||
|
||||
const handleOnSliderValueChange = (
|
||||
sliderId: string,
|
||||
e: [a: number, b: number]
|
||||
) => {
|
||||
const updatedSliders = sliders.map((slider) => {
|
||||
const updatedSliders = multirangeSliders.map((slider) => {
|
||||
if (sliderId !== slider.id) return slider;
|
||||
|
||||
return { ...slider, startValue: e[0], endValue: e[1] };
|
||||
});
|
||||
|
||||
setSliders(updatedSliders);
|
||||
setMultirangeSliders(updatedSliders);
|
||||
};
|
||||
|
||||
const handleOnSwitcherClick = (switcherId: string) => {
|
||||
@@ -72,8 +71,8 @@ const SidebarFilters = () => {
|
||||
|
||||
const handleOnResetClick = () => {
|
||||
setApartmentTypeCheckboxes(initialApartmentTypeCheckboxes);
|
||||
setRoveHomeCheckboxes(initialRoveHomeCheckboxes);
|
||||
setSliders(initialSliders);
|
||||
setRoveHomeTypeCheckboxes(initialRoveHomeCheckboxes);
|
||||
setMultirangeSliders(initialSliders);
|
||||
setSwitchers(initialSwitchers);
|
||||
};
|
||||
|
||||
@@ -94,7 +93,7 @@ const SidebarFilters = () => {
|
||||
Rove Home
|
||||
</p>
|
||||
<div className="flex flex-col gap-2">
|
||||
{roveHomeCheckboxes.map((checkbox) => (
|
||||
{roveHomeTypeCheckboxes.map((checkbox) => (
|
||||
<Checkbox
|
||||
checkbox={checkbox}
|
||||
key={checkbox.id}
|
||||
@@ -118,7 +117,7 @@ const SidebarFilters = () => {
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col pt-6 w-full gap-8">
|
||||
{sliders.map((slider) => (
|
||||
{multirangeSliders.map((slider) => (
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="flex justify-between items-center">
|
||||
<p className="text-[#0D1922] text-m font-semibold ">
|
||||
|
||||
@@ -21,7 +21,10 @@ const SortButton = ({ sortList, onClick }: SortButtonProps) => {
|
||||
className="text-[#00BED7] text-m leading-5 flex gap-2"
|
||||
onClick={handleOnClick}
|
||||
>
|
||||
Sort by ascending price{" "}
|
||||
Sort by{" "}
|
||||
<div className="w-[17ch]">
|
||||
{sortList.find((sort) => sort.isSelected)?.title.toLocaleLowerCase()}{" "}
|
||||
</div>
|
||||
<div
|
||||
className={`transition-all duration-300 ease-in-out ${
|
||||
isSelected ? "rotate-180" : "rotate-0"
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import Button from "../Button";
|
||||
import HeartIcon from "../icons/Heart";
|
||||
|
||||
const ApartmentCard = () => {
|
||||
return (
|
||||
<div className="bg-white flex flex-col p-4 rounded-lg gap-4 cursor-pointer select-none">
|
||||
<div className="flex gap-4 justify-between">
|
||||
<div className="flex gap-1 flex-col">
|
||||
<p className="text-[#00BED7] text-s leading-5">
|
||||
Rove Home Marasi Drive
|
||||
</p>
|
||||
<div className="text-[#73787C] flex gap-2 items-center w-fit">
|
||||
<p className="text-caption-m font-semibold leading-4">East Wing</p>
|
||||
<div className="w-1 h-1 bg-[#E2E2DC] rounded-full"></div>
|
||||
<p className="text-caption-m font-semibold leading-4">Floor 11</p>
|
||||
<div className="w-1 h-1 bg-[#E2E2DC] rounded-full"></div>
|
||||
<p className="text-caption-m font-semibold leading-4">№ 213</p>
|
||||
</div>
|
||||
</div>
|
||||
<Button icon={<HeartIcon isFilled={false} />} buttonType="favorite" />
|
||||
</div>
|
||||
<div className="w-full aspect-square rounded-lg">
|
||||
<img src="/images/layout-1.png" alt="" className="h-full" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ApartmentCard;
|
||||
@@ -0,0 +1,52 @@
|
||||
import Button from "../Button";
|
||||
import LeftArrowSliderIcon from "../icons/LeftArrowSliderIcon";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
const ApartmentSidebar = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleOnBackClick = () => {
|
||||
navigate(-1);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="h-full w-[360px] bg-[#F3F3F2] flex flex-col items-center justify-between border-r">
|
||||
<div className="w-full py-6 px-6 flex flex-col items-start">
|
||||
<div className="flex justify-between border-b border-[#E2E2DC] w-full pb-4 gap-4 items-center">
|
||||
<Button
|
||||
icon={<LeftArrowSliderIcon />}
|
||||
buttonType="cta"
|
||||
onClick={handleOnBackClick}
|
||||
/>
|
||||
<h2 className="text-subheadline-s font-semibold text-[#0D1922]">
|
||||
1 bedroom apartment
|
||||
</h2>
|
||||
</div>
|
||||
<div className="flex gap-1 flex-col pt-6">
|
||||
<p className="text-[#00BED7] text-m leading-5">
|
||||
Rove Home Marasi Drive
|
||||
</p>
|
||||
<div className="text-[#73787C] flex gap-2 items-center w-fit pt-1">
|
||||
<p className="text-caption-m font-semibold leading-4">
|
||||
East Wing
|
||||
</p>
|
||||
<div className="w-1 h-1 bg-[#E2E2DC] rounded-full"></div>
|
||||
<p className="text-caption-m font-semibold leading-4">
|
||||
Floor 11-35
|
||||
</p>
|
||||
</div>
|
||||
<p className="text-[#00BED7] text-subheadline-s font-bold pt-4">
|
||||
AED 1668888
|
||||
</p>
|
||||
</div>
|
||||
<div className="w-full aspect-square mt-4 border-b pb-4">
|
||||
<img src="/images/layout-1.png" alt="" className="h-full" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ApartmentSidebar;
|
||||
@@ -0,0 +1,54 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { initialSortList, layoutsCards } from "../../consts/initialSearchPage";
|
||||
import useSearchFilters from "../../store/useSearchFilters";
|
||||
import SearchIcon from "../icons/SearchIcon";
|
||||
import SortButton from "../searchPage/SortButton";
|
||||
import { sortCardBy } from "../../calc/sortCard";
|
||||
import ApartmentCard from "./ApartmentCard";
|
||||
|
||||
const Units = () => {
|
||||
const [sortList, setSortList] = useState(initialSortList);
|
||||
const [cards, setCards] = useState(layoutsCards);
|
||||
const { roveHomeTypeCheckboxes, apartmentTypeCheckboxes, multirangeSliders } =
|
||||
useSearchFilters();
|
||||
|
||||
const handleOnSortClick = (sortId: string) => {
|
||||
const updatedSortList = sortList.map((sort) => {
|
||||
const isSelected = sort.id === sortId;
|
||||
return { ...sort, isSelected: isSelected };
|
||||
});
|
||||
setSortList(updatedSortList);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const sortedCards = sortCardBy(sortList, layoutsCards);
|
||||
|
||||
setCards(sortedCards);
|
||||
}, [
|
||||
sortList,
|
||||
roveHomeTypeCheckboxes,
|
||||
apartmentTypeCheckboxes,
|
||||
multirangeSliders,
|
||||
]);
|
||||
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]">Units</h2>
|
||||
<p className="text-[#73787C]">145</p>
|
||||
</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">
|
||||
{cards.map(() => (
|
||||
<ApartmentCard />
|
||||
))}
|
||||
</div>
|
||||
<div className="bg-white rounded-lg mt-4 py-[10px] flex justify-center select-none cursor-pointer items-center gap-2">
|
||||
<SearchIcon /> Show 12 more apartments
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default Units;
|
||||
@@ -6,6 +6,7 @@ const backgroundColors: ButtonStyle = {
|
||||
secondary: "bg-[#ffffff] hover:bg-[#F3F3F2] active:bg-[#fff]",
|
||||
tertiary: "bg-[#0D192266] hover:bg-[#0D1922B2]",
|
||||
fab: "bg-[#ffffff] hover:bg-[#F3F3F2]",
|
||||
favorite: "bg-[#FFFFFF] hover:bg-[#F3F3F2]",
|
||||
};
|
||||
|
||||
const textColors: ButtonStyle = {
|
||||
@@ -14,6 +15,7 @@ const textColors: ButtonStyle = {
|
||||
secondary: "text-[#0D1922]",
|
||||
tertiary: "text-[#ffffff]",
|
||||
fab: "text-[#0D1922]",
|
||||
favorite: "text-[#F3F3F2]",
|
||||
};
|
||||
|
||||
const borders: ButtonStyle = {
|
||||
@@ -22,6 +24,7 @@ const borders: ButtonStyle = {
|
||||
secondary: "rounded-lg border border-[#E2E2DC] active:border-[#00BED7]",
|
||||
tertiary: "rounded-full",
|
||||
fab: "rounded-full",
|
||||
favorite: "rounded-lg border border-[#E2E2DC]",
|
||||
};
|
||||
|
||||
const paddings: ButtonStyle = {
|
||||
@@ -30,6 +33,7 @@ const paddings: ButtonStyle = {
|
||||
secondary: "py-3 px-6",
|
||||
tertiary: "py-1 px-3",
|
||||
fab: "py-3 px-6",
|
||||
favorite: "p-[10px]",
|
||||
};
|
||||
|
||||
export { textColors, backgroundColors, borders, paddings };
|
||||
|
||||
@@ -32,7 +32,7 @@ const initialSliders: IMultirangeSlider[] = [
|
||||
];
|
||||
|
||||
const initialApartmentTypeCheckboxes: ICheckbox[] = [
|
||||
{ title: "Studio Flex", id: "1", disabled: true, selected: false },
|
||||
{ title: "Studio Flex", id: "1", selected: false },
|
||||
{ title: "Studio", id: "2", selected: false },
|
||||
{ title: "1 Bedroom", id: "3", selected: false },
|
||||
{ title: "2 Bedroom", id: "4", selected: false },
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
import { ILayoutCard } from "../types/layoutCard";
|
||||
import { ISort } from "../types/sortType";
|
||||
|
||||
const layoutsCards: ILayoutCard[] = [
|
||||
{
|
||||
id: "1",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "Studio Flex",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 10488888,
|
||||
square: 619,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "1 Bedroom",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 1668888,
|
||||
square: 619,
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "1 Bedroom",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 1668888,
|
||||
square: 609,
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "1 Bedroom",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 1138888,
|
||||
square: 609,
|
||||
},
|
||||
{
|
||||
id: "5",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "Studio Flex",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 10488888,
|
||||
square: 609,
|
||||
},
|
||||
{
|
||||
id: "6",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "1 Bedroom",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 1668888,
|
||||
square: 609,
|
||||
},
|
||||
{
|
||||
id: "7",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "1 Bedroom",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 1668888,
|
||||
square: 609,
|
||||
},
|
||||
{
|
||||
id: "8",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "1 Bedroom",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 1138888,
|
||||
square: 609,
|
||||
},
|
||||
{
|
||||
id: "9",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "Studio Flex",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 10488888,
|
||||
square: 609,
|
||||
},
|
||||
{
|
||||
id: "10",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "1 Bedroom",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 1668888,
|
||||
square: 609,
|
||||
},
|
||||
{
|
||||
id: "11",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "1 Bedroom",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 1668888,
|
||||
square: 609,
|
||||
},
|
||||
{
|
||||
id: "12",
|
||||
roveHome: "Marasi Drive",
|
||||
apartmentType: "1 Bedroom",
|
||||
wing: "East Wing",
|
||||
floorStart: 11,
|
||||
floorEnd: 35,
|
||||
units: 234,
|
||||
cost: 1138888,
|
||||
square: 609,
|
||||
},
|
||||
];
|
||||
|
||||
const initialSortList: ISort[] = [
|
||||
{
|
||||
id: "1",
|
||||
title: "Ascending price",
|
||||
isSelected: true,
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
title: "Decreasing price",
|
||||
isSelected: false,
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
title: "Ascending Squares",
|
||||
isSelected: false,
|
||||
},
|
||||
{
|
||||
id: "4",
|
||||
title: "Ascending Floor",
|
||||
isSelected: false,
|
||||
},
|
||||
];
|
||||
|
||||
export { initialSortList, layoutsCards };
|
||||
@@ -7,6 +7,8 @@ import "./index.css";
|
||||
import Complex from "./pages/Complex";
|
||||
import ComplexWing from "./pages/ComplexWing";
|
||||
import Search from "./pages/Search";
|
||||
import SearchParticularApartments from "./pages/SearchParticularApartments";
|
||||
import SearchApartment from "./pages/SearchApartment";
|
||||
|
||||
const router = createBrowserRouter([
|
||||
{
|
||||
@@ -37,6 +39,14 @@ const router = createBrowserRouter([
|
||||
path: "/search",
|
||||
element: <Search />,
|
||||
},
|
||||
{
|
||||
path: "/search/:apartmentType",
|
||||
element: <SearchParticularApartments />,
|
||||
},
|
||||
{
|
||||
path: "/search/:apartmentType/:apartmentId",
|
||||
element: <SearchApartment />,
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import { useState } from "react";
|
||||
import Button from "../components/Button";
|
||||
import Footer from "../components/Footer";
|
||||
import SwitchToggle from "../components/SwitchToggle";
|
||||
import HeartIcon from "../components/icons/Heart";
|
||||
import LeftArrowSliderIcon from "../components/icons/LeftArrowSliderIcon";
|
||||
import { ISwitchLabel } from "../types/switchLabel";
|
||||
|
||||
const apartmentLayouts: ISwitchLabel[] = [
|
||||
{ id: "1", label: "Layout" },
|
||||
{ id: "2", label: "On the floor" },
|
||||
];
|
||||
|
||||
const SearchApartment = () => {
|
||||
const [currentLabel, setCurrentLabel] = useState(apartmentLayouts[0]);
|
||||
const handleOnSwitchClick = (label: ISwitchLabel) => {
|
||||
setCurrentLabel(label);
|
||||
};
|
||||
return (
|
||||
<div className="overflow-scroll h-screen w-screen pt-14">
|
||||
<div className="grid grid-cols-4 border px-4 pt-6 pb-4 gap-4">
|
||||
<div className="flex flex-col col-span-3">
|
||||
<div className="flex justify-between w-full gap-4 items-center pb-3">
|
||||
<div className="flex gap-4 items-center ">
|
||||
<Button icon={<LeftArrowSliderIcon />} buttonType="cta" />
|
||||
<div className="flex flex-col">
|
||||
<p className="text-[#73787C] text-caption-m font-semibold">
|
||||
№ 213
|
||||
</p>
|
||||
<h2 className="text-subheadline-s font-semibold text-[#0D1922]">
|
||||
1 bedroom apartment
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<Button buttonType="favorite" icon={<HeartIcon />} />
|
||||
</div>
|
||||
<div className="p-10 pt-6 rounded-lg bg-white flex flex-col items-center gap-8">
|
||||
<SwitchToggle
|
||||
labels={apartmentLayouts}
|
||||
currentLabel={currentLabel}
|
||||
onClick={handleOnSwitchClick}
|
||||
/>
|
||||
<div className="w-full px-[304px] ">
|
||||
<img className="w-full" src="/images/layout-1.png" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-span-1 bg-white rounded-lg"></div>
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SearchApartment;
|
||||
@@ -0,0 +1,17 @@
|
||||
import Footer from "../components/Footer";
|
||||
import ApartmentSidebar from "../components/searchParticularApartmentsPage/ApartmentSidebar";
|
||||
import Units from "../components/searchParticularApartmentsPage/Units";
|
||||
|
||||
const SearchParticularApartments = () => {
|
||||
return (
|
||||
<div className="overflow-scroll h-screen w-screen pt-14">
|
||||
<div className="flex">
|
||||
<ApartmentSidebar />
|
||||
<Units />
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SearchParticularApartments;
|
||||
@@ -0,0 +1,37 @@
|
||||
import { create } from "zustand";
|
||||
import { ICheckbox } from "../types/checkbox";
|
||||
import {
|
||||
initialApartmentTypeCheckboxes,
|
||||
initialRoveHomeCheckboxes,
|
||||
initialSliders,
|
||||
initialSwitchers,
|
||||
} from "../consts/initialSearchFilters";
|
||||
import { IMultirangeSlider } from "../types/multirangeSlider";
|
||||
import { ISwitcher } from "../types/switcher";
|
||||
|
||||
interface Store {
|
||||
apartmentTypeCheckboxes: ICheckbox[];
|
||||
setApartmentTypeCheckboxes: (typeCheckboxes: ICheckbox[]) => void;
|
||||
roveHomeTypeCheckboxes: ICheckbox[];
|
||||
setRoveHomeTypeCheckboxes: (typeCheckboxes: ICheckbox[]) => void;
|
||||
multirangeSliders: IMultirangeSlider[];
|
||||
setMultirangeSliders: (multirangeSliders: IMultirangeSlider[]) => void;
|
||||
switchers: ISwitcher[];
|
||||
setSwitchers: (switchers: ISwitcher[]) => void;
|
||||
}
|
||||
|
||||
const useSearchFilters = create<Store>((set) => ({
|
||||
apartmentTypeCheckboxes: initialApartmentTypeCheckboxes,
|
||||
setApartmentTypeCheckboxes: (typeCheckboxes) =>
|
||||
set(() => ({ apartmentTypeCheckboxes: typeCheckboxes })),
|
||||
roveHomeTypeCheckboxes: initialRoveHomeCheckboxes,
|
||||
setRoveHomeTypeCheckboxes: (typeCheckboxes) =>
|
||||
set(() => ({ roveHomeTypeCheckboxes: typeCheckboxes })),
|
||||
multirangeSliders: initialSliders,
|
||||
setMultirangeSliders: (multirangeSliders) =>
|
||||
set(() => ({ multirangeSliders: multirangeSliders })),
|
||||
switchers: initialSwitchers,
|
||||
setSwitchers: (switchers) => set(() => ({ switchers: switchers })),
|
||||
}));
|
||||
|
||||
export default useSearchFilters;
|
||||
@@ -0,0 +1,14 @@
|
||||
import { RoveHome } from "./layoutCard";
|
||||
|
||||
interface IApartmentCard {
|
||||
id: string;
|
||||
roveHome: RoveHome;
|
||||
wing: string;
|
||||
floor: number;
|
||||
cost: number;
|
||||
square: number;
|
||||
number: number;
|
||||
imgSrc?: string;
|
||||
}
|
||||
|
||||
export type { IApartmentCard };
|
||||
+7
-1
@@ -1,4 +1,10 @@
|
||||
type ButtonType = "primary" | "tertiary" | "cta" | "fab" | "secondary";
|
||||
type ButtonType =
|
||||
| "primary"
|
||||
| "tertiary"
|
||||
| "cta"
|
||||
| "fab"
|
||||
| "secondary"
|
||||
| "favorite";
|
||||
type ButtonStyle = {
|
||||
[key in ButtonType]: string;
|
||||
};
|
||||
|
||||
@@ -14,4 +14,4 @@ interface ILayoutCard {
|
||||
imgSrc?: string;
|
||||
}
|
||||
|
||||
export type { ILayoutCard };
|
||||
export type { ILayoutCard, ApartmentType, RoveHome };
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||
"lib": ["ESNext.Array", "DOM", "ESNext", "DOM.Iterable", "ES2020"],
|
||||
"module": "ESNext",
|
||||
"skipLibCheck": true,
|
||||
|
||||
|
||||
@@ -462,10 +462,10 @@
|
||||
resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz"
|
||||
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
|
||||
|
||||
"@remix-run/router@1.15.3":
|
||||
version "1.15.3"
|
||||
resolved "https://registry.npmjs.org/@remix-run/router/-/router-1.15.3.tgz"
|
||||
integrity sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w==
|
||||
"@remix-run/router@1.16.1":
|
||||
version "1.16.1"
|
||||
resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.16.1.tgz#73db3c48b975eeb06d0006481bde4f5f2d17d1cd"
|
||||
integrity sha512-es2g3dq6Nb07iFxGk5GuHN20RwBZOsuDQN7izWIisUcv9r+d2C5jQxqmgkdebXgReWfiyUabcki6Fg77mSNrig==
|
||||
|
||||
"@rollup/rollup-android-arm-eabi@4.14.3":
|
||||
version "4.14.3"
|
||||
@@ -585,6 +585,11 @@
|
||||
resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz"
|
||||
integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==
|
||||
|
||||
"@types/history@^4.7.11":
|
||||
version "4.7.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64"
|
||||
integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==
|
||||
|
||||
"@types/json-schema@^7.0.15":
|
||||
version "7.0.15"
|
||||
resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz"
|
||||
@@ -602,6 +607,23 @@
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-router-dom@^5.3.3":
|
||||
version "5.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.3.3.tgz#e9d6b4a66fcdbd651a5f106c2656a30088cc1e83"
|
||||
integrity sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==
|
||||
dependencies:
|
||||
"@types/history" "^4.7.11"
|
||||
"@types/react" "*"
|
||||
"@types/react-router" "*"
|
||||
|
||||
"@types/react-router@*":
|
||||
version "5.1.20"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.20.tgz#88eccaa122a82405ef3efbcaaa5dcdd9f021387c"
|
||||
integrity sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==
|
||||
dependencies:
|
||||
"@types/history" "^4.7.11"
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-transition-group@^4.4.10":
|
||||
version "4.4.10"
|
||||
resolved "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz"
|
||||
@@ -1865,20 +1887,20 @@ react-refresh@^0.14.0:
|
||||
resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz"
|
||||
integrity sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==
|
||||
|
||||
react-router-dom@^6.22.3:
|
||||
version "6.22.3"
|
||||
resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.22.3.tgz"
|
||||
integrity sha512-7ZILI7HjcE+p31oQvwbokjk6OA/bnFxrhJ19n82Ex9Ph8fNAq+Hm/7KchpMGlTgWhUxRHMMCut+vEtNpWpowKw==
|
||||
react-router-dom@^6.23.1:
|
||||
version "6.23.1"
|
||||
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.23.1.tgz#30cbf266669693e9492aa4fc0dde2541ab02322f"
|
||||
integrity sha512-utP+K+aSTtEdbWpC+4gxhdlPFwuEfDKq8ZrPFU65bbRJY+l706qjR7yaidBpo3MSeA/fzwbXWbKBI6ftOnP3OQ==
|
||||
dependencies:
|
||||
"@remix-run/router" "1.15.3"
|
||||
react-router "6.22.3"
|
||||
"@remix-run/router" "1.16.1"
|
||||
react-router "6.23.1"
|
||||
|
||||
react-router@6.22.3:
|
||||
version "6.22.3"
|
||||
resolved "https://registry.npmjs.org/react-router/-/react-router-6.22.3.tgz"
|
||||
integrity sha512-dr2eb3Mj5zK2YISHK++foM9w4eBnO23eKnZEDs7c880P6oKbrjz/Svg9+nxqtHQK+oMW4OtjZca0RqPglXxguQ==
|
||||
react-router@6.23.1:
|
||||
version "6.23.1"
|
||||
resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.23.1.tgz#d08cbdbd9d6aedc13eea6e94bc6d9b29cb1c4be9"
|
||||
integrity sha512-fzcOaRF69uvqbbM7OhvQyBTFDVrrGlsFdS3AL+1KfIBtGETibHzi3FkoTRyiDJnWNc2VxrfvR+657ROHjaNjqQ==
|
||||
dependencies:
|
||||
"@remix-run/router" "1.15.3"
|
||||
"@remix-run/router" "1.16.1"
|
||||
|
||||
react-swipeable@^7.0.1:
|
||||
version "7.0.1"
|
||||
|
||||
Reference in New Issue
Block a user