Skip to content

Commit

Permalink
Build Center & Songs Components
Browse files Browse the repository at this point in the history
  • Loading branch information
thunder30 committed Jan 10, 2022
1 parent 04f646c commit 6d51d0d
Show file tree
Hide file tree
Showing 13 changed files with 299 additions and 34 deletions.
11 changes: 11 additions & 0 deletions atoms/playlistAtom.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { atom } from 'recoil'

export const playlistState = atom({
key: 'playlistState',
default: null,
})

export const playlistIdState = atom({
key: 'playlistIdState',
default: '37i9dQZF1EUMDoJuT8yJsl',
})
80 changes: 80 additions & 0 deletions components/Center.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { useSession } from 'next-auth/react'
import { ChevronDownIcon } from '@heroicons/react/outline'
import { useEffect, useState } from 'react'
import { shuffle } from 'lodash'
import { useRecoilState, useRecoilValue } from 'recoil'
import { playlistIdState, playlistState } from '../atoms/playlistAtom'
import useSpotify from '../hooks/useSpotify'
import Songs from './Songs'

const colors = [
'from-indigo-500',
'from-blue-500',
'from-green-500',
'from-red-500',
'from-yellow-500',
'from-pink-500',
'from-purple-500',
]

function Center() {
const spotifyApi = useSpotify()
const { data: session } = useSession()
const [color, setColor] = useState(null)
const playlistId = useRecoilValue(playlistIdState)
const [playlist, setPlaylist] = useRecoilState(playlistState)

console.log('Playlist - ', playlist)

useEffect(() => {
setColor(shuffle(colors).pop())
}, [playlistId])

useEffect(() => {
spotifyApi
.getPlaylist(playlistId)
.then((data) => setPlaylist(data.body))
.catch((error) => console.log(error))
}, [spotifyApi, playlistId])

return (
<div className="flex-grow h-screen overflow-y-scroll scrollbar-hide">
<header className="absolute top-5 right-8">
<div
className="flex items-center bg-black space-x-3
opacity-90 hover:opacity-80 cursor-pointer rounded-full p-1 pr-2 text-white text-sm"
>
<img
className="rounded-full w-10 h-10"
src={session?.user.image}
alt="avatar"
/>
<h2>{session?.user.name}</h2>
<ChevronDownIcon className="h-5 w-5" />
</div>
</header>
<section
className={`flex items-end space-x-7
bg-gradient-to-b to-black ${color} h-80 text-white p-8`}
>
<img
className="w-44 h-44 shadow-2xl"
src={playlist?.images[0]?.url}
alt="playlist image"
/>
<div>
<p>PLAYLIST</p>
<h1 className="text-2xl md:text-3xl xl:text-5xl font-bold">
{playlist?.name}
</h1>
</div>
</section>

<div>
<Songs />
</div>
</div>
)
}

export default Center
47 changes: 35 additions & 12 deletions components/Sidebar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,36 @@ import {
HeartIcon,
} from '@heroicons/react/outline'
import { signOut, useSession } from 'next-auth/react'
import { useEffect, useState } from 'react'
import { useRecoilState } from 'recoil'
import useSpotify from '../hooks/useSpotify'
import { playlistIdState } from '../atoms/playlistAtom'

