Переглянути джерело

styles for log-in and register pages written. adaptive fonts added. some other tweaks done

miskson 2 роки тому
батько
коміт
7ae89d8b8c

+ 0 - 1
src/App.js

@@ -88,7 +88,6 @@ const GreetPg = () =>
 
 const Player = () =>
   <div>
-    {/* <header><Link to="/player">Player</Link></header> */}
     <div className='page'>
       <aside className='sidebar' >
         <Sidebar.LogoutBtnConnect />

+ 22 - 5
src/App.scss

@@ -1,8 +1,23 @@
-@import './styles/Sidebar.scss';
-@import './styles/Page.scss';
-@import './styles/Playerbar.scss';
+@import "./styles/Sidebar.scss";
+@import "./styles/Page.scss";
+@import "./styles/Playerbar.scss";
+@import "./styles/Forms.scss";
 
-body { 
+$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}));
+  }
+}
+
+body {
   background-color: #100d23;
   ::-webkit-scrollbar {
     width: 12px;
@@ -51,4 +66,6 @@ body {
   color: #05f09b;
 }
 
-.lightText {font-weight: 300;}
+.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>
     </>
   )

+ 22 - 21
src/components/Playerbar.js

@@ -1,14 +1,14 @@
 import { useEffect, useState } from "react"
 import { connect } from "react-redux"
-import { 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}) =>
+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)}
+        {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 }) => {
@@ -20,12 +20,12 @@ const Playerbar = ({ player, playTrack, pauseTrack, switchTrack, setTrackVolume,
 
     return (
         <footer className="playerbar">
-            {_player?.track ?  
-                <div style={{display: `${_player?.track ? 'block' : 'none'}`}}>
+            {_player?.track ?
+                <div style={{ display: `${_player?.track ? 'block' : 'none'}` }}>
                     <div>
                         <input
-                            className="playerbar__range plumline"
-                            style={{width: '95%'}}
+                            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)}
@@ -35,16 +35,16 @@ const Playerbar = ({ player, playTrack, pauseTrack, switchTrack, setTrackVolume,
                         <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?.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%'}}>
+                    <div style={{ marginTop: '0.5%' }}>
                         <button onClick={() => switchTrack(false, _player?.playlistIndex, _player?.playlist)}>
                             {_player?.playlistIndex === 0 ? <FontAwesomeIcon icon={faFastBackward} /> :
-                                                            <FontAwesomeIcon icon={faBackward} />}
+                                <FontAwesomeIcon icon={faBackward} />}
                         </button>
 
                         {_player?.isPlaying ?
@@ -53,20 +53,21 @@ const Playerbar = ({ player, playTrack, pauseTrack, switchTrack, setTrackVolume,
                         }
 
                         <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} />}
+                            {_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
-                                className="playerbar__range blueline"
-                                type="range" min="0" max="1" step="any" 
-                                onChange={(e) => setTrackVolume(e.target.value)} />
+                                className="playerbar__range blueline blueThumb"
+                                type="range" min="0" max="1" step="any"
+                                onChange={(e) => setTrackVolume(e.target.value)} 
+                            />
                         </label>
                     </div>
-                </div> : <div style={{width:'inherit', height:'inherit', padding:'2em'}}>C'mon, push the play button on some track :)</div>}
+                </div> : <></>}
         </footer>
     )
 }

+ 7 - 3
src/components/Sidebar/index.js

@@ -1,4 +1,5 @@
 import * as action from '../../actions'
+import plugPic from '../../assets/default.png'
 
 import { useState, useEffect, useCallback } from 'react';
 import { connect } from 'react-redux';
@@ -15,7 +16,8 @@ const LogoutBtn = ({ onLogout }) =>
     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)
@@ -24,7 +26,9 @@ const ProfileWindow = ({ user }) => {
   return (
     <section >
       <h3>{userInfo?.login || 'user'}</h3>
-      <img 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>
   )
 }
@@ -56,7 +60,7 @@ const UserTracksBtn = ({ userId }) => {
     setId(userId)
   }, [userId])
 
-  return (<Link to={`/player/tracks/:${_id}`} className='sidebar__link highlightYellow'>MY UPLOADS <FontAwesomeIcon icon={faUpload}/></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)
 

+ 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;
+        }
+    }
+}

+ 26 - 9
src/styles/Page.scss

@@ -1,7 +1,8 @@
+@import './adaptivefont.scss';
+
 .page {
     display: flex;
-    max-height: 89vh;
-    min-height: 30vh;
+    height: 89vh;
     overflow: none;
 
     &__window {
@@ -18,7 +19,9 @@
 
         ul {
             text-align: start;
-            small { color: whitesmoke;}
+            small {
+                color: whitesmoke;
+            }
         }
     }
 }
@@ -46,13 +49,27 @@
             padding: 1%;
             margin: 0 5%;
         }
-        
-        small, strong {
+
+        small,
+        strong {
             display: block;
         }
 
-        .artist {font-weight: 700; text-align: start;}
-        .album {font-weight: 400; text-align: start;}
-        .title {font-size: large; font-weight: 700; text-align: start;}
+        .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;
+        }
     }
-}
+}

+ 18 - 5
src/styles/Playerbar.scss

@@ -1,6 +1,5 @@
 .playerbar {
-    //border-top: 1px solid #05f09b;
-    position: fixed;
+    position: sticky;
     bottom: 0;
     left: 0;
     width: 100%;
@@ -12,13 +11,13 @@
         -webkit-appearance: none;
         outline: none;
         cursor: pointer;
+        
         &::-webkit-slider-thumb {
             -webkit-appearance: none;
             border: 1px solid #000000;
             height: 20px;
             width: 20px;
             border-radius: 100%;
-            background: yellow;
             cursor: pointer;
             margin-top: -8px;
             box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
@@ -53,11 +52,25 @@
 }
 
 .plumline {
-    &::-webkit-slider-runnable-track { background: #2f1dce;}
+    &::-webkit-slider-runnable-track {
+        background: #2f1dce;
+    }
 }
 
 .blueline {
-    &::-webkit-slider-runnable-track { 
+    &::-webkit-slider-runnable-track {
         background: #70b2e7;
     }
+}
+
+.yellowThumb {
+    &::-webkit-slider-thumb {
+        background: yellow;
+    }
+}
+
+.blueThumb {
+    &::-webkit-slider-thumb {
+        background: #499fe6;
+    }
 }

+ 11 - 3
src/styles/Sidebar.scss

@@ -1,10 +1,13 @@
+@import './adaptivefont.scss';
+
 .sidebar {
     background-color: #1e1d45;
     width: 30%; 
     overflow:auto;
   
     &__link {
-      font-size: medium;
+      @include adaptive-font(20, 13);
+      //font-size: medium;
       display: block;
       text-decoration: none;
       border-left: 5px solid #05f09b;
@@ -38,7 +41,8 @@
       padding: 0.5%;
       
       input {
-        font-size: medium;
+        @include adaptive-font(20, 12);
+        //font-size: medium;
         outline: none;
         background-color: transparent;
         width: 80%;
@@ -63,8 +67,12 @@
   
     &__profile {
       margin: 0 auto;
+      h3 {
+        font-size: large;
+      }
       img {
-        max-width: 100px;
+        max-width: 50%;
+        //max-width: 100px;
         height: auto;
         border-radius: 10%;
         border: 2px solid #70b2e7;

+ 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}));
+  }
+}