playlistById.js 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. import React, {useState, useEffect} from 'react';
  2. import { store } from '../store/store';
  3. import Button from 'react-bootstrap/Button';
  4. import Modal from 'react-bootstrap/Modal';
  5. import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
  6. import {faTrash, faPen, faUserAstronaut, faCompactDisc,
  7. faPlus, faAlignCenter, faPlay, faHeart} from '@fortawesome/free-solid-svg-icons';
  8. import { actionFullSetPlaylist, actionFullSetTrack, actionAddPlaylistToQueue} from '../store/playerReducer';
  9. import {connect} from 'react-redux';
  10. import { TracksAll } from './Tracks';
  11. import { LoadTrackModal } from './LoadTrackModal';
  12. import { EditPlaylistModal } from './EditPlaylistModal';
  13. import { Link } from 'react-router-dom';
  14. import { sendForm } from './SendForm';
  15. import { history } from '../App';
  16. import {ButtonGroup, Dropdown} from "react-bootstrap";
  17. import { actionPlaylistById, actionUsersPlaylists } from '../store/promiseReducer';
  18. export const PlaylistById = ({playlist, tracks}) => {
  19. let id = window.location.href.split('/')[4];
  20. const getAnswer = () => {
  21. store.dispatch(actionPlaylistById(id));
  22. };
  23. useEffect(() => {
  24. getAnswer();
  25. }, []);
  26. const [modalShow, setModalShow] = React.useState(false);
  27. const [deletePllstModal, setDeletePllstModal] = useState(false);
  28. const [modalTrackShow, setModalTrackShow] = React.useState(false);
  29. return(
  30. <>
  31. <div className='d-flex justify-content-around w-100'>
  32. <div className='w-100 pt-4'>
  33. <div className='d-flex mb-3 w-100'>
  34. <div className='me-4 playlist-img-box rounded-5'
  35. style={{backgroundImage: `url(${playlist.photo})`, backgroundSize: "cover", backgroundRepeat: "no-repeat", backgroundPosition: "center"}}>
  36. </div>
  37. <div className='w-100'>
  38. <div className="d-flex flex-column justify-content-between h-100">
  39. <div className="w-100 row">
  40. <div className='d-flex justify-content-between align-items-center w-100'>
  41. <p className='h4 m-0'>{playlist.name}</p>
  42. {playlist.user_id === store.getState().auth.user.id?
  43. <>
  44. <div className="d-flex row g-2">
  45. <div className="col">
  46. <Button variant="outline-success" title='Add tracks' onClick={() => setModalShow(true)}>
  47. <FontAwesomeIcon icon={faPlus} />
  48. </Button>
  49. <LoadTrackModal id={playlist?.id} show={modalShow} onHide={() => setModalShow(false)} />
  50. </div>
  51. <div className="col">
  52. <Button variant="outline-secondary" title='Edit playlist' onClick={() => setModalTrackShow(true)}>
  53. <FontAwesomeIcon icon={faPen} />
  54. </Button>
  55. <EditPlaylistModal tracks={tracks} show={modalTrackShow} playlist={playlist}
  56. onHide={() => {setModalTrackShow(false);
  57. setTimeout(() => store.dispatch(actionPlaylistById(playlist?.id)), 100)
  58. }}></EditPlaylistModal>
  59. </div>
  60. <div className="col">
  61. <Button variant="outline-danger" title='Delete playlist' onClick={() => setDeletePllstModal(true)}>
  62. <FontAwesomeIcon icon={faTrash} />
  63. </Button>
  64. </div>
  65. </div>
  66. <Modal
  67. show={deletePllstModal} onHide={() => setDeletePllstModal(false)}
  68. keyboard={false} playlist={playlist}>
  69. <Modal.Header closeButton>
  70. <Modal.Title className='w-100 text-center'>Delete Playlist?</Modal.Title>
  71. </Modal.Header>
  72. <Modal.Body className='text-center'>
  73. Are you really want to delete playlist <span className='text-danger'><i>"{playlist.name}"</i></span>?
  74. </Modal.Body>
  75. <Modal.Footer className='d-flex justify-content-center'>
  76. <Button className='mx-2' variant="secondary" onClick={() => setDeletePllstModal(false)}>
  77. Close
  78. </Button>
  79. <Button className='mx-2' variant="danger" onClick={() => {
  80. sendForm(`playlists/${playlist.id}/delete`);
  81. setDeletePllstModal(false)
  82. setTimeout(() => {
  83. store.dispatch(actionUsersPlaylists(store.getState().auth?.user?.id));
  84. history.push('/user');}, 100) }}>Delete</Button>
  85. </Modal.Footer>
  86. </Modal>
  87. </>: <></>
  88. }
  89. </div>
  90. <Link className="link-secondary mb-2" title='Author' to='#'><FontAwesomeIcon className='me-2' icon={faUserAstronaut} /> {playlist.user_name}</Link>
  91. <p className='text-white-50 mb-2'>
  92. <FontAwesomeIcon className='me-2' icon={faCompactDisc} /> {playlist?.tracks?.length} Tracks
  93. </p>
  94. <p className='text-white-50 mb-2'>
  95. <FontAwesomeIcon className='me-2' icon={faAlignCenter} /> {playlist.description ?? "There could be a description here, but I'm too lazy"}
  96. </p>
  97. </div>
  98. <div className="w-100">
  99. <div className='d-flex'>
  100. <div className='row g-2'>
  101. <div className="col">
  102. <Dropdown
  103. as={ButtonGroup}
  104. align={"end"}>
  105. <Button className='d-flex align-items-center' variant="outline-light" title='Play' onClick={async() => {
  106. store.dispatch(actionFullSetPlaylist(playlist.tracks));
  107. store.dispatch(actionFullSetTrack(store.getState().player?.playlist[0]));
  108. }}>
  109. <FontAwesomeIcon className='me-2' icon={faPlay}/>
  110. Play
  111. </Button>
  112. <Dropdown.Toggle split variant="outline-light" id="dropdown-split-basic"/>
  113. <Dropdown.Menu variant="dark">
  114. <Dropdown.Item onClick={() => {
  115. store.dispatch(actionAddPlaylistToQueue(playlist.tracks))
  116. }}>Add to Queue</Dropdown.Item>
  117. </Dropdown.Menu>
  118. </Dropdown>
  119. </div>
  120. {playlist.user_id !== store.getState().auth.user.id ?
  121. <div className="col">
  122. <button type="button" className="btn btn-outline-danger">
  123. <FontAwesomeIcon icon={faHeart}/>
  124. </button>
  125. </div>
  126. : <></>}
  127. </div>
  128. </div>
  129. </div>
  130. </div>
  131. </div>
  132. </div>
  133. <CAllTracks />
  134. </div>
  135. </div>
  136. </>)}
  137. export const CPlaylistById = connect(state => ({playlist: state.promise.plstById?.payload || {},
  138. tracks: state.promise.plstById?.payload?.tracks}) || [] )(PlaylistById);
  139. const CAllTracks = connect(state => ({tracks: state.promise?.plstById?.payload?.tracks || [],
  140. playlist: state.promise.plstById?.payload || {},} ) )(TracksAll);