From e774d7bda97615e6ffd17ba834a18b8cac1964f7 Mon Sep 17 00:00:00 2001 From: Elian Date: Sun, 26 May 2024 19:22:22 -0700 Subject: [PATCH 1/2] added item pagination with 10 items per page and 4 buttons to select from along with arrows --- .../src/components/ResultsBar/ResultsBar.jsx | 147 +++++++++++++++--- packages/web/src/utils/Utils.js | 1 - 2 files changed, 124 insertions(+), 24 deletions(-) diff --git a/packages/web/src/components/ResultsBar/ResultsBar.jsx b/packages/web/src/components/ResultsBar/ResultsBar.jsx index 23ba064..562da70 100644 --- a/packages/web/src/components/ResultsBar/ResultsBar.jsx +++ b/packages/web/src/components/ResultsBar/ResultsBar.jsx @@ -1,7 +1,8 @@ -import { useContext, useCallback, useState } from "react"; +import { useContext, useCallback, useState, useEffect, useRef } from "react"; import "./ResultsBar.css"; import ResultCard from "../ResultCard/ResultCard"; -import { Box, Flex, Text, Button } from "@chakra-ui/react"; +import { Box, Flex, Text, Button, IconButton } from "@chakra-ui/react"; +import { ChevronRightIcon, ChevronLeftIcon } from "@chakra-ui/icons"; import DataContext from "../../context/DataContext"; import { UserAuth } from "../../context/AuthContext"; import Fuse from "fuse.js"; @@ -18,8 +19,6 @@ export default function ResultsBar({ const { data, setData } = useContext(DataContext); const { user } = UserAuth(); - const [itemsonScreenLimit, setItemsOnScreenLimit] = useState(10); - const filterItemCallback = useCallback( (item) => filterItem(item, findFilter, user), [findFilter, user] @@ -60,33 +59,128 @@ export default function ResultsBar({ ? data.filter(filterItemCallback).map(mapItem) : results.filter(filterItemCallback).map(mapItem); - // Callback function that increases the number of items displayed on the screen by 10 - const handleLoadMore = useCallback(() => { - setItemsOnScreenLimit(itemsonScreenLimit + 10); - }, [itemsonScreenLimit]); - const loadMoreButton = ( + + + // Display only the 10 items on the screen and only 4 buttons (the last one is always there) + const itemsOnScreenLimit = 10; + const buttonLimit = 3; + + const [selectedPageNumber, setSelectedPageNumber] = useState(1); + const [paginationButtons, setPaginationButtons] = useState([]) + const [viewableResults, setViewableResults] = useState([]) + + const changeViewToNewPage = useCallback((newSelectedPage) => { + const pageStart = (newSelectedPage * itemsOnScreenLimit) - itemsOnScreenLimit + const pageEnd = Math.min((newSelectedPage * itemsOnScreenLimit), allResults.length) + + setViewableResults(allResults.slice( + pageStart, + pageEnd + )); + }, [allResults, allResults.length]); + + const updatePaginationButtons = useCallback( + (newSelectedPage) => { + changeViewToNewPage(newSelectedPage); + setSelectedPageNumber(newSelectedPage); + + const maxIndex = Math.floor(allResults.length / itemsOnScreenLimit) + 1; + if (newSelectedPage >= maxIndex - buttonLimit) { + setPaginationButtons(createPaginationButtons(maxIndex - buttonLimit, newSelectedPage)); + } + else { + const startPage = newSelectedPage - ((newSelectedPage - 1) % 3); + setPaginationButtons(createPaginationButtons(startPage, newSelectedPage)); + } + }, + [allResults, allResults.length, changeViewToNewPage] + ) + const PageButton = useCallback(({ keyProp, selected }) => ( - ); + ), [updatePaginationButtons]); - // Retrieve all items that meet the filter criteria + function createPaginationButtons(startPageNumber, selectedPageNumber) { + const buttons_array = []; + for (let i = startPageNumber; i < startPageNumber + buttonLimit; i++) { + buttons_array.push(); + } + return buttons_array; + } + + + const handlePageArrowClick = useCallback((direction) => { + const maxIndex = Math.floor(allResults.length / itemsOnScreenLimit) + 1 + + let startPage = 0; + let selected = 0; + if (direction == "right" && selectedPageNumber < maxIndex) { + if (selectedPageNumber >= maxIndex - buttonLimit) { + startPage = maxIndex - buttonLimit; + selected = maxIndex; + } + else { + startPage = selectedPageNumber + (3 - ((selectedPageNumber - 1) % 3)); + selected = startPage + ((selectedPageNumber - 1) % 3); + if (startPage > maxIndex - buttonLimit) + startPage = maxIndex - buttonLimit; + } + + setSelectedPageNumber(selected); + changeViewToNewPage(selected); + setPaginationButtons(createPaginationButtons(startPage, selected)); + } + else if (direction == "left" && selectedPageNumber > 0) { + if (selectedPageNumber <= 3) { + startPage = 1; + selected = 1; + } + else if (selectedPageNumber == maxIndex) { + startPage = maxIndex - 4; + selected = maxIndex - 4; + } + else { + startPage = selectedPageNumber - (3 + (selectedPageNumber - 1) % 3); + selected = startPage + ((selectedPageNumber - 1) % 3); + } + + setSelectedPageNumber(selected); + changeViewToNewPage(selected); + setPaginationButtons(createPaginationButtons(startPage, selected)); + } + }, [allResults, allResults.length, selectedPageNumber]) + + + + const firstRender = useRef(true); + useEffect(() => { + if (!firstRender.current || allResults.length === 0) + return; + + firstRender.current = false; + const pageStart = (selectedPageNumber * itemsOnScreenLimit) - itemsOnScreenLimit + const pageEnd = Math.min((selectedPageNumber * itemsOnScreenLimit), allResults.length) + + setViewableResults(allResults.slice( + pageStart, + pageEnd + )); + setPaginationButtons(createPaginationButtons(1, 1)); + }, [allResults]) - // Display only the first 10 items on the screen, all items if there are less than 10 items left to be loaded - const viewableResults = allResults.slice( - 0, - Math.min(itemsonScreenLimit, allResults.length) - ); // Define JSX for empty results bar (no result cards) const noResults = ( @@ -100,13 +194,20 @@ export default function ResultsBar({ return ( {allResults.length > 0 ? viewableResults : noResults} - {viewableResults.length < allResults.length && loadMoreButton} + + + } height="40px" width="10px" marginTop="10px" marginBottom="10px" onClick={() => handlePageArrowClick("left")} /> + {paginationButtons} + + } height="40px" width="10px" marginTop="10px" marginBottom="10px" onClick={() => handlePageArrowClick("right")} /> + + ); } diff --git a/packages/web/src/utils/Utils.js b/packages/web/src/utils/Utils.js index a92c509..6bb13aa 100644 --- a/packages/web/src/utils/Utils.js +++ b/packages/web/src/utils/Utils.js @@ -1,6 +1,5 @@ // Define callback function to return filtered items (filtered according to search bar and filter markers) const filterItem = (item, findFilter, user) => { - console.log(item); return ( ((findFilter.islost && item.islost) || (findFilter.isFound && !item.islost)) && From 877d391dbbeac57cf3ce3bc8930c44b502bea1fc Mon Sep 17 00:00:00 2001 From: Elian Date: Tue, 28 May 2024 12:44:16 -0700 Subject: [PATCH 2/2] added pagination scroll and removed empty space, fixed map issues --- packages/web/src/components/Home/Home.jsx | 5 +- packages/web/src/components/Map/Map.jsx | 50 +++++++++---------- .../src/components/ResultsBar/ResultsBar.jsx | 23 +++++---- 3 files changed, 40 insertions(+), 38 deletions(-) diff --git a/packages/web/src/components/Home/Home.jsx b/packages/web/src/components/Home/Home.jsx index 9f8bead..8a9b8ca 100644 --- a/packages/web/src/components/Home/Home.jsx +++ b/packages/web/src/components/Home/Home.jsx @@ -142,8 +142,7 @@ export default function Home() { e.preventDefault(); try { await axios.patch( - `${ - import.meta.env.VITE_REACT_APP_AWS_BACKEND_URL + `${import.meta.env.VITE_REACT_APP_AWS_BACKEND_URL }/leaderboard/changeSubscription`, { email: user.email, @@ -564,7 +563,7 @@ export default function Home() { colorScheme="#74a2fa" color="#5f85cf" spacing={3} - // boxShadow="5px 2px 9px rgba(0, 0, 0, 0.2);" + // boxShadow="5px 2px 9px rgba(0, 0, 0, 0.2);" >