diff --git a/README.md b/README.md index 83ce771..4f729fc 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,42 @@ -# 📊 Project: Complex API 2 - -### 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... -``` +# Baby Name Selector App + +> Get inspired to choose the perfect baby name by checking out related songs. + +> Screenshot of completed Baby Name Selector API App + +## Table of Contents + +1. [Tech Stack](#tech-stack) +1. [Development](#development) + 1. [Baby Names API](#baby-names-api) + 1. [Spotify API](#spotify-api) + 1. [Notes](#notes) + +## Tech Stack + +- **HTML** +- **CSS** +- **JavaScript** + +## Development + +### Baby Names API + +- Obtain a free API key from API Ninjas at: https://api-ninjas.com/. +- Update the `API_NINJA_KEY` value with your key on line 1 of main.js. + +### Spotify API + +- Obtain your free `CLIENT_ID` and `CLIENT_SECRET` from Spotify at: https://developer.spotify.com/documentation/web-api. +- In the terminal, run the following command to get a temporary access token, replacing `CLIENT_ID` and `CLIENT_SECRET` accordingly (tokens expire in one hour). See https://developer.spotify.com/documentation/web-api/tutorials/client-credentials-flow for more information. + + `curl -X POST "https://accounts.spotify.com/api/token" \ +-H "Content-Type: application/x-www-form-urlencoded" \ +-d "grant_type=client_credentials&client_id=CLIENT_ID&client_secret=CLIENT_SECRET"` + +- Update the `SPOTIFY_TOKEN` value with your generated token on line 2 of main.js. +- Open the app in your browser, select a gender, pick a name and get inspired! + +### Notes + +Visit the official API Ninjas' Baby Names documentation at https://api-ninjas.com/api/babynames and the Spotify documentation at https://developer.spotify.com/documentation/web-api/ for more information on API use, copyright, and rate limitations. diff --git a/images/screenshot.png b/images/screenshot.png new file mode 100644 index 0000000..30d8af6 Binary files /dev/null and b/images/screenshot.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..f643ba7 --- /dev/null +++ b/index.html @@ -0,0 +1,42 @@ + + + + + + + + + Baby Name Selector + + + +

Baby Name Selector

