فهرست منبع

Merge branch 'styles-implement' of Sergei-Levshnia/player-project into dev

Sergei-Levshnia 2 سال پیش
والد
کامیت
679423fc41

+ 0 - 38
src/App.css

@@ -1,38 +0,0 @@
-.App {
-  text-align: center;
-}
-
-.App-logo {
-  height: 40vmin;
-  pointer-events: none;
-}
-
-@media (prefers-reduced-motion: no-preference) {
-  .App-logo {
-    animation: App-logo-spin infinite 20s linear;
-  }
-}
-
-.App-header {
-  background-color: #282c34;
-  min-height: 100vh;
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  justify-content: center;
-  font-size: calc(10px + 2vmin);
-  color: white;
-}
-
-.App-link {
-  color: #61dafb;
-}
-
-@keyframes App-logo-spin {
-  from {
-    transform: rotate(0deg);
-  }
-  to {
-    transform: rotate(360deg);
-  }
-}

+ 28 - 19
src/App.js

@@ -1,15 +1,15 @@
-import './App.css';
+import './App.scss';
 import * as action from './actions'
 import * as reducer from './reducers'
 import * as Logcomp from './components/Login'
 import * as Sidebar from './components/Sidebar'
 import * as Page from './components/Page'
-import  {PlayerbarConnect} from './components/Playerbar'
+import { PlayerbarConnect } from './components/Playerbar'
 
 import thunk from 'redux-thunk';
 import { createStore, combineReducers, applyMiddleware } from 'redux';
 import { Provider } from 'react-redux';
-import { Link, Route, Router, Switch } from 'react-router-dom';
+import { Route, Router, Switch } from 'react-router-dom';
 import createHistory from 'history/createBrowserHistory'
 
 export function jwtDecode(token) {
@@ -65,37 +65,46 @@ if (store.getState().auth?.token) {
   history.push('/login')
 }
 
+const GreetPg = () =>
+  <>
+    <h2>Welcome to online Player!</h2>
+    <div className='startpage__ulwrapper'>
+      <ul>
+        <li>
+          <strong className='highlightYellow'>Click "MY UPLOADS" - </strong><small>To see all of your uploaded tracks.</small>
+        </li>
+        <li>
+          <strong className='highlightGreen'>Click "NEW PLAYLIST" - </strong><small>To create new playlist.</small>
+        </li>
+        <li>
+          <strong>Drag 'n' drop track to playlist area - </strong><small>To upload the track and add it to current playlist.</small>
+        </li>
+        <li>
+          <strong>Drag a track within playlist - </strong><small>To chage the order of playlist tracks.</small>
+        </li>
+      </ul>
+    </div>
+  </>
+
 const Player = () =>
   <div>
-    {/* <header><Link to="/player">Player</Link></header> */}
-    <div style={{ border:'1px solid blue', display: 'flex', maxHeight: '89vh', minHeight:'30vh', overflow:'none'}}>
-      <aside style={{width: '30%', overflow:'auto'}}>
+    <div className='page'>
+      <aside className='sidebar' >
         <Sidebar.LogoutBtnConnect />
         <Sidebar.ProfileWindowDropzoneConnect />
         <Sidebar.UserTracksBtnConnect />
         <Sidebar.PlaylistAddConnect />
         <Sidebar.PlaylistsConnect />
       </aside>
-      <main style={{ border: '1px solid red', width: '80%', height:'inherit', overflow:'auto'}}>
+      <main className='page__window'>
         <Switch>
           <Route path="/player/playlist/:_id" component={Page.PlaylistPageConnect} exact />
           <Route path="/player/tracks/:_id" component={Page.UserTracksPageConnect} exact />
-          <>
-            <h2>Welcome to online Player!</h2>
-            <div style={{ width: '50%', margin: '0 auto' }}>
-              <ul style={{ textAlign: 'start' }}>
-                <li><strong>Click "NEW PLAYLIST" - </strong><small>To create new playlist.</small></li>
-                <li><strong>Drag 'n' drop track to playlist area - </strong><small>To upload the track and add it to current playlist.</small></li>
-                <li><strong>Drag a track within playlist - </strong><small>To chage the order of playlist tracks.</small></li>
-                <li><strong>Click "MY UPLOADS" - </strong><small>To see all of your uploaded tracks.</small></li>
-              </ul>
-            </div>
-          </>
+          <GreetPg />
         </Switch>
       </main>
     </div>
     <PlayerbarConnect />
-    {/* <PlayerBar /> */}
   </div>
 
 function App() {

+ 57 - 0
src/App.scss

@@ -0,0 +1,57 @@
+@import "./styles/Sidebar.scss";
+@import "./styles/Page.scss";
+@import "./styles/Playerbar.scss";
+@import "./styles/Forms.scss";
+
+body {
+  background-color: #100d23;
+  ::-webkit-scrollbar {
+    width: 12px;
+
+    &-track {
+      background-color: transparent;
+      border: 1px solid rgba(105, 105, 105, 0.384);
+    }
+
+    &-thumb {
+      background-color: #534f7459;
+
+      &:hover {
+        background-color: #534f74c7;
+      }
+    }
+  }
+
+  :hover {
+    transition: 0.1s;
+  }
+}
+
+.App {
+  text-align: center;
+  color: #70b2e7;
+}
+
+.highlightYellow {
+  color: yellow;
+  border-color: yellow;
+}
+
+.highlightRed {
+  color: red;
+  border-color: red;
+}
+
+.highlightGreen {
+  color: #05f09b;
+  border-color: #05f09b;
+}
+
+.highlightPaleGreen {
+  background-color: #0e6147;
+  color: #05f09b;
+}
+
+.lightText {
+  font-weight: 300;
+}

+ 8 - 12
src/actions/index.js

@@ -12,14 +12,12 @@ const actionTrackSet = (track, audio, playlist) =>
     volume: audio.volume
 })
 
