Untitled

mail@pastecode.io avatar
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;