- Backend: PostgreSQl, Ruby / Rails
- Frontend: JavaScript, React, Redux, HTMl CSS
Spotifly is bug-themed music site based off of Spotify. Spotifly allows you to listen the hottest new music from the best bugs around, be carful not to get an earworm!
- Song objects created with url links to hosted royalty free images and .mp3 files
//App.jsx
this.state = {
tracks: [
{
img:
"https://icon-library.net/images/music-icon-transparent/music-icon-transparent-11.jpg",
name: "Starter Song 1",
desc: "Song to initialize player",
src:
"https://ia600901.us.archive.org/7/items/exp037/wrexsoul_-_alchemy_sound_-_12_-_dreamland_64kb.mp3"
},
{
img:
"https://icon-library.net/images/music-icon-transparent/music-icon-transparent-11.jpg",
name: "Starter Song 2",
desc: "Song to initialize player",
src:
"https://ia800901.us.archive.org/7/items/exp037/wrexsoul_-_alchemy_sound_-_03_-_2000_fathoms_and_diving_64kb.mp3"
}
]
- Songs and playlists are joined through a joins table allowing them to be added into a playlist where they can be played
- Similar to sportify, many duplicates of the same song can be added to a single playlist
class PlaylistSong < ApplicationRecord
belongs_to :playlist,
class_name: :Playlist,
foreign_key: :playlist_id
belongs_to :song,
class_name: :Song,
foreign_key: :song_id
end
- Search takes in queries from an input and updates the matching results based on matching characters in the song title or artist
getInfo() {
let songTitles = [];
this.props.songs.map(song => {
if (
song.title.toLowerCase().includes(this.state.query.toLowerCase()) ||
song.artist.toLowerCase().includes(this.state.query.toLowerCase())
) {
let titleAndId = song;
songTitles.push(titleAndId);
}
});
let data = songTitles;
this.setState({
results: data
});
}
- These matches are fed into a sugestions compontent that converts each into a song item
- These song items are then listed without duplicates in order to allow the user to add songs into a playlist
const Suggestions = props => {
let options = props.results.map(song => (
<SongItemContainer key={song.id} song={song} func={props.func} inPlaylist={false} />)
);
if (options.length === 0) {
options = ["No Matching Songs Found :("];
}
return (
<section id="index-songlist-search" className="songlist">
<div className="nav-profile-dropdown-links-container">
<ul className="song-list-ul">{options}</ul>
</div>
</section>
);
};
- Styling of some components is based off of the url pathname to provide dryer code
//App.jsx
switch (this.props.location.pathname) {
case "/signup":
headerClass += " signup";
outerDivClass += "signup-div";
greetingContainerBoolean += "hidden";
bannerContainer += " signup";
logoWrapper += " signup";
logoId = "auth-logo";
break;
case "/login":
headerClass += " login";
outerDivClass += "login-div";
greetingContainerBoolean += "hidden";
bannerContainer += " login";
logoWrapper += " login";
logoId = "auth-logo";
break;
case "/account":
headerClass += " account";
outerDivClass += "account-div";
break;
default:
headerClass += " default";
outerDivClass += "default-div";
break;
}
- Used to style components and in and if else to separate the two main sites(player and sign-in/splash)
- make custom music player to have better control over it
- albums
- search expansion