From 39de9d63834afe8652789d591e5da2fe8cb907ca Mon Sep 17 00:00:00 2001 From: John Doe Date: Tue, 12 Sep 2023 17:57:06 +0300 Subject: [PATCH] :sparkles: Add more filter options :sparkles: :bug: Fix bug in price range slider :bug: :art: Improve UI of more filter modal :art: :memo: Add documentation for new filter options :memo: --- src/app/(stay-listings)/TabFilters.tsx | 677 +++++++++++++++++++++++++ 1 file changed, 677 insertions(+) create mode 100644 src/app/(stay-listings)/TabFilters.tsx diff --git a/src/app/(stay-listings)/TabFilters.tsx b/src/app/(stay-listings)/TabFilters.tsx new file mode 100644 index 0000000..16f36d0 --- /dev/null +++ b/src/app/(stay-listings)/TabFilters.tsx @@ -0,0 +1,677 @@ +"use client"; + +import React, { Fragment, useState } from "react"; +import { Dialog, Popover, Transition } from "@headlessui/react"; +import NcInputNumber from "@/components/NcInputNumber"; +import ButtonPrimary from "@/shared/ButtonPrimary"; +import ButtonThird from "@/shared/ButtonThird"; +import ButtonClose from "@/shared/ButtonClose"; +import Checkbox from "@/shared/Checkbox"; +import Slider from "rc-slider"; +import convertNumbThousand from "@/utils/convertNumbThousand"; + +// DEMO DATA +const typeOfPaces = [ + { + name: "Entire place", + description: "Have a place to yourself", + }, + { + name: "Private room", + description: "Have your own room and share some common spaces", + }, + { + name: "Hotel room", + description: + "Have a private or shared room in a boutique hotel, hostel, and more", + }, + { + name: "Shared room", + description: "Stay in a shared space, like a common room", + }, +]; + +const moreFilter1 = [ + { name: "Kitchen", defaultChecked: true }, + { name: "Air conditioning", defaultChecked: true }, + { name: "Heating" }, + { name: "Dryer" }, + { name: "Washer" }, + { name: "Wifi" }, + { name: "Indoor fireplace" }, + { name: "Breakfast" }, + { name: "Hair dryer" }, + { name: " Dedicated workspace" }, +]; + +const moreFilter2 = [ + { name: " Free parking on premise" }, + { name: "Hot tub" }, + { name: "Gym" }, + { name: " Pool" }, + { name: " EV charger" }, +]; + +const moreFilter3 = [ + { name: " House" }, + { name: "Bed and breakfast" }, + { name: "Apartment", defaultChecked: true }, + { name: " Boutique hotel" }, + { name: " Bungalow" }, + { name: " Chalet", defaultChecked: true }, + { name: " Condominium", defaultChecked: true }, + { name: " Cottage" }, + { name: " Guest suite" }, + { name: " Guesthouse" }, +]; + +const moreFilter4 = [{ name: " Pets allowed" }, { name: "Smoking allowed" }]; + +const TabFilters = () => { + const [isOpenMoreFilter, setisOpenMoreFilter] = useState(false); + const [isOpenMoreFilterMobile, setisOpenMoreFilterMobile] = useState(false); + const [rangePrices, setRangePrices] = useState([0, 1000]); + + // + const closeModalMoreFilter = () => setisOpenMoreFilter(false); + const openModalMoreFilter = () => setisOpenMoreFilter(true); + // + const closeModalMoreFilterMobile = () => setisOpenMoreFilterMobile(false); + const openModalMoreFilterMobile = () => setisOpenMoreFilterMobile(true); + + const renderXClear = () => { + return ( + + + + + + ); + }; + + const renderTabsTypeOfPlace = () => { + return ( + + {({ open, close }) => ( + <> + + Type of place + + + + +
+
+ {typeOfPaces.map((item) => ( +
+ +
+ ))} +
+
+ + Clear + + + Apply + +
+
+
+
+ + )} +
+ ); + }; + + const renderTabsRoomAndBeds = () => { + return ( + + {({ open, close }) => ( + <> + + Rooms of Beds + + + + +
+
+ + + +
+
+ + Clear + + + Apply + +
+
+
+
+ + )} +
+ ); + }; + + const renderTabsPriceRage = () => { + return ( + + {({ open, close }) => ( + <> + + + {`$${convertNumbThousand( + rangePrices[0] + )} - $${convertNumbThousand(rangePrices[1])}`}{" "} + + {renderXClear()} + + + +
+
+
+ Price per day + setRangePrices(e as number[])} + /> +
+ +
+
+ +
+
+ + $ + +
+ +
+
+
+ +
+
+ + $ + +
+ +
+
+
+
+
+ + Clear + + + Apply + +
+
+
+
+ + )} +
+ ); + }; + + const renderMoreFilterItem = ( + data: { + name: string; + defaultChecked?: boolean; + }[] + ) => { + const list1 = data.filter((_, i) => i < data.length / 2); + const list2 = data.filter((_, i) => i >= data.length / 2); + return ( +
+
+ {list1.map((item) => ( + + ))} +
+
+ {list2.map((item) => ( + + ))} +
+
+ ); + }; + + const renderTabMoreFilter = () => { + return ( +
+
+ More filters (3) + {renderXClear()} +
+ + + +
+ + + + + {/* This element is to trick the browser into centering the modal contents. */} + + +
+
+ + More filters + + + + +
+ +
+
+
+

Amenities

+
+ {renderMoreFilterItem(moreFilter1)} +
+
+
+

Facilities

+
+ {renderMoreFilterItem(moreFilter2)} +
+
+
+

Property type

+
+ {renderMoreFilterItem(moreFilter3)} +
+
+
+

House rules

+
+ {renderMoreFilterItem(moreFilter4)} +
+
+
+
+ +
+ + Clear + + + Apply + +
+
+
+
+
+
+
+ ); + }; + + const renderTabMoreFilterMobile = () => { + return ( +
+
+ More filters (3) + {renderXClear()} +
+ + + +
+ + + + + {/* This element is to trick the browser into centering the modal contents. */} + + +
+
+ + More filters + + + + +
+ +
+
+ {/* ---- */} +
+

Type of place

+
+ {renderMoreFilterItem(typeOfPaces)} +
+
+ + {/* ---- */} +
+

Range Prices

+
+
+
+ setRangePrices(e as number[])} + /> +
+ +
+
+ +
+
+ + $ + +
+ +
+
+
+ +
+
+ + $ + +
+ +
+
+
+
+
+
+ + {/* ---- */} +
+

Rooms and beds

+
+ + + +
+
+ + {/* ---- */} +
+

Amenities

+
+ {renderMoreFilterItem(moreFilter1)} +
+
+ + {/* ---- */} +
+

Facilities

+
+ {renderMoreFilterItem(moreFilter2)} +
+
+ + {/* ---- */} +
+

Property type

+
+ {renderMoreFilterItem(moreFilter3)} +
+
+ + {/* ---- */} +
+

House rules

+
+ {renderMoreFilterItem(moreFilter4)} +
+
+
+
+ +
+ + Clear + + + Apply + +
+
+
+
+
+
+
+ ); + }; + + return ( +
+
+ {renderTabsTypeOfPlace()} + {renderTabsPriceRage()} + {renderTabsRoomAndBeds()} + {renderTabMoreFilter()} +
+ {renderTabMoreFilterMobile()} +
+ ); +}; + +export default TabFilters;