+
+
+ + + +
+ + +
+
+
+ + + diff --git a/main.js b/main.js new file mode 100644 index 0000000..c60cc89 --- /dev/null +++ b/main.js @@ -0,0 +1,371 @@ +const API_NINJA_KEY = ""; // ADD KEY +const SPOTIFY_TOKEN = ""; // ADD TOKEN +const SONG_LIMIT = 3; + +document.querySelector("button").onclick = getBabyName; + +const listSection = document.getElementById("name-list"); +const musicSection = document.getElementById("music-list"); + +function getBabyName() { + const gender = document.querySelector('input[name="gender"]:checked').value; + + const babyURL = `https://api.api-ninjas.com/v1/babynames?gender=${gender}`; + + // Reset lists to clear any previous data + listSection.innerText = ""; + musicSection.innerText = ""; + + fetch(babyURL, { headers: { "X-Api-Key": API_NINJA_KEY } }) + .then((res) => res.json()) + .then((data) => { + // Comment out fetch call and use obj below for testing to prevent getting rate limited + // const data = [ + // "Sapphire", + // "Milly", + // "Florence", + // "Jessica", + // "Talia", + // "Lily", + // "Zainab", + // "Tiffany", + // "Roxanne", + // "Lexie", + // ]; + + data.forEach((name, index) => { + const nameElement = document.createElement("p"); + nameElement.id = `artist-${index}`; + nameElement.innerText = name; + nameElement.classList.add(gender); + nameElement.onclick = () => { + // Only highlight the actively selected name + document.querySelector(".active")?.classList.remove("active"); + nameElement.classList.add("active"); + getMusic(name); + }; + listSection.appendChild(nameElement); + }); + }) + .catch((err) => console.error(err)); +} + +function getMusic(name) { + const spotifyURL = `https://api.spotify.com/v1/search?q=${name}&type=track&limit=${SONG_LIMIT}`; + + fetch(spotifyURL, { + headers: { + Authorization: `Bearer ${SPOTIFY_TOKEN}`, + }, + }) + .then((res) => res.json()) + .then((data) => { + // Comment out fetch call and use obj below for testing to prevent getting rate limited + // const data = { + // tracks: { + // href: "https://api.spotify.com/v1/search?offset=0&limit=3&query=Sapphire&type=track&locale=en-US,en;q%3D0.9", + // limit: 3, + // next: "https://api.spotify.com/v1/search?offset=3&limit=3&query=Sapphire&type=track&locale=en-US,en;q%3D0.9", + // offset: 0, + // previous: null, + // total: 901, + // items: [ + // { + // album: { + // album_type: "single", + // artists: [ + // { + // external_urls: { + // spotify: + // "https://open.spotify.com/artist/6eUKZXaKkcviH0Ku9w2n3V", + // }, + // href: "https://api.spotify.com/v1/artists/6eUKZXaKkcviH0Ku9w2n3V", + // id: "6eUKZXaKkcviH0Ku9w2n3V", + // name: "Ed Sheeran", + // type: "artist", + // uri: "spotify:artist:6eUKZXaKkcviH0Ku9w2n3V", + // }, + // ], + // available_markets: [], + // external_urls: { + // spotify: + // "https://open.spotify.com/album/1ZrWlhMUoyMKsoQ1tvRR2t", + // }, + // href: "https://api.spotify.com/v1/albums/1ZrWlhMUoyMKsoQ1tvRR2t", + // id: "1ZrWlhMUoyMKsoQ1tvRR2t", + // images: [ + // { + // height: 640, + // width: 640, + // url: "https://i.scdn.co/image/ab67616d0000b2736fbb60d6a7e03ccb940a518e", + // }, + // { + // height: 300, + // width: 300, + // url: "https://i.scdn.co/image/ab67616d00001e026fbb60d6a7e03ccb940a518e", + // }, + // { + // height: 64, + // width: 64, + // url: "https://i.scdn.co/image/ab67616d000048516fbb60d6a7e03ccb940a518e", + // }, + // ], + // is_playable: true, + // name: "Sapphire", + // release_date: "2025-06-05", + // release_date_precision: "day", + // total_tracks: 1, + // type: "album", + // uri: "spotify:album:1ZrWlhMUoyMKsoQ1tvRR2t", + // }, + // artists: [ + // { + // external_urls: { + // spotify: + // "https://open.spotify.com/artist/6eUKZXaKkcviH0Ku9w2n3V", + // }, + // href: "https://api.spotify.com/v1/artists/6eUKZXaKkcviH0Ku9w2n3V", + // id: "6eUKZXaKkcviH0Ku9w2n3V", + // name: "Ed Sheeran", + // type: "artist", + // uri: "spotify:artist:6eUKZXaKkcviH0Ku9w2n3V", + // }, + // ], + // available_markets: [], + // disc_number: 1, + // duration_ms: 179082, + // explicit: false, + // external_ids: { + // isrc: "GBAHS2500262", + // }, + // external_urls: { + // spotify: + // "https://open.spotify.com/track/4Q0qVhFQa7j6jRKzo3HDmP", + // }, + // href: "https://api.spotify.com/v1/tracks/4Q0qVhFQa7j6jRKzo3HDmP", + // id: "4Q0qVhFQa7j6jRKzo3HDmP", + // is_local: false, + // is_playable: true, + // name: "Sapphire", + // popularity: 86, + // preview_url: null, + // track_number: 1, + // type: "track", + // uri: "spotify:track:4Q0qVhFQa7j6jRKzo3HDmP", + // }, + // { + // album: { + // album_type: "single", + // artists: [ + // { + // external_urls: { + // spotify: + // "https://open.spotify.com/artist/6eUKZXaKkcviH0Ku9w2n3V", + // }, + // href: "https://api.spotify.com/v1/artists/6eUKZXaKkcviH0Ku9w2n3V", + // id: "6eUKZXaKkcviH0Ku9w2n3V", + // name: "Ed Sheeran", + // type: "artist", + // uri: "spotify:artist:6eUKZXaKkcviH0Ku9w2n3V", + // }, + // { + // external_urls: { + // spotify: + // "https://open.spotify.com/artist/4YRxDV8wJFPHPTeXepOstw", + // }, + // href: "https://api.spotify.com/v1/artists/4YRxDV8wJFPHPTeXepOstw", + // id: "4YRxDV8wJFPHPTeXepOstw", + // name: "Arijit Singh", + // type: "artist", + // uri: "spotify:artist:4YRxDV8wJFPHPTeXepOstw", + // }, + // ], + // available_markets: [], + // external_urls: { + // spotify: + // "https://open.spotify.com/album/6lAh6JtFaIvFshi8oz05m7", + // }, + // href: "https://api.spotify.com/v1/albums/6lAh6JtFaIvFshi8oz05m7", + // id: "6lAh6JtFaIvFshi8oz05m7", + // images: [ + // { + // height: 640, + // width: 640, + // url: "https://i.scdn.co/image/ab67616d0000b2735a3f69aab66f912e54529606", + // }, + // { + // height: 300, + // width: 300, + // url: "https://i.scdn.co/image/ab67616d00001e025a3f69aab66f912e54529606", + // }, + // { + // height: 64, + // width: 64, + // url: "https://i.scdn.co/image/ab67616d000048515a3f69aab66f912e54529606", + // }, + // ], + // is_playable: true, + // name: "Sapphire (feat. Arijit Singh)", + // release_date: "2025-07-24", + // release_date_precision: "day", + // total_tracks: 1, + // type: "album", + // uri: "spotify:album:6lAh6JtFaIvFshi8oz05m7", + // }, + // artists: [ + // { + // external_urls: { + // spotify: + // "https://open.spotify.com/artist/6eUKZXaKkcviH0Ku9w2n3V", + // }, + // href: "https://api.spotify.com/v1/artists/6eUKZXaKkcviH0Ku9w2n3V", + // id: "6eUKZXaKkcviH0Ku9w2n3V", + // name: "Ed Sheeran", + // type: "artist", + // uri: "spotify:artist:6eUKZXaKkcviH0Ku9w2n3V", + // }, + // { + // external_urls: { + // spotify: + // "https://open.spotify.com/artist/4YRxDV8wJFPHPTeXepOstw", + // }, + // href: "https://api.spotify.com/v1/artists/4YRxDV8wJFPHPTeXepOstw", + // id: "4YRxDV8wJFPHPTeXepOstw", + // name: "Arijit Singh", + // type: "artist", + // uri: "spotify:artist:4YRxDV8wJFPHPTeXepOstw", + // }, + // ], + // available_markets: [], + // disc_number: 1, + // duration_ms: 180648, + // explicit: false, + // external_ids: { + // isrc: "GBAHS2500513", + // }, + // external_urls: { + // spotify: + // "https://open.spotify.com/track/65dt1vedDHPOCCPS3mVhtN", + // }, + // href: "https://api.spotify.com/v1/tracks/65dt1vedDHPOCCPS3mVhtN", + // id: "65dt1vedDHPOCCPS3mVhtN", + // is_local: false, + // is_playable: true, + // name: "Sapphire (feat. Arijit Singh)", + // popularity: 72, + // preview_url: null, + // track_number: 1, + // type: "track", + // uri: "spotify:track:65dt1vedDHPOCCPS3mVhtN", + // }, + // { + // album: { + // album_type: "single", + // artists: [ + // { + // external_urls: { + // spotify: + // "https://open.spotify.com/artist/54S56FDCzOYP1EY3hb7wbW", + // }, + // href: "https://api.spotify.com/v1/artists/54S56FDCzOYP1EY3hb7wbW", + // id: "54S56FDCzOYP1EY3hb7wbW", + // name: "sodistilled", + // type: "artist", + // uri: "spotify:artist:54S56FDCzOYP1EY3hb7wbW", + // }, + // ], + // available_markets: [], + // external_urls: { + // spotify: + // "https://open.spotify.com/album/03CCh40PIqkk9fWVv7Ycrl", + // }, + // href: "https://api.spotify.com/v1/albums/03CCh40PIqkk9fWVv7Ycrl", + // id: "03CCh40PIqkk9fWVv7Ycrl", + // images: [ + // { + // height: 640, + // width: 640, + // url: "https://i.scdn.co/image/ab67616d0000b27366087e5db825bca3bfaa90fe", + // }, + // { + // height: 300, + // width: 300, + // url: "https://i.scdn.co/image/ab67616d00001e0266087e5db825bca3bfaa90fe", + // }, + // { + // height: 64, + // width: 64, + // url: "https://i.scdn.co/image/ab67616d0000485166087e5db825bca3bfaa90fe", + // }, + // ], + // is_playable: true, + // name: "purity killed me", + // release_date: "2024-12-27", + // release_date_precision: "day", + // total_tracks: 4, + // type: "album", + // uri: "spotify:album:03CCh40PIqkk9fWVv7Ycrl", + // }, + // artists: [ + // { + // external_urls: { + // spotify: + // "https://open.spotify.com/artist/54S56FDCzOYP1EY3hb7wbW", + // }, + // href: "https://api.spotify.com/v1/artists/54S56FDCzOYP1EY3hb7wbW", + // id: "54S56FDCzOYP1EY3hb7wbW", + // name: "sodistilled", + // type: "artist", + // uri: "spotify:artist:54S56FDCzOYP1EY3hb7wbW", + // }, + // ], + // available_markets: [], + // disc_number: 1, + // duration_ms: 175285, + // explicit: false, + // external_ids: { + // isrc: "QZS7J2441795", + // }, + // external_urls: { + // spotify: + // "https://open.spotify.com/track/3g5dJ6IddDW3QFbTXmGWTX", + // }, + // href: "https://api.spotify.com/v1/tracks/3g5dJ6IddDW3QFbTXmGWTX", + // id: "3g5dJ6IddDW3QFbTXmGWTX", + // is_local: false, + // is_playable: true, + // name: "sapphire", + // popularity: 47, + // preview_url: null, + // track_number: 3, + // type: "track", + // uri: "spotify:track:3g5dJ6IddDW3QFbTXmGWTX", + // }, + // ], + // }, + // }; + + musicSection.innerHTML = `

