From 354bc493cf9d060760deb5980b32e98a96cf8c19 Mon Sep 17 00:00:00 2001 From: Jhonatan Jacome Date: Fri, 6 Dec 2024 16:17:10 -0500 Subject: [PATCH] Update search and add new route API #27 --- frontend/next.config.mjs | 2 +- .../(page)/explore/components/SongItem.tsx | 2 +- .../(page)/explore/components/SongList.tsx | 78 +++++++++++---- frontend/src/hooks/useFilterSongs.ts | 28 +++++- frontend/src/types/ui/Song.ts | 44 ++++++--- frontend/src/utils/fetchSongs.ts | 95 ++++++++++++++++++- frontend/src/utils/fetchindividuales.ts | 89 +++++++++++++++++ 7 files changed, 305 insertions(+), 33 deletions(-) create mode 100644 frontend/src/utils/fetchindividuales.ts diff --git a/frontend/next.config.mjs b/frontend/next.config.mjs index eaa8022..0992b77 100644 --- a/frontend/next.config.mjs +++ b/frontend/next.config.mjs @@ -1,7 +1,7 @@ /** @type {import('next').NextConfig} */ const nextConfig = { images: { - domains: ["cdn-images.dzcdn.net"], // Dominio para poder trabajar con las imagenes + domains: ["cdn-images.dzcdn.net", "api.deezer.com"], //rutas para las imagenes de las canciones }, }; diff --git a/frontend/src/app/(page)/explore/components/SongItem.tsx b/frontend/src/app/(page)/explore/components/SongItem.tsx index 0007824..53423a5 100644 --- a/frontend/src/app/(page)/explore/components/SongItem.tsx +++ b/frontend/src/app/(page)/explore/components/SongItem.tsx @@ -8,7 +8,7 @@ interface SongItemProps { title_short: string; duration: string; preview: string; - md5_image: string; + md5_image: string | null; artist: string; artistImage: string; genres: string; diff --git a/frontend/src/app/(page)/explore/components/SongList.tsx b/frontend/src/app/(page)/explore/components/SongList.tsx index da42541..433bcd7 100644 --- a/frontend/src/app/(page)/explore/components/SongList.tsx +++ b/frontend/src/app/(page)/explore/components/SongList.tsx @@ -1,11 +1,15 @@ import React, { useState, useEffect, useCallback } from "react"; import SongItem from "./SongItem"; import Player from "@/components/ui/Player"; -import { fetchSongs } from "@/utils/fetchSongs"; +import { + fetchSongsByGenre, + fetchSongsBySearchTerm, + fetchSongs, +} from "@/utils/fetchSongs"; import { useFilterSongs } from "@/hooks/useFilterSongs"; import { Song } from "@/types/ui/Song"; import { formatDuration } from "@/utils/formatDuration"; -import { mockSongs } from "@/data/mockSongs"; // Importa los datos hardcodeados +//import { mockSongs } from "@/data/mockSongs"; interface SongListProps { searchTerm?: string; @@ -18,27 +22,70 @@ export default function SongList({ }: SongListProps) { const [selectedSong, setSelectedSong] = useState(null); const [isPlaying, setIsPlaying] = useState(false); - const [songs, setSongs] = useState([]); // Inicializar vacĂ­o + const [songs, setSongs] = useState([]); + const [initialSongs, setInitialSongs] = useState([]); + + useEffect(() => { + const genres = [ + "pop", + "rock", + "electronica", + "clasica", + "hip-hop", + "rap", + "k-pop", + ]; + + const loadInitialSongs = async () => { + try { + const promises = genres.map((genre) => fetchSongsByGenre(genre)); + const results = await Promise.all(promises); + const allSongs = results.flat(); + + const randomFetchedSongs = await fetchSongs(""); + + const combinedSongs: Song[] = []; + const maxLength = Math.max(allSongs.length, randomFetchedSongs.length); + for (let i = 0; i < maxLength; i++) { + if (i < allSongs.length) { + combinedSongs.push(allSongs[i]); + } + if (i < randomFetchedSongs.length) { + combinedSongs.push(randomFetchedSongs[i]); + } + } + + setInitialSongs(combinedSongs); + } catch (error) { + console.error("Error fetching initial songs:", error); + } + }; + + loadInitialSongs(); + }, []); useEffect(() => { const loadSongs = async () => { try { - const fetchedSongs = await fetchSongs(searchTerm); - console.log("Fetched Songs:", fetchedSongs); // Debug log + let fetchedSongs: Song[] = []; + + if (searchTerm) { + fetchedSongs = await fetchSongsBySearchTerm(searchTerm); + } else { + fetchedSongs = await fetchSongs(""); + } - // Intercalar canciones de la API y mockSongs const combinedSongs: Song[] = []; - const maxLength = Math.max(fetchedSongs.length, mockSongs.length); + const maxLength = Math.max(fetchedSongs.length, initialSongs.length); for (let i = 0; i < maxLength; i++) { if (i < fetchedSongs.length) { combinedSongs.push(fetchedSongs[i]); } - if (i < mockSongs.length) { - combinedSongs.push(mockSongs[i]); + if (i < initialSongs.length) { + combinedSongs.push(initialSongs[i]); } } - // Limitar a las primeras 15 canciones setSongs(combinedSongs.slice(0, 15)); } catch (error) { console.error("Error fetching songs:", error); @@ -46,7 +93,7 @@ export default function SongList({ }; loadSongs(); - }, [searchTerm]); + }, [searchTerm, initialSongs]); const handlePlay = useCallback( (song: Song) => { @@ -91,7 +138,6 @@ export default function SongList({ }, []); const filteredSongs = useFilterSongs(songs, searchTerm, selectedGenre); - console.log("Filtered Songs:", filteredSongs); // Debug log return (
@@ -106,8 +152,8 @@ export default function SongList({ duration={formatDuration(song.duration)} md5_image={song.md5_image} preview={song.preview} - artist={song.artist.name} - artistImage={song.artist.picture_medium} + artist={song.artist?.name || "Unknown Artist"} + artistImage={song.artist?.picture_medium || ""} isFavorite={song.isFavorite} isSelected={selectedSong?.id === song.id} onPlay={() => handlePlay(song)} @@ -119,10 +165,10 @@ export default function SongList({ { + if (!Array.isArray(songs)) { + return []; + } + + return songs.filter((song) => { + const matchesSearch = [song.title, song.artist?.name, ...(Array.isArray(song.album.genres) ? song.album.genres : [song.album.genres])] + .map((field) => (typeof field === "string" ? field : "").toLowerCase()) + .some((value) => value.includes(searchTerm.toLowerCase())); + + const genres = Array.isArray(song.album.genres) ? song.album.genres : [song.album.genres]; + const matchesGenre = + selectedGenre === "Todos" || genres.some((genre) => + genre.toLowerCase().includes(selectedGenre.toLowerCase()) + ); + + return matchesSearch && matchesGenre; + }); +}; diff --git a/frontend/src/types/ui/Song.ts b/frontend/src/types/ui/Song.ts index 14955c3..5d6022b 100644 --- a/frontend/src/types/ui/Song.ts +++ b/frontend/src/types/ui/Song.ts @@ -5,7 +5,7 @@ export interface Song { title_short: string; duration: string; preview: string; - md5_image: string; + md5_image: string | null; artist: Artist; album: Album; isFavorite: boolean; @@ -16,23 +16,41 @@ export interface Song { export interface Artist { id: string; name: string; - picture: string; - picture_small: string; picture_medium: string; - picture_big: string; - picture_xl: string; - tracklist: string; + picture: string | null; + picture_small: string | null; + picture_big: string | null; + picture_xl: string | null; + tracklist: string | null; } export interface Album { id: string; title: string; - cover: string; - cover_small: string; - cover_medium: string; - cover_big: string; - cover_xl: string; - md5_image: string; - tracklist: string; genres: string | null; + cover: string | null; + cover_small: string | null; + cover_medium: string | null; + cover_big: string | null; + cover_xl: string | null; + md5_image: string | null; + tracklist: string | null; + +} + +export interface newSong { + id: string; + title: string; + duration: number; + preview: string; + artist: { + id: string; + name: string; + picture_medium: string; + }; + album: { + id: string; + title: string; + genres: string[]; + }; } diff --git a/frontend/src/utils/fetchSongs.ts b/frontend/src/utils/fetchSongs.ts index 30240e0..f8ca565 100644 --- a/frontend/src/utils/fetchSongs.ts +++ b/frontend/src/utils/fetchSongs.ts @@ -1,3 +1,6 @@ + +//Primera ruta api deezer + export const fetchSongs = async (track: string) => { const genres = ["pop", "rock", "electronica", "clasica", "hip-hop", "rap", "k-pop"]; @@ -17,7 +20,7 @@ export const fetchSongs = async (track: string) => { const data = await response.json(); //console.log('API Response:', data); // Debug log - // Asegurarse de acceder al arreglo de canciones dentro de la estructura de datos + // Acceder al arreglo de canciones dentro de la estructura de datos const songs = data.data.data || []; //console.log('Extracted Songs:', songs); // Debug log @@ -28,3 +31,93 @@ export const fetchSongs = async (track: string) => { return []; } }; + + +//Nueva ruta +/* +export const fetchSongs = async (track: string) => { + const response = await fetch(`http://144.33.15.219:8080/search/?track=${encodeURIComponent(track)}&page=0&size=15`, { + headers: { + 'accept': 'application/json' + } + }); + + if (!response.ok) { + throw new Error('Error fetching songs'); + } + + const data = await response.json(); + const songs = data.data || []; + + if (songs.length > 0) { + return songs.map(song => ({ + id: song.id.toString(), + title: song.title, + title_short: song.title, + duration: song.duration.toString(), + preview: song.preview, + md5_image: null, + artist: { + id: song.artist.id.toString(), + name: song.artist.name, + picture_medium: song.artist.picture_medium, + picture: null, + picture_small: null, + picture_big: null, + picture_xl: null, + tracklist: null + }, + album: { + id: song.album.id.toString(), + title: song.album.genres, + genres: song.album.genres, + cover: null, + cover_small: null, + cover_medium: null, + cover_big: null, + cover_xl: null, + md5_image: null, + tracklist: null + }, + isFavorite: false + })); + } else { + console.warn('No songs found'); + return []; + } +}; +*/ + + +//Ruta para traer canciones por genero +export const fetchSongsByGenre = async (genre: string) => { + const url = `http://144.33.15.219:8080/tracks?genre=${genre}`; + return fetchSongsList(url); +}; + +export const fetchSongsBySearchTerm = async (searchTerm: string) => { + const url = `http://144.33.15.219:8080/search?track=${encodeURIComponent(searchTerm)}`; + return fetchSongsList(url); +}; + +const fetchSongsList = async (url: string) => { + const response = await fetch(url, { + headers: { + 'accept': 'application/json' + } + }); + + if (!response.ok) { + throw new Error('Error fetching songs'); + } + + const data = await response.json(); + const songs = data.data || []; + + if (songs.length > 0) { + return songs; + } else { + console.warn('No songs found'); + return []; + } +}; diff --git a/frontend/src/utils/fetchindividuales.ts b/frontend/src/utils/fetchindividuales.ts new file mode 100644 index 0000000..19bf27a --- /dev/null +++ b/frontend/src/utils/fetchindividuales.ts @@ -0,0 +1,89 @@ +/*Primera ruta +export const fetchSongs = async (track: string) => { + const genres = ["pop", "rock", "electronica", "clasica", "hip-hop", "rap", "k-pop"]; + + const formattedTrack = track ? `'${track}'` : `'${genres[Math.floor(Math.random() * genres.length)]}'`; + //console.log(`Fetching songs for track: ${formattedTrack}`); // Debug log + + const response = await fetch(`http://144.33.15.219:8080/search?track=${encodeURIComponent(formattedTrack)}`, { + headers: { + 'accept': 'application/json' + } + }); + + if (!response.ok) { + throw new Error('Error fetching songs'); + } + + const data = await response.json(); + //console.log('API Response:', data); // Debug log + + // Asegurarse de acceder al arreglo de canciones dentro de la estructura de datos + const songs = data.data.data || []; + //console.log('Extracted Songs:', songs); // Debug log + + if (songs.length > 0) { + return songs; + } else { + console.warn('No songs found'); + return []; + } +}; + + +*/ +// Nueva ruta implementada + +/* +export const fetchSongs = async (track: string) => { + const response = await fetch(`http://144.33.15.219:8080/search/?track=${encodeURIComponent(track)}&page=0&size=15`, { + headers: { + 'accept': 'application/json' + } + }); + + if (!response.ok) { + throw new Error('Error fetching songs'); + } + + const data = await response.json(); + const songs = data.data || []; + + if (songs.length > 0) { + return songs.map(song => ({ + id: song.id.toString(), + title: song.title, + title_short: song.title, + duration: song.duration.toString(), + preview: song.preview, + md5_image: null, + artist: { + id: song.artist.id.toString(), + name: song.artist.name, + picture_medium: song.artist.picture_medium, + picture: null, + picture_small: null, + picture_big: null, + picture_xl: null, + tracklist: null + }, + album: { + id: song.album.id.toString(), + title: song.album.genres, + genres: song.album.genres, + cover: null, + cover_small: null, + cover_medium: null, + cover_big: null, + cover_xl: null, + md5_image: null, + tracklist: null + }, + isFavorite: false + })); + } else { + console.warn('No songs found'); + return []; + } +}; +*/ \ No newline at end of file