Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…player into main
  • Loading branch information
TidbitsJS committed Sep 17, 2022
2 parents a2dd415 + 2cd1217 commit a9dedf8
Showing 23 changed files with 74 additions and 154 deletions.
12 changes: 5 additions & 7 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useSelector } from 'react-redux';
import { Route, Routes } from 'react-router-dom';

import { Searchbar, Sidebar, SongPlay, TopPlay } from './components';
import { ArtistDetails, AroundYou, Discover, Search, SongDetails, TopCharts, TopArtists } from './pages';
import { Searchbar, Sidebar, MusicPlayer, TopPlay } from './components';
import { ArtistDetails, TopArtists, AroundYou, Discover, Search, SongDetails, TopCharts } from './pages';

const App = () => {
const { activeSong } = useSelector((state) => state.player);
@@ -20,7 +20,6 @@ const App = () => {
<Route path="/top-artists" element={<TopArtists />} />
<Route path="/top-charts" element={<TopCharts />} />
<Route path="/around-you" element={<AroundYou />} />

<Route path="/artists/:id" element={<ArtistDetails />} />
<Route path="/songs/:songid" element={<SongDetails />} />
<Route path="/search/:searchTerm" element={<Search />} />
@@ -30,13 +29,12 @@ const App = () => {
<TopPlay />
</div>
</div>

</div>

{activeSong?.title && (
<div className="absolute h-28 bottom-0 left-0 right-0 flex animate-slideup bg-gradient-to-br from-white/10 to-[#2a2a80] backdrop-blur-lg rounded-t-3xl z-10">
<SongPlay />
</div>
<div className="absolute h-28 bottom-0 left-0 right-0 flex animate-slideup bg-gradient-to-br from-white/10 to-[#2a2a80] backdrop-blur-lg rounded-t-3xl z-10">
<MusicPlayer />
</div>
)}
</div>
);
16 changes: 16 additions & 0 deletions src/assets/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export const genres = [
{ title: 'Pop', value: 'POP' },
{ title: 'Hip-Hop', value: 'HIP_HOP_RAP' },
{ title: 'Dance', value: 'DANCE' },
{ title: 'Electronic', value: 'ELECTRONIC' },
{ title: 'Soul', value: 'SOUL_RNB' },
{ title: 'Alternative', value: 'ALTERNATIVE' },
{ title: 'Rock', value: 'ROCK' },
{ title: 'Latin', value: 'LATIN' },
{ title: 'Film', value: 'FILM_TV' },
{ title: 'Country', value: 'COUNTRY' },
{ title: 'Worldwide', value: 'WORLDWIDE' },
{ title: 'Reggae', value: 'REGGAE_DANCE_HALL' },
{ title: 'House', value: 'HOUSE' },
{ title: 'K-Pop', value: 'K_POP' },
];
11 changes: 5 additions & 6 deletions src/components/DetailsHeader.jsx
Original file line number Diff line number Diff line change
@@ -9,12 +9,11 @@ const DetailsHeader = ({ artistId, artistData, songData }) => (
<img
alt="profile"
src={
artistId
? artistData?.artists[artistId].attributes?.artwork?.url
.replace('{w}', '500')
.replace('{h}', '500')
: songData?.images?.coverart
}
artistId ? artistData?.artists[artistId].attributes?.artwork?.url
.replace('{w}', '500')
.replace('{h}', '500')
: songData?.images?.coverart
}
className="sm:w-48 w-28 sm:h-48 h-28 rounded-full object-cover border-2 shadow-xl shadow-black"
/>

File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable jsx-a11y/media-has-caption */
import React, { useState, useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';

@@ -9,10 +8,10 @@ import Seekbar from './Seekbar';
import Track from './Track';
import VolumeBar from './VolumeBar';

const SongPlay = () => {
const MusicPlayer = () => {
const { activeSong, currentSongs, currentIndex, isActive, isPlaying } = useSelector((state) => state.player);
const [duration, setDuration] = useState(0);
const [seekTime, setSeekTime] = useState(0); // forces player to update its time
const [seekTime, setSeekTime] = useState(0);
const [appTime, setAppTime] = useState(0);
const [volume, setVolume] = useState(0.3);
const [repeat, setRepeat] = useState(false);
@@ -34,12 +33,11 @@ const SongPlay = () => {
};

const handleNextSong = () => {
// pause the song first before starting the next song to prevent error play() request interrupted by new load request
dispatch(playPause(false));

if (!shuffle) {
dispatch(nextSong((currentIndex + 1) % currentSongs.length));
} else {
// picks a random index if shuffle is true
dispatch(nextSong(Math.floor(Math.random() * currentSongs.length)));
}
};
@@ -57,7 +55,6 @@ const SongPlay = () => {
return (
<div className="relative sm:px-12 px-8 w-full flex items-center justify-between">
<Track isPlaying={isPlaying} isActive={isActive} activeSong={activeSong} />

<div className="flex-1 flex flex-col items-center justify-center">
<Controls
isPlaying={isPlaying}
@@ -71,7 +68,6 @@ const SongPlay = () => {
handlePrevSong={handlePrevSong}
handleNextSong={handleNextSong}
/>

<Seekbar
value={appTime}
min="0"
@@ -80,7 +76,6 @@ const SongPlay = () => {
setSeekTime={setSeekTime}
appTime={appTime}
/>

<Player
activeSong={activeSong}
volume={volume}
@@ -93,16 +88,9 @@ const SongPlay = () => {
onLoadedData={(event) => setDuration(event.target.duration)}
/>
</div>

<VolumeBar
value={volume}
min="0"
max="1"
onChange={(event) => setVolume(event.target.value)}
setVolume={setVolume}
/>
<VolumeBar value={volume} min="0" max="1" onChange={(event) => setVolume(event.target.value)} setVolume={setVolume} />
</div>
);
};

export default SongPlay;
export default MusicPlayer;
1 change: 1 addition & 0 deletions src/components/Searchbar.jsx
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@ const Searchbar = () => {
<FiSearch aria-hidden="true" className="w-5 h-5 ml-4" />
<input
name="search-field"
autoComplete="off"
id="search-field"
className="flex-1 bg-transparent border-none placeholder-gray-500 outline-none text-base text-white p-4"
placeholder="Search"
9 changes: 2 additions & 7 deletions src/components/Sidebar.jsx
Original file line number Diff line number Diff line change
@@ -21,10 +21,7 @@ const NavLinks = ({ handleClick }) => (
className="flex flex-row justify-start items-center my-8 text-sm font-medium text-gray-400 hover:text-cyan-400"
onClick={() => handleClick && handleClick()}
>
<item.icon
className="w-6 h-6 mr-2"
/>

<item.icon className="w-6 h-6 mr-2" />
{item.name}
</NavLink>
))}
@@ -50,9 +47,7 @@ const Sidebar = () => {
)}
</div>

<div
className={`absolute top-0 h-screen w-2/3 bg-gradient-to-tl from-white/10 to-[#483D8B] backdrop-blur-lg z-10 p-6 md:hidden smooth-transition ${mobileMenuOpen ? 'left-0' : '-left-full'}`}
>
<div className={`absolute top-0 h-screen w-2/3 bg-gradient-to-tl from-white/10 to-[#483D8B] backdrop-blur-lg z-10 p-6 md:hidden smooth-transition ${mobileMenuOpen ? 'left-0' : '-left-full'}`}>
<img src={logo} alt="logo" className="w-full h-14 object-contain" />
<NavLinks handleClick={() => setMobileMenuOpen(false)} />
</div>
1 change: 0 additions & 1 deletion src/components/TopPlay.jsx
Original file line number Diff line number Diff line change
@@ -116,7 +116,6 @@ const TopPlay = () => {
</SwiperSlide>
))}
</Swiper>

</div>
</div>
);
4 changes: 2 additions & 2 deletions src/components/index.js
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ import ArtistCard from './ArtistCard';
import DetailsHeader from './DetailsHeader';
import SongBar from './SongBar';
import RelatedSongs from './RelatedSongs';
import SongPlay from './songplay';
import MusicPlayer from './MusicPlayer';
import Loader from './Loader';
import Error from './Error';

@@ -19,7 +19,7 @@ export {
DetailsHeader,
SongBar,
RelatedSongs,
SongPlay,
MusicPlayer,
Loader,
Error,
};
4 changes: 2 additions & 2 deletions src/pages/AroundYou.jsx
Original file line number Diff line number Diff line change
@@ -3,13 +3,13 @@ import axios from 'axios';
import { useSelector } from 'react-redux';

import { Error, Loader, SongCard } from '../components';
import { useFetchSongsByCountryQuery } from '../redux/services/shazamCore';
import { useGetSongsByCountryQuery } from '../redux/services/shazamCore';

const CountryTracks = () => {
const [country, setCountry] = useState(null);
const [loading, setLoading] = useState(true);
const { activeSong, isPlaying } = useSelector((state) => state.player);
const { data, isFetching, error } = useFetchSongsByCountryQuery(country);
const { data, isFetching, error } = useGetSongsByCountryQuery(country);

useEffect(() => {
axios
8 changes: 2 additions & 6 deletions src/pages/ArtistDetails.jsx
Original file line number Diff line number Diff line change
@@ -3,16 +3,12 @@ import { useParams } from 'react-router-dom';
import { useSelector } from 'react-redux';
import { DetailsHeader, Error, Loader, RelatedSongs } from '../components';

import { useFetchArtistDetailsQuery } from '../redux/services/shazamCore';
import { useGetArtistDetailsQuery } from '../redux/services/shazamCore';

const ArtistDetails = () => {
const { id: artistId } = useParams();
const { activeSong, isPlaying } = useSelector((state) => state.player);
const {
data: artistData,
isFetching: isFetchingArtistDetails,
error,
} = useFetchArtistDetailsQuery(artistId);
const { data: artistData, isFetching: isFetchingArtistDetails, error } = useGetArtistDetailsQuery(artistId);

if (isFetchingArtistDetails) return <Loader title="Loading artist details..." />;

37 changes: 7 additions & 30 deletions src/pages/Discover.jsx
Original file line number Diff line number Diff line change
@@ -3,55 +3,32 @@ import { useDispatch, useSelector } from 'react-redux';

import { Error, Loader, SongCard } from '../components';
import { selectGenreListId } from '../redux/features/playerSlice';
import { useFetchSongsByGenreQuery } from '../redux/services/shazamCore';

const genres = [
'POP',
'HIP_HOP_RAP',
'DANCE',
'ELECTRONIC',
'SOUL_RNB',
'ALTERNATIVE',
'ROCK',
'LATIN',
'FILM_TV',
'COUNTRY',
'AFRO_BEATS',
'WORLDWIDE',
'REGGAE_DANCE_HALL',
'HOUSE',
'K_POP',
'FRENCH_POP',
'SINGER_SONGWRITER',
'REG_MEXICO',
];
import { useGetSongsByGenreQuery } from '../redux/services/shazamCore';
import { genres } from '../assets/constants';

const Discover = () => {
const dispatch = useDispatch();
const { genreListId } = useSelector((state) => state.player);
const { activeSong, isPlaying } = useSelector((state) => state.player);
const { data, isFetching, error } = useFetchSongsByGenreQuery(genreListId || 'POP');
const { data, isFetching, error } = useGetSongsByGenreQuery(genreListId || 'POP');

if (isFetching) return <Loader title="Loading songs..." />;

if (error) return <Error />;

const genreTitle = genres.find(({ value }) => value === genreListId)?.title;

return (
<div className="flex flex-col">
<div className="w-full flex justify-between items-center sm:flex-row flex-col mt-4 mb-10">
<h2 className="font-bold text-3xl text-white text-left">Discover {genreListId || 'pop'}</h2>
<h2 className="font-bold text-3xl text-white text-left">Discover {genreTitle}</h2>

<select
onChange={(e) => dispatch(selectGenreListId(e.target.value))}
value={genreListId || 'pop'}
className="bg-black text-gray-300 p-3 text-sm rounded-lg outline-none sm:mt-0 mt-5"
>
{genres.map((genre) => (
<option
value={genre}
>{genre}
</option>
))}
{genres.map((genre) => <option value={genre.value}>{genre.title}</option>)}
</select>
</div>

4 changes: 2 additions & 2 deletions src/pages/Search.jsx
Original file line number Diff line number Diff line change
@@ -3,12 +3,12 @@ import { useSelector } from 'react-redux';
import { useParams } from 'react-router-dom';

import { Error, Loader, SongCard } from '../components';
import { useFetchSongsBySearchQuery } from '../redux/services/shazamCore';
import { useGetSongsBySearchQuery } from '../redux/services/shazamCore';

const Search = () => {
const { searchTerm } = useParams();
const { activeSong, isPlaying } = useSelector((state) => state.player);
const { data, isFetching, error } = useFetchSongsBySearchQuery(searchTerm);
const { data, isFetching, error } = useGetSongsBySearchQuery(searchTerm);

const songs = data?.tracks?.hits.map((song) => song.track);

2 changes: 2 additions & 0 deletions src/pages/SongDetails.jsx
Original file line number Diff line number Diff line change
@@ -16,6 +16,8 @@ const SongDetails = () => {

if (isFetchingSongDetails && isFetchinRelatedSongs) return <Loader title="Searching song details" />;

console.log(songData);

if (error) return <Error />;

const handlePauseClick = () => {
6 changes: 3 additions & 3 deletions src/pages/TopArtists.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React from 'react';

import { ArtistCard, Error, Loader } from '../components';
import { useGetSongsQuery } from '../redux/services/shazam';
import { useGetTopChartsQuery } from '../redux/services/shazamCore';

const TopArtists = () => {
const { data, isFetching, error } = useGetSongsQuery({ genreListId: 'genre-global-chart-1' });
const { data, isFetching, error } = useGetTopChartsQuery();

if (isFetching) return <Loader title="Loading artists..." />;

@@ -15,7 +15,7 @@ const TopArtists = () => {
<h2 className="font-bold text-3xl text-white text-left mt-4 mb-10">Top artists</h2>

<div className="flex flex-wrap sm:justify-start justify-center gap-8">
{data?.tracks.map((track) => <ArtistCard key={track.key} track={track} />)}
{data?.map((track) => <ArtistCard key={track.key} track={track} />)}
</div>
</div>
);
7 changes: 7 additions & 0 deletions src/redux/features/playerSlice.js
Original file line number Diff line number Diff line change
@@ -15,34 +15,41 @@ const playerSlice = createSlice({
reducers: {
setActiveSong: (state, action) => {
state.activeSong = action.payload.song;

if (action.payload?.data?.tracks?.hits) {
state.currentSongs = action.payload.data.tracks.hits;
} else if (action.payload?.data?.properties) {
state.currentSongs = action.payload?.data?.tracks;
} else {
state.currentSongs = action.payload.data;
}

state.currentIndex = action.payload.i;
state.isActive = true;
},

nextSong: (state, action) => {
if (state.currentSongs[action.payload]?.track) {
state.activeSong = state.currentSongs[action.payload]?.track;
} else {
state.activeSong = state.currentSongs[action.payload];
}

state.currentIndex = action.payload;
state.isActive = true;
},

prevSong: (state, action) => {
if (state.currentSongs[action.payload]?.track) {
state.activeSong = state.currentSongs[action.payload]?.track;
} else {
state.activeSong = state.currentSongs[action.payload];
}

state.currentIndex = action.payload;
state.isActive = true;
},

playPause: (state, action) => {
state.isPlaying = action.payload;
},
Loading

0 comments on commit a9dedf8

Please sign in to comment.