Rest95

[...query].js

Dec 9th, 2021
820
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import {
  2.   getStaticPathsCategories,
  3.   getStaticPropsCategories,
  4.   getQuery,
  5. } from "../../lib/CategoriesQuery";
  6. import { useDisclosure } from "@chakra-ui/hooks";
  7. import { Box, SimpleGrid, Stack, Text, Skeleton } from "@chakra-ui/react";
  8. import React, { useEffect, useState } from "react";
  9. import { FiltersModal, ProductCard, ShopHeader } from "../../components";
  10. import { useFilters } from "../../hooks/useFilters";
  11. import useTranslation from "next-translate/useTranslation";
  12. import { Spinner } from "@chakra-ui/spinner";
  13. import { Button } from "@chakra-ui/button";
  14. import { useRouter } from "next/router";
  15. import { Progress } from "@chakra-ui/react";
  16.  
  17. export const getStaticPaths = async ({ locales }) => {
  18.   return await getStaticPathsCategories(locales);
  19. };
  20.  
  21. export const getStaticProps = async (context) => {
  22.   return await getStaticPropsCategories(context);
  23. };
  24.  
  25. const defaultFiltersObj = {
  26.   order: [
  27.     {
  28.       value: "choices",
  29.       query: "&order_by=our_choices",
  30.     },
  31.   ],
  32.   attributes: [],
  33. };
  34.  
  35. const CategoriesList = ({ category, products, attributes }) => {
  36.   const { t } = useTranslation("common");
  37.   const [productsList, setProductsList] = useState([]);
  38.   const [totalProducts, setTotalProducts] = useState(null);
  39.   const [actualSlug, setActualSlug] = useState(null);
  40.   const [actualPage, setActualPage] = useState(1);
  41.   const [currentPage, setCurrentPage] = useState(1);
  42.   const [pageUp, setPageUp] = useState(1);
  43.   const [activeFilters, setActiveFilters] = useState({ ...defaultFiltersObj });
  44.   const [filters, setFilters] = useState({ ...defaultFiltersObj });
  45.   const { isOpen, onOpen, onClose } = useDisclosure();
  46.   const [loading, setLoading] = useState(false);
  47.   const [loadingFromFilters, setLoadingFromFilters] = useState(false);
  48.   const router = useRouter();
  49.  
  50.   useEffect(() => {
  51.     if (!(products && products.products && products.products.length > 0))
  52.       return;
  53.     let tempProductsList = [];
  54.     let filteredArr = [];
  55.     if (actualSlug && actualSlug !== category.slug) {
  56.       filteredArr = [...products.products];
  57.       setActualSlug(category.slug);
  58.       setCurrentPage(1);
  59.     } else {
  60.       tempProductsList = [...productsList, ...products.products];
  61.       filteredArr = tempProductsList.reduce((acc, current) => {
  62.         const x = acc.find((item) => item.id === current.id);
  63.         if (!x) {
  64.           return acc.concat([current]);
  65.         } else {
  66.           return acc;
  67.         }
  68.       }, []);
  69.     }
  70.  
  71.     setProductsList([...filteredArr]);
  72.     setTotalProducts(products.total);
  73.     setLoading(false);
  74.     setLoadingFromFilters(false);
  75.     // eslint-disable-next-line react-hooks/exhaustive-deps
  76.   }, [products]);
  77.  
  78.   useEffect(() => {
  79.     setActualSlug(category.slug);
  80.     let url = router.asPath.split("?")[1];
  81.     if (router.asPath.includes("page=")) {
  82.       if (url && url.length > 0) {
  83.         let searchParams = url.split("&");
  84.         searchParams.forEach((s) => {
  85.           if (s.includes("page=")) {
  86.             let tempP = s.split("=");
  87.             setActualPage(parseInt(tempP[1]));
  88.             setPageUp(parseInt(tempP[1]) - 1);
  89.           }
  90.         });
  91.       }
  92.     }
  93.     // eslint-disable-next-line react-hooks/exhaustive-deps
  94.   }, []);
  95.  
  96.   const toggleFilters = () => {
  97.     isOpen ? onClose() : onOpen();
  98.   };
  99.  
  100.   useFilters(
  101.     activeFilters,
  102.     setActiveFilters,
  103.     filters,
  104.     setFilters,
  105.     attributes,
  106.     currentPage,
  107.     setCurrentPage
  108.   );
  109.  
  110.   useEffect(() => {
  111.     window.addEventListener("scroll", shopHeaderFixed);
  112.     function shopHeaderFixed() {
  113.       let headerTopBar = document.querySelector(".shopHeader");
  114.       let header = document.querySelector(".headerContainer");
  115.       if (!headerTopBar) return;
  116.       if (
  117.         window.pageYOffset > header.offsetTop &&
  118.         window.pageYOffset > headerTopBar.offsetHeight - 12 &&
  119.         window.innerWidth <= 992
  120.       ) {
  121.         headerTopBar.style.paddingTop = "0.75rem";
  122.         headerTopBar.style.background = "white";
  123.         headerTopBar.style.boxShadow = "1px 4px 8px rgba(4, 28, 44, 0.25)";
  124.       } else {
  125.         headerTopBar.style.background = "transparent";
  126.         headerTopBar.style.boxShadow = "none";
  127.       }
  128.     }
  129.  
  130.     return () => {
  131.       window.removeEventListener("scroll", shopHeaderFixed);
  132.     };
  133.     // eslint-disable-next-line react-hooks/exhaustive-deps
  134.   }, []);
  135.  
  136.   const pushToNextPage = () => {
  137.     setLoading(true);
  138.     let url = router.asPath.split("?")[1];
  139.     let urlToPush = router.asPath;
  140.     if (router.asPath.includes("page=")) {
  141.       if (url && url.length > 0) {
  142.         let searchParams = url.split("&");
  143.         searchParams.forEach((s) => {
  144.           if (s.includes("page=")) {
  145.             let tempP = s.split("=");
  146.             urlToPush = urlToPush.replace(
  147.               `${s}`,
  148.               `page=${parseInt(tempP[1]) + 1}`
  149.             );
  150.           }
  151.         });
  152.       }
  153.     } else {
  154.       if (url && url.length > 0) {
  155.         urlToPush = router.asPath + "&page=2";
  156.       } else {
  157.         urlToPush = router.asPath + "?order_by=our_choices&page=2";
  158.       }
  159.     }
  160.     router.push(urlToPush, null, { scroll: false });
  161.   };
  162.  
  163.   const loadPrevious = async () => {
  164.     try {
  165.       setLoading(true);
  166.       const queryParams = getQuery(router.query);
  167.       let searchQuery = ``;
  168.       let orderQuery = `&_sort=order_value:DESC`;
  169.       let pagination = `&_start=0&_limit=${process.env.NEXT_PUBLIC_PER_PAGE}`;
  170.  
  171.       let haveAttributesToSearch = false;
  172.       if (Object.keys(queryParams).length !== 0) {
  173.         for (const [key, value] of Object.entries(queryParams)) {
  174.           if (key.includes("attr_")) {
  175.             haveAttributesToSearch = true;
  176.           }
  177.         }
  178.         if (haveAttributesToSearch) {
  179.           searchQuery += `&sellable_items.stock_gte=1`;
  180.         }
  181.         for (const [key, value] of Object.entries(queryParams)) {
  182.           if (key.includes("attr_")) {
  183.             let attr_key = key.replace("attr_", "");
  184.             if (value.length > 0) {
  185.               value.forEach((v) => {
  186.                 searchQuery += `&sellable_items.search_string_contains=${attr_key}-${v}`;
  187.               });
  188.             }
  189.           } else if (key === "order_by") {
  190.             if (value.split(":")[0] === "price") {
  191.               orderQuery = `&_sort=sellable_items.price:${value.split(":")[1]}`;
  192.             } else if (value.split(":")[0] === "created_at") {
  193.               orderQuery = `&_sort=created_at:${value.split(":")[1]}`;
  194.             } else if (value.split(":")[0] === "our_choices") {
  195.               orderQuery = `&_sort=order_value:DESC`;
  196.             }
  197.           } else if (key === "page") {
  198.             pagination = `&_start=${
  199.               (pageUp - 1) * process.env.NEXT_PUBLIC_PER_PAGE
  200.             }&_limit=${process.env.NEXT_PUBLIC_PER_PAGE}`;
  201.           } else {
  202.             searchQuery += `&${key}=${value}`;
  203.           }
  204.         }
  205.       }
  206.       searchQuery += `${searchQuery}${orderQuery}`;
  207.  
  208.       const res = await fetch(
  209.         `${process.env.NEXT_PUBLIC_API_URL}products/store/find?categories_in=${category.id}&published_at_null=false${searchQuery}${pagination}&_locale=${router.locale}`
  210.       );
  211.       const dataProducts = await res.json();
  212.       setProductsList([...dataProducts.products, ...productsList]);
  213.       setPageUp(pageUp - 1);
  214.       setLoading(false);
  215.     } catch (error) {
  216.       console.log(error);
  217.     }
  218.   };
  219.  
  220.   const sk = [];
  221.   for (let i = 0; i < process.env.NEXT_PUBLIC_PER_PAGE; i++) {
  222.     sk.push(
  223.       <Stack
  224.         key={`sk_${i}`}
  225.         spacing="4"
  226.         transitionProperty="box-shadow"
  227.         transitionDuration="0.3s"
  228.         className="group"
  229.         bg="white"
  230.         position="relative"
  231.         _hover={{ boxShadow: "0 0 15px rgba(4, 28, 44, 0.25)" }}
  232.       >
  233.         <Skeleton minH="250px" />
  234.         <Skeleton>
  235.           {" "}
  236.           <Stack
  237.             spacing="2"
  238.             p={{ base: "0.5rem", lg: "1rem" }}
  239.             zIndex="5"
  240.             bg="white"
  241.             h="full"
  242.             justify="space-between"
  243.             align="start"
  244.           >
  245.             <Text
  246.               color="#041C2C"
  247.               fontSize="sm"
  248.               letterSpacing="wider"
  249.               textTransform="uppercase"
  250.             >
  251.               Loading text
  252.             </Text>
  253.             <Text color="ff.primary" fontWeight="600">
  254.               price
  255.             </Text>
  256.           </Stack>
  257.         </Skeleton>
  258.       </Stack>
  259.     );
  260.   }
  261.  
  262.   return (
  263.     <>
  264.       <FiltersModal
  265.         isOpen={isOpen}
  266.         onOpen={onOpen}
  267.         onClose={onClose}
  268.         filters={filters}
  269.         setFilters={setFilters}
  270.         setActiveFilters={setActiveFilters}
  271.         attributes={attributes}
  272.         setProductsList={setProductsList}
  273.         setCurrentPage={setCurrentPage}
  274.         setLoadingFromFilters={setLoadingFromFilters}
  275.       />
  276.       <Box
  277.         px={{ base: "4", lg: "8", "2xl": "0" }}
  278.         maxW="8xl"
  279.         mx="auto"
  280.         py={{
  281.           base: "6",
  282.           md: "8",
  283.           lg: "12",
  284.         }}
  285.         className="headerContainer"
  286.       >
  287.         <Stack
  288.           align="center"
  289.           maxW="8xl"
  290.           mx="auto"
  291.           spacing={{
  292.             md: "8",
  293.             lg: "12",
  294.           }}
  295.         >
  296.           <Box
  297.             position={{ base: "sticky", lg: "static" }}
  298.             top={{ base: "80px", lg: "0" }}
  299.             px={{ base: "0.75rem", lg: "0" }}
  300.             pb={{ base: "0.75rem", lg: "0" }}
  301.             w="full"
  302.             zIndex="10"
  303.             className="shopHeader"
  304.           >
  305.             <ShopHeader
  306.               category={category}
  307.               total={totalProducts}
  308.               totalType={t("headerProducts")}
  309.               toggleFilters={toggleFilters}
  310.               filtersCount={activeFilters.attributes.length}
  311.             />
  312.           </Box>
  313.           {/* <Text // ------------------------------------- PROMOTION TEXT
  314.             w="full"
  315.             fontSize="xs"
  316.             textAlign="center"
  317.             color="ff.primary"
  318.             opacity="0.5"
  319.           >
  320.             TROCAS PERMITIDAS ATÉ DIA 31 DE DEZEMBRO DE 2021. Promoções válidas
  321.             nos artigos assinalados de 20 de Setembro a 30 de Novembro de 2021.
  322.             A percentagens de desconto aplicadas são de 40%, 50% ou 60%.
  323.           </Text> */}
  324.           {currentPage && currentPage !== 1 && actualPage !== 1 && pageUp > 0 && (
  325.             <Stack>
  326.               <Button
  327.                 bg="transparent"
  328.                 borderRadius="0"
  329.                 fontWeight="600"
  330.                 borderWidth="1px"
  331.                 borderStyle="solid"
  332.                 borderColor="ff.primary"
  333.                 fontSize={{ base: "0.6rem", lg: "0.65rem", xl: "0.7rem" }}
  334.                 textTransform="uppercase"
  335.                 color="ff.primary"
  336.                 px="2rem"
  337.                 _hover={{ background: "ff.primary", color: "white" }}
  338.                 _focus={{ outline: "none" }}
  339.                 onClick={() => {
  340.                   loadPrevious();
  341.                 }}
  342.                 isLoading={loading}
  343.                 loadingText="A carregar"
  344.                 spinner={<Spinner color="gray.500" />}
  345.               >
  346.                 Carregar Anterior
  347.               </Button>
  348.             </Stack>
  349.           )}
  350.           {loadingFromFilters && (
  351.             <SimpleGrid
  352.               w="full"
  353.               columns={{
  354.                 base: 2,
  355.                 sm: 3,
  356.                 lg: 4,
  357.               }}
  358.               gap={{
  359.                 base: "8",
  360.                 lg: "12",
  361.               }}
  362.               zIndex="5"
  363.             >
  364.               {sk}
  365.             </SimpleGrid>
  366.           )}
  367.           <SimpleGrid
  368.             w="full"
  369.             columns={{
  370.               base: 2,
  371.               sm: 3,
  372.               lg: 4,
  373.             }}
  374.             gap={{
  375.               base: "8",
  376.               lg: "12",
  377.             }}
  378.             zIndex="5"
  379.           >
  380.             {productsList &&
  381.               productsList.map((product, index) => (
  382.                 <ProductCard key={product.slug} product={product} />
  383.               ))}
  384.           </SimpleGrid>
  385.  
  386.           <Stack>
  387.             {currentPage < totalProducts / process.env.NEXT_PUBLIC_PER_PAGE && (
  388.               <Button
  389.                 bg="transparent"
  390.                 borderRadius="0"
  391.                 fontWeight="600"
  392.                 borderWidth="1px"
  393.                 borderStyle="solid"
  394.                 borderColor="ff.primary"
  395.                 fontSize={{ base: "0.6rem", lg: "0.65rem", xl: "0.7rem" }}
  396.                 textTransform="uppercase"
  397.                 color="ff.primary"
  398.                 px="2rem"
  399.                 _hover={{ background: "ff.primary", color: "white" }}
  400.                 _focus={{ outline: "none" }}
  401.                 onClick={() => {
  402.                   pushToNextPage();
  403.                 }}
  404.                 isLoading={loading}
  405.                 loadingText="A carregar"
  406.                 spinner={<Spinner color="gray.500" />}
  407.               >
  408.                 Carregar Mais
  409.               </Button>
  410.             )}
  411.             <Box>
  412.               <Stack mt="6">
  413.                 <Text
  414.                   color="ff.primary"
  415.                   fontSize={{ base: "0.7rem", lg: "0.75rem", xl: "0.8rem" }}
  416.                   textAlign="center"
  417.                 >
  418.                   {productsList.length} produtos visualizados de{" "}
  419.                   {totalProducts ? totalProducts : 0}
  420.                 </Text>
  421.                 <Progress
  422.                   width="180px"
  423.                   height="3px"
  424.                   colorScheme="gray"
  425.                   value={(productsList.length * 100) / totalProducts}
  426.                 />
  427.               </Stack>
  428.             </Box>
  429.           </Stack>
  430.         </Stack>
  431.       </Box>
  432.     </>
  433.   );
  434. };
  435.  
  436. export default CategoriesList;
  437.  
RAW Paste Data