Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
49 changes: 27 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
# 📊 Project: Complex API

### Goal: Use data returned from one api to make a request to another api and display the data returned

### How to submit your code for review:

- Fork and clone this repo
- Create a new branch called answer
- Checkout answer branch
- Push to your fork
- Issue a pull request
- Your pull request description should contain the following:
- (1 to 5 no 3) I completed the challenge
- (1 to 5 no 3) I feel good about my code
- Anything specific on which you want feedback!

Example:
```
I completed the challenge: 5
I feel good about my code: 4
I'm not sure if my constructors are setup cleanly...
```
# Music Calculator
<hr>

_This is an app that sends a request to the Tastedive and AudioDB APIs to calculate a new artist for you to enjoy based off of magical musical calculations._

<hr>

<a style="text-align:center" href="https://godwinkamau.github.io/complex-api/">Here is the rendered project</a>

<br>

<img src="./Screenshot 2025-11-09 at 9.23.46 PM.png" alt="preview of the app">


## How It's Made:
_Tech used: HTML, CSS, JavaScript, Restful APIs_

I used fetch requests to grab an artist from a music database. The result(s) of your search(es) are then passed through TasteDive to find artists that cross-correlate with your artists. The top result is displayed while tertiary results are given as links for you to follow up on.


## Lessons Learned:
API databases are really fun! The extent that people go to to make information accessible is amazing. On the tech side, I learned about properly working with asynchronous behavior using ```.then()``` statements.

### More Projects:
<a href="https://github.com/godwinKamau/wu-tang-generator-bootcamp">Wu-Tang Name Generator</a>

<a href="https://github.com/godwinKamau/chatroom">A really slick chatroom</a>
Binary file added Screenshot 2025-11-09 at 9.23.46 PM.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
146 changes: 146 additions & 0 deletions css/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
body {
display:flex;
flex-direction: column;
background-color: #000;
color:white;
font-family: 'Lexend','Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
}

.introContainer{
height:150px;
display: flex;
align-content: center;
justify-content: space-between;
}

h1 {
font-family: 'Poiret One',Arial, Helvetica, sans-serif;
}

.directions {
height:20%;
text-align: center;
font-family: 'Poiret One',Arial, Helvetica, sans-serif;
}

h4 {
font-size: 1.3rem;
}

.inputs {
display: flex;
height: 50%;
width: 100%;
flex-direction: row;
align-content: center;
justify-content: space-around;
flex-wrap: wrap;
font-size: 1.5rem;
}

.inputs > div {
display: flex;
align-content: center;
justify-content: center;
flex-wrap: wrap;
}

input {
height:3rem;
font-size: 1.5rem;
width:25%;
background-color: gray;
}

.title{
background-color: #121212;
width:35%;
padding-left: 30px;
}
/* got this button from this site: https://prismic.io/blog/css-button-animations */
.btn {
position: relative;
padding: 1.5rem 3rem;
font-size: 1.1rem;
font-weight: 600;
color: #fff;
background: none;
border: none;
cursor: pointer;
overflow: hidden;
transition: all 0.4s ease;
min-width: 200px;
z-index: 1;
height:100px;
margin: auto;
}

.neon-pulse {
background: #000;
border: 2px solid #0ff;
box-shadow: 0 0 10px rgba(0, 255, 255, 0.3);
overflow: visible;
}

.neon-pulse::before,
.neon-pulse::after {
content: "";
position: absolute;
inset: -4px;
border: 2px solid #0ff;
border-radius: inherit;
animation: pulseOut 2s ease-out infinite;
opacity: 0;
}

.neon-pulse::after {
animation-delay: 1s;
}

@keyframes pulseOut {
0% {
transform: scale(1);
opacity: 1;
}
100% {
transform: scale(1.5);
opacity: 0;
}
}

