diff --git a/public/css/spotify-lab.css b/public/css/spotify-lab.css index 6063712..223540e 100644 --- a/public/css/spotify-lab.css +++ b/public/css/spotify-lab.css @@ -7,8 +7,9 @@ --title-text: #f9fbfad5; --background-user: #d4d5d6; } -/* clase para ocualtar elementos con JS */ -.ocultar{ + +/* clase para ocultar elementos con JS */ +.ocultar { display: none; } @@ -46,7 +47,7 @@ body { padding: 20px; } -.genero-item{ +.genero-item { padding: 10px 20px; border: none; border-radius: 30px; @@ -61,7 +62,7 @@ body { margin-bottom: 20px; } -#cont-generos{ +#cont-generos { display: flex; flex-direction: column; justify-content: center; @@ -70,13 +71,13 @@ body { margin-bottom: 6%; } -.cont-btn-generos{ +.cont-btn-generos { display: grid; grid-template-columns: 50% 50%; width: 100%; } -.lab-form{ +.lab-form { width: 80%; display: flex; flex-direction: column; @@ -86,13 +87,13 @@ body { font-weight: 500; } -.lab-form input{ - width: 100%; +.lab-form input { + width: 90%; border-radius: 4px; border-style: none; } -.lab-form input[type="range"]{ +.lab-form input[type="range"] { height: 15px; background: white; outline: none; @@ -100,7 +101,7 @@ body { transition: opacity 0.2s; } -.lab-form input[type="range"]::-webkit-slider-thumb{ +.lab-form input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 25px; @@ -110,7 +111,7 @@ body { border-radius: 50%; } -.lab-form input[type="range"]::-moz-range-thumb{ +.lab-form input[type="range"]::-moz-range-thumb { width: 25px; height: 25px; background: blue; @@ -119,36 +120,27 @@ body { } -#valorTempo{ +#valorTempo { margin-bottom: 5%; } -.lab-form button{ +.lab-form button { font-size: 15px; padding: 10px; border-radius: 30px; width: 30%; - background-color: rgb(76, 253, 94); + background-color: rgb(87, 238, 102); margin: auto; border-style: none; } -.lab-form button:hover{ +.lab-form button:hover { border-right: 5px solid; border-left: 5px solid; border-color: rgba(67, 155, 222, 0.5); transition: ease-in-out 0.2s; } -/* No funciona TODO: */ -/* .user-pic-lg { - width: 670px; - height: 670px; - border-radius: 100%; - transform: scale(1.1); - box-shadow: 0 0 10px 10px rgba(73, 223, 215, 0.762); -} */ - .lab-resultado-container { display: flex; flex-direction: column; @@ -161,12 +153,13 @@ body { padding: 40px; } -.lab-intro{ +.lab-intro { display: flex; flex-direction: row-reverse; align-self: flex-end; } -.lab-intro #getInfo{ + +.lab-intro #getInfo { background-color: #f3f3f3; height: 30px; width: 30px; @@ -177,7 +170,7 @@ body { cursor: pointer; } -#info{ +#info { background-color: rgb(200, 246, 241); border-radius: 20px; text-align: center; @@ -187,7 +180,7 @@ body { margin: 0 1%; } -.lab-intro{ +.lab-intro { position: absolute; top: 5%; right: 2%; @@ -214,8 +207,8 @@ body { .valoracion { width: 100%; */ - /* Hacer que la valoración ocupe todo el ancho disponible en su área */ - /* margin: 10px; +/* Hacer que la valoración ocupe todo el ancho disponible en su área */ +/* margin: 10px; border-radius: 20px; background-color: rgba(255, 255, 255, 0.211); padding: 10px; @@ -225,21 +218,43 @@ body { grid-area: musica; } -.spotify-playlists{ - display : flex; +/* #btnEnviar{ + background-color: #f3f3f3; + border-radius: 30px; + padding: 10px; + border-style: none; + cursor: pointer; +} */ + +.spotify-playlists { + display: flex; flex: wrap; justify-items: center; - } - .spotify-playlist{ +} + +.spotify-playlist { width: 40%; +} + +#btnEnviar { + font-size: 17px; + padding: 10px; + border-radius: 30px; + width: 30%; + background-color: rgb(180, 87, 238); + margin: auto; + border-style: none; + :hover { + cursor: pointer; } +} @media screen and (max-width: 1200px) { /* Modal Info */ - .lab-intro{ + .lab-intro { position: absolute; top: 0; right: 0; diff --git a/public/js/lab.js b/public/js/lab.js index a36b505..433a014 100644 --- a/public/js/lab.js +++ b/public/js/lab.js @@ -8,11 +8,10 @@ for(let genero of arrGeneros){ let currentValues = inpGenero.value ? inpGenero.value.split(',') : []; let value = e.target.textContent.toLowerCase(); - if(currentValues.length < 5 && !currentValues.includes(value)){ + if(currentValues.length < 2 && !currentValues.includes(value)){ currentValues.push(value); inpGenero.value = currentValues.join(','); } - }); } @@ -28,42 +27,37 @@ function limpiarCadenaGenero(){ /**-----------> Colores aleatorios boton */ document.addEventListener('DOMContentLoaded', ()=>{ - // const buttons = document.querySelectorAll('.genero-item') for(let btn of arrGeneros){ const greenShade = getRandomGreenShade(); btn.style.backgroundColor = greenShade; } }); - function getRandomGreenShade(){ const r = 200 + Math.floor(Math.random()*55); const g = 200 + Math.floor(Math.random()*55); const b = 200 + Math.floor(Math.random()*55); const color = `rgb(${r}, ${g}, ${b})` - return color; } /**-----------> Slider tempo */ - let inpTempo = document.getElementById('tempo'); inpTempo.addEventListener('click', ()=>{ let tempoValue = inpTempo.value; let tempoSpan = document.getElementById('valorTempo'); tempoSpan.textContent = tempoValue; - // tempoSpan.innerHTML = tempoValue; + console.log(tempoValue); }); /**-----------> Boton info */ - const btnInfo = document.getElementById('getInfo'); const infoModal = document.getElementById('info'); btnInfo.addEventListener('click', ()=>{ infoModal.classList.toggle('ocultar'); }); - +/**-----------> API */ let codeFlowToken; async function getAccessToken() { @@ -104,7 +98,7 @@ async function fetchWebApi(endpoint, method, body = null) { } async function getTopTracks() { - const response = await fetchWebApi('v1/me/top/tracks?time_range=long_term&limit=5', 'GET'); + const response = await fetchWebApi('v1/me/top/tracks?time_range=long_term&limit=3', 'GET'); if (response && response.items) { console.log(response.items); return response.items; @@ -114,16 +108,23 @@ async function getTopTracks() { } } -async function getRecommendations(seedTracksIds) { - if (!Array.isArray(seedTracksIds) || seedTracksIds.length === 0) { - console.error('Invalid seed tracks IDs'); - return []; +async function getRecommendations(seedTracksIds, seedGenres, targetEnergy) { + + let endpoint = `v1/recommendations?limit=15`; + + if (seedGenres && seedGenres.length > 0) { + endpoint += `&seed_genres=${encodeURIComponent(seedGenres.join(','))}`; } - // v1/recommendations?seed_artists=4NHQUGzhtTLFvgF5SZesLK&seed_genres=classical%2Ccountry&seed_tracks=0c6xIDDpzE81m2q797ordA - // v1/recommendations?limit=9&seed_tracks=${seedTracksIds.join(',')} - const response = await fetchWebApi( - `v1/recommendations?limit=9&seed_tracks=${seedTracksIds.join(',')}`, 'GET' - ); + + if (Array.isArray(seedTracksIds) && seedTracksIds.length != 0) { + endpoint += `&seed_tracks=${encodeURIComponent(seedTracksIds.join(','))}`; + } + + if (targetEnergy) { + endpoint += `&target_energy=${targetEnergy}`; + } + + const response = await fetchWebApi(endpoint, 'GET'); if (response && response.tracks) { console.log(response.tracks); return response.tracks; @@ -139,11 +140,12 @@ async function createPlaylist(tracksUri) { console.error('Failed to fetch user info'); return null; } - + let playlistName = document.getElementById('playlistName').value; + console.log('playlistName:', playlistName); const userId = userResponse.id; const playlistResponse = await fetchWebApi( `v1/users/${userId}/playlists`, 'POST', { - "name": "Music-Life Lab recommendations", + "name": playlistName || "Music-Life Lab", "description": "Playlist created in the Music-Life Lab", "public": false } @@ -164,6 +166,7 @@ async function createPlaylist(tracksUri) { } async function generatePlaylist() { + console.log('generando playlist'); await getAccessToken(); // Ensure token is obtained if (!codeFlowToken) { console.error('No valid token found'); @@ -185,7 +188,10 @@ async function generatePlaylist() { } console.log('topTracksIds:', topTracksIds); - const recommendedTracks = await getRecommendations(topTracksIds); + let seedGenres = inpGenero.value ? inpGenero.value.split(',') : null; + let targetEnergy = inpTempo.value ? parseFloat(inpTempo.value) : null; + + const recommendedTracks = await getRecommendations(topTracksIds, seedGenres, targetEnergy); if (recommendedTracks.length === 0) { console.error('No recommendations available'); return; @@ -206,12 +212,23 @@ async function generatePlaylist() { title="Spotify Embed: Recommendation Playlist" src="https://open.spotify.com/embed/playlist/${createdPlaylist.id}?utm_source=generator&theme=1" width="100%" - height="320" + height="380" frameBorder="0" allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture" loading="lazy" >`; } +btnEnviar.addEventListener('click', generatePlaylist); + +// https://api.spotify.com/v1/recommendations?seed_artists=4NHQUGzhtTLFvgF5SZesLK&seed_genres=classical%2Ccountry&seed_tracks=0c6xIDDpzE81m2q797ordA + +// https://api.spotify.com/v1/recommendations?seed_genres=classical%2Ctechno&seed_tracks=0c6xIDDpzE81m2q797ordA%2CC0nLMjIuOsMjEq4IKuJ2twa%2C57dlsdCfq4XUf2AvIMk1jS&target_tempo=0.85 + +// https://api.spotify.com/v1/recommendations?limit=15&seed_genres=jazz%2Cindie%2Crock&seed_tracks=5lxZ3KmRdRn6iW5tE1Fwjp%2C5tMLIgw6yxobsAyIVvfHo5%2C0GdiWLQt5VYtMEcero6AOW%2C0nLMjIuOsMjEq4IKuJ2twa%2C57dlsdCfq4XUf2AvIMk1jS&target_energy=0.75 + + +// https://api.spotify.com/v1/recommendations?seed_genres=classical%2Ctechno&seed_tracks=%275lxZ3KmRdRn6iW5tE1Fwjp%27%2C+%275tMLIgw6yxobsAyIVvfHo5%27%2C+%270GdiWLQt5VYtMEcero6AOW%27%2C+%270nLMjIuOsMjEq4IKuJ2twa%27%2C+%2757dlsdCfq4XUf2AvIMk1jS%27&target_tempo=0.85 + +// https://api.spotify.com/v1/recommendations?seed_genres=classical%2Cindie&seed_tracks=5lxZ3KmRdRn6iW5tE1Fwjp%2C5tMLIgw6yxobsAyIVvfHo5%2C0GdiWLQt5VYtMEcero6AOW%2C0nLMjIuOsMjEq4IKuJ2twa%2C57dlsdCfq4XUf2AvIMk1jS -btnEnviar.addEventListener('click', generatePlaylist); \ No newline at end of file diff --git a/public/oauthSpotifyLibrary.php b/public/oauthSpotifyLibrary.php index e2a5921..01b3ba3 100644 --- a/public/oauthSpotifyLibrary.php +++ b/public/oauthSpotifyLibrary.php @@ -15,12 +15,17 @@ // Later, after Spotify redirects to your redirect URI if (isset($_GET['code'])) { $state = $_GET['state']; + //console log de php + $storedState = $_SESSION['state']; // Fetch the stored state value from somewhere. A session for example if ($state !== $storedState) { + echo ""; // The state returned isn't the same as the one we've stored, we shouldn't continue - header('Location: ' . DOC_ROOT . '/public/index.php'); - die('State mismatch'); + // $msje = "Error al conectar con Spotify"; + // $mensajeCodificado = urlencode($msj); + // header("Location: http://music-life.es/index.php?mensaje=" . $mensajeCodificado); + // die('State mismatch'); } // Request an access token using the code from Spotify diff --git a/public/spotifyLab.php b/public/spotifyLab.php index ec04bdf..8267c20 100644 --- a/public/spotifyLab.php +++ b/public/spotifyLab.php @@ -23,9 +23,8 @@ 'email' => $spotifyUserResponse->email, 'image' => $spotifyUserResponse->images[0]->url, ]; -} else { - echo 'No se ha podido conectar con Spotify'; } + ?> @@ -89,28 +85,29 @@ con Spotify -
- -
+ + +
+ +

- Classic + Classical Jazz Pop Rock - Alternative + Techno Indie
- - + + 0 - - +
@@ -142,11 +139,11 @@
-

Tu nueva playlist:

+ +

Crea tu playlist

+
-
?