Browse Source

add track to playlist, styles

Stepanova Asya 1 year ago
parent
commit
e2d0811bcb

+ 1 - 1
src/App.js

@@ -11,7 +11,7 @@ import { actionAllPlaylists, actionUsersPlaylists } from './store/promiseReducer
 import { Header } from './components/header';
 import { Main } from './components/Routs';
 import {CAllPlaylists} from './components/Playlist';
-import {СNowPlayingPlayer} from './components/playing';
+
 
 
 

+ 64 - 59
src/components/EditProfile.js

@@ -6,6 +6,7 @@ import image from '../images/card.png';
 import { actionAuthLogin } from '../store/authReducer';
 import {Link} from 'react-router-dom';
 import Form from 'react-bootstrap/Form';
+import {Accordion} from "react-bootstrap";
 
 
 export async function sendForm (url, data) {
@@ -33,6 +34,7 @@ export function EditProfile  (props)  {
     const [login, setLogin] = useState(props.user?.login);
     const [name, setName] = useState(props.user?.name);
     const [avatar, setAvatar] = useState((props.user?.avatar || image));
+    const [description, setDescription] = useState(props.user?.description);
     const [passwordConfirm, setPasswordConfirm] = useState('');
     const [password, setPassword] = useState('');
     const [textModal, setTextModal] = useState('');
@@ -43,6 +45,7 @@ export function EditProfile  (props)  {
         const data = new FormData();
         login && login!==props.user?.login && data.append("login", login);
         name && name!==props.user?.name && data.append("name", name);
+        data.append("description", description);
         avatar.name && data.append("avatar",  avatar, avatar.name);
         
         setTextModal(( typeof(await sendForm('profile/edit', data))==='string')? (await sendForm('profile/edit', data)) : '');
@@ -59,70 +62,72 @@ export function EditProfile  (props)  {
       }
 
     return (<>
-   <div className='d-flex container align-items-center justify-content-center'>
-        <div className=''>
-            <img className='m-4' alt='...' src={props.user?.avatar || image} width='150px'/>
-        </div>
-        <div className=''>
-            <h5>Name: {store.getState().auth?.user?.name}</h5>
-            <p>Login: {store.getState().auth?.user?.login}</p>
-        </div>
-    </div>
-    <Form onSubmit={postForm} className='d-flex justify-content-center align-items-center'>
-        <div>
-        <Form.Group className="mb-3" controlId="formBasicLogin">
-            <Form.Label>Change Login:</Form.Label>
-            <div className='d-flex'>
-                <Form.Control type="text"  className="me-1" placeholder={login}
-                        value={login} onChange={e => setLogin(e.target.value)} />
-                <Button variant="outline-danger" type="submit">Save</Button>
-            </div>
-            <Form.Text className="text-muted">{textModal || "*login must be unique"}</Form.Text>
-        </Form.Group>
-
-        <Form.Group className="mb-3" controlId="formBasicName">
-            <Form.Label>Change Name:</Form.Label>
-            <div className='d-flex'>
-                <Form.Control type="text"  className="me-1" placeholder="Anastasiia"
-                    value={name} onChange={e => setName(e.target.value)} />
-                <Button variant="outline-danger" type="submit">Save</Button>
+    <div className='d-flex  w-100'>
+            <div className="me-4">
+                <div className='mb-3 playlist-img-box rounded-5' style={{backgroundImage: `url(${props.user?.avatar || image})`, backgroundSize: "cover", backgroundRepeat: "no-repeat", backgroundPosition: "center"}}></div>
+                <Form.Group className="mb-3" controlId="formBasicAvatar">
+                    <div className='d-flex'>
+                        <Form.Control type="file" className="me-1" name="picture" accept="image/*" onChange={e => setAvatar(e.target.files[0])} multiple={false} />
+                    </div>
+                </Form.Group>
             </div>
-        </Form.Group>
+            <div className='w-100'>
+                <div className="d-flex flex-column justify-content-between h-100">
+                    <div className="w-100 row">
+                        <Form onSubmit={postForm}>
+                            <Form.Group className="mb-3" controlId="formBasicAvatar">
+                                <Form.Label>Change Login:</Form.Label>
+                                <Form.Control type="text"  className="me-1" placeholder={login}
+                                              value={login} onChange={e => setLogin(e.target.value)} />
+                            </Form.Group>
+                            <Form.Group className="mb-3" controlId="formBasicAvatar">
+                                <Form.Label>Change Name:</Form.Label>
+                                <Form.Control type="text"  className="me-1" placeholder="Anastasiia"
+                                                                                    value={name} onChange={e => setName(e.target.value)} />
+                            </Form.Group>
+                            <Form.Group className="mb-3" controlId="formBasicAvatar">
+                                <Form.Label>Change About Me:</Form.Label>
+                                <Form.Control as="textarea" rows="3"  className="me-1"
+                                                                                    value={description !== 'null' ? description : ''} onChange={e => setDescription(e.target.value)} />
+                            </Form.Group>
+                            <div className="d-flex justify-content-between align-items-center mb-3">
+                                    <Link to={'/user'}>Back to home Page</Link>
+                                    <Button variant="outline-success" type="submit">Save</Button>
+                            </div>
+                        </Form>
+                        <Accordion className="border-0">
+                            <Accordion.Item eventKey="0" className="border-0">
+                                <Accordion.Header className="btn-dark">Change Password</Accordion.Header>
+                                <Accordion.Body className="bg-dark">
+                                    <Form onSubmit={postEditPassword} className=''>
+                                        <div className="d-flex m-0">
+                                            <Form.Group className="col-6 px-3" controlId="formBasicNewPassword">
+                                                <Form.Label>New Password:</Form.Label>
+                                                <Form.Control type="password" className="" placeholder="new password"
+                                                              value={password} onChange={e => setPassword(e.target.value)} />
+                                                <Form.Text className="text-muted m-0 p-0">* Minimum 8 symbols.</Form.Text>
+                                            </Form.Group>
 
-        <Form.Group className="mb-3" controlId="formBasicAvatar">
-            <Form.Label>Change Avatar:</Form.Label>
-            <div className='d-flex'>
-                <Form.Control type="file" className="me-1" name="picture" accept="image/*" onChange={e => setAvatar(e.target.files[0])} multiple={false} />
-                <Button variant="outline-danger" type="submit">Save</Button>
-            </div>
-        </Form.Group>
-        </div>
-    </Form>
-    <h5 className='d-flex justify-content-center'> Change Password:</h5>
-    <Form onSubmit={postEditPassword} className='d-flex justify-content-center align-items-center'>
-    
-        <div>
-            <Form.Group className="mb-3" controlId="formBasicNewPassword">
-                <Form.Label>New Password:</Form.Label>
-                <Form.Control type="password" className="" placeholder="new password"
-                        value={password} onChange={e => setPassword(e.target.value)} />
-                <Form.Text className="text-muted">* Minimum 8 symbols.</Form.Text>
-            </Form.Group>
-            
 
-            <Form.Group className="mb-3" controlId="formBasicConfirmPassword">
-                <Form.Label>Confirm New Password:</Form.Label>
-                <Form.Control type="password" placeholder="confirm new password"
-                        value={passwordConfirm} onChange={e => setPasswordConfirm(e.target.value)} />
-            </Form.Group>
-            <div className='d-flex justify-content-between'>
-                <Button variant="outline-danger" type="submit" disabled={ password.length < 8 || password !== passwordConfirm}>
-                    Change Password
-                </Button>
-                <Link to={'/user'}>Back to home Page</Link>
+                                            <Form.Group className="col-6 px-3" controlId="formBasicConfirmPassword">
+                                                <Form.Label>Confirm New Password:</Form.Label>
+                                                <Form.Control type="password" placeholder="confirm new password"
+                                                              value={passwordConfirm} onChange={e => setPasswordConfirm(e.target.value)} />
+                                            </Form.Group>
+                                        </div>
+                                        <div className='text-end'>
+                                            <Button variant="outline-success" type="submit" disabled={ password.length < 8 || password !== passwordConfirm}>
+                                                Change Password
+                                            </Button>
+                                        </div>
+                                    </Form>
+                                </Accordion.Body>
+                            </Accordion.Item>
+                        </Accordion>
+                    </div>
+                </div>
             </div>
         </div>
-    </Form>
     </>)
 }
 export const CEditProfile = connect(state => ({ user: state.auth?.user }))(EditProfile);

+ 15 - 3
src/components/Playlist.js

@@ -1,20 +1,32 @@
-import React from 'react';
+import React, { useEffect } from 'react';
 import 'bootstrap/dist/css/bootstrap.min.css';
 import {connect}   from 'react-redux';
 import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
 import {faCompactDisc} from "@fortawesome/free-solid-svg-icons";
 import { Playlist } from './userPlaylists';
+import { store } from '../store/store';
+import { actionAllPlaylists } from '../store/promiseReducer';
 
 
 export const PlaylistsAll = ({playlists}) => 
-<>
+{
+const getAnswer =  () => {
+  store.dispatch(actionAllPlaylists());
+};
+
+useEffect(() => {
+  getAnswer();
+}, []);
+
+return (<>
   <div className="d-flex justify-content-between align-items-center py-3">
     <h3 className="text-uppercase"> <FontAwesomeIcon icon={faCompactDisc} className="me-2"/>Playlists</h3>
   </div>
 <div className='RootCategories d-flex justify-content-start flex-wrap'>
   {playlists.map((playlist, i) => <Playlist key={i} playlist={playlist}/>)}
 </div>
-</>
+</>)
+}
 
 
 export const CAllPlaylists = connect(state => ({playlists: state.promise.allPlaylists?.payload?.playlists?.data || []}), )(PlaylistsAll);

+ 10 - 5
src/components/Routs.js

@@ -11,7 +11,7 @@ import {СNowPlayingPlayer} from './playing'
 import { CEditProfile } from './EditProfile';
 import { Header } from './header';
 import { CArtistPage } from '../pages/artistPage';
-import { AlbumPage } from '../pages/albumPage';
+import { CAlbumPage } from '../pages/albumPage';
 
 export const Main = ({auth}) =>
 
@@ -23,14 +23,19 @@ export const Main = ({auth}) =>
           {auth && <Redirect from='/login' to={'/user'} exact />} 
           {auth && <Redirect from='/register' to={'/user'} exact />}
           {!auth && <Redirect from='/user' to={'/login'} exact />} 
+          {!auth && <Redirect from='/editprofile' to={'/login'} exact />}
+          {!auth && <Redirect from='/allplaylists' to={'/login'} exact />}
+          {!auth && <Redirect from='/playlist' to={'/login'} exact />}
+          {!auth && <Redirect from='/artists' to={'/login'} exact />}
+          {!auth && <Redirect from='/albums' to={'/login'} exact />}
           <Route path={'/login'} component={LoginForm} />
           <Route path={'/register'} component={CRegisterForm}/>
           <Route path={'/editprofile'} component={CEditProfile}/>
           <Route path={'/allplaylists'} component={Aside}/>
           <Route path={'/playlist'} component={CPlaylistById} />
           <Route path={'/user'} component={CUserPage} />
-          <Route path={'/artist'} component={CArtistPage} />
-          <Route path={'/album'} component={AlbumPage} />
+          <Route path={'/artists'} component={CArtistPage} />
+          <Route path={'/albums'} component={CAlbumPage} />
           <Route exact path="/">{auth ? <Redirect to="/user"/> : <Redirect to="/login" /> }</Route>
         </Switch>
       </div>
@@ -41,8 +46,8 @@ export const Main = ({auth}) =>
 const Content = ({children}) => 
   <>
   {store.getState().auth?.token && <Header/>}
-    <section className='d-flex justify-content-around py-4'>
-      <div className={store.getState().auth?.token ? 'col-7' : 'col-12'}>
+    <section className='d-flex justify-content-center container-fluid pt-3'>
+      <div className={store.getState().auth?.token ? 'col-7 pe-3' : 'col-12 pe-3'}>
         {children}
       </div>
       {/* <div className='col-5'> */}

+ 27 - 17
src/components/Tracks.js

@@ -14,16 +14,13 @@ import { Dropdown , Form} from 'react-bootstrap';
 
 export let audio = new Audio();
 
-//!  --------
-// // const playlists = store.getState().promise?.usersPlaylists?.payload?.playlists;
-
-// const playlistOption = (playlists = null) => {
-//     // if (playlists) {
-//         // console.log(playlists)
-//         return <option value={"1"}>Add to...</option>
-//     // }
-// }
-//! ------
+const PlaylistOption = () => {
+    const playlists = store.getState().promise?.usersPlaylists?.payload?.playlists;
+     if (playlists) {
+        console.log(playlists);
+        return (playlists.map((playlistone, i) => <option value={playlistone.id} className="bg-dark" key={i}>{playlistone.name}</option>))
+     }
+}
 
 const ButtonDeleteTrack = (track) => {
     const [deletePllstModal, setDeletePllstModal] = useState(false);
@@ -59,7 +56,15 @@ const ButtonDeleteTrack = (track) => {
 }
 
 
-const Track = ({track,  playlist}) => 
+const Track = ({track,  playlist}) => {
+    // const [select, setSelect] = React.useState('');
+    const PostLoadTracks = async(form)  =>{
+        console.log(form.target)
+        const data = new FormData(form.target);
+        sendForm('playlists/add-track', data);
+
+      }  
+return(
 <tr>
 <td scope="row" width={30} data-id={track.id}>
     <div className="col">
@@ -77,10 +82,10 @@ const Track = ({track,  playlist}) =>
         <Link className="link-light" to='#'>  {track.name}</Link>
     </td>
     <td onClick={() => store.dispatch(actionArtistById(track.artist_id))}>
-        <Link className="link-light" to={`/artist/${track.artist_id}`}>  {track.id3.artist}</Link>
+        <Link className="link-light" to={`/artists/${track.artist_id}`}>  {track.id3.artist}</Link>
     </td>
     <td> 
-        <Link className="link-light" to='#'> {track.id3.getAlbum}</Link>
+        <Link className="link-light" to={`/albums/${track?.album?.id}`}> {track.id3.getAlbum}</Link>
     </td>
     <td align={"right"}>
         <Dropdown align={"end"}>
@@ -89,10 +94,14 @@ const Track = ({track,  playlist}) =>
             <Dropdown.Menu variant={"dark"}>
             {playlist?.user_id === store.getState().auth.user.id ? <ButtonDeleteTrack track={track} /> :
 
-            <Form className="input-group d-flex">
-                <select className="dropdown-item w-auto" id="inputGroupSelect04"
+            <Form className="input-group d-flex" onSubmit={(e) => {
+                e.preventDefault();
+                PostLoadTracks(e);
+            }}>
+                <input type={"hidden"} name="trackId" value={track?.id}></input>
+                <select className="dropdown-item btn btn-outline-secondary w-75" name="playlistId" id="inputGroupSelect04"
                         aria-label="Example select with button addon">
-                    {/* {playlistOption()} */}
+                    <PlaylistOption/>
                 </select>
                 <button type={"submit"} className="btn btn-outline-secondary w-auto"><FontAwesomeIcon icon={faCheck}/></button>
             </Form>
@@ -104,7 +113,8 @@ const Track = ({track,  playlist}) =>
             </Dropdown.Menu>
         </Dropdown>
     </td>
-</tr>
+</tr>)
+}
 
 
 export const TracksAll = ({tracks, playlist}) => 

+ 41 - 29
src/components/createPlaylist.js

@@ -5,6 +5,7 @@ import Button from 'react-bootstrap/Button';
 import { actionUsersPlaylists } from '../store/promiseReducer';
 import { store } from '../store/store';
 import { history } from '../App';
+import {Form} from "react-bootstrap";
 
 
 export const CreatePlaylist = (props) => {
@@ -26,42 +27,53 @@ export const CreatePlaylist = (props) => {
     store.dispatch(actionUsersPlaylists(store.getState().auth?.user?.id));
     //history.push(`/playlist/${result.playlist.id}`)
   }
+  const PreViewImage = (image) => {
+    if (image && typeof (image) !== "string") {
+        return <div className="d-flex justify-content-center">
+            <label htmlFor="fileImage" className='me-4 playlist-img-box rounded-5 cursor-pointer' style={{backgroundImage: `url(${URL.createObjectURL(image)})`, backgroundSize: "cover", backgroundRepeat: "no-repeat", backgroundPosition: "center"}}></label>
+        </div>
+    }
+}
+
 
   return <>
   <Modal
         {...props}
-        size="lg"
         aria-labelledby="contained-modal-title-vcenter"
         centered
       >
-  <Modal.Header closeButton>
-      <Modal.Title id="contained-modal-title-vcenter">Create new Playlist</Modal.Title>
-  </Modal.Header>
-  <Modal.Body >
-    <form onSubmit={PostCreatePlaylist} className="authorization center align-items-center justify-content-center  d-flex" id='CreatePlaylistForm'>
-      <div className="border p-3 col-9">
-      {/* <hr/> */}
-        <div className="d-flex justify-content-between">
-          <div className="w-auto">
-              <label  className="form-label">Image</label>
-              <input type="file" name="picture" accept="image/*" id="file" className='form-control mb-3' onChange={(e) => setImage(e.target.files[0])} multiple={false}/>
-              <input className="form-check-input me-3" type="checkbox" id="flexCheckIndeterminate" checked={privat} onChange={e => setPrivat(e.target.checked? 1 : 0)}/>
-              <label className="form-check-label" >Private?</label>    
-          </div>
-          <div className="w-50">
-              <label  className="form-label">Name</label><br/>
-              <input type="text" id="username" className='input form-control mb-3' value={name} onChange={e => setName(e.target.value)}/>
-              <label  className="form-label">Description</label>
-              <textarea type="password" id="password" className='form-control mb-3' value={description} onChange={e => setDescription(e.target.value)}/>
-          </div>
-        </div>
-            {/* <button type='submit' className="btn btn-outline-danger" onClick={props.onHide} >Create</button> */}
-        </div>
-    </form>
-    </Modal.Body>
-    <Modal.Footer> 
-      <Button variant="outline-danger" type='submit' form='CreatePlaylistForm' className="btn btn-outline-danger" onClick={props.onHide}>Create</Button> 
-    </Modal.Footer> 
+      <Modal.Header closeButton>
+          <Modal.Title id="contained-modal-title-vcenter">Create new Playlist</Modal.Title>
+      </Modal.Header>
+      <Modal.Body >
+          <Form onSubmit={PostCreatePlaylist} id='loadTracksForm'>
+              {PreViewImage(image)}
+              <Form.Group className="mb-3" >
+                  <Form.Label>Image</Form.Label>
+                  <Form.Control type="file" name="picture" accept="image/*" id="fileImage" className='form-control mb-3' onChange={(e) => {
+                      setImage(e.target.files[0]);
+                  }} multiple={false} />
+              </Form.Group>
+              <Form.Group className="mb-3" >
+                  <Form.Label>Name</Form.Label>
+                  <Form.Control type="text" id="username" className='input form-control mb-3' onChange={e => setName(e.target.value)} />
+              </Form.Group>
+              <Form.Group className="mb-3" >
+                  <Form.Label>Description</Form.Label>
+                  <Form.Control as="textarea" name="description" rows={3}  id="description" className='form-control mb-3' onChange={e => setDescription(e.target.value)} />
+              </Form.Group>
+              <Form.Check
+                  type="switch"
+                  id="flexCheckIndeterminate"
+                  label="Private?"
+                  checked={privat}
+                  onChange={e => setPrivat(e.target.checked? 1 : 0)}
+              />
+          </Form>
+      </Modal.Body>
+      <Modal.Footer>
+          <Button variant="outline-success w-100" type='submit' form='loadTracksForm' onClick={props.onHide}>Save</Button>
+      </Modal.Footer>
     </Modal>
   </>
 }

+ 44 - 26
src/components/header.js

@@ -1,44 +1,62 @@
 import logo from '../images/musicico.png';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
-import {faArrowRightFromBracket} from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import {faArrowRightFromBracket, faCompactDisc, faUserEdit} from '@fortawesome/free-solid-svg-icons'
 import {connect}   from 'react-redux';
 import { actionAuthLogout } from '../store/authReducer';
 import React from 'react';
 import {Link} from 'react-router-dom';
+import {Container, Nav, Navbar, NavDropdown, ContainerProps, Image} from "react-bootstrap";
+import image from "../images/card.png";
+import {store} from "../store/store";
 
 
 
 
 export const Header = ({children}) => 
 <header id="header">
-  <nav className="navbar navbar-expand-lg navbar-dark bg-dark border-bottom">
-    <div className="container flex justify-content-between ">
-    
-        <div className='d-flex align-items-center justify-content-center' >
-        <Link to={"/allplaylists"}  className="navbar-brand" ><img className='logo' src={logo} alt='logo'/>Music</Link>
-        </div>
-
-        <div className="d-flex">
-
-            <div className="d-flex align-items-center" id="navbarSupportedContent">
-                <Link to={"/allplaylists"} className="navbar-brand nav-link active" aria-current="page" >To all playlists</Link>
-            </div>
-            <div className="d-flex align-items-center" id="navbarSupportedContent">
-                <Link to={"/user"} className="navbar-brand nav-link active" aria-current="page" >Home</Link>
-            </div>
-            <input className="form-control me-2 " type="search" placeholder="Search" aria-label="Search"/>
-        
-        </div>
-            <CLogout/>
-        
-    </div>
-  </nav>
+<Navbar collapseOnSelect expand="lg" bg="dark" variant="dark" className="border-bottom">
+        <Container>
+            <Navbar.Brand className="">
+                <Link to={'/allplaylists'} className="text-decoration-none text-white d-flex align-items-center">
+                <img className='logo' src={"https://cdn0.iconfinder.com/data/icons/internet-2020/1080/Applemusicandroid-512.png"} alt='logo'/>
+                    Music
+                </Link>
+            </Navbar.Brand>
+            <Navbar.Toggle aria-controls="responsive-navbar-nav" />
+            <Navbar.Collapse id="responsive-navbar-nav">
+                <Nav className="me-auto">
+                    <Link to={'/user'} className="nav-link">Home</Link>
+                    <Link to={'/allplaylists'} className="nav-link">Playlists</Link>
+                    {/*<Nav.Link href="/allplaylists">Albums</Nav.Link>*/}
+                    {/*<Nav.Link href="/allplaylists">Artists</Nav.Link>*/}
+                </Nav>
+                <Nav className="d-flex align-items-center">
+                    {/*<Link to={"/user"} className="nav-link me-2">{store.getState().auth.user?.name}</Link>*/}
+                    <NavDropdown className="me-2" title={store.getState().auth.user?.name} id="collasible-nav-dropdown">
+                        <NavDropdown.Item className="px-0">
+                            <Link to={'/user'}><FontAwesomeIcon icon={faCompactDisc} className="me-2"/>My playlists</Link>
+                        </NavDropdown.Item>
+
+                        <NavDropdown.Item className="px-0">
+                            <Link to={'/editprofile'}><FontAwesomeIcon icon={faUserEdit} className="me-2"/>Edit profile</Link>
+                        </NavDropdown.Item>
+                        <NavDropdown.Item className="px-0">
+                            <CLogout/>
+                        </NavDropdown.Item>
+                    </NavDropdown>
+                    <Link to={"/user"}>
+                        <Image className="nav-avatar rounded-circle" src={store.getState().auth.user?.avatar}></Image>
+                    </Link>
+                </Nav>
+            </Navbar.Collapse>
+        </Container>
+    </Navbar>
   {children}
 </header>
 
 const ImgLogout = () => {
-    return <FontAwesomeIcon icon={faArrowRightFromBracket} className='fa-2x'/>  
+    return <><FontAwesomeIcon icon={faArrowRightFromBracket} className="me-2"/>Logout</>
 }
 
 const CLogout = connect(state => ({children: <ImgLogout/>}), 
-                                              {onClick: actionAuthLogout})('button')
+                                              {onClick: actionAuthLogout})('a')

+ 8 - 8
src/components/playing.js

@@ -3,7 +3,7 @@ import React, {useState, useEffect} from 'react';
 import {faVolumeDown, faVolumeUp, faRandom, faStepBackward, faStopCircle, faStepForward, faPlayCircle, faRepeat} from '@fortawesome/free-solid-svg-icons'
 import { store } from '../store/store';
 import {actionPlayerRandom, actionFullPlay, actionFullPause, actionFullSetVolume, actionPrevTrack, actionNextTrack, actionSetRepeat, actionSetRandom} from '../store/playerReducer';
-import {Provider, connect}   from 'react-redux';
+import {connect}   from 'react-redux';
 import { audio } from './Tracks';
 import img_album from '../images/default_album.gif';
 import {Nav, Tab, Tabs} from "react-bootstrap";
@@ -30,16 +30,16 @@ export let NowPlayingPlayer = (props) => {
         if (props.currentTime) audio.currentTime = newCurrent
     }, [newCurrent]);
     
-    let album_photo = (props.track?.album?.photo) ? `http://player-api/storage/albums/${props.track?.album?.photo}` : img_album 
+    let album_photo = props.track?.album?.photo
     const [key, setKey] = useState('home');
     return(
-        <div className="player col-xxl-3 col-lg-5 ">
+        <div className="player col-xxl-3 col-lg-5 ps-3">
             <div className="wrapper ">
                 <Tabs
                     id="fill-tab-example"
                     activeKey={key}
                     onSelect={(k) => setKey(k)}
-                    fill
+                    fill className="mb-3"
                 >
                     <Tab className="text-white bg-dark" tabClassName="text-white bg-dark" eventKey="home" title="Player">
                         <div className="flex-column justify-content-center align-items-center d-flex">
@@ -59,7 +59,7 @@ export let NowPlayingPlayer = (props) => {
                                 <div className="now-playing">{props.track?.id3?.artist || 'Artist'  }</div>
                             </div>
         
-                            <div className="slider-container duration w-100">
+                            <div className="slider-container duration w-100 mb-3">
         
                                 <div className="d-flex align-items-end justify-content-between">
                                     <div className="slider-container d-flex flex-column w-75 pe-2" >
@@ -92,7 +92,7 @@ export let NowPlayingPlayer = (props) => {
         
                             <div className="buttons">
                                 <div className="random-track">
-                                    <FontAwesomeIcon icon={faRandom} className={props.random === 1 ? 'fa-2x text-white-50 cursor-pointer' : 'fa-2x text-primary cursor-pointer'}
+                                    <FontAwesomeIcon icon={faRandom} className={props.random === 1 ? 'fa-1x text-white-50 cursor-pointer' : 'fa-1x text-primary cursor-pointer'}
                                          onClick={() => {
                                              props.random === 1 ? store.dispatch(actionSetRandom(2)) : store.dispatch(actionSetRandom(1))
                                              store.dispatch(actionPlayerRandom());
@@ -104,7 +104,7 @@ export let NowPlayingPlayer = (props) => {
         
                                 </div>
                                 <div className="play-track">
-                                    <FontAwesomeIcon icon={(!props.isPlaying) ? faPlayCircle : faStopCircle} className='fa-5x cursor-pointer'
+                                    <FontAwesomeIcon icon={(!props.isPlaying) ? faPlayCircle : faStopCircle} className='fa-4x cursor-pointer'
                                          onClick={() => {
                                              if(store.getState()?.player?.isPlaying === true) {
                                                  store.dispatch(actionFullPause());
@@ -119,7 +119,7 @@ export let NowPlayingPlayer = (props) => {
                                     }}/>
                                 </div>
                                 <div className="random-track">
-                                    <FontAwesomeIcon icon={faRepeat} className={props.repeat === 1 ? 'fa-2x text-white-50 cursor-pointer' : 'fa-2x text-primary cursor-pointer'}
+                                    <FontAwesomeIcon icon={faRepeat} className={props.repeat === 1 ? 'fa-1x text-white-50 cursor-pointer' : 'fa-1x text-primary cursor-pointer'}
                                                      onClick={() => (props.repeat === 1 ? store.dispatch(actionSetRepeat(2)) : store.dispatch(actionSetRepeat(1)))}/>
                                 </div>
         

+ 2 - 0
src/components/playlistById.js

@@ -125,11 +125,13 @@ export const PlaylistById = ({playlist, tracks}) => {
                                             </Dropdown.Menu>
                                         </Dropdown>
                                     </div>
+                                    {playlist.user_id !== store.getState().auth.user.id ?
                                     <div className="col">
                                         <button type="button" className="btn btn-outline-danger">
                                             <FontAwesomeIcon icon={faHeart}/> 
                                         </button>
                                     </div>
+                                        : <></>}
                                 </div>
                             </div>
                         </div>

+ 8 - 5
src/components/userPlaylists.js

@@ -11,14 +11,16 @@ import Button from "react-bootstrap/Button";
 
 
 
-export const Playlist = ({playlist}) => 
+export const Playlist = ({playlist}) => {
+  let link = ((window.location.href.split('/')[3]) === 'artists' ? 'albums' : 'playlist');
+  return(
   <div className="">
       <div className="me-4 mb-4 p-4 playlist-img-box rounded-5 position-relative"
-           style={{backgroundImage: `url(${playlist.photo || image})`, backgroundSize: "cover", backgroundRepeat: "no-repeat", backgroundPosition: "center", width:250, height:250}}
+           style={{backgroundImage: `url(${playlist.photo})`, backgroundSize: "cover", backgroundRepeat: "no-repeat", backgroundPosition: "center", width:250, height:250}}
       >
           <div className="playlist-grey-box"></div>
-          <Link className="d-flex justify-content-between flex-wrap border-0 link-light position-relative text-decoration-none h4 text-wrap"
-                to={`/playlist/${playlist.id}`} onClick={() => {
+          <Link className="d-flex justify-content-between flex-wrap border-0 link-light position-relative text-decoration-none h6 text-wrap"
+                to={`/${link}/${playlist.id}`} onClick={() => {
                   store.dispatch(actionPlaylistById(playlist.id));
                 }}>
               <span className="playlist-title w-75">{playlist.name}</span>
@@ -44,7 +46,8 @@ export const Playlist = ({playlist}) =>
               />
           </Button>
       </div>
-  </div>
+  </div>)
+}
   
   export const UsersPlaylistsAll = ({playlists}) => {
     const [modalShow, setModalShow] = React.useState(false);

+ 36 - 6
src/index.css

@@ -55,10 +55,10 @@ code {
   border-radius: 20px!important;
 }
 .playlist-img-box{
-  min-height: 250px;
-  min-width: 250px;
-  max-height: 250px;
-  max-width: 250px;
+  min-height: 180px;
+  min-width: 180px;
+  max-height: 180px;
+  max-width: 180px;
   overflow: hidden;
 }
 .cursor-pointer {
@@ -143,7 +143,7 @@ code {
   font-size: 1rem;
 }
 .track-name{
-  font-size: 2.5rem;
+  font-size: 1.5rem;
 }
 .track-artist{
   margin-top: 5px;
@@ -233,9 +233,39 @@ i.fa-step-backward{
   color: black;
 }
 .tab-content{
-  max-height: 450px;
+  max-height: 490px;
 }
 .playing-list{
   max-height: inherit;
   overflow: auto;
+}
+.accordion-button{
+  background: inherit!important;
+  color: inherit!important;
+  border: none!important;
+  text-decoration: underline;
+}
+.nav-avatar{
+  width: 50px;
+  height: 50px;
+  border: 2px solid white;
+  /*border-radius: ;*/
+}
+.dropdown-menu a{
+  display: block;
+  width: 100%;
+  padding: 0.25rem 1rem;
+  clear: both;
+  font-weight: 400;
+  color: #212529;
+  text-align: inherit;
+  text-decoration: none;
+  white-space: nowrap;
+  background-color: transparent;
+  border: 0;
+}
+.dropdown-menu a:hover{
+  color: #1e2125;
+  background-color: #e9ecef;
+  cursor: pointer;
 }

+ 18 - 2
src/pages/albumPage.js

@@ -1,4 +1,20 @@
+import { connect } from "react-redux"
+import { store } from "../store/store";
+import { useEffect } from "react";
+import { TracksAll } from "../components/Tracks";
+import { actionPlaylistById } from "../store/promiseReducer";
+import { PlaylistById } from "../components/playlistById";
 
+export const AlbumPage = ({playlist, tracks}) => {
+    return(
+        <CAlbumPlaylist playlist={playlist} tracks={tracks}/>
+    )
+}
+    
 
-export const AlbumPage = () => 
-    <>Album</>
+
+
+export const CAlbumPlaylist = connect(state => ({playlist: state.promise.plstById?.payload || {},
+                                        tracks: state.promise.plstById?.payload?.tracks || []} ), )(PlaylistById);
+export const CAlbumPage = connect(state => ({playlist: state.promise.plstById?.payload || {},
+                            tracks: state.promise.plstById?.payload?.tracks || []} ), )(AlbumPage);

+ 15 - 5
src/pages/userPage.js

@@ -8,9 +8,18 @@ import {
     faCompactDisc,
     faHeadphonesSimple} from "@fortawesome/free-solid-svg-icons";
 import {UsersPlaylistsAll} from '../components/userPlaylists';
+import { actionUsersPlaylists } from "../store/promiseReducer";
+import { useEffect } from "react";
 
 
-export const UserPage = ({user}) => {
+export const UserPage = ({user, playlists}) => {
+    const getAnswer =  () => {
+        store.dispatch(actionUsersPlaylists(store.getState().auth?.user?.id));
+    };
+
+    useEffect(() => {
+      getAnswer();
+    }, []);
         return(<>
         <div className='d-flex  w-100'>
                 <div className='me-4 playlist-img-box rounded-5' style={{backgroundImage: `url(${user?.avatar || image})`, backgroundSize: "cover", backgroundRepeat: "no-repeat", backgroundPosition: "center"}}>
@@ -25,15 +34,16 @@ export const UserPage = ({user}) => {
                                 <p className='text-white-50 mb-2'><FontAwesomeIcon className='me-2' icon={faHeadphonesSimple} /> 100 Tracks</p>
                                 <p className='text-white-50 mb-2'><FontAwesomeIcon className='me-2' icon={faCompactDisc} /> 8 PLaylists</p>
                                 <p className='text-white-50 mb-2'><FontAwesomeIcon className='me-2' icon={faAlignCenter} />
-                                    Lorem ipsum dolor sit amet, consectetur adipisicing elit. A aliquid amet animi aspernatur facere iste nisi omnis optio, vel vitae? Accusantium assumenda autem cumque ducimus eum ipsa, maiores pariatur repudiandae?
+                                    {store.getState().auth?.user?.description !== 'null' ? store.getState().auth?.user?.description : "Lorem ipsum dolor sit amet, consectetur adipisicing elit. A aliquid amet animi aspernatur facere iste nisi omnis optio, vel vitae? Accusantium assumenda autem cumque ducimus eum ipsa, maiores pariatur repudiandae?" }
                                 </p>
                         </div>
                     </div>
                 </div>
             </div>
-        <СUsersPlaylists/>
+        <UsersPlaylistsAll playlists={playlists}/>
         </>)
     }
     
-export const CUserPage = connect(state => ({user: state.auth?.user || {}} ) )(UserPage);
-export const СUsersPlaylists = connect(state => ({playlists: state.promise?.usersPlaylists?.payload?.playlists|| []}))(UsersPlaylistsAll);
+export const CUserPage = connect(state => ({user: state.auth?.user || {},
+    playlists: state.promise?.usersPlaylists?.payload?.playlists|| []} ) )(UserPage);
+//export const СUsersPlaylists = connect(state => ({playlists: state.promise?.usersPlaylists?.payload?.playlists|| []}))(UsersPlaylistsAll);

+ 2 - 0
src/store/authReducer.js

@@ -1,3 +1,5 @@
+//import { store } from "./store";
+import { store } from '../store/store';
 
 export const authReducer = function(state, {type, token, user}) {
     if (state === undefined) {

+ 5 - 3
src/store/promiseReducer.js

@@ -62,8 +62,10 @@ export const actionUsersPlaylists = (id) =>
     actionPromise('usersPlaylists', gql('/profile/' + id + '/playlists'))
 
 
-export const actionPlaylistById = (_id) => 
-  actionPromise('plstById', gql('/playlists/'+_id))
+export const actionPlaylistById = (_id) => {
+    let link = (((window.location.href.split('/')[3] === 'artists' || window.location.href.split('/')[3]) === 'albums') ? 'albums' : 'playlists');
+    return (actionPromise('plstById', gql('/'+link+'/'+_id)))
+}
 
   export const actionNowPlaylist = (_id) => 
   actionPromise('plstnow', gql('/playlists/'+_id))
@@ -77,4 +79,4 @@ export const actionPlaylistById = (_id) =>
 };
 
 export const actionArtistById = (_id) => 
-actionPromise('artistById', gql('/artist/'+_id))
+actionPromise('artistById', gql('/artists/'+_id))