diff --git a/src/App.jsx b/src/App.jsx
index ac2b351..16e4b10 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -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 = () => {
} />
} />
} />
-
} />
} />
} />
@@ -30,13 +29,12 @@ const App = () => {
-
{activeSong?.title && (
-
-
-
+
+
+
)}
);
diff --git a/src/assets/constants.js b/src/assets/constants.js
new file mode 100644
index 0000000..8f645ae
--- /dev/null
+++ b/src/assets/constants.js
@@ -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' },
+];
diff --git a/src/components/DetailsHeader.jsx b/src/components/DetailsHeader.jsx
index 37cb97e..66b17e9 100644
--- a/src/components/DetailsHeader.jsx
+++ b/src/components/DetailsHeader.jsx
@@ -9,12 +9,11 @@ const DetailsHeader = ({ artistId, artistData, songData }) => (
diff --git a/src/components/songplay/Controls.jsx b/src/components/MusicPlayer/Controls.jsx
similarity index 100%
rename from src/components/songplay/Controls.jsx
rename to src/components/MusicPlayer/Controls.jsx
diff --git a/src/components/songplay/Player.jsx b/src/components/MusicPlayer/Player.jsx
similarity index 100%
rename from src/components/songplay/Player.jsx
rename to src/components/MusicPlayer/Player.jsx
diff --git a/src/components/songplay/Seekbar.jsx b/src/components/MusicPlayer/Seekbar.jsx
similarity index 100%
rename from src/components/songplay/Seekbar.jsx
rename to src/components/MusicPlayer/Seekbar.jsx
diff --git a/src/components/songplay/Track.jsx b/src/components/MusicPlayer/Track.jsx
similarity index 100%
rename from src/components/songplay/Track.jsx
rename to src/components/MusicPlayer/Track.jsx
diff --git a/src/components/songplay/VolumeBar.jsx b/src/components/MusicPlayer/VolumeBar.jsx
similarity index 100%
rename from src/components/songplay/VolumeBar.jsx
rename to src/components/MusicPlayer/VolumeBar.jsx
diff --git a/src/components/songplay/index.jsx b/src/components/MusicPlayer/index.jsx
similarity index 84%
rename from src/components/songplay/index.jsx
rename to src/components/MusicPlayer/index.jsx
index 94172ba..157d577 100644
--- a/src/components/songplay/index.jsx
+++ b/src/components/MusicPlayer/index.jsx
@@ -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 (
-
{
handlePrevSong={handlePrevSong}
handleNextSong={handleNextSong}
/>
-
{
setSeekTime={setSeekTime}
appTime={appTime}
/>
-
{
onLoadedData={(event) => setDuration(event.target.duration)}
/>
-
-
setVolume(event.target.value)}
- setVolume={setVolume}
- />
+ setVolume(event.target.value)} setVolume={setVolume} />
);
};
-export default SongPlay;
+export default MusicPlayer;
diff --git a/src/components/Searchbar.jsx b/src/components/Searchbar.jsx
index 3bbb5e5..6fc8a10 100644
--- a/src/components/Searchbar.jsx
+++ b/src/components/Searchbar.jsx
@@ -22,6 +22,7 @@ const Searchbar = () => {
(
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.name}
))}
@@ -50,9 +47,7 @@ const Sidebar = () => {
)}
-
+
setMobileMenuOpen(false)} />
diff --git a/src/components/TopPlay.jsx b/src/components/TopPlay.jsx
index 94ae0fa..a6c421b 100644
--- a/src/components/TopPlay.jsx
+++ b/src/components/TopPlay.jsx
@@ -116,7 +116,6 @@ const TopPlay = () => {
))}
-
);
diff --git a/src/components/index.js b/src/components/index.js
index 5e775e6..5b56d1b 100644
--- a/src/components/index.js
+++ b/src/components/index.js
@@ -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,
};
diff --git a/src/pages/AroundYou.jsx b/src/pages/AroundYou.jsx
index c77f3a7..4da4e1b 100644
--- a/src/pages/AroundYou.jsx
+++ b/src/pages/AroundYou.jsx
@@ -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
diff --git a/src/pages/ArtistDetails.jsx b/src/pages/ArtistDetails.jsx
index 0fa0df2..cb14e5b 100644
--- a/src/pages/ArtistDetails.jsx
+++ b/src/pages/ArtistDetails.jsx
@@ -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 ;
diff --git a/src/pages/Discover.jsx b/src/pages/Discover.jsx
index 67f566a..7da80ea 100644
--- a/src/pages/Discover.jsx
+++ b/src/pages/Discover.jsx
@@ -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 ;
if (error) return ;
+ const genreTitle = genres.find(({ value }) => value === genreListId)?.title;
+
return (
-
Discover {genreListId || 'pop'}
+ Discover {genreTitle}
diff --git a/src/pages/Search.jsx b/src/pages/Search.jsx
index 1177636..9c5333f 100644
--- a/src/pages/Search.jsx
+++ b/src/pages/Search.jsx
@@ -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);
diff --git a/src/pages/SongDetails.jsx b/src/pages/SongDetails.jsx
index 0791722..da0a255 100644
--- a/src/pages/SongDetails.jsx
+++ b/src/pages/SongDetails.jsx
@@ -16,6 +16,8 @@ const SongDetails = () => {
if (isFetchingSongDetails && isFetchinRelatedSongs) return
;
+ console.log(songData);
+
if (error) return
;
const handlePauseClick = () => {
diff --git a/src/pages/TopArtists.jsx b/src/pages/TopArtists.jsx
index b9d1855..ac956d4 100644
--- a/src/pages/TopArtists.jsx
+++ b/src/pages/TopArtists.jsx
@@ -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
;
@@ -15,7 +15,7 @@ const TopArtists = () => {
Top artists
- {data?.tracks.map((track) =>
)}
+ {data?.map((track) =>
)}
);
diff --git a/src/redux/features/playerSlice.js b/src/redux/features/playerSlice.js
index ea1d3c5..c6f5271 100644
--- a/src/redux/features/playerSlice.js
+++ b/src/redux/features/playerSlice.js
@@ -15,6 +15,7 @@ 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) {
@@ -22,27 +23,33 @@ const playerSlice = createSlice({
} 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;
},
diff --git a/src/redux/services/shazam.js b/src/redux/services/shazam.js
deleted file mode 100644
index d8dffec..0000000
--- a/src/redux/services/shazam.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
-
-export const shazamApi = createApi({
- reducerPath: 'shazamApi',
- baseQuery: fetchBaseQuery({
- baseUrl: 'https://shazam.p.rapidapi.com',
- prepareHeaders: (headers) => {
- headers.set('X-RapidAPI-Key', import.meta.env.VITE_SHAZAM_CORE_RAPID_API_KEY);
-
- return headers;
- },
- }),
- endpoints: (builder) => ({
- getCountries: builder.query({
- query: () => '/charts/list',
- }),
- getSongs: builder.query({
- query: ({ countryListId, cityListId, genreListId }) => {
- if (countryListId) return `/charts/track?locale=en-US&listId=${countryListId}&pageSize=20&startFrom=0`;
- if (cityListId) return `/charts/track?locale=en-US&listId=${cityListId}&pageSize=20&startFrom=0`;
- if (genreListId) return `/charts/track?locale=en-US&listId=${genreListId}&pageSize=20&startFrom=0`;
- return '/charts/track?locale=en-US&listId=ip-country-chart-DE&pageSize=20&startFrom=0';
- },
- }),
- }),
-});
-
-export const { useGetSongsQuery, useGetCountriesQuery } = shazamApi;
diff --git a/src/redux/services/shazamCore.js b/src/redux/services/shazamCore.js
index 0de788f..ddf781a 100644
--- a/src/redux/services/shazamCore.js
+++ b/src/redux/services/shazamCore.js
@@ -3,7 +3,7 @@ import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
export const shazamCoreApi = createApi({
reducerPath: 'shazamCoreApi',
baseQuery: fetchBaseQuery({
- baseUrl: 'https://shazam-core.p.rapidapi.com',
+ baseUrl: 'https://shazam-core.p.rapidapi.com/v1',
prepareHeaders: (headers) => {
headers.set('X-RapidAPI-Key', import.meta.env.VITE_SHAZAM_CORE_RAPID_API_KEY);
@@ -11,50 +11,22 @@ export const shazamCoreApi = createApi({
},
}),
endpoints: (builder) => ({
- // ** GET SONGS BY GENRE
- fetchSongsByGenre: builder.query({
- query: (genre) => `/v1/charts/genre-world?genre_code=${genre}`,
- }),
- // ** GET SONGS BY COUNTRY
- fetchSongsByCountry: builder.query({
- query: (countryCode) => `/v1/charts/country?country_code=${countryCode}`,
- }),
- // ** GET SONGS BY COUNTRY AND GENRE
- fetchSongsByCountryAndGenre: builder.query({
- query: (countryCode, genre) => `/v1/charts/genre-country?country_code=${countryCode}&genre_code=${genre}`,
- }),
- // ** GET SONGS BY CITY
- fetchSongsByCity: builder.query({
- query: (cityId) => `/v1/charts/city?city_id=${cityId}`,
- }),
- // ** GET SONGS BY SEARCH QUERY
- fetchSongsBySearch: builder.query({
- query: (searchTerm) => `/v1/search/multi?search_type=SONGS_ARTISTS&query=${searchTerm}`,
- }),
- // ** GET ARTIST DETAILS
- fetchArtistDetails: builder.query({
- query: (artistId) => `/v1/artists/details?artist_id=${artistId}`,
- }),
- getTopCharts: builder.query({
- query: () => '/v1/charts/world',
- }),
- getSongDetails: builder.query({
- query: ({ songid }) => `/v1/tracks/details?track_id=${songid}`,
- }),
- getSongRelated: builder.query({
- query: ({ songid }) => `/v1/tracks/related?track_id=${songid}`,
- }),
+ getTopCharts: builder.query({ query: () => '/charts/world' }),
+ getSongsByGenre: builder.query({ query: (genre) => `/charts/genre-world?genre_code=${genre}` }),
+ getSongsByCountry: builder.query({ query: (countryCode) => `/charts/country?country_code=${countryCode}` }),
+ getSongsBySearch: builder.query({ query: (searchTerm) => `/search/multi?search_type=SONGS_ARTISTS&query=${searchTerm}` }),
+ getArtistDetails: builder.query({ query: (artistId) => `/artists/details?artist_id=${artistId}` }),
+ getSongDetails: builder.query({ query: ({ songid }) => `/tracks/details?track_id=${songid}` }),
+ getSongRelated: builder.query({ query: ({ songid }) => `/tracks/related?track_id=${songid}` }),
}),
});
export const {
- useFetchSongsByCityQuery,
- useFetchSongsByCountryAndGenreQuery,
- useFetchSongsByGenreQuery,
- useFetchSongsByCountryQuery,
- useFetchSongsBySearchQuery,
- useFetchArtistDetailsQuery,
useGetTopChartsQuery,
+ useGetSongsByGenreQuery,
+ useGetSongsByCountryQuery,
+ useGetSongsBySearchQuery,
+ useGetArtistDetailsQuery,
useGetSongDetailsQuery,
useGetSongRelatedQuery,
} = shazamCoreApi;
diff --git a/src/redux/store.js b/src/redux/store.js
index 26ed76c..ed87d04 100644
--- a/src/redux/store.js
+++ b/src/redux/store.js
@@ -1,14 +1,12 @@
import { configureStore } from '@reduxjs/toolkit';
import { shazamCoreApi } from './services/shazamCore';
-import { shazamApi } from './services/shazam';
import playerReducer from './features/playerSlice';
export const store = configureStore({
reducer: {
- [shazamApi.reducerPath]: shazamApi.reducer,
[shazamCoreApi.reducerPath]: shazamCoreApi.reducer,
player: playerReducer,
},
- middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(shazamCoreApi.middleware, shazamApi.middleware),
+ middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(shazamCoreApi.middleware),
});