From 8f43ad605b292234cc4ef1e61eef728726e0a3d6 Mon Sep 17 00:00:00 2001 From: Raghart Date: Mon, 12 Jan 2026 16:58:10 -0400 Subject: [PATCH 1/4] r refactoring DetailSongs infinite-Scroll --- back/public/index.html | 2 +- .../DetailsPath/Layout/DetailSongs.tsx | 38 ++++++++++++------- .../DetailsPath/Layout/DetailsLayout.tsx | 9 ++--- .../components/Pagination/PaginateSongs.ts | 16 ++++++++ .../Utils/hooks/useGetDetailSongs.tsx | 10 +---- 5 files changed, 46 insertions(+), 29 deletions(-) create mode 100644 front/src/components/Pagination/PaginateSongs.ts diff --git a/back/public/index.html b/back/public/index.html index 426c412..349d7bc 100644 --- a/back/public/index.html +++ b/back/public/index.html @@ -17,7 +17,7 @@ color: white; } - + diff --git a/front/src/components/DetailsPath/Layout/DetailSongs.tsx b/front/src/components/DetailsPath/Layout/DetailSongs.tsx index 03991d5..dfbd3a3 100644 --- a/front/src/components/DetailsPath/Layout/DetailSongs.tsx +++ b/front/src/components/DetailsPath/Layout/DetailSongs.tsx @@ -1,5 +1,4 @@ -import { SimpleGrid, Skeleton } from "@chakra-ui/react"; -import InfiniteScrollList from "@/components/Pagination/InfiniteScrollList"; +import { Center, For, SimpleGrid, Skeleton } from "@chakra-ui/react"; import SongCard from "../../SongCard/SongCard"; import { ValidDetail } from "@/types/utilTypes"; import NotFound from "@/components/Error/NotFound"; @@ -7,23 +6,34 @@ import { useAppSelector } from "@/components/Utils/redux-hooks"; import useGetDetailSongs from "@/components/Utils/hooks/useGetDetailSongs"; import { SONGCARD_SIZES } from "@/components/constants/SongCardC"; import { SongResponse } from "@/types/songTypes"; +import InfiniteScroll from "react-infinite-scroll-component"; +import PaginateSongs from "@/components/Pagination/PaginateSongs"; +import LoadingBeat from "@/components/Utils/LoadingBeat"; const DetailSongs = ({ type, filterValue, error }: { type: ValidDetail, filterValue: string, error: string }) => { - const { data, loading, visibleSongs, onLoadMore } = useGetDetailSongs(type, filterValue); + const { data, loading, detailSongs } = useGetDetailSongs(type, filterValue); + const { visibleSongs, loadMoreSongs } = PaginateSongs(detailSongs); + const { activeSong, isPlaying } = useAppSelector(state => state.songs.songState); - if (!loading && !data && visibleSongs.length === 0) return + if (!loading && !data && detailSongs.length === 0) return return( - - {data ? ( - } onLoadMore={onLoadMore} - error={`There was an error while Trying to manage the received data!`} items={visibleSongs} /> - ) : ( - Array.from({ length: 20 }).map((_, idx) => ( - - )))} - + } next={loadMoreSongs} + style={{ display: "block", paddingBottom: 80 }}> + + {!data && (Array.from({ length: 20 }).map((_, idx) => ))} + + {data && ( + + {(song: SongResponse) => } + + )} + + ); }; diff --git a/front/src/components/DetailsPath/Layout/DetailsLayout.tsx b/front/src/components/DetailsPath/Layout/DetailsLayout.tsx index e479977..346f6ec 100644 --- a/front/src/components/DetailsPath/Layout/DetailsLayout.tsx +++ b/front/src/components/DetailsPath/Layout/DetailsLayout.tsx @@ -1,7 +1,7 @@ import NotFound from "@/components/Error/NotFound"; import { ValidDetail } from "@/types/utilTypes"; import HighlightTitle from "../Utils/HightlightTitle"; -import { Flex } from "@chakra-ui/react"; +import { Box } from "@chakra-ui/react"; import ScrollUpArrow from "@/components/Utils/ScrollUpArrow"; import DetailSongs from "./DetailSongs"; import { isString, isValidDetail } from "@/types/verify"; @@ -13,16 +13,15 @@ const DetailsLayout = ({ type, gradientInit, gradientMid, error } : { type: Vali const { filterValue, hightlightDetails } = useDetailFilter(type); if (!isValidDetail(type) || !isString(filterValue)) return return ( - - + + - + ); }; diff --git a/front/src/components/Pagination/PaginateSongs.ts b/front/src/components/Pagination/PaginateSongs.ts new file mode 100644 index 0000000..a1ee8c8 --- /dev/null +++ b/front/src/components/Pagination/PaginateSongs.ts @@ -0,0 +1,16 @@ +import { SongResponse } from "@/types/songTypes"; +import { useState } from "react"; + +const PaginateSongs = (songs: SongResponse[]) => { + const [visibleCount, setVisibleCount] = useState(20); + const visibleSongs = songs.slice(0, visibleCount); + const loadMoreSongs = () => { + if (visibleSongs.length < songs.length) { + setVisibleCount(prev => prev + 20); + } + } + + return { visibleSongs, loadMoreSongs } +}; + +export default PaginateSongs; \ No newline at end of file diff --git a/front/src/components/Utils/hooks/useGetDetailSongs.tsx b/front/src/components/Utils/hooks/useGetDetailSongs.tsx index db1dad9..d047a5b 100644 --- a/front/src/components/Utils/hooks/useGetDetailSongs.tsx +++ b/front/src/components/Utils/hooks/useGetDetailSongs.tsx @@ -2,21 +2,13 @@ import { getAllAlbumSongs, getAllArtistSongs } from "@/queries/DetailQueries"; import { SongResponse } from "@/types/songTypes"; import { ValidDetail } from "@/types/utilTypes"; import { useQuery } from "@apollo/client"; -import { useState } from "react"; const useGetDetailSongs = (type: ValidDetail, filterValue: string) => { - const [visibleCount, setVisibleCount] = useState(20); const query = type === "album" ? getAllAlbumSongs : getAllArtistSongs; const variables = type === "album" ? { album: filterValue } : { artist: filterValue }; const { loading, data } = useQuery(query, { variables }); const detailSongs: SongResponse[] = data?.getAllAlbumSongs ?? data?.getAllArtistSongs ?? []; - const visibleSongs = detailSongs.slice(0, visibleCount); - - const onLoadMore = () => { - if (visibleSongs.length < detailSongs.length) { setVisibleCount(prev => prev + 20); } - }; - - return { data, loading, visibleSongs, onLoadMore } + return { data, loading, detailSongs } }; export default useGetDetailSongs; \ No newline at end of file From 990199d2aa1d2fef193fd1fa0bac505d7144d960 Mon Sep 17 00:00:00 2001 From: Raghart Date: Mon, 12 Jan 2026 18:35:30 -0400 Subject: [PATCH 2/4] r refactoring GenreSelection to use new inf-Scroll --- back/public/index.html | 2 +- .../DetailsPath/Layout/DetailSongs.tsx | 1 - .../components/GenrePath/GenreSelection.tsx | 28 +++++++++++-------- .../src/components/Utils/hooks/useGenreSel.ts | 4 +-- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/back/public/index.html b/back/public/index.html index 349d7bc..514f730 100644 --- a/back/public/index.html +++ b/back/public/index.html @@ -17,7 +17,7 @@ color: white; } - + diff --git a/front/src/components/DetailsPath/Layout/DetailSongs.tsx b/front/src/components/DetailsPath/Layout/DetailSongs.tsx index dfbd3a3..d380943 100644 --- a/front/src/components/DetailsPath/Layout/DetailSongs.tsx +++ b/front/src/components/DetailsPath/Layout/DetailSongs.tsx @@ -13,7 +13,6 @@ import LoadingBeat from "@/components/Utils/LoadingBeat"; const DetailSongs = ({ type, filterValue, error }: { type: ValidDetail, filterValue: string, error: string }) => { const { data, loading, detailSongs } = useGetDetailSongs(type, filterValue); const { visibleSongs, loadMoreSongs } = PaginateSongs(detailSongs); - const { activeSong, isPlaying } = useAppSelector(state => state.songs.songState); if (!loading && !data && detailSongs.length === 0) return diff --git a/front/src/components/GenrePath/GenreSelection.tsx b/front/src/components/GenrePath/GenreSelection.tsx index af0756b..3389ba6 100644 --- a/front/src/components/GenrePath/GenreSelection.tsx +++ b/front/src/components/GenrePath/GenreSelection.tsx @@ -1,29 +1,35 @@ -import { Flex, SimpleGrid } from "@chakra-ui/react"; -import InfiniteScrollList from "@/components/Pagination/InfiniteScrollList"; +import { Box, Center, For, SimpleGrid } from "@chakra-ui/react"; import GenreCard from "./GenreCard"; import ScrollUpArrow from "@/components/Utils/ScrollUpArrow"; import GenreSelHeader from "./GenreSelHeader"; import useGenreSel from "../Utils/hooks/useGenreSel"; import { Zoom } from "react-awesome-reveal"; import { GenreListFormat } from "@/types/genreTypes"; +import InfiniteScroll from "react-infinite-scroll-component"; +import { genreList } from "../Utils/genreIconList"; +import LoadingBeat from "../Utils/LoadingBeat"; const GenreSelection = () => { - const { visibleGenres, onLoadMore } = useGenreSel(); + const { visibleGenres, loadMoreGenres } = useGenreSel(); return( - - + + - - items={visibleGenres} error="Error with Genre's Pagination" - renderItem={(genre: GenreListFormat) => ()} - onLoadMore={onLoadMore} /> - + } dataLength={visibleGenres.length} + style={{ paddingBottom: 80 }}> + + + {(genre: GenreListFormat) => } + + + - + ); }; diff --git a/front/src/components/Utils/hooks/useGenreSel.ts b/front/src/components/Utils/hooks/useGenreSel.ts index a8fd010..45c5a0e 100644 --- a/front/src/components/Utils/hooks/useGenreSel.ts +++ b/front/src/components/Utils/hooks/useGenreSel.ts @@ -5,13 +5,13 @@ const useGenreSel = () => { const [visibleCount, setVisibleCount] = useState(20); const visibleGenres = genreList.slice(0, visibleCount); - const onLoadMore = () => { + const loadMoreGenres = () => { if (visibleGenres.length < genreList.length) { setVisibleCount(prev => prev + 20); }; }; - return { visibleGenres, onLoadMore }; + return { visibleGenres, loadMoreGenres }; }; export default useGenreSel; \ No newline at end of file From 640df38298c79d5496bbea84a5320b2a4408c0e3 Mon Sep 17 00:00:00 2001 From: Raghart Date: Mon, 12 Jan 2026 20:17:43 -0400 Subject: [PATCH 3/4] r refactoring LaraRecommendations to use new inf-Scroll --- back/public/index.html | 2 +- .../LaraRecommendations.tsx | 32 +++++++++++-------- .../src/components/Utils/hooks/useSongRec.tsx | 2 +- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/back/public/index.html b/back/public/index.html index 514f730..f9292dd 100644 --- a/back/public/index.html +++ b/back/public/index.html @@ -17,7 +17,7 @@ color: white; } - + diff --git a/front/src/components/LaraRecommendationsPath/LaraRecommendations.tsx b/front/src/components/LaraRecommendationsPath/LaraRecommendations.tsx index 187c99a..503d63f 100644 --- a/front/src/components/LaraRecommendationsPath/LaraRecommendations.tsx +++ b/front/src/components/LaraRecommendationsPath/LaraRecommendations.tsx @@ -1,5 +1,4 @@ -import { Flex, SimpleGrid } from "@chakra-ui/react"; -import InfiniteScrollList from "../Pagination/InfiniteScrollList"; +import { Box, Center, For, SimpleGrid } from "@chakra-ui/react"; import SongCard from "../SongCard/SongCard"; import LaraHeader from "./LaraHeader"; import { Navigate } from "react-router-dom"; @@ -8,28 +7,35 @@ import useSongRec from "../Utils/hooks/useSongRec"; import { useAppSelector } from "../Utils/redux-hooks"; import { Zoom } from "react-awesome-reveal"; import { SongResponse } from "@/types/songTypes"; +import InfiniteScroll from "react-infinite-scroll-component"; +import LoadingBeat from "../Utils/LoadingBeat"; const LaraRecommendations = () => { - const { visibleSongs, loadMoreSongs } = useSongRec(); + const { visibleSongs, recommendations, loadMoreSongs } = useSongRec(); const { activeSong, isPlaying } = useAppSelector(state => state.songs.songState); if (visibleSongs.length === 0) return + return( - - + + - - } items={visibleSongs} - error="There are no song Recommendations avaible in the DB with the data provided" - onLoadMore={loadMoreSongs} /> - + } + style={{ overflow: "visible" }}> + + + {(song: SongResponse) => } + + + - + ); }; diff --git a/front/src/components/Utils/hooks/useSongRec.tsx b/front/src/components/Utils/hooks/useSongRec.tsx index b7e9662..e30d859 100644 --- a/front/src/components/Utils/hooks/useSongRec.tsx +++ b/front/src/components/Utils/hooks/useSongRec.tsx @@ -12,7 +12,7 @@ const useSongRec = () => { }; }; - return { visibleSongs, loadMoreSongs }; + return { visibleSongs, recommendations, loadMoreSongs }; }; export default useSongRec; \ No newline at end of file From c52d98b34e2d85b982e99995400655f91e90d88a Mon Sep 17 00:00:00 2001 From: Raghart Date: Mon, 12 Jan 2026 20:30:48 -0400 Subject: [PATCH 4/4] r changing bottom padding and fixing bugs --- back/public/index.html | 2 +- .../components/ArtistPath/ArtistSelection.tsx | 2 +- .../DetailsPath/Layout/DetailSongs.tsx | 7 ++-- .../DetailsPath/Layout/DetailsLayout.tsx | 2 +- .../components/GenreDetails/GenreDetails.tsx | 4 +-- .../components/GenrePath/GenreSelection.tsx | 4 +-- .../Pagination/InfiniteScrollList.tsx | 33 ------------------- .../components/Pagination/PaginateSongs.ts | 4 +-- 8 files changed, 12 insertions(+), 46 deletions(-) delete mode 100644 front/src/components/Pagination/InfiniteScrollList.tsx diff --git a/back/public/index.html b/back/public/index.html index f9292dd..328bb60 100644 --- a/back/public/index.html +++ b/back/public/index.html @@ -17,7 +17,7 @@ color: white; } - + diff --git a/front/src/components/ArtistPath/ArtistSelection.tsx b/front/src/components/ArtistPath/ArtistSelection.tsx index 60f13aa..f15b5ac 100644 --- a/front/src/components/ArtistPath/ArtistSelection.tsx +++ b/front/src/components/ArtistPath/ArtistSelection.tsx @@ -14,7 +14,7 @@ const ArtistSelection = () => { const dataLength = data?.getAllArtists ? data.getAllArtists.length : 20; return( - + diff --git a/front/src/components/DetailsPath/Layout/DetailSongs.tsx b/front/src/components/DetailsPath/Layout/DetailSongs.tsx index d380943..24a79cf 100644 --- a/front/src/components/DetailsPath/Layout/DetailSongs.tsx +++ b/front/src/components/DetailsPath/Layout/DetailSongs.tsx @@ -7,19 +7,18 @@ import useGetDetailSongs from "@/components/Utils/hooks/useGetDetailSongs"; import { SONGCARD_SIZES } from "@/components/constants/SongCardC"; import { SongResponse } from "@/types/songTypes"; import InfiniteScroll from "react-infinite-scroll-component"; -import PaginateSongs from "@/components/Pagination/PaginateSongs"; import LoadingBeat from "@/components/Utils/LoadingBeat"; +import usePaginateSongs from "@/components/Pagination/PaginateSongs"; const DetailSongs = ({ type, filterValue, error }: { type: ValidDetail, filterValue: string, error: string }) => { const { data, loading, detailSongs } = useGetDetailSongs(type, filterValue); - const { visibleSongs, loadMoreSongs } = PaginateSongs(detailSongs); + const { visibleSongs, loadMoreSongs } = usePaginateSongs(detailSongs); const { activeSong, isPlaying } = useAppSelector(state => state.songs.songState); if (!loading && !data && detailSongs.length === 0) return return( } next={loadMoreSongs} - style={{ display: "block", paddingBottom: 80 }}> + loader={
} next={loadMoreSongs} style={{ overflow: "visible" }}> {!data && (Array.from({ length: 20 }).map((_, idx) => return ( - + diff --git a/front/src/components/GenreDetails/GenreDetails.tsx b/front/src/components/GenreDetails/GenreDetails.tsx index 70b9eb2..9141f9e 100644 --- a/front/src/components/GenreDetails/GenreDetails.tsx +++ b/front/src/components/GenreDetails/GenreDetails.tsx @@ -20,13 +20,13 @@ const GenreDetails = () => { message={`The genre: "${genre}" was not found in the DB!`} />; return ( - + } style={{ display: "block" }}> + loader={
} style={{ overflow: "visible" }}> {!data && (Array.from({ length: 20 }).map((_, idx) => ( diff --git a/front/src/components/GenrePath/GenreSelection.tsx b/front/src/components/GenrePath/GenreSelection.tsx index 3389ba6..452be58 100644 --- a/front/src/components/GenrePath/GenreSelection.tsx +++ b/front/src/components/GenrePath/GenreSelection.tsx @@ -12,7 +12,7 @@ import LoadingBeat from "../Utils/LoadingBeat"; const GenreSelection = () => { const { visibleGenres, loadMoreGenres } = useGenreSel(); return( - + @@ -20,7 +20,7 @@ const GenreSelection = () => { } dataLength={visibleGenres.length} - style={{ paddingBottom: 80 }}> + style={{ overflow: "visible" }}> {(genre: GenreListFormat) => } diff --git a/front/src/components/Pagination/InfiniteScrollList.tsx b/front/src/components/Pagination/InfiniteScrollList.tsx deleted file mode 100644 index 8f29fb5..0000000 --- a/front/src/components/Pagination/InfiniteScrollList.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { useCallback, useEffect, useRef } from "react"; -import { Box, For } from "@chakra-ui/react"; -import { InfiniteScrollItems } from "@/types/utilTypes"; - -const InfiniteScrollList = ({ items, renderItem, error, onLoadMore }: - { items: Items[], error: string, renderItem: (item: Items) => React.ReactNode, onLoadMore: () => void }) => { - const loader = useRef(null); - - const handleObserver = useCallback((entries: IntersectionObserverEntry[]) => { - const target = entries[0]; - if (target.isIntersecting) { - onLoadMore(); - }; - }, [onLoadMore]) - - useEffect(() => { - const option = { root: null, rootMargin: "20px", threshold: 0.25 }; - const observer = new IntersectionObserver(handleObserver, option); - if (loader.current) observer.observe(loader.current); - return () => observer.disconnect(); - }, [handleObserver]); - - return( - <> - {error}}> - {(renderItem)} - - - - ); -}; - -export default InfiniteScrollList; \ No newline at end of file diff --git a/front/src/components/Pagination/PaginateSongs.ts b/front/src/components/Pagination/PaginateSongs.ts index a1ee8c8..9431765 100644 --- a/front/src/components/Pagination/PaginateSongs.ts +++ b/front/src/components/Pagination/PaginateSongs.ts @@ -1,7 +1,7 @@ import { SongResponse } from "@/types/songTypes"; import { useState } from "react"; -const PaginateSongs = (songs: SongResponse[]) => { +const usePaginateSongs = (songs: SongResponse[]) => { const [visibleCount, setVisibleCount] = useState(20); const visibleSongs = songs.slice(0, visibleCount); const loadMoreSongs = () => { @@ -13,4 +13,4 @@ const PaginateSongs = (songs: SongResponse[]) => { return { visibleSongs, loadMoreSongs } }; -export default PaginateSongs; \ No newline at end of file +export default usePaginateSongs; \ No newline at end of file