From 5b57f1b9acd8c997f4298160c3312a25485be688 Mon Sep 17 00:00:00 2001 From: Alessio Ganzarolli Date: Sat, 2 Aug 2025 06:39:52 +0200 Subject: [PATCH] feat: spotify search --- app/src/components/Queue.tsx | 201 +++++++++++++++++++++++------------ 1 file changed, 135 insertions(+), 66 deletions(-) diff --git a/app/src/components/Queue.tsx b/app/src/components/Queue.tsx index 595a808..dc12600 100644 --- a/app/src/components/Queue.tsx +++ b/app/src/components/Queue.tsx @@ -8,11 +8,17 @@ import { IonSearchbar, IonTitle, IonToolbar, + IonList, + IonItem, + IonLabel, } from "@ionic/react"; -import React, { useState } from "react"; +import React, { useState, useEffect, useRef } from "react"; + import { ArrowBigUp, Plus } from "lucide-react"; -import { motion, AnimatePresence } from "framer-motion"; +import { useCoda } from "../hooks/useCoda"; + + interface NowPlayingDiscProps { id: string; @@ -23,19 +29,80 @@ interface NowPlayingDiscProps { upvotes?: number; } -interface QueueProps { - songs: NowPlayingDiscProps[]; - onUpvote: (id: string) => void; -} +const Queue: React.FC = () => { + const { records, addRecord, updateVoti } = useCoda(); -const Queue: React.FC = ({ songs, onUpvote }) => { const [showModal, setShowModal] = useState(false); const [searchText, setSearchText] = useState(""); + const [searchResults, setSearchResults] = useState([]); + const debounceTimeout = useRef(); - // Ordina i brani in ordine decrescente per upvotes - const sortedSongs = [...songs].sort( - (a, b) => (b.upvotes ?? 0) - (a.upvotes ?? 0) - ); + // Ordina i brani in ordine decrescente per voti (dal DB) + const sortedSongs = [...records].sort((a, b) => b.voti - a.voti); + + // Effetto debounce per chiamare API dopo 2 secondi + useEffect(() => { + if (!searchText) { + setSearchResults([]); + return; + } + + if (debounceTimeout.current) { + clearTimeout(debounceTimeout.current); + } + + debounceTimeout.current = setTimeout(() => { + fetch( + `https://fbbb261497e3.ngrok-free.app/music/search?query=${encodeURIComponent(searchText)}` + ) + .then((res) => res.json()) + .then((data) => { + const results: NowPlayingDiscProps[] = data.tracks?.items.map((item: any) => ({ + id: item.id, + coverUrl: item.album?.images?.[0]?.url || "", + title: item.name, + artist: item.artists?.map((a: any) => a.name).join(", ") || "", + upvotes: 0, + upvoted: false, + })) || []; + + setSearchResults(results); + }) + .catch((err) => { + console.error("Error fetching search results:", err); + setSearchResults([]); + }); + }, 2000); + + return () => { + if (debounceTimeout.current) { + clearTimeout(debounceTimeout.current); + } + }; + }, [searchText]); + + // Funzione per aggiungere o incrementare voto in DB + const handleAddSong = (song: NowPlayingDiscProps) => { + // Cerco se è già presente nel DB (records) + const existing = records.find((r) => r.id === song.id); + + if (existing) { + // Incrementa il voto + updateVoti(existing.id, true); + } else { + // Aggiunge la nuova canzone al DB + addRecord({ + titolo: song.title, + coverUrl: song.coverUrl, + artista: song.artist, + color: "#ff6600", // puoi decidere un colore o gestirlo dinamicamente + voti: 1, + }); + } + setShowModal(false); + setSearchText(""); + setSearchResults([]); + }; return (
@@ -46,71 +113,57 @@ const Queue: React.FC = ({ songs, onUpvote }) => { color="white" strokeWidth={2} onClick={() => setShowModal(true)} + style={{ cursor: "pointer" }} />
- - {sortedSongs.map((song) => { - const isUpvoted = song.upvoted ?? false; - const votes = song.upvotes ?? 0; + {sortedSongs.map((song) => ( +
+ {`${song.titolo} +
+
{song.titolo}
+
{song.artista}
+
- return ( - updateVoti(song.id, true)} + > + - {`${song.title} -
-
{song.title}
-
{song.artist}
-
- -
onUpvote(song.id)} - > - - {votes} - - -
-
- ); - })} - + {song.voti} + + +
+ + ))} setShowModal(false)}> Add Songs - setShowModal(false)}> + setShowModal(false)} + > Close @@ -121,6 +174,22 @@ const Queue: React.FC = ({ songs, onUpvote }) => { onIonInput={(e) => setSearchText(e.detail.value!)} placeholder="Search..." /> + + + {searchResults.map((song) => ( + handleAddSong(song)}> + {song.title} + +

{song.title}

+

{song.artist}

+
+
+ ))} +