diff --git a/src/app/(flight-listings)/TabFilters.tsx b/src/app/(flight-listings)/TabFilters.tsx new file mode 100644 index 0000000..3496c85 --- /dev/null +++ b/src/app/(flight-listings)/TabFilters.tsx @@ -0,0 +1,858 @@ +"use client"; + +import React, { Fragment, useState } from "react"; +import { Dialog, Popover, Tab, Transition } from "@headlessui/react"; +import ButtonPrimary from "@/shared/ButtonPrimary"; +import ButtonThird from "@/shared/ButtonThird"; +import ButtonClose from "@/shared/ButtonClose"; +import Checkbox from "@/shared/Checkbox"; +import convertNumbThousand from "@/utils/convertNumbThousand"; +import Slider from "rc-slider"; +import { XMarkIcon } from "@heroicons/react/24/outline"; + +// DEMO DATA +const typeOfAirlines = [ + { + name: "Star Alliance", + }, + { + name: "Air China", + }, + { + name: "Air India", + }, + { + name: "Air New Zealand", + }, + { + name: "Asiana", + }, + { + name: "Bangkok Airways", + }, +]; +const stopPoints = [ + { + name: "Nonstop", + }, + { + name: "Up to 1 stops", + }, + { + name: "Up to 2 stops", + }, + { + name: "Any number of stops", + }, +]; + +// +const TabFilters = () => { + const [isOpenMoreFilter, setisOpenMoreFilter] = useState(false); + // + const [isOnSale, setIsOnSale] = useState(true); + const [rangePrices, setRangePrices] = useState([100, 5000]); + const [tripTimes, setTripTimes] = useState(10); + const [stopPontsStates, setStopPontsStates] = useState([]); + const [airlinesStates, setAirlinesStates] = useState([]); + + // + let [catTimes, setCatTimes] = useState({ + "Take Off": { + Departure: [0, 24], + Arrival: [0, 24], + }, + Landing: { + Departure: [0, 24], + Arrival: [0, 24], + }, + }); + + // + const closeModalMoreFilter = () => setisOpenMoreFilter(false); + const openModalMoreFilter = () => setisOpenMoreFilter(true); + + // + const handleChangeStopPoint = (checked: boolean, name: string) => { + checked + ? setStopPontsStates([...stopPontsStates, name]) + : setStopPontsStates(stopPontsStates.filter((i) => i !== name)); + }; + + const handleChangeAirlines = (checked: boolean, name: string) => { + checked + ? setAirlinesStates([...airlinesStates, name]) + : setAirlinesStates(airlinesStates.filter((i) => i !== name)); + }; + + // + + const renderXClear = () => { + return ( + + + + ); + }; + + const renderTabsTimeFlightTab = () => { + return ( +
+ + + {Object.keys(catTimes).map((category) => ( + + `w-full py-2.5 text-sm leading-5 font-medium text-primary-700 dark:text-primary-400 rounded-lg focus:outline-none focus:ring-2 ring-offset-2 ring-offset-blue-400 ring-white ring-opacity-60 ${ + selected + ? "bg-white dark:bg-neutral-800 shadow" + : " hover:bg-white/[0.15] dark:hover:bg-neutral-800" + }` + } + > + {category} + + ))} + + + {Object.values(catTimes).map((posts, idx) => { + return ( + + + {idx ? " Tokyo to Singapore" : " Singapore to Tokyo"} + +
+
+
+ + Departure time: + + {posts.Departure[0]}:00 - {posts.Departure[1]} + :00 + +
+ + setCatTimes((catTimes) => + !idx + ? { + ...catTimes, + "Take Off": { + ...posts, + Departure: val as [number, number], + }, + } + : { + ...catTimes, + Landing: { + ...posts, + Departure: val as [number, number], + }, + } + ) + } + allowCross={false} + /> +
+
+
+ + Arrival time: + + {posts.Arrival[0]}:00 - {posts.Arrival[1]}:00 + +
+ + setCatTimes((catTimes) => + !idx + ? { + ...catTimes, + "Take Off": { + ...posts, + Arrival: val as [number, number], + }, + } + : { + ...catTimes, + Landing: { + ...posts, + Arrival: val as [number, number], + }, + } + ) + } + allowCross={false} + /> +
+
+ ); + })} +
+
+
+ ); + }; + + const renderTabsTypeOfAirlines = () => { + return ( + + {({ open, close }) => ( + <> + + Airlines + {!airlinesStates.length ? ( + + ) : ( + setAirlinesStates([])}> + {renderXClear()} + + )} + + + +
+
+ + handleChangeAirlines(checked, "All Airlines") + } + /> +
+ {typeOfAirlines.map((item) => ( +
+ + handleChangeAirlines(checked, item.name) + } + /> +
+ ))} +
+
+ { + close(); + setAirlinesStates([]); + }} + sizeClass="px-4 py-2 sm:px-5" + > + Clear + + + Apply + +
+
+
+
+ + )} +
+ ); + }; + + const renderTabsStopPoints = () => { + return ( + + {({ open, close }) => ( + <> + + Stop points + {!stopPontsStates.length ? ( + + ) : ( + setStopPontsStates([])}> + {renderXClear()} + + )} + + + +
+
+ {stopPoints.map((item) => ( +
+ + handleChangeStopPoint(checked, item.name) + } + /> +
+ ))} +
+
+ { + close(); + setStopPontsStates([]); + }} + sizeClass="px-4 py-2 sm:px-5" + > + Clear + + + Apply + +
+
+
+
+ + )} +
+ ); + }; + + const renderTabsTimeFlight = () => { + return ( + + {({ open, close }) => ( + <> + + Flight time + + + + +
+
+ {renderTabsTimeFlightTab()} +
+
+ + Clear + + + Apply + +
+
+
+
+ + )} +
+ ); + }; + + const renderTabsTripTime = () => { + return ( + + {({ open, close }) => ( + <> + + less than {tripTimes} hours + {renderXClear()} + + + +
+
+
+
+ Trip time: + {` <${tripTimes} hours`} +
+ + setTripTimes(e as number)} + /> +
+
+
+ + Clear + + + Apply + +
+
+
+
+ + )} +
+ ); + }; + + const renderTabsPriceRage = () => { + return ( + + {({ open, close }) => ( + <> + + + {`$${convertNumbThousand( + rangePrices[0] + )} - $${convertNumbThousand(rangePrices[1])}`}{" "} + + {renderXClear()} + + + +
+
+
+ Price per person + setRangePrices(e as number[])} + /> +
+ +
+
+ +
+
+ + $ + +
+ +
+
+
+ +
+
+ + $ + +
+ +
+
+
+
+
+ + Clear + + + Apply + +
+
+
+
+ + )} +
+ ); + }; + + const renderTabOnSale = () => { + return ( +
setIsOnSale(!isOnSale)} + > + On sale + {isOnSale && renderXClear()} +
+ ); + }; + + const renderMoreFilterItem = ( + data: { + name: string; + description?: 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) => ( + + ))} +
+
+ ); + }; + + // FOR RESPONSIVE MOBILE + const renderTabMobileFilter = () => { + return ( +
+
+ + Flights filters (3) + + {renderXClear()} +
+ + + +
+ + + + + {/* This element is to trick the browser into centering the modal contents. */} + + +
+
+ + Flight filters + + + + +
+ +
+
+ {/* --------- */} + {/* ---- */} +
+

Airlines

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

Stop points

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

Range Prices

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

+ Strip times + {` <${tripTimes} hours`} +

+
+ setTripTimes(e as number)} + /> +
+
+ + {/* --------- */} + {/* ---- */} +
+

Flight times

+
+ {renderTabsTimeFlightTab()} +
+
+
+
+ +
+ + Clear + + + Apply + +
+
+
+
+
+
+
+ ); + }; + + return ( +
+ {/* FOR DESKTOP */} +
+ {renderTabsTypeOfAirlines()} + {renderTabsTripTime()} + {renderTabsStopPoints()} + {renderTabsPriceRage()} + {renderTabsTimeFlight()} + {renderTabOnSale()} +
+ + {/* FOR RESPONSIVE MOBILE */} +
+ {renderTabMobileFilter()} + {renderTabOnSale()} +
+
+ ); +}; + +export default TabFilters;