Songs Related to "${name}"

`; + + data.tracks.items.forEach((song) => { + const { id } = song; + const section = document.createElement("section"); + section.id = id; + + section.innerHTML = ` + + `; + musicSection.appendChild(section); + }); + }) + .catch((err) => console.error(err)); +} diff --git a/style.css b/style.css new file mode 100644 index 0000000..136a09f --- /dev/null +++ b/style.css @@ -0,0 +1,168 @@ +* { + box-sizing: border-box; + padding: 0; + margin: 0; + font-weight: unset; + font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + letter-spacing: 0.4px; +} + +:root { + --baby-pink: rgba(255, 203, 217, 1); + --light-baby-pink: rgba(255, 203, 217, 0.4); + --baby-blue: rgba(184, 215, 233, 1); + --light-baby-blue: rgba(184, 215, 233, 0.4); + --baby-yellow: rgba(248, 229, 183, 1); + --light-baby-yellow: rgba(248, 229, 183, 0.4); + --black: rgba(51, 51, 51, 1); + --grey: rgba(140, 140, 140, 0.8); + --white: rgba(246, 246, 246, 1); + --3d-effect: -webkit-linear-gradient( + top, + rgba(0, 0, 0, 0), + rgba(0, 0, 0, 0.1) + ); +} + +body { + max-width: 90vw; + margin: auto; + color: var(--black); + background-color: var(--white); + padding: 4em 0; +} + +h1 { + margin-bottom: 1em; + text-align: center; +} + +main { + display: flex; + flex-direction: column; +} + +#genders { + display: flex; + gap: 1em; +} + +.card { + display: flex; + flex-direction: column; + flex: 1; + gap: 2em; + justify-content: space-evenly; + align-items: center; + color: var(--white); + border-radius: 2em; + padding: 1em; + font-size: 1.45rem; + background-image: var(--3d-effect); + cursor: pointer; + text-shadow: 0 0 10px var(--black); +} + +.card:hover, +button:hover, +#name-list > section:hover { + transform: scale(1.02); + opacity: 0.85; +} + +input[type="radio"] { + width: 20px; + height: 20px; +} + +.card:nth-child(1) { + background-color: var(--baby-pink); + box-shadow: 0 2px 6px var(--baby-pink); +} + +.card:nth-child(2) { + background-color: var(--baby-blue); + box-shadow: 0 2px 6px var(--baby-blue); +} + +.card:nth-child(3) { + background-color: var(--baby-yellow); + box-shadow: 0 2px 6px var(--baby-yellow); +} + +input { + cursor: pointer; +} + +button { + font-size: 1rem; + padding: 1em 2em; + border: none; + border-radius: 0.5em; + letter-spacing: 1px; + margin: 1em 0 2em; + background-image: var(--3d-effect); + cursor: pointer; + align-self: center; +} + +#name-list { + display: flex; + flex-wrap: wrap; + gap: 1em; + justify-content: center; + margin-top: 2em; +} + +#name-list > p { + background-color: white; + border-radius: 0.5em; + box-shadow: 0 2px 6px var(--grey); + padding: 0.8em 1.2em; + cursor: pointer; + min-width: 120px; + text-align: center; +} + +#name-list p.boy:hover, +#name-list p.boy.active { + background-color: var(--light-baby-blue); +} + +#name-list p.girl:hover, +#name-list p.girl.active { + background-color: var(--light-baby-pink); +} + +#name-list p.neutral:hover, +#name-list p.neutral.active { + background-color: var(--light-baby-yellow); +} + +#music-list { + margin-top: 4em; + text-align: center; + display: flex; + flex-direction: column; + gap: 1em; +} + +#music-list p { + margin-bottom: 0.5em; +} + +@media screen and (max-width: 600px) { + main { + max-width: 300px; + margin: auto; + } + + #genders { + flex-direction: column; + max-width: 300px; + } + + iframe { + width: 100%; + } +}