.recContainer{
display: flex;
height:700px;
background: linear-gradient(132deg, #000000,#007300, #00007b,#7e003f,#7a0000,#807e7e);
background-size: 400% 400%;
animation: BackgroundGradient 15s ease infinite;
justify-content: space-around;
}

@keyframes BackgroundGradient {
0% {background-position: 0% 50%;}
50% {background-position: 100% 50%;}
100% {background-position: 0% 50%;}
}

a{
color:black
}

h2 {
font-size: 1.5rem;
}

li {
padding:4px;
display: inline-flex;
flex-wrap: wrap;
}

img {
margin-right: 5px;
}

a:hover {
color:white
}
46 changes: 46 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Music Recommender</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="I really need to get off Spotify">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Lexend:wght@100..900&family=Poiret+One&display=swap" rel="stylesheet">
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
<section class="introContainer">
<section class="title">
<h1>Music Calculator</h1>
<p>Find a new artist by mixing artists together</p>
</section>
<section class="calculator">
<section class="directions">
<h4>Input your music/musicians here</h4>
</section>
<section class="inputs">
<input type="text"><div> + </div><input type="text" name="" id=""><div> + </div><input type="text">
</section>
</section>
<button class="btn neon-pulse">
<span>Calculate!</span>
</button>

</section>


<section class="recContainer">
<img>
<section class="words">
<h2></h2>
<a></a>
<h3></h3>
<h4></h4>
<ul></ul>
</section>
</section>
<script type="text/javascript" src="js/main.js"></script>
</body>
</html>
113 changes: 113 additions & 0 deletions js/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// const spotifyAPIKey = 'bd5fd62c63e64962ab58abf607daaddb'

// ///access codes/// needs to be updated every hour
// let Spotifyaccess = {"access_token":"BQCikM5m0vjgBmjhToCQak0PMKq7HGHElIoZnMsFb5MW2ywxuRftEZoc1yYVkUnEogHAmopYZFkLzL_vbb5wiJUt7ma0aeDZG5vIYoMsk6v_9D2AzQpxhdY_9LjT2HhqL41VE2_n-3Y","token_type":"Bearer","expires_in":3600}



// //learned how to use headers and cURL from this article: https://apidog.com/blog/curl-javascript-fetch/
// // fetch('https://api.spotify.com/v1/playlists/7f87ZT5QeiF5Ycyv4EUn3q', {
// // headers: {
// // 'Authorization':`Bearer ${Spotifyaccess.access_token}`
// // },
// // method:'GET'
// // })
// // .then(res => res.json())
// // .then(data => {
// // let musicChoices = []
// // data.tracks.items.forEach(item =>
// // musicChoices.push(item.track.name.toLowerCase().split(' ').join('+'))
// // )
// // const musicString = musicChoices.join('%2C+')
// // console.log(musicString)

// // fetch(`https://corsproxy.io/?url=https://tastedive.com/api/similar?q=${musicString}&type=music&k=${tastediveAPI}&info=1`)
// // .then(res => res.json())
// // .then(data => {
// // console.log(data)
// // console.log(data.similar.results[0])
// // })
// // })
// // .catch(err => console.log('Error: ' + err))

document.querySelector('button').addEventListener('click',calculate)

function calculate() {
const musicArray = []
document.querySelectorAll('input').forEach(input =>
musicArray.push(input.value.toLowerCase().split(' ').join('+'))
)
const musicString = musicArray.join('%2C+')
console.log(musicString)
const tastediveAPI = '1059798-GodwinKa-6A33A965'
fetch(`https://corsproxy.io/?url=https://tastedive.com/api/similar?q=${musicString}&type=music&k=${tastediveAPI}&info=1`)
.then(res => res.json())
.then(data => {
console.log(data)
const topArtist = data.similar.results[0].name
console.log(topArtist)
document.querySelector('h2').innerText = topArtist
const taString = topArtist.split(' ').join('+')
console.log(taString)
document.querySelector('a').href= data.similar.results[0].yUrl
document.querySelector('a').innerText = data.similar.results[0].yUrl
const list = document.querySelector('ul')
for (let i = 1; i < 15;i++){
let listItem = document.createElement('li')
let linkClick = document.createElement('a')
linkClick.href = data.similar.results[i].yUrl
linkClick.innerText = data.similar.results[i].name
list.appendChild(listItem)
listItem.appendChild(linkClick)
}
fetch(`https://www.theaudiodb.com/api/v1/json/123/search.php?s=${taString}`)
.then(res => res.json())
.then(newData => {
console.table(newData.artists[0])
document.querySelector('img').src = newData.artists[0].strArtistThumb
document.querySelector('.words > h4').innerText = 'Related Artists'

if(newData.artists[0].strBiographyEN.length > 250) {
const strArray = newData.artists[0].strBiographyEN.split(' ').slice(0,250).join(' ')
document.querySelector('h3').innerText = strArray + ' ...'
} else {
document.querySelector('h3').innerText = newData.artists[0].strBiographyEN
}
})
.catch(err => console.log(err))

})
.catch(err => console.log('Error: ' + err))
}


//create an array with the isrc's from the spotify playlist,
// get and convert them into tidal ids
// post new playlist and patch it with new songs

//experiment in Tidal API: multiple isrc's

//////// TIDAL EXPERIMENTAION /////////////////

// const tidalAPIKey = 'E6I4SGtorVrBzt4XaEsguN5rzZQaAoGA0RpeokQXikg='
// let TidalAccess = {"scope":"","token_type":"Bearer","access_token":"eyJraWQiOiJ2OU1GbFhqWSIsImFsZyI6IkVTMjU2In0.eyJ0eXBlIjoibzJfYWNjZXNzIiwic2NvcGUiOiIiLCJnVmVyIjowLCJzVmVyIjowLCJjaWQiOjE5ODQ5LCJleHAiOjE3NTk1Mzc5MTMsImlzcyI6Imh0dHBzOi8vYXV0aC50aWRhbC5jb20vdjEifQ.JnYWtc-mNvFvDScyGk6q-qg9ks3okJ0BIsuntLU5lnmAIqvkPcRFoE37rRZEr0nQQla5twNC9R5AF1_vmqV-Cw","expires_in":43200}

// fetch('https://openapi.tidal.com/v2/tracks?countryCode=US&filter%5Bisrc%5D=USQX92501822', {
// headers: {
// 'Authorization':`Bearer ${TidalAccess.access_token}`
// },
// method:'GET'
// })
// .then(res => res.json())
// .then(data => console.log(data))
// .catch(err => console.log('Error: ' + err))

// fetch('https://openapi.tidal.com/v2/users/me', {
// method:'GET',
// headers: {
// 'Authorization':`Bearer ${TidalAccess.access_token}`,
// }
// })
// .then(res => res.json())
// .then(data => console.log(data))
// .catch(err => console.log('Error: ' + err))