function Sidebar() {
const spotifyApi = useSpotify()
const { data: session, status } = useSession()
console.log(session)
const [playlist, setPlaylist] = useState([])
const [playlistId, setPlaylistId] = useRecoilState(playlistIdState)
//console.log('session sidebar - ', session)
// console.log(` YOu picked playlistId: `, playlistId)

useEffect(() => {
if (spotifyApi.getAccessToken()) {
spotifyApi
.getUserPlaylists()
.then((data) => {
setPlaylist(data.body.items)
})
.catch((err) => console.error(err))
}
}, [session, spotifyApi])

return (
<div className="text-gray-500 p-5 text-sm border-r border-gray-900">
<div
className="text-gray-500 p-5 text-xs lg:text-sm border-r border-gray-900
overflow-y-scroll scrollbar-hide h-screen sm:max-w-[12rem] lg:max-w-[15rem]
hidden md:inline-flex"
>
<div className="space-y-4">
<button
className="flex items-center space-x-4 hover:text-white"
Expand Down Expand Up @@ -49,16 +73,15 @@ function Sidebar() {
<hr className="border-t-[0.1px] border-gray-900" />

{/* Playlist */}
<p className="cursor-point hover:text-white">Playlist name</p>
<p className="cursor-point hover:text-white">Playlist name</p>
<p className="cursor-point hover:text-white">Playlist name</p>
<p className="cursor-point hover:text-white">Playlist name</p>
<p className="cursor-point hover:text-white">Playlist name</p>
<p className="cursor-point hover:text-white">Playlist name</p>
<p className="cursor-point hover:text-white">Playlist name</p>
<p className="cursor-point hover:text-white">Playlist name</p>
<p className="cursor-point hover:text-white">Playlist name</p>
<p className="cursor-point hover:text-white">Playlist name</p>
{playlist.map((playlist) => (
<p
key={playlist.id}
className="cursor-pointer hover:text-white"
onClick={() => setPlaylistId(playlist.id)}
>
{playlist.name}
</p>
))}
</div>
</div>
)
Expand Down
30 changes: 30 additions & 0 deletions components/Song.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { millisToMinutesAndSeconds } from '../lib/time'

function Song({ order, track }) {
// console.log(track)
return (
<div className="grid grid-cols-2">
<div className="flex items-center space-x-4">
<p>{order + 1}</p>
<img
className="w-10 h-10"
src={track.track.album.images[0].url}
alt="track image"
/>
<div>
<p>{track.track.name}</p>
<p>{track.track.artists[0].name}</p>
</div>
</div>
<div
className="flex items-center justify-between
ml-auto md:ml-0"
>
<p className="hidden md:inline">{track.track.album.name}</p>
<p>{millisToMinutesAndSeconds(track.track.duration_ms)}</p>
</div>
</div>
)
}

export default Song
17 changes: 17 additions & 0 deletions components/Songs.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useRecoilValue } from 'recoil'
import { playlistState } from '../atoms/playlistAtom'
import Song from './Song'

function Songs() {
const playlist = useRecoilValue(playlistState)

return (
<div className="flex flex-col px-8 space-y-1 pb-20 text-white">
{playlist?.tracks.items.map((track, index) => (
<Song key={track.track.id} order={index} track={track} />
))}
</div>
)
}

export default Songs
27 changes: 27 additions & 0 deletions hooks/useSpotify.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { signIn, useSession } from 'next-auth/react'
import { useEffect } from 'react'
import SpotifyWebApi from 'spotify-web-api-node'
// import spotifyApi from '../lib/spotify'

const spotifyApi = new SpotifyWebApi({
clientId: process.env.NEXT_PUBLIC_CLIENT_ID,
clientSecret: process.env.NEXT_PUBLIC_CLIENT_SECRET,
})

function useSpotify() {
const { data: session, status } = useSession()

useEffect(() => {
if (session) {
// If refresh token attempt fails, direct user to login
if (session.error === 'RefreshAccessTokenError') {
signIn()
}

spotifyApi.setAccessToken(session.user.accessToken)
}
}, [session])
return spotifyApi
}

export default useSpotify
10 changes: 10 additions & 0 deletions lib/time.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { constSelector } from 'recoil'

export const millisToMinutesAndSeconds = (millis) => {
const minutes = Math.floor(millis / 60000)
const seconds = ((millis % 60000) / 1000).toFixed(0)

return seconds == 60
? minutes + 1 + ':00'
: minutes + ':' + (seconds < 10 ? '0' : '') + seconds
}
62 changes: 61 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@
},
"dependencies": {
"@heroicons/react": "^1.0.5",
"lodash": "^4.17.21",
"next": "latest",
"next-auth": "^4.0.6",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"spotify-web-api-node": "^5.0.2"
"recoil": "^0.5.2",
"spotify-web-api-node": "^5.0.2",
"tailwind-scrollbar-hide": "^1.1.7"
},
"devDependencies": {
"@types/node": "17.0.4",
Expand Down
Loading

0 comments on commit 6d51d0d

Please sign in to comment.