AddSongToPlaylist.vue 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. <template>
  2. <modal title="Add Song To Playlist">
  3. <template #body>
  4. <h4 class="songTitle">
  5. {{ currentSong.title }}
  6. </h4>
  7. <h5 class="songArtist">
  8. {{ currentSong.artists }}
  9. </h5>
  10. <aside class="menu">
  11. <p class="menu-label">Playlists</p>
  12. <ul class="menu-list">
  13. <li v-for="(playlist, index) in playlistsArr" :key="index">
  14. <div class="playlist">
  15. <span
  16. v-if="playlists[playlist._id].hasSong"
  17. class="icon is-small"
  18. @click="removeSongFromPlaylist(playlist._id)"
  19. >
  20. <i class="material-icons">playlist_add_check</i>
  21. </span>
  22. <span
  23. v-else
  24. class="icon"
  25. @click="addSongToPlaylist(playlist._id)"
  26. >
  27. <i class="material-icons">playlist_add</i>
  28. </span>
  29. {{ playlist.displayName }}
  30. </div>
  31. </li>
  32. </ul>
  33. </aside>
  34. </template>
  35. </modal>
  36. </template>
  37. <script>
  38. import { mapState } from "vuex";
  39. import Toast from "toasters";
  40. import Modal from "../../components/Modal.vue";
  41. import io from "../../io";
  42. export default {
  43. components: { Modal },
  44. data() {
  45. return {
  46. playlists: {},
  47. playlistsArr: [],
  48. songId: null,
  49. song: null
  50. };
  51. },
  52. mounted() {
  53. this.songId = this.currentSong.songId;
  54. this.song = this.currentSong;
  55. io.getSocket(socket => {
  56. this.socket = socket;
  57. this.socket.emit("playlists.indexForUser", res => {
  58. if (res.status === "success") {
  59. res.data.forEach(playlist => {
  60. this.playlists[playlist._id] = playlist;
  61. });
  62. this.recalculatePlaylists();
  63. }
  64. });
  65. });
  66. },
  67. computed: {
  68. ...mapState("station", {
  69. currentSong: state => state.currentSong
  70. })
  71. },
  72. methods: {
  73. addSongToPlaylist(playlistId) {
  74. this.socket.emit(
  75. "playlists.addSongToPlaylist",
  76. false,
  77. this.currentSong.songId,
  78. playlistId,
  79. res => {
  80. new Toast({ content: res.message, timeout: 4000 });
  81. if (res.status === "success") {
  82. this.playlists[playlistId].songs.push(this.song);
  83. }
  84. this.recalculatePlaylists();
  85. }
  86. );
  87. },
  88. removeSongFromPlaylist(playlistId) {
  89. this.socket.emit(
  90. "playlists.removeSongFromPlaylist",
  91. this.songId,
  92. playlistId,
  93. res => {
  94. new Toast({ content: res.message, timeout: 4000 });
  95. if (res.status === "success") {
  96. this.playlists[playlistId].songs.forEach(
  97. (song, index) => {
  98. if (song.songId === this.songId)
  99. this.playlists[playlistId].songs.splice(
  100. index,
  101. 1
  102. );
  103. }
  104. );
  105. }
  106. this.recalculatePlaylists();
  107. }
  108. );
  109. },
  110. recalculatePlaylists() {
  111. this.playlistsArr = Object.values(this.playlists).map(playlist => {
  112. let hasSong = false;
  113. for (let i = 0; i < playlist.songs.length; i += 1) {
  114. if (playlist.songs[i].songId === this.songId) {
  115. hasSong = true;
  116. }
  117. }
  118. playlist.hasSong = hasSong; // eslint-disable-line no-param-reassign
  119. this.playlists[playlist._id] = playlist;
  120. return playlist;
  121. });
  122. }
  123. }
  124. };
  125. </script>
  126. <style lang="scss" scoped>
  127. @import "../../styles/global.scss";
  128. .modal-card-body {
  129. padding: 16px;
  130. display: flex;
  131. }
  132. .icon.is-small {
  133. margin-right: 10px !important;
  134. }
  135. .songTitle {
  136. font-size: 22px;
  137. padding: 0 10px;
  138. }
  139. .songArtist {
  140. font-size: 19px;
  141. font-weight: 200;
  142. padding: 0 10px;
  143. }
  144. .menu-label {
  145. font-size: 16px;
  146. }
  147. </style>