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
46 changes: 33 additions & 13 deletions my-app/src/App.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import './App.css';
import React, { useState, useRef, useEffect } from 'react'
import { BrowserRouter, Routes, Route } from 'react-router-dom'
import { BrowserRouter, Routes, Route, useLocation } from 'react-router-dom'
import { Sidebar } from './components/Sidebar/Sidebar';
import { TopBar } from './components/Dashboard/TopBar/TopBar'
import { PlaybackControls } from './components/Dashboard/PlaybackControls/PlaybackControls'
Expand Down Expand Up @@ -43,24 +43,39 @@ function App() {


const apiSearch = async () => {
const url = `https://api.jamendo.com/v3.0/${filterWord}/?client_id=${apiKey}&format=jsonpretty&limit=10&namesearch=${encodeURIComponent(searchInput)}`;

try{
//let url = `https://api.jamendo.com/v3.0/${filterWord}${currArtist ? '/' + currArtist : ''}/?client_id=${apiKey}&format=jsonpretty${currArtist ? '' : '&limit=10'}&namesearch=${encodeURIComponent(searchInput)}`;
let url = `https://api.jamendo.com/v3.0/${filterWord}/`

if (currArtist) url += `/?client_id=${apiKey}&format=jsonpretty&namesearch=${currArtist.toLowerCase().replace(/\s+/g, '+')}`
else url += `?client_id=${apiKey}&format=jsonpretty&limit=10&namesearch=${encodeURIComponent(searchInput)}`

console.log(url)

try {

const response = await fetch(url);
if(!response.ok){
throw new Error(`API request failed with status ${response.status}`);
};

const data = await response.json();

setSearchResults(data.results);


}catch (err){
console.log(err);
}
} catch (err){
console.log(err);}
// } finally {
// setSearchResults([])
// }
};

const location = useLocation();
useEffect(() => {
console.log(filterWord)
setIsSearching(true); // reset old data on route change
}, [location.pathname, filterWord]);

const toggleChat = () => {
setChatDisplay(prev => !prev)
}
Expand Down Expand Up @@ -88,9 +103,9 @@ function App() {

}, [isSearching])

useEffect(() => {
setIsSearching(true)
}, [filterWord])
// useEffect(() => {
// setIsSearching(true)
// }, [filterWord])

