AddSongToPlaylist.vue 3.2 KB

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