Untitled
unknown
jsx
a year ago
9.5 kB
3
Indexable
Never
import React from "react"; import styles from "./filter.module.scss"; // import stores from "../../../data/stores/stores.json"; import { useState } from "react"; import Link from "next/link"; import Container from "@/components/atoms/Container"; import { useEffect } from "react"; import Select from "react-select"; import { Swiper, SwiperSlide } from "swiper/react"; import { Navigation } from "swiper"; import "swiper/css"; import "swiper/css/navigation"; import useMediaQuery from "../../../hooks/useMediaQuery"; import parse from "html-react-parser"; const Filter = ({ data }) => { // console.log("data", data); const alphabet = "#ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""); alphabet.unshift("ALL"); const alphabetWithoutAll = alphabet.slice(1); const [filteredChar, setFilteredChar] = useState("ALL"); const [filterByCategory, setFilterByCategory] = useState("All categories"); const [isClickAndCollect, setIsClickAndCollect] = useState(false); // const [results, setResults] = useState( // data?.stores.sort((a, b) => a.title.localeCompare(b.title)) // ); const [results, setResults] = useState(data?.stores); const [sortedResults, setSortedResults] = useState(sortResults(results)); const [usedLetters, setUsedLetters] = useState([]); const isDesktop = useMediaQuery("(min-width: 1024px)"); // console.log("stores", data.stores); const colourStyles = { indicatorSeparator: (styles) => ({ ...styles, display: "none", }), placeholder: (styles) => ({ ...styles, textTransform: "uppercase", fontSize: "12px", "@media only screen and (min-width: 960px)": { ...styles["@media only screen and (min-width: 960px)"], fontSize: "12px", }, "@media only screen and (min-width: 1366px)": { ...styles["@media only screen and (min-width: 1366px)"], fontSize: "14px", }, "@media only screen and (min-width: 1920px)": { ...styles["@media only screen and (min-width: 1920px)"], fontSize: "18px", }, }), indicatorSeparator: (styles) => ({ ...styles, display: "none", }), valueContainer: (styles) => ({ ...styles, padding: "0", }), dropdownIndicator: (styles) => ({ ...styles, color: "black", padding: 0, }), control: (styles) => ({ ...styles, background: "white", outline: "none", cursor: "pointer", border: "none", borderBottom: "0.5px solid #B9B9B9 !important", borderRadius: 0, boxShadow: "none", }), option: (styles) => { return { ...styles, background: "white", color: "black", cursor: "pointer", "&:hover": { backgroundColor: "black", color: "white", }, }; }, }; function sortResults(array) { const result = []; array.forEach((store) => { if (!result[store.title.charAt(0)]) { result[store.title.charAt(0)] = []; } result[store.title.charAt(0)].push(store); }); return result; } useEffect(() => { setUsedLetters(Object.keys(sortResults(results))); }, [results, data.stores]); let filteredCategories = []; data.stores .map((store) => { return { label: store.categories.map((x) => x.name) }; }) .forEach((x) => (filteredCategories = filteredCategories.concat(x.label))); let uniqueCategories = [...new Set(filteredCategories)].map((x) => { return { label: parse(x) }; }); // Sort categories alphabetically uniqueCategories.sort((a, b) => a.label.localeCompare(b.label)); // Push "All categories" to the first index in array uniqueCategories.splice(0, 0, { label: "All categories" }); const returnUniqueCategoryNames = (array) => { return array.map((x) => { return parse(x.name); }); }; useEffect(() => { setResults( data.stores.filter((store) => { if ( filterByCategory !== "All categories" && !returnUniqueCategoryNames(store.categories).includes( filterByCategory ) ) { return false; } if (isClickAndCollect && !store.clickAndCollect) { return false; } return store; }) ); }, [filterByCategory, isClickAndCollect, data.stores]); useEffect(() => { setSortedResults(sortResults(results)); }, [results]); useEffect(() => { if (!usedLetters.includes(filteredChar || filteredChar.toLowerCase())) { setFilteredChar(alphabet[0]); } }, [usedLetters]); const selectCategory = (selectedOption) => { setFilterByCategory(selectedOption.label); }; return ( <div className={styles.component}> <div className={styles.component_intro}> <div className={styles.component_categories}> {/* Category select */} <Select name="categories" id="categories-filter" styles={colourStyles} options={uniqueCategories} onChange={selectCategory} placeholder={"Sort by category"} /> </div> {/* Click and collect filter */} <div className={styles.clickAndCollect}> <input type="checkbox" id="clickAndCollect" onClick={() => setIsClickAndCollect(!isClickAndCollect)} /> <label htmlFor="clickAndCollect" className={styles.clickAndCollect_label} > Filter Click & collect </label> </div> </div> {/* Letter list */} <Container type="content" className={styles.letter_list_wrap}> {!isDesktop ? ( <Swiper modules={[Navigation]} slidesPerView={"auto"} draggable scrollbar={{ draggable: true, dragSize: 24 }} className={`swiper-nav-slider ${styles.letter_list}`} > {alphabet.map((letter, index) => ( <SwiperSlide key={index}> <button className={ letter === filteredChar ? styles.letter_list_item_active : styles.letter_list_item } onClick={() => setFilteredChar(letter)} disabled={ !usedLetters.includes(letter || letter.toLowerCase()) && letter !== "ALL" } > {letter} </button> </SwiperSlide> ))} </Swiper> ) : ( <> <div className={styles.letter_list}> {alphabet.map((letter, index) => ( <button className={ letter === filteredChar ? styles.letter_list_item_active : styles.letter_list_item } onClick={() => setFilteredChar(letter)} disabled={ !usedLetters.includes(letter || letter.toLowerCase()) && letter !== "ALL" } key={index} > <span>{letter}</span> </button> ))} </div> </> )} </Container> {/* Results table */} <Container type="content" className={styles.results}> {filteredChar === "ALL" ? ( alphabetWithoutAll .filter((letter) => Object.keys(sortedResults).includes(letter)) .map((letter, index) => ( <div key={index}> <span className={styles.results_letter}>{letter}</span> <div className={styles.results_item} key={index}> <div className={styles.result}> <ul> {sortedResults[letter]?.map((result, index) => ( <li className={styles.result_item} key={index}> <Link href={`stores/${result.slug}`} passHref> {result.title} </Link> </li> ))} </ul> </div> </div> </div> )) ) : ( <div className={styles.results_item}> <div className={styles.result}> <span className={styles.results_letter}>{filteredChar}</span> <ul> {!sortedResults[filteredChar] ? ( <div className={styles.noResults}> <p>No stores found with current selection</p> </div> ) : ( sortedResults[filteredChar]?.map((result, index) => ( <li key={index}> <Link href={`stores/${result.slug}`} passHref> {result?.title} </Link> </li> )) )} </ul> </div> </div> )} </Container> </div> ); }; export default Filter;