// Load favorite songs from local storage
useEffect(() => {
Expand Down Expand Up @@ -119,7 +134,7 @@ function App() {

return (
<AuthProvider>
<BrowserRouter>
{/* <BrowserRouter> */}
<SignUp
isOpen={showAuth}
onClose={() => setShowAuth(false)}
Expand Down Expand Up @@ -154,7 +169,11 @@ function App() {
/>
}/>
<Route path='/artist' element={
<ArtistPage artist={currArtist}/>
<ArtistPage
artist={searchResults}
favoriteSongs={favoriteSongs}
setFavoriteSongs={setFavoriteSongs}
/>
}/>
<Route path='/favorites' element={
<Favorites audioRef={audioRef} audioPlaying={audioPlaying} setAudioPlaying={setAudioPlaying} setTrack={setTrack} trackQueue={trackQueue} setTrackQueue={setTrackQueue}/>
Expand All @@ -172,6 +191,7 @@ function App() {
trackQueue={trackQueue}
setTrackQueue={setTrackQueue}
filterWord={filterWord}
setFilterWord={setFilterWord}
isSearching={isSearching}
setFavoriteSongs={setFavoriteSongs}
setCurrArtist={setCurrArtist}
Expand Down Expand Up @@ -211,7 +231,7 @@ function App() {
/>
</div>
</div>
</BrowserRouter>
{/* </BrowserRouter> */}
</AuthProvider>
);
}
Expand Down
45 changes: 37 additions & 8 deletions my-app/src/components/Artist Page/Artist/Artist.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,58 @@ import { Albums } from '../Albums/Albums'



export function Artist({ songs, setSongs, updateFavorites, title}) {
export function Artist({ songs, setSongs, title, handleToggle, favoriteSongs, setFavoriteSongs}) {
const [color, setColor] = useState('#ffff')
const [scrollRatio, setScrollRatio] = useState(0)
const contentRef = useRef(null)

const gradient = {
background: `linear-gradient(${color}, black 80%)`
}

const profileStyle = {
opacity: 1 - scrollRatio,
//transform: `scale(${1 - scrollRatio * 0.2})`, // optional shrink effect
height: `${100 - scrollRatio * 100}%`, // optional collapse effect
transition: 'all 0.3s ease',
overflow: 'hidden',
};

useEffect(() => {
setColor('#' + Math. floor(Math. random()*16777215))
}, []);
}, []);

useEffect(() => {
const content = contentRef.current
const handleScroll = () => {
const scrollTop = content.scrollTop
const maxScroll = 150
const ratio = Math.min(scrollTop / maxScroll, 1)
setScrollRatio(ratio)
}

content?.addEventListener('scroll', handleScroll)
return () => content?.removeEventListener('scroll', handleScroll)
}, [])

const gradient = {
background: `linear-gradient(${color}, black 80%)`
}

return (
<div className={styles.container} >
<div className={styles.container}>
<section className={styles.profile}>
<Profile />
</section>
<section className={styles.content} style={gradient}>
<section
className={styles.content}
style={gradient} // ensure it's scrollable
>
<Info />
<Songs
songs={songs}
setSongs={setSongs}
updateFavorites={updateFavorites}
favoriteSongs={favoriteSongs}
setFavoriteSongs={setFavoriteSongs}
title={title}
handleToggle={handleToggle}
/>
<Albums />
</section>
Expand Down
29 changes: 23 additions & 6 deletions my-app/src/components/Artist Page/ArtistPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,20 @@ import { SongCard } from './Song Card/SongCard.jsx';



export function ArtistPage({ artist, songs, setSongs, favoriteSongs, updateFavorites }) {
export function ArtistPage({ artist, favoriteSongs, setFavoriteSongs }) {
console.log(artist)
const [currSong, setCurrSong] = useState(null)
const [toggleSong, setToggleSong] = useState(false)
const [songs, setSongs] = useState([artist[0].tracks])

const handleToggle = (i) => {
if (currSong == i) {
setToggleSong(!toggleSong)
} else {
setToggleSong(true)
setCurrSong(i)
}
}

return (
<main className={styles.contentArea}>
Expand All @@ -15,14 +28,18 @@ export function ArtistPage({ artist, songs, setSongs, favoriteSongs, updateFavor
artist={artist}
songs={songs}
setSongs={setSongs}
favoriteSongs={favoriteSongs}
updateFavorites={updateFavorites}
favoriteSongs={favoriteSongs}
setFavoriteSongs={setFavoriteSongs}
handleToggle={handleToggle}
title='Popular Songs'
/>
</section>
<section className={styles.songCard} >
<SongCard/>
</section>
{toggleSong && (
<section className={styles.songCard} >
<SongCard/>
</section>
)}

</main>
)
}
1 change: 0 additions & 1 deletion my-app/src/components/Artist Page/Profile/Profile.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ export function Profile() {
return (
<div className={styles.profile}>
<img src='https://picsum.photos/250' alt='' className={styles.img} />
<h1 className={styles.name}>Artist Name</h1>
</div>
)
}
41 changes: 32 additions & 9 deletions my-app/src/components/Artist Page/Songs/Songs.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,37 @@ import styles from './Songs.module.css'
import { SongLike } from './SongLike'


export function Songs({ songs, setSongs, audioRef, audioPlaying, setAudioPlaying, setTrack, trackQueue, setTrackQueue, fav }) {
export function Songs({
songs,
setSongs,
audioRef,
audioPlaying,
setAudioPlaying,
setTrack,
trackQueue,
setTrackQueue,
favoriteSongs,
setFavoriteSongs,
title,
onLike,
toggleSong,
handleToggle
}) {

// const [songs, setSongs] = useState([
// {id: 1, title: `Song 1`, album: 'Album Name', release: new Date().getFullYear(), isLiked: false},
// {id: 2, title: `Song 2`, album: 'Album Name', release: new Date().getFullYear(), isLiked: false},
// {id: 3, title: `Song 3`, album: 'Album Name', release: new Date().getFullYear(), isLiked: false},
// {id: 4, title: `Song 4`, album: 'Album Name', release: new Date().getFullYear(), isLiked: false},
// {id: 5, title: `Song 5`, album: 'Album Name', release: new Date().getFullYear(), isLiked: false}
// ])
const handleLike = (id) => {
console.log(id)
const updatedSongs = songs.map(song =>
song.id === id
? { ...song, isLiked: !song.isLiked }
: song
)

setSongs(updatedSongs)

const filteredSongs = updatedSongs.filter((song) => song.isLiked)

setFavoriteSongs([...favoriteSongs, filteredSongs])
}

const handlePlay = (song) => {

Expand Down Expand Up @@ -60,12 +81,14 @@ export function Songs({ songs, setSongs, audioRef, audioPlaying, setAudioPlaying
};
if (!Array.isArray(songs)) return null;

if (!Array.isArray(songs)) return null;

return (
<div className={styles.song_container}>
<h2 className={styles.title}>{fav? "Favorited Songs": "Popular Songs"}</h2>
<ol className={styles.song_list}>
{songs.map((song) =>
<li className={styles.song} key={song.id}>
<li className={styles.song} key={song.id} onClick={() => handleToggle(song.id)}>
<div className={styles.img_div}>
<button style={{cursor: "pointer", background: 'none', border: 'none'}} className={styles.img_btn}>
<img src={song.album_image} alt='song image' className={styles.song_img} onClick={() => {handlePlay(song)}} />
Expand Down
4 changes: 3 additions & 1 deletion my-app/src/components/Dashboard/TopBar/Search/Search.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export function Search({
trackQueue,
setTrackQueue,
filterWord,
setFilterWord,
isSearching,
setFavoriteSongs,
setCurrArtist
Expand Down Expand Up @@ -70,7 +71,7 @@ export function Search({
<span className={styles.bouncing_dot}>.</span>
</div>
: searchResults.length > 1
? filterWord === 'tracks'
? filterWord === 'tracks'
? (<Songs
songs={searchResults}
setSongs={setSearchResults}
Expand All @@ -86,6 +87,7 @@ export function Search({
: filterWord === 'artists'
? (<Artists
artists={searchResults}
setFilterWord={setFilterWord}
setCurrArtist={setCurrArtist}
style={{height: '100%'}}
/>)
Expand Down
4 changes: 3 additions & 1 deletion my-app/src/components/Dashboard/TopBar/TopBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export function TopBar({ showFilter, setShowFilter, showDropdown, setShowDropdow
})
setFilterWord(e.target.id)
}

const handleLogout = async () => {
try {
await signOut(auth);
Expand All @@ -35,7 +36,7 @@ export function TopBar({ showFilter, setShowFilter, showDropdown, setShowDropdow
<div className={styles.searchContainer}>
<div className={styles.searchWrapper}>
<Search className={styles.searchIcon} style={{cursor: 'pointer'}} onClick={(e) => {

if (!searchInput) return
setIsSearching(true);
nav('/search');

Expand All @@ -47,6 +48,7 @@ export function TopBar({ showFilter, setShowFilter, showDropdown, setShowDropdow
value={searchInput}
onChange={handleChange}
onKeyDown={(e) => {
if (!searchInput) return
if(e.key === 'Enter'){
setIsSearching(true);
nav('/search');
Expand Down
10 changes: 6 additions & 4 deletions my-app/src/components/Search Results/Artists.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,29 @@ import styles from './Artists.module.css'
import { Globe } from 'lucide-react'
import { useNavigate } from 'react-router-dom'

export const Artists = ({ artists, setCurrArtist }) => {
export const Artists = ({ artists, setFilterWord, setCurrArtist }) => {

const nav = useNavigate()
if (!Array.isArray(artists)) return null;

const handleClick = (artist) => {
console.log(artist)
setCurrArtist(artist)
setFilterWord('artists/tracks')
nav('/artist')
}

if (!Array.isArray(artists)) return null

return (
<div className={styles.container}>
<h1 className={styles.title}>Artist Results</h1>
<div className={styles.artistList}>
{artists.map((artist) => (
<div key={artist.id} className={styles.artistCard}>
<button onClick={() => {handleClick(artist.name)}}>
<img src={artist.image} alt={artist.name} className={styles.img}/>
<img src={artist.image || 'https://picsum.photos/301/201' } alt={artist.name} className={styles.img}/>
</button>
<h2>{artist.name.length > 12 ? artist.name.slice(0, 15) + '...' : artist.name}</h2>
<h2>{artist.name.length > 12 ? artist.name.slice(0,12) + '...' : artist.name}</h2>
<div className={styles.info}>
<p>Founded: {artist.joindate ? artist.joindate.slice(0,4) : 'Unknown'}</p>
<a href={artist.website} target='_blank' rel='noreferrer' className={styles.artistLink}><Globe/></a>
Expand Down
5 changes: 4 additions & 1 deletion my-app/src/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import { BrowserRouter } from 'react-router-dom';
import App from './App';
import reportWebVitals from './reportWebVitals';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
<BrowserRouter>
<App/>
</BrowserRouter>
</React.StrictMode>
);

Expand Down