diff --git a/frontend/public/songs/1.mp3 b/frontend/public/songs/1.mp3 new file mode 100644 index 0000000..6e9b924 Binary files /dev/null and b/frontend/public/songs/1.mp3 differ diff --git a/frontend/public/songs/10.mp3 b/frontend/public/songs/10.mp3 new file mode 100644 index 0000000..ef1b5c1 Binary files /dev/null and b/frontend/public/songs/10.mp3 differ diff --git a/frontend/public/songs/11.mp3 b/frontend/public/songs/11.mp3 new file mode 100644 index 0000000..a6e12a1 Binary files /dev/null and b/frontend/public/songs/11.mp3 differ diff --git a/frontend/public/songs/12.mp3 b/frontend/public/songs/12.mp3 new file mode 100644 index 0000000..7519882 Binary files /dev/null and b/frontend/public/songs/12.mp3 differ diff --git a/frontend/public/songs/13.mp3 b/frontend/public/songs/13.mp3 new file mode 100644 index 0000000..4f4149f Binary files /dev/null and b/frontend/public/songs/13.mp3 differ diff --git a/frontend/public/songs/14.mp3 b/frontend/public/songs/14.mp3 new file mode 100644 index 0000000..5d25bb2 Binary files /dev/null and b/frontend/public/songs/14.mp3 differ diff --git a/frontend/public/songs/15.mp3 b/frontend/public/songs/15.mp3 new file mode 100644 index 0000000..ab9f05c Binary files /dev/null and b/frontend/public/songs/15.mp3 differ diff --git a/frontend/public/songs/16.mp3 b/frontend/public/songs/16.mp3 new file mode 100644 index 0000000..4c686de Binary files /dev/null and b/frontend/public/songs/16.mp3 differ diff --git a/frontend/public/songs/17.mp3 b/frontend/public/songs/17.mp3 new file mode 100644 index 0000000..e59f27f Binary files /dev/null and b/frontend/public/songs/17.mp3 differ diff --git a/frontend/public/songs/18.mp3 b/frontend/public/songs/18.mp3 new file mode 100644 index 0000000..fa64d46 Binary files /dev/null and b/frontend/public/songs/18.mp3 differ diff --git a/frontend/public/songs/2.mp3 b/frontend/public/songs/2.mp3 new file mode 100644 index 0000000..0d3aa92 Binary files /dev/null and b/frontend/public/songs/2.mp3 differ diff --git a/frontend/public/songs/3.mp3 b/frontend/public/songs/3.mp3 new file mode 100644 index 0000000..ad8455a Binary files /dev/null and b/frontend/public/songs/3.mp3 differ diff --git a/frontend/public/songs/4.mp3 b/frontend/public/songs/4.mp3 new file mode 100644 index 0000000..ad8455a Binary files /dev/null and b/frontend/public/songs/4.mp3 differ diff --git a/frontend/public/songs/5.mp3 b/frontend/public/songs/5.mp3 new file mode 100644 index 0000000..ad8c5e3 Binary files /dev/null and b/frontend/public/songs/5.mp3 differ diff --git a/frontend/public/songs/6.mp3 b/frontend/public/songs/6.mp3 new file mode 100644 index 0000000..9812b8f Binary files /dev/null and b/frontend/public/songs/6.mp3 differ diff --git a/frontend/public/songs/7.mp3 b/frontend/public/songs/7.mp3 new file mode 100644 index 0000000..6d4a998 Binary files /dev/null and b/frontend/public/songs/7.mp3 differ diff --git a/frontend/public/songs/8.mp3 b/frontend/public/songs/8.mp3 new file mode 100644 index 0000000..0b5868e Binary files /dev/null and b/frontend/public/songs/8.mp3 differ diff --git a/frontend/public/songs/9.mp3 b/frontend/public/songs/9.mp3 new file mode 100644 index 0000000..6388b2e Binary files /dev/null and b/frontend/public/songs/9.mp3 differ diff --git a/frontend/src/app/(page)/explore/components/SongItem.tsx b/frontend/src/app/(page)/explore/components/SongItem.tsx index 351d648..4d32408 100644 --- a/frontend/src/app/(page)/explore/components/SongItem.tsx +++ b/frontend/src/app/(page)/explore/components/SongItem.tsx @@ -3,12 +3,18 @@ import Image from "next/image"; import { Heart } from "lucide-react"; interface SongItemProps { + id: string; title: string; + title_short: string; + duration: string; + preview: string; + md5_image: string; artist: string; genre: string; - duration: string; + isSelected: boolean; isFavorite: boolean; + onFavoriteToggle: () => void; onPlay: () => void; } diff --git a/frontend/src/app/(page)/explore/components/SongList.tsx b/frontend/src/app/(page)/explore/components/SongList.tsx index 406d5c3..fedb3af 100644 --- a/frontend/src/app/(page)/explore/components/SongList.tsx +++ b/frontend/src/app/(page)/explore/components/SongList.tsx @@ -1,10 +1,10 @@ -// SongList.tsx -import React, { useState } from "react"; +import React, { useState, useCallback } from "react"; import SongItem from "./SongItem"; import Player from "@/components/ui/Player"; import { useFilterSongs } from "@/hooks/useFilterSongs"; import { mockSongs } from "@/data/mockSongs"; import { Song } from "@/types/ui/Song"; +import { formatDuration } from "@/app/utils/formatDuration"; interface SongListProps { searchTerm?: string; @@ -18,42 +18,89 @@ export default function SongList({ const [selectedSong, setSelectedSong] = useState(null); const [isPlaying, setIsPlaying] = useState(false); const [songs, setSongs] = useState(mockSongs); - const filteredSongs = useFilterSongs(songs, searchTerm, selectedGenre); - const handlePlay = (song: Song) => { - setSelectedSong(song); - setIsPlaying(true); - }; + const handlePlay = useCallback( + (song: Song) => { + if (selectedSong?.id === song.id) { + setIsPlaying(!isPlaying); + } else { + setSelectedSong(song); + setIsPlaying(true); + } + }, + [selectedSong, isPlaying] + ); + + const handlePlayPause = useCallback(() => { + setIsPlaying(!isPlaying); + }, [isPlaying]); + + const handleNext = useCallback(() => { + if (!selectedSong) return; + const currentIndex = filteredSongs.findIndex( + (song) => song.id === selectedSong.id + ); + if (currentIndex < filteredSongs.length - 1) { + setSelectedSong(filteredSongs[currentIndex + 1]); + setIsPlaying(true); + } + }, [selectedSong, filteredSongs]); + + const handlePrevious = useCallback(() => { + if (!selectedSong) return; + const currentIndex = filteredSongs.findIndex( + (song) => song.id === selectedSong.id + ); + if (currentIndex > 0) { + setSelectedSong(filteredSongs[currentIndex - 1]); + setIsPlaying(true); + } + }, [selectedSong, filteredSongs]); - const toggleFavorite = (songId: string) => { + const toggleFavorite = useCallback((songId: string) => { setSongs((prevSongs) => prevSongs.map((song) => song.id === songId ? { ...song, isFavorite: !song.isFavorite } : song ) ); - }; + }, []); return (
- {filteredSongs.map((song) => ( - handlePlay(song)} - onFavoriteToggle={() => toggleFavorite(song.id)} - /> - ))} +
+ {filteredSongs.map((song) => ( + handlePlay(song)} + onFavoriteToggle={() => toggleFavorite(song.id)} + /> + ))} +
{selectedSong && ( setIsPlaying(!isPlaying)} + onPlayPause={handlePlayPause} + onNext={handleNext} + onPrevious={handlePrevious} + onFavoriteToggle={() => + selectedSong && toggleFavorite(selectedSong.id) + } /> )}
diff --git a/frontend/src/app/utils/formatDuration.ts b/frontend/src/app/utils/formatDuration.ts new file mode 100644 index 0000000..95fff0a --- /dev/null +++ b/frontend/src/app/utils/formatDuration.ts @@ -0,0 +1,6 @@ +export function formatDuration(durationInSeconds: string): string { + const totalSeconds = parseInt(durationInSeconds, 10); + const minutes = Math.floor(totalSeconds / 60); + const seconds = totalSeconds % 60; + return `${minutes}:${seconds.toString().padStart(2, "0")}`; +} diff --git a/frontend/src/components/ui/GenroButtons.tsx b/frontend/src/components/ui/GenroButtons.tsx index 3aff45d..0e773d8 100644 --- a/frontend/src/components/ui/GenroButtons.tsx +++ b/frontend/src/components/ui/GenroButtons.tsx @@ -7,7 +7,7 @@ interface GenreButtonsProps { const genres = [ "Todos", - "Electronica", + "Electrónica", "Pop", "Rock", "Rap", diff --git a/frontend/src/components/ui/Player.tsx b/frontend/src/components/ui/Player.tsx index 03840f7..84ebd68 100644 --- a/frontend/src/components/ui/Player.tsx +++ b/frontend/src/components/ui/Player.tsx @@ -1,5 +1,6 @@ import React, { useEffect, useRef, useState } from "react"; import Image from "next/image"; +import { formatDuration } from "@/app/utils/formatDuration"; import { SkipBack, Rewind, @@ -13,21 +14,91 @@ import { interface PlayerProps { currentSong?: { + id: string; title: string; artist: string; duration: string; genre: string; + preview: string; + isFavorite: boolean; }; isPlaying: boolean; onPlayPause: () => void; + onNext?: () => void; + onPrevious?: () => void; + onFavoriteToggle: (songId: string) => void; + isFavorite: boolean; } -const Player: React.FC = ({ currentSong }) => { - const [isPlaying, setIsPlaying] = useState(false); - const [isFavorite, setIsFavorite] = useState(false); - const [progress, setProgress] = useState(0); // Progreso de la canción +const Player: React.FC = ({ + currentSong, + isPlaying, + onPlayPause, + onNext, + onPrevious, + onFavoriteToggle, +}) => { + const [progress, setProgress] = useState(0); + const [currentTime, setCurrentTime] = useState("00:00"); + const [error, setError] = useState(null); const playerRef = useRef(null); + const audioRef = useRef(null); + const initializeAudio = () => { + if (!currentSong?.preview) return; + + if (audioRef.current) { + audioRef.current.pause(); + audioRef.current.src = ""; + } + + audioRef.current = new Audio(currentSong.preview); + audioRef.current.preload = "auto"; + + audioRef.current.addEventListener("loadeddata", () => { + setError(null); + if (isPlaying) { + audioRef.current?.play(); + } + }); + + audioRef.current.addEventListener("timeupdate", updateProgress); + audioRef.current.addEventListener("ended", handleSongEnd); + audioRef.current.addEventListener("error", handleAudioError); + }; + + useEffect(() => { + initializeAudio(); + return () => { + if (audioRef.current) { + audioRef.current.removeEventListener("timeupdate", updateProgress); + audioRef.current.removeEventListener("ended", handleSongEnd); + audioRef.current.removeEventListener("error", handleAudioError); + audioRef.current.pause(); + audioRef.current = null; + } + }; + }, [currentSong?.preview]); + + useEffect(() => { + if (!audioRef.current || error) return; + + if (isPlaying) { + audioRef.current.play().catch(handleAudioError); + } else { + audioRef.current.pause(); + } + }, [isPlaying, currentSong]); + + const updateProgress = () => { + if (!audioRef.current) return; + const duration = audioRef.current.duration; + const currentTime = audioRef.current.currentTime; + const progressPercent = (currentTime / duration) * 100; + setProgress(progressPercent); + setCurrentTime(formatTime(currentTime)); + }; + //Para que el player se mueva con el scroll y no pase a cubrir el footer useEffect(() => { const handleScroll = () => { const footer = document.querySelector("footer"); @@ -47,14 +118,56 @@ const Player: React.FC = ({ currentSong }) => { return () => window.removeEventListener("scroll", handleScroll); }, []); - useEffect(() => { - if (isPlaying) { - const interval = setInterval(() => { - setProgress((prev) => (prev >= 100 ? 0 : prev + 1)); - }, 1000); // Simula el progreso - return () => clearInterval(interval); - } - }, [isPlaying]); + const handleSongEnd = () => { + setProgress(0); + setCurrentTime("00:00"); + onPlayPause(); + if (onNext) onNext(); + }; + + const handleAudioError = (e: Event) => { + console.error("Audio error:", e); + setError("Error playing audio"); + onPlayPause(); + }; + + const handleSeek = (e: React.MouseEvent) => { + if (!audioRef.current) return; + + const progressBar = e.currentTarget; + const rect = progressBar.getBoundingClientRect(); + const x = e.clientX - rect.left; + const width = rect.width; + const percentage = x / width; + const seekTime = audioRef.current.duration * percentage; + + audioRef.current.currentTime = seekTime; + setProgress(percentage * 100); + }; + + const handleFastForward = () => { + if (!audioRef.current) return; + audioRef.current.currentTime = Math.min( + audioRef.current.currentTime + 10, + audioRef.current.duration + ); + }; + + const handleRewind = () => { + if (!audioRef.current) return; + audioRef.current.currentTime = Math.max( + audioRef.current.currentTime - 10, + 0 + ); + }; + + const formatTime = (time: number): string => { + const minutes = Math.floor(time / 60); + const seconds = Math.floor(time % 60); + return `${minutes.toString().padStart(2, "0")}:${seconds + .toString() + .padStart(2, "0")}`; + }; if (!currentSong) return null; @@ -63,7 +176,6 @@ const Player: React.FC = ({ currentSong }) => { ref={playerRef} className="fixed left-0 right-0 bottom-0 bg-black border border-primary shadow-[0_0_10px_rgba(0,227,227,0.1)] flex" > - {/* Contenedor de la imagen */}
= ({ currentSong }) => { />
- {/* Contenedor derecho */}
- {/* Información de la canción */}

{currentSong.title}

{currentSong.artist}

setIsFavorite(!isFavorite)} + className={`w-6 h-6 cursor-pointer transition-colors + ${ + currentSong.isFavorite + ? "text-primary fill-primary" + : "text-primary/60 hover:text-primary" + } + `} + onClick={() => onFavoriteToggle(currentSong.id)} />
- {/* Controles del reproductor */} +
- {/* Barra de progreso */} +
- 00:00 -
+ + {currentTime} + +
= ({ currentSong }) => { />
- {currentSong.duration} + {formatDuration(currentSong.duration)}
diff --git a/frontend/src/data/mockSongs.ts b/frontend/src/data/mockSongs.ts index 47937ff..420a363 100644 --- a/frontend/src/data/mockSongs.ts +++ b/frontend/src/data/mockSongs.ts @@ -1,9 +1,292 @@ import { Song } from "@/types/ui/Song"; export const mockSongs: Song[] = [ - { id: "1", title: "Electro Waves", artist: "DJ Spark", genre: "Electronica", duration: "3:45", imageUrl: "/bg-4.jpg", isFavorite: false }, - { id: "2", title: "Pop Paradise", artist: "Melody Queen", genre: "Pop", duration: "3:20", imageUrl: "/bg-4.jpg", isFavorite: false }, - { id: "3", title: "Electro Waves", artist: "DJ Spark", genre: "Electronica", duration: "3:45", imageUrl: "/bg-4.jpg", isFavorite: false }, - { id: "4", title: "Rock Anthem", artist: "The Guitars", genre: "Rock", duration: "4:10", imageUrl: "/bg-4.jpg", isFavorite: true }, - { id: "5", title: "Anthem", artist: "The Guitars", genre: "Rock", duration: "4:10", imageUrl: "/bg-4.jpg", isFavorite: true }, + { + id: "1", + title: "Morning Breeze", + title_short: "Morning", + duration: "30", + preview: "/songs/1.mp3", + md5_image: "abc123", + artist: { + id: "1", + name: "Acoustic Soul", + picture: "/artist-1.jpg", + picture_small: "/artist-1-small.jpg", + picture_medium: "/artist-1-medium.jpg", + picture_big: "/artist-1-big.jpg", + picture_xl: "/artist-1-xl.jpg", + tracklist: "/artist-1-tracklist" + }, + album: { + id: "1", + title: "Acoustic Dreams", + cover: "/album-1.jpg", + cover_small: "/album-1-small.jpg", + cover_medium: "/album-1-medium.jpg", + cover_big: "/album-1-big.jpg", + cover_xl: "/album-1-xl.jpg", + md5_image: "def456", + tracklist: "/album-1-tracklist" + }, + isFavorite: false, + genre: "Pop", + imageUrl: "/bg-1.jpg" + }, + { + id: "2", + title: "City Nights", + title_short: "City ", + duration: "30", + preview: "/songs/2.mp3", + md5_image: "abc123", + artist: { + id: "2", + name: "Acoustic Soul", + picture: "/artist-1.jpg", + picture_small: "/artist-1-small.jpg", + picture_medium: "/artist-1-medium.jpg", + picture_big: "/artist-1-big.jpg", + picture_xl: "/artist-1-xl.jpg", + tracklist: "/artist-1-tracklist" + }, + album: { + id: "2", + title: "Acoustic Dreams", + cover: "/album-1.jpg", + cover_small: "/album-1-small.jpg", + cover_medium: "/album-1-medium.jpg", + cover_big: "/album-1-big.jpg", + cover_xl: "/album-1-xl.jpg", + md5_image: "def456", + tracklist: "/album-1-tracklist" + }, + isFavorite: false, + genre: "Rap", + imageUrl: "/bg-1.jpg" + }, + { + id: "3", + title: "Summer Chil", + title_short: "Summer ", + duration: "30", + preview: "/songs/3.mp3", + md5_image: "abc123", + artist: { + id: "3", + name: "Acoustic Soul", + picture: "/artist-1.jpg", + picture_small: "/artist-1-small.jpg", + picture_medium: "/artist-1-medium.jpg", + picture_big: "/artist-1-big.jpg", + picture_xl: "/artist-1-xl.jpg", + tracklist: "/artist-1-tracklist" + }, + album: { + id: "3", + title: "Acoustic Dreams", + cover: "/album-1.jpg", + cover_small: "/album-1-small.jpg", + cover_medium: "/album-1-medium.jpg", + cover_big: "/album-1-big.jpg", + cover_xl: "/album-1-xl.jpg", + md5_image: "def456", + tracklist: "/album-1-tracklist" + }, + isFavorite: false, + genre: "Pop", + imageUrl: "/bg-1.jpg" + }, + { + id: "4", + title: "Epic Adventure", + title_short: "Adventure", + duration: "30", + preview: "/songs/4.mp3", + md5_image: "abc123", + artist: { + id: "4", + name: "Orchestra Waves", + picture: "/artist-1.jpg", + picture_small: "/artist-1-small.jpg", + picture_medium: "/artist-1-medium.jpg", + picture_big: "/artist-1-big.jpg", + picture_xl: "/artist-1-xl.jpg", + tracklist: "/artist-1-tracklist" + }, + album: { + id: "4", + title: "Acoustic Dreams", + cover: "/album-1.jpg", + cover_small: "/album-1-small.jpg", + cover_medium: "/album-1-medium.jpg", + cover_big: "/album-1-big.jpg", + cover_xl: "/album-1-xl.jpg", + md5_image: "def456", + tracklist: "/album-1-tracklist" + }, + isFavorite: false, + genre: "Pop", + imageUrl: "/bg-1.jpg" + }, + { + id: "5", + title: "Deep Beats", + title_short: "Deep ", + duration: "30", + preview: "/songs/5.mp3", + md5_image: "abc123", + artist: { + id: "5", + name: "Acoustic Soul", + picture: "/artist-1.jpg", + picture_small: "/artist-1-small.jpg", + picture_medium: "/artist-1-medium.jpg", + picture_big: "/artist-1-big.jpg", + picture_xl: "/artist-1-xl.jpg", + tracklist: "/artist-1-tracklist" + }, + album: { + id: "5", + title: "Acoustic Dreams", + cover: "/album-1.jpg", + cover_small: "/album-1-small.jpg", + cover_medium: "/album-1-medium.jpg", + cover_big: "/album-1-big.jpg", + cover_xl: "/album-1-xl.jpg", + md5_image: "def456", + tracklist: "/album-1-tracklist" + }, + isFavorite: false, + genre: "Electrónica", + imageUrl: "/bg-1.jpg" + }, + { + id: "6", + title: "Golden Memories", + title_short: "Golden ", + duration: "30", + preview: "/songs/6.mp3", + md5_image: "abc123", + artist: { + id: "6", + name: "Acoustic Soul", + picture: "/artist-1.jpg", + picture_small: "/artist-1-small.jpg", + picture_medium: "/artist-1-medium.jpg", + picture_big: "/artist-1-big.jpg", + picture_xl: "/artist-1-xl.jpg", + tracklist: "/artist-1-tracklist" + }, + album: { + id: "6", + title: "Acoustic Dreams", + cover: "/album-1.jpg", + cover_small: "/album-1-small.jpg", + cover_medium: "/album-1-medium.jpg", + cover_big: "/album-1-big.jpg", + cover_xl: "/album-1-xl.jpg", + md5_image: "def456", + tracklist: "/album-1-tracklist" + }, + isFavorite: false, + genre: "Pop", + imageUrl: "/bg-1.jpg" + }, { + id: "7", + title: "Latin Fiesta", + title_short: "Fiesta ", + duration: "30", + preview: "/songs/7.mp3", + md5_image: "abc123", + artist: { + id: "7", + name: "Acoustic Soul", + picture: "/artist-1.jpg", + picture_small: "/artist-1-small.jpg", + picture_medium: "/artist-1-medium.jpg", + picture_big: "/artist-1-big.jpg", + picture_xl: "/artist-1-xl.jpg", + tracklist: "/artist-1-tracklist" + }, + album: { + id: "7", + title: "Acoustic Dreams", + cover: "/album-1.jpg", + cover_small: "/album-1-small.jpg", + cover_medium: "/album-1-medium.jpg", + cover_big: "/album-1-big.jpg", + cover_xl: "/album-1-xl.jpg", + md5_image: "def456", + tracklist: "/album-1-tracklist" + }, + isFavorite: false, + genre: "K-pop", + imageUrl: "/bg-1.jpg" + }, { + id: "8", + title: "Acoustic Dream", + title_short: "Dream ", + duration: "30", + preview: "/songs/8.mp3", + md5_image: "abc123", + artist: { + id: "8", + name: "Acoustic Soul", + picture: "/artist-1.jpg", + picture_small: "/artist-1-small.jpg", + picture_medium: "/artist-1-medium.jpg", + picture_big: "/artist-1-big.jpg", + picture_xl: "/artist-1-xl.jpg", + tracklist: "/artist-1-tracklist" + }, + album: { + id: "8", + title: "Acoustic Dreams", + cover: "/album-1.jpg", + cover_small: "/album-1-small.jpg", + cover_medium: "/album-1-medium.jpg", + cover_big: "/album-1-big.jpg", + cover_xl: "/album-1-xl.jpg", + md5_image: "def456", + tracklist: "/album-1-tracklist" + }, + isFavorite: false, + genre: "Pop", + imageUrl: "/bg-1.jpg" + }, { + id: "9", + title: "Nightfall Symphony", + title_short: "Symphony ", + duration: "30", + preview: "/songs/9.mp3", + md5_image: "abc123", + artist: { + id: "9", + name: "Acoustic Soul", + picture: "/artist-1.jpg", + picture_small: "/artist-1-small.jpg", + picture_medium: "/artist-1-medium.jpg", + picture_big: "/artist-1-big.jpg", + picture_xl: "/artist-1-xl.jpg", + tracklist: "/artist-1-tracklist" + }, + album: { + id: "9", + title: "Acoustic Dreams", + cover: "/album-1.jpg", + cover_small: "/album-1-small.jpg", + cover_medium: "/album-1-medium.jpg", + cover_big: "/album-1-big.jpg", + cover_xl: "/album-1-xl.jpg", + md5_image: "def456", + tracklist: "/album-1-tracklist" + }, + isFavorite: false, + genre: "clásica", + imageUrl: "/bg-1.jpg" + }, + + + ]; diff --git a/frontend/src/hooks/useFilterSongs.ts b/frontend/src/hooks/useFilterSongs.ts index 5767295..47805c4 100644 --- a/frontend/src/hooks/useFilterSongs.ts +++ b/frontend/src/hooks/useFilterSongs.ts @@ -1,11 +1,18 @@ import { Song } from "@/types/ui/Song"; -export const useFilterSongs = (songs: Song[], searchTerm: string, selectedGenre: string): Song[] => { +export const useFilterSongs = ( + songs: Song[], + searchTerm: string, + selectedGenre: string +): Song[] => { return songs.filter((song) => { - const matchesSearch = [song.title, song.artist, song.genre].some((field) => - field.toLowerCase().includes(searchTerm.toLowerCase()) - ); - const matchesGenre = selectedGenre === "Todos" || song.genre === selectedGenre; + const matchesSearch = [song.title, song.artist, song.genre] + .map((field) => (typeof field === "string" ? field : "").toLowerCase()) + .some((value) => value.includes(searchTerm.toLowerCase())); + + const matchesGenre = + selectedGenre === "Todos" || song.genre === selectedGenre; + return matchesSearch && matchesGenre; }); }; diff --git a/frontend/src/types/ui/Song.ts b/frontend/src/types/ui/Song.ts index 36724b8..371e338 100644 --- a/frontend/src/types/ui/Song.ts +++ b/frontend/src/types/ui/Song.ts @@ -1,13 +1,41 @@ + export interface Song { id: string; title: string; - artist: string; - genre: string; + title_short: string; duration: string; - imageUrl: string; + preview: string; + md5_image: string; + artist: Artist; + album: Album; isFavorite: boolean; + genre: string; + imageUrl: string; } export interface Genre { name: string; } + +export interface Artist { + id: string; + name: string; + picture: string; + picture_small: string; + picture_medium: string; + picture_big: string; + picture_xl: string; + tracklist: string; +} + +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; +}