+const actionTrackEject = () => ({type: 'EJECT_TRACK'})
 const actionTrackSetDuration = (time) => ({ type: 'SET_DURATION', duration: time })
-
 const actionTrackSetCurrTime = (time) => ({ type: 'SET_CURRTIME', currentTime: time })
-
 const actionTrackSetVolume = (value) => ({ type: 'SET_VOLUME', volume: value })
 const actionTrackPlay = () => ({ type: 'PLAY_TRACK' })
 const actionTrackPause = (currentTime) => ({ type: 'PAUSE_TRACK', currentTime: currentTime })
-
 const actionPlaylistSet = (playlist) => ({type: 'SET_PLAYLIST', playlist: playlist})
 const actionSetPlaylistIndex = (index) => ({type: 'SET_INDEX', playlistIndex: index})
 
@@ -76,15 +74,6 @@ audio.onended = () => store.dispatch(switchTrack(true, store.getState().player.p
 audio.ondurationchange = (e) =>  store.dispatch(actionTrackSetDuration(e.target.duration))
 audio.ontimeupdate = (e) => store.dispatch(actionTrackSetCurrTime(e.target.currentTime))
 
-
-
-
-
-
-
-
-
-
 const actionPending = name => ({ type: 'PROMISE', status: 'PENDING', name })
 const actionResolved = (name, payload) => ({ type: 'PROMISE', status: 'RESOLVED', name, payload })
 const actionRejected = (name, error) => ({ type: 'PROMISE', status: 'REJECTED', name, error })
@@ -103,6 +92,13 @@ export const actionPromise = (name, promise) =>
 
 export const actionAuthLogin = token => ({ type: 'AUTH_LOGIN', token })
 export const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' })
+export const actionFullLogout = () =>
+    dispatch => {
+        audio.pause()
+        dispatch(actionTrackEject())
+        dispatch(actionAuthLogout())
+    }
+
 export const actionLogin = (login, password) =>
     actionPromise('login', gql(`
   query log($login:String!, $password:String!) {

BIN
src/assets/default.png


+ 21 - 17
src/components/Login/index.js

@@ -12,19 +12,24 @@ const RegisterForm = ({ onRegister }) => {
   return (
     <>
       <h1>Web-player</h1>
-      <div>
-        <h2>Registration</h2>
-        <input type="text" placeholder='Login' onChange={(e) => setLogin(e.target.value)} />
-        <br />
-        <input type="password" placeholder='Password' onChange={(e) => setPassword(e.target.value)} />
-        <br />
-        <input disabled={!password} type="password" placeholder='Repeat Password' onChange={(e) => setPassword2(e.target.value)} />
-        <br />
+      <div className='forms'>
+        <h2 className='highlightYellow'>Registration</h2>
+        <input className='forms__input' type="text" placeholder='Login' onChange={(e) => setLogin(e.target.value)} />
+        <input className='forms__input' type="password" placeholder='Password' onChange={(e) => setPassword(e.target.value)} />
+        <input 
+          className='forms__input' 
+          disabled={!password} type="password" placeholder='Repeat Password *' 
+          onChange={(e) => setPassword2(e.target.value)} 
+        />
         <small style={{ color: 'red' }}>{password2 && password2 !== password ? 'Passwords do not match' : ''}</small>
         <br />
-        <button disabled={!password || !login || password2 !== password} onClick={() => onRegister(login, password)}>Register</button>
+        <button 
+          className='forms__button highlightYellow' 
+          disabled={!password || !login || password2 !== password} 
+          onClick={() => onRegister(login, password)}
+        >Register</button>
         <br />
-        <Link to="/login">Back to log-in page</Link>
+        <Link className='sidebar__link highlightYellow' to="/login">Back to log-in page</Link>
       </div>
     </>
   )
@@ -44,22 +49,21 @@ const LoginForm = ({ loged, onLogin }) => {
   return (
     <>
       <h1>Web-player</h1>
-      <div>
-        <h2>Log-in</h2>
-        <input type="text" placeholder='Login' onChange={(e) => setLogin(e.target.value)} />
-        <br />
-        <input type="password" placeholder='Password' onChange={(e) => setPassword(e.target.value)} />
-        <br />
+      <div className='forms'>
+        <h2 className='highlightYellow'>Log-in</h2>
+        <input className='forms__input' type="text" placeholder='Login' onChange={(e) => setLogin(e.target.value)} />
+        <input className='forms__input' type="password" placeholder='Password' onChange={(e) => setPassword(e.target.value)} />
         <small style={{ color: 'red' }}>
           {loged.status === 'REJECTED' || (loged.status === 'RESOLVED' && !loged.payload)? 'invalid login or password' : ''}
         </small>
         <br />
         <button
+          className='forms__button highlightGreen'
           disabled={!password || !login}
           onClick={() => { onLogin(login, password) }}
         >Login</button>
         <p>- OR -</p>
-        <Link to="/registration">Register new user</Link>
+        <Link className='forms__link highlightYellow' to="/registration">Register new user</Link>
       </div>
     </>
   )

+ 27 - 25
src/components/Page/index.js

@@ -15,25 +15,25 @@ const Track = ({ track, playlist, player, setTrack, playTrack, pauseTrack }) =>
   useEffect(() => setPlayer(player), [player])
 
   return (
-    <li style={{ border: '1px solid black', display: 'flex', alignItems: 'center' }}>
-      <div style={{ marginRight: '2%', padding: '2%' }}>
-
-        {isPlay && _player?.isPlaying && _player.track?._id === track._id ?
-          <button style={{ fontSize: '3vh', padding: '10px' }} onClick={() => { pauseTrack(); setPlay(false) }}> <FontAwesomeIcon style={{pointerEvents:'none'}} icon={faPause} /> </button> :
-          <button
-            style={{ fontSize: '3vh', padding: '10px' }}
-            onClick={() => {
-              if (track?._id !== _player?.track?._id) setTrack(track, playlist)
-              playTrack()
-              setPlay(true)
-            }}
-          > <FontAwesomeIcon style={{pointerEvents:'none'}} icon={faPlay} /> </button>
-        }
-      </div>
-      <div style={{ textAlign: 'left' }}>
-        <h5>{track.id3.artist || 'Artist: unknown'}</h5>
-        <h6>{track.id3.album || 'Album: unknown'}</h6>
-        <h5>{track.id3.title || track.originalFileName}</h5>
+    <li className={isPlay && _player?.isPlaying && _player.track?._id === track._id ? 'playlist__track highlightPaleGreen' : 'playlist__track'}>
+      {isPlay && _player?.isPlaying && _player.track?._id === track._id ?
+        <button 
+          className='highlightYellow' 
+          onClick={() => { pauseTrack(); setPlay(false) }}
+        ><FontAwesomeIcon style={{pointerEvents:'none'}} icon={faPause} /></button> :
+        <button
+          className='highlightGreen'
+          onClick={() => {
+            if (track?._id !== _player?.track?._id) setTrack(track, playlist)
+            playTrack()
+            setPlay(true)
+          }}
+        ><FontAwesomeIcon style={{pointerEvents:'none'}} icon={faPlay} /></button>
+      }
+      <div>
+        <small className='artist'>{track.id3.artist || 'Artist: unknown'}</small>
+        <small className='album'>{track.id3.album || 'Album: unknown'}</small>
+        <small className='title'>{track.id3.title || track.originalFileName}</small>
       </div>
     </li>
   )
@@ -71,7 +71,7 @@ const Playlist = ({ player, playlist, setPlaylist, updPlaylist, setIndex }) => {
 
   return (
     <>
-      <h2>{playlist[0]?.name || 'Playlist'}</h2>
+      <h2 className='highlightGreen'>{playlist[0]?.name || 'Playlist'}</h2>
       <SortableContainer onSortEnd={onSortEnd}>
         {(_tracks || []).map((track, index) => <SortableItem index={index} track={track} playlist={playlist[0]} />)}
       </SortableContainer>
@@ -104,9 +104,10 @@ const PlaylistTrackDropzone = ({ playlist, uploadTrack }) => {
   return (
     <div
       {...getRootProps()}
-      style={{ height: 'fit-content', border: `${isDragActive ? '1px solid mediumseagreen' : '1px solid black'}` }}
+      className='playlist'
+      style={{ border: `${isDragActive ? '1px solid yellow' : '1px solid transparent'}` }}
     >
-      {isDragActive ? <small>...drag here</small> : <small>to upload drag track here</small>}
+      <small className='lightText'>{isDragActive ? '...drop here' : 'to upload: drag and drop track here'}</small>
       <PlaylistConnect />
     </div>
   )
@@ -126,7 +127,7 @@ const UserTracks = ({ user, tracks }) => {
   let tracksRev = [...tracks].reverse()
   return (
     <>
-      <h2>{user.login || 'My'} uploaded tracks:</h2>
+      <h2 className='highlightYellow'>{user.login || 'My'} uploaded tracks:</h2>
       <ul>{(tracksRev || []).map(track => <TrackConnect track={track} playlist={tracksRev} />)}</ul>
     </>
   )
@@ -145,9 +146,10 @@ const UserTracksDropzone = ({ onLoad }) => {
   return (
     <div
       {...getRootProps()}
-      style={{ height: 'fit-content', border: `${isDragActive ? '1px solid mediumseagreen' : '1px solid black'}` }}
+      className='playlist'
+      style={{ height: 'fit-content', border: `${isDragActive ? '1px solid yellow' : '1px solid black'}` }}
     >
-      {isDragActive ? <small>...drag here</small> : <small>to upload drag track here</small>}
+      <small className='lightText'>{isDragActive ? '...drop here' : 'to upload: drag and drop track here'}</small>
       <UserTracksConnect />
     </div>
   )

+ 44 - 39
src/components/Playerbar.js

@@ -1,14 +1,14 @@
 import { useEffect, useState } from "react"
 import { connect } from "react-redux"
-import { faHome, faPlay, faPause, faForward, faBackward, faFastForward, faFastBackward, faVolumeUp} from "@fortawesome/free-solid-svg-icons";
+import { faPlay, faPause, faForward, faBackward, faFastForward, faFastBackward, faVolumeUp } from "@fortawesome/free-solid-svg-icons";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 import * as action from "../actions"
 
 
-const Timestamp = ({time}) =>
-    <small style={{margin: '0 10px'}}>
-        {Math.floor((time / 60) % 60) < 10? `0` + Math.floor((time / 60) % 60) : Math.floor((time / 60) % 60)} : 
-        {Math.floor(time % 60) < 10?  `0`+ Math.floor(time % 60) : Math.floor(time % 60)}
+const Timestamp = ({ time }) =>
+    <small className="timestamp highlightYellow">
+        {Math.floor((time / 60) % 60) < 10 ? `0` + Math.floor((time / 60) % 60) : Math.floor((time / 60) % 60)}:
+        {Math.floor(time % 60) < 10 ? `0` + Math.floor(time % 60) : Math.floor(time % 60)}
     </small>
 
 const Playerbar = ({ player, playTrack, pauseTrack, switchTrack, setTrackVolume, setCurrentTime }) => {
@@ -19,51 +19,56 @@ const Playerbar = ({ player, playTrack, pauseTrack, switchTrack, setTrackVolume,
     }, [player, _player])
 
     return (
-        <>
-            {_player?.track ?  
-                <footer style={{display: `${_player?.track ? 'block' : 'none'}`, width: '95%', margin:'0 auto'}}>
-                    <input
-                        style={{width:'100%'}}
-                        type="range" min="0" max={_player?.duration} step="any"
-                        value={_player?.currentTime}
-                        onChange={(e) => setCurrentTime(e.target.value)}
-                    />
-                    <div style={{display:"flex", justifyContent:"space-between", width:'95%', margin:'0 auto'}}>
-                        <Timestamp time={_player?.currentTime} />
-                        {_player ? (_player.track?.id3?.artist && _player.track?.id3?.title ?
-                            <strong>{_player.track?.id3?.artist} - {_player.track?.id3?.title}</strong> :
-                            <strong>{_player.track?.originalFileName}</strong>) : ''}
+        <footer className="playerbar">
+            {_player?.track ?
+                <div style={{ display: `${_player?.track ? 'block' : 'none'}` }}>
+                    <div>
+                        <input
+                            className="playerbar__range plumline yellowThumb"
+                            style={{ width: '95%' }}
+                            type="range" min="0" max={_player?.duration} step="any"
+                            value={_player?.currentTime}
+                            onChange={(e) => setCurrentTime(e.target.value)}
+                        />
+                    </div>
+                    <div className="playerbar__info">
+                        <Timestamp className="playerbar" time={_player?.currentTime} />
+                        <strong className="highlightYellow">
+                            <small className="lightText highlightGreen">{(_player.playlist.name || 'Uploads') + ' : '}</small>
+                            {(_player.track?.id3?.artist && _player.track?.id3?.title ?
+                                _player.track?.id3?.artist + ' - ' + _player.track?.id3?.title :
+                                _player.track?.originalFileName)}
+                        </strong>
                         <Timestamp time={_player?.duration} />
                     </div>
-                    <div style={{marginTop:'0.5%'}}>
-                        <button
-                            style={{ fontSize: '2vh', padding: '5px' }}
-                            onClick={() => switchTrack(false, _player?.playlistIndex, _player?.playlist)}
-                        >
-                            {_player?.playlistIndex === 0 ? <FontAwesomeIcon icon={faFastBackward} />:
-                                                            <FontAwesomeIcon icon={faBackward} />}
+                    <div style={{ marginTop: '0.5%' }}>
+                        <button onClick={() => switchTrack(false, _player?.playlistIndex, _player?.playlist)}>
+                            {_player?.playlistIndex === 0 ? <FontAwesomeIcon icon={faFastBackward} /> :
+                                <FontAwesomeIcon icon={faBackward} />}
                         </button>
 
                         {_player?.isPlaying ?
-                            <button style={{ fontSize: '2vh', padding: '5px' }} onClick={() => pauseTrack()}><FontAwesomeIcon icon={faPause} /></button> :
-                            <button style={{ fontSize: '2vh', padding: '5px' }} onClick={() => playTrack()}><FontAwesomeIcon icon={faPlay} /></button>
+                            <button onClick={() => pauseTrack()}><FontAwesomeIcon icon={faPause} /></button> :
+                            <button onClick={() => playTrack()}><FontAwesomeIcon icon={faPlay} /></button>
                         }
 
-                        <button
-                            style={{ fontSize: '2vh', padding: '5px' }}
-                            onClick={() => switchTrack(true, _player?.playlistIndex, _player?.playlist)}
-                        >
-                            {_player?.playlistIndex === (_player?.playlist?.constructor.name === 'Array'? _player?.playlist?.length - 1 : _player?.playlist?.tracks.length - 1) ? 
-                                <FontAwesomeIcon icon={faFastForward} /> : <FontAwesomeIcon icon={faForward} />}
+                        <button onClick={() => switchTrack(true, _player?.playlistIndex, _player?.playlist)}>
+                            {_player?.playlistIndex === (_player?.playlist?.constructor.name === 'Array' ?
+                                _player?.playlist?.length - 1 : _player?.playlist?.tracks.length - 1) ?
+                                <FontAwesomeIcon icon={faFastForward} /> :
+                                <FontAwesomeIcon icon={faForward} />}
                         </button>
-                        <label style={{marginLeft: '1%'}}>
+                        <label style={{ marginLeft: '1%' }}>
                             <FontAwesomeIcon icon={faVolumeUp} />
-                            <input type="range" min="0" max="1" step="any" onChange={(e) => setTrackVolume(e.target.value)} />
+                            <input
+                                className="playerbar__range blueline blueThumb"
+                                type="range" min="0" max="1" step="any"
+                                onChange={(e) => setTrackVolume(e.target.value)} 
+                            />
                         </label>
                     </div>
-                    {/* <small>{_player?.playlistIndex}</small> */}
-                </footer> : <div style={{width:'inherit', height:'inherit', padding:'2em'}}>C'mon, Push the play button on some track :)</div>}
-        </>
+                </div> : <></>}
+        </footer>
     )
 }
 

+ 38 - 51
src/components/Sidebar/index.js

@@ -1,36 +1,34 @@
 import * as action from '../../actions'
+import plugPic from '../../assets/default.png'
 
 import { useState, useEffect, useCallback } from 'react';
 import { connect } from 'react-redux';
 import { Link } from 'react-router-dom';
-import { history, backendURL } from '../../App';
+import { backendURL } from '../../App';
 import { useDropzone } from 'react-dropzone'
+import { faPlus, faBan, faSignOutAlt, faUpload} from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 
 const LogoutBtn = ({ onLogout }) =>
-  <div
-    style={{ border: '1px solid black', backgroundColor: 'red', color: 'white' }}
-    onClick={() => { onLogout(); history.push('/login') }}
-  >log-out[X]</div>
+  <Link
+    to='/login'
+    className='sidebar__link highlightRed'
+    onClick={() =>  onLogout()}
+  >LOG-OUT <FontAwesomeIcon icon={faSignOutAlt}/></Link>
 
-export const LogoutBtnConnect = connect(null, { onLogout: action.actionAuthLogout })(LogoutBtn)
+//export const LogoutBtnConnect = connect(null, { onLogout: action.actionAuthLogout })(LogoutBtn)
+export const LogoutBtnConnect = connect(null, { onLogout: action.actionFullLogout })(LogoutBtn)
 
 const ProfileWindow = ({ user }) => {
   let [userInfo, setUserInfo] = useState(user.payload)
-
-  useEffect(() => {
-    setUserInfo(user.payload)
-  }, [user, userInfo])
+  useEffect(() => setUserInfo(user.payload), [user, userInfo])
 
   return (
-    <section>
+    <section >
       <h3>{userInfo?.login || 'user'}</h3>
-      <img
-        width={150}
-        height={'auto'}
-        style={{ border: '1px solid black', display: 'block', margin: '5% auto', marginBottom: '2px' }}
-        src={userInfo?.avatar?.url ? backendURL + '/' + userInfo?.avatar?.url : ''}
-        alt='avatar'
-      />
+      {userInfo?.avatar?.url ? 
+                        <img src={backendURL + '/' + userInfo?.avatar?.url} alt='avatar'/> : 
+                        <img src={plugPic} alt='avatar' />}
     </section>
   )
 }
@@ -43,10 +41,13 @@ const ProfileWindowDropzone = ({ onLoad }) => {
   const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop })
 
   return (
-    <div {...getRootProps()} style={isDragActive ? { border: '1px solid mediumseagreen' } : { border: '1px solid black' }}>
+    <div {...getRootProps()} 
+      className='sidebar__profile' 
+      style={isDragActive ? { backgroundColor: '#0e6147' } : { backgroundColor: 'transparent' }}
+    >
       <input {...getInputProps()} />
       <ProfileWindowConnect />
-      {isDragActive ? <small>drag here...</small> : <small>change avatar</small>}
+      <small className='lightText'>{isDragActive ? '...drop here' : 'change avatar'}</small>
     </div>
   )
 }
@@ -59,18 +60,7 @@ const UserTracksBtn = ({ userId }) => {
     setId(userId)
   }, [userId])
 
-  return (
-    <Link
-      to={`/player/tracks/:${_id}`}
-      style={{
-        display: 'block',
-        backgroundColor: 'purple',
-        color: 'white',
-        margin: '5px',
-        padding: '5px'
-      }}
-    >MY UPLOADS</Link>
-  )
+  return (<Link to={`/player/tracks/:${_id}`} className='sidebar__link highlightYellow'>UPLOADS <FontAwesomeIcon icon={faUpload}/></Link>)
 }
 export const UserTracksBtnConnect = connect(state => ({ userId: state.promise.userData?.payload?._id || '' }))(UserTracksBtn)
 
@@ -82,28 +72,28 @@ const PlaylistAdd = ({ addPlaylist }) => {
       {
         !clicked ?
           <button
-            style={{ border: '1px solid black', backgroundColor: 'mediumseagreen', width: '95%', padding: '5px', margin: '5px' }}
+            className='sidebar__button highlightPaleGreen'
             onClick={() => setClicked(true)}
           >NEW PLAYLIST</button>
           :
-          <div style={{ width: '95%', margin: '0 auto' }}>
+          <div className='sidebar__addpanel'>
             <input
-              style={{ width: '72%', padding: '5px' }}
-              placeholder='Playlist name'
+              placeholder='NEW PLATLIST NAME'
               value={name}
               onChange={(e) => setName(e.target.value)}
             />
+            <div className='sidebar__addpanel btnWrapper'>
+              <button
+                disabled={!name}
+                className='highlightGreen'
+                onClick={() => { addPlaylist(name); setClicked(false); setName(''); }}
+              ><FontAwesomeIcon icon={faPlus} /></button>
 
-            <button
-              disabled={!name}
-              style={{ padding: '5px', backgroundColor: 'mediumseagreen' }}
-              onClick={() => { addPlaylist(name); setClicked(false); setName(''); }}
-            >+</button>
-
-            <button
-              style={{ padding: '5px', backgroundColor: 'red' }}
-              onClick={() => { setClicked(false); setName('') }}
-            >X</button>
+              <button
+                className='highlightRed'
+                onClick={() => { setClicked(false); setName('') }}
+              ><FontAwesomeIcon icon={faBan} /></button>
+            </div>
           </div>
       }
     </div>
@@ -111,16 +101,13 @@ const PlaylistAdd = ({ addPlaylist }) => {
 }
 export const PlaylistAddConnect = connect(null, { addPlaylist: action.actionAddPlaylist })(PlaylistAdd)
 
-const Playlists = ({ playlists }) => {
+const Playlists = ( { playlists }) => {
   return (
     <div>
       {
         playlists?.payload ? playlists.payload.map(item => {
           return (
-            <Link
-              style={{ display: 'block', backgroundColor:'darkcyan', color: 'cyan', margin: '5px', padding: '5px' }}
-              to={`/player/playlist/:${item._id}`}
-            >{item.name}</Link>
+            <Link className='sidebar__link' to={`/player/playlist/:${item._id}`}>{item.name}</Link>
           )
         }).reverse() : ''
       }

+ 1 - 4
src/reducers/index.js

@@ -41,10 +41,7 @@ export function playerReducer(state, { type, track, playlist, duration, currentT
     if (type === 'SET_DURATION') return { ...state, 'duration': duration }
     if (type === 'SET_VOLUME') return { ...state, 'volume': volume }
     if (type === 'SET_PLAYLIST')  return { ...state, 'playlist': playlist} 
-    if (type === 'SET_INDEX')  {
-        console.log('SEt_INDEX', playlistIndex)
-        return { ...state, 'playlistIndex': playlistIndex}
-    } 
+    if (type === 'SET_INDEX')   return { ...state, 'playlistIndex': playlistIndex} 
 
     if (type === 'SET_TRACK') {
         return {

+ 64 - 0
src/styles/Forms.scss

@@ -0,0 +1,64 @@
+.forms {
+    background-color: #131341;
+    width: fit-content;
+    margin: 0 auto;
+    padding: 2%;
+    font-size: large;
+    border-radius: 5%;
+    box-shadow: 0 0 15px black;
+
+    &__link {
+        font-size: medium;
+        display: block;
+        text-decoration: none;
+        border-left: 5px solid #05f09b;
+        background-color: #100d23;
+        color: #05f09b;
+        margin: 5px;
+        padding: 5px;
+    
+        &:hover {
+          background-color: #323151;
+        }
+    }
+
+    &__input {
+        display: block;
+        font-size: x-large;
+        border-style: none;
+        outline: none;
+        background: transparent;
+        margin: 5% 0 0 0;
+        border-bottom: 2px solid gray;
+        color: #83d6f6;
+
+        &:focus {
+            border-bottom: 2px solid #05f09b;
+            color: #05f09b;
+        }
+
+        &:disabled {
+            &::placeholder { color: rgba(128, 128, 128, 0.274); }
+            border-color: rgba(128, 128, 128, 0.274);
+        }
+    }
+
+    &__button {
+        display: block;
+        margin: 0 auto;
+        margin-top: 10px;
+        font-size: large;
+        padding: 3%;
+        background: transparent;
+        border-style: none;
+        border: 1px solid;
+        &:active {
+            background-color: #0e6147;
+        }
+
+        &:disabled {
+            color: grey;
+            border-color: #0e6147;
+        }
+    }
+}

+ 75 - 0
src/styles/Page.scss

@@ -0,0 +1,75 @@
+@import './adaptivefont.scss';
+
+.page {
+    display: flex;
+    height: 89vh;
+    overflow: none;
+
+    &__window {
+        width: 80%;
+        height: inherit;
+        overflow: auto;
+    }
+}
+
+.startpage {
+    &__ulwrapper {
+        width: 50%;
+        margin: 0 auto;
+
+        ul {
+            text-align: start;
+            small {
+                color: whitesmoke;
+            }
+        }
+    }
+}
+
+.playlist {
+    background-color: #1e1d45;
+    height: fit-content;
+    width: 90%;
+    margin: 0 auto;
+    padding: 1% 2%;
+    &__track {
+        display: flex;
+        align-items: center;
+        background-color: #2a3da941;
+        margin: 10px;
+        padding: 2% 0;
+        color: #83d6f6;
+        box-shadow: 0 0 5px black;
+
+        button {
+            display: block;
+            background-color: #1e1d45;
+            border-style: solid;
+            font-size: x-large;
+            padding: 1%;
+            margin: 0 5%;
+        }
+
+        small,
+        strong {
+            display: block;
+        }
+
+        .artist {
+            @include adaptive-font(16, 12);
+            font-weight: 700;
+            text-align: start;
+        }
+        .album {
+            @include adaptive-font(14, 10);
+            font-weight: 400;
+            text-align: start;
+        }
+        .title {
+            @include adaptive-font(18, 13);
+            //font-size: large;
+            font-weight: 700;
+            text-align: start;
+        }
+    }
+}

+ 76 - 0
src/styles/Playerbar.scss

@@ -0,0 +1,76 @@
+.playerbar {
+    position: sticky;
+    bottom: 0;
+    left: 0;
+    width: 100%;
+    padding-bottom: 1%;
+    background-color: #131341;
+
+    &__range {
+        margin: 0 10px 6px 10px;
+        -webkit-appearance: none;
+        outline: none;
+        cursor: pointer;
+        
+        &::-webkit-slider-thumb {
+            -webkit-appearance: none;
+            border: 1px solid #000000;
+            height: 20px;
+            width: 20px;
+            border-radius: 100%;
+            cursor: pointer;
+            margin-top: -8px;
+            box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
+        }
+
+        &::-webkit-slider-runnable-track {
+            width: 100%;
+            border: 1px solid rgba(255, 255, 0, 0.26);
+            height: 4px;
+        }
+    }
+
+    &__info {
+        display: flex;
+        justify-content: space-between;
+        width: 95%;
+        margin: 0 auto;
+    }
+
+    button {
+        font-size: large;
+        padding: 0.5%;
+        background-color: yellow;
+        border: none;
+        margin: 0 5px;
+    }
+}
+
+.timestamp {
+    margin: 0 10px;
+    font-weight: 500;
+}
+
+.plumline {
+    &::-webkit-slider-runnable-track {
+        background: #2f1dce;
+    }
+}
+
+.blueline {
+    &::-webkit-slider-runnable-track {
+        background: #70b2e7;
+    }
+}
+
+.yellowThumb {
+    &::-webkit-slider-thumb {
+        background: yellow;
+    }
+}
+
+.blueThumb {
+    &::-webkit-slider-thumb {
+        background: #499fe6;
+    }
+}

+ 82 - 0
src/styles/Sidebar.scss

@@ -0,0 +1,82 @@
+@import './adaptivefont.scss';
+
+.sidebar {
+    background-color: #1e1d45;
+    width: 30%; 
+    overflow:auto;
+  
+    &__link {
+      @include adaptive-font(20, 13);
+      //font-size: medium;
+      display: block;
+      text-decoration: none;
+      border-left: 5px solid #05f09b;
+      background-color: #100d23;
+      color: #05f09b;
+      margin: 5px;
+      padding: 5px;
+  
+      &:hover {
+        background-color: #323151;
+      }
+    }
+  
+    &__button {
+      font-size: medium;
+      width: 100%;
+      border-style: none;
+      padding: 10px;
+  
+      &:active {
+        background-color: #05f09b;
+        color: #0e6147;
+      }
+    }
+  
+    &__addpanel {
+      display: flex;
+      width: 95%;
+      margin: 0 auto;
+      border: 1px solid #05f09b;
+      padding: 0.5%;
+      
+      input {
+        @include adaptive-font(20, 12);
+        //font-size: medium;
+        outline: none;
+        background-color: transparent;
+        width: 80%;
+        color: #05f09b;
+        border-style: none;
+      }
+  
+      .btnWrapper {
+        display: inline-block;
+        width: 20%;
+        border: none;
+  
+        button {
+          border: none;
+          background-color: transparent;
+          font-size: large;
+          padding: 4% 5% 2% 5%;
+          margin: 0 2%;
+        }
+      }
+    }
+  
+    &__profile {
+      margin: 0 auto;
+      h3 {
+        font-size: large;
+      }
+      img {
+        max-width: 45%;
+        //max-width: 100px;
+        height: auto;
+        border-radius: 10%;
+        border: 2px solid #70b2e7;
+        box-shadow: 0 0 15px black;
+      }
+    }
+  }

+ 13 - 0
src/styles/adaptivefont.scss

@@ -0,0 +1,13 @@
+$maxWidth: 1280;
+@mixin adaptive-font($pcSize, $mobSize) {
+  $additionSize: $pcSize - $mobSize;
+  $additionMobSize: $additionSize + $additionSize * 0.7;
+  //  for all screen width less than 767px(iPad)
+  @media (max-width: 767px) {
+    font-size: calc(#{$mobSize + px} + #{$additionMobSize} * ((100vw - 350px) / #{$maxWidth}));
+  }
+  // for all screen width more than 767px
+  @media (min-width: 767px) {
+    font-size: calc(#{$mobSize + px} + #{$additionSize} * (100vw / #{$maxWidth}));
+  }
+}