AddSongToPlaylist.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  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. this.currentSong.songId,
  79. playlistId,
  80. res => {
  81. new Toast({ content: res.message, timeout: 4000 });
  82. if (res.status === "success") {
  83. this.playlists[playlistId].songs.push(this.song);
  84. }
  85. this.recalculatePlaylists();
  86. }
  87. );
  88. },
  89. removeSongFromPlaylist(playlistId) {
  90. this.socket.emit(
  91. "playlists.removeSongFromPlaylist",
  92. this.songId,
  93. playlistId,
  94. res => {
  95. new Toast({ content: res.message, timeout: 4000 });
  96. if (res.status === "success") {
  97. this.playlists[playlistId].songs.forEach(
  98. (song, index) => {
  99. if (song.songId === this.songId)
  100. this.playlists[playlistId].songs.splice(
  101. index,
  102. 1
  103. );
  104. }
  105. );
  106. }
  107. this.recalculatePlaylists();
  108. }
  109. );
  110. },
  111. recalculatePlaylists() {
  112. this.playlistsArr = Object.values(this.playlists).map(playlist => {
  113. let hasSong = false;
  114. for (let i = 0; i < playlist.songs.length; i += 1) {
  115. if (playlist.songs[i].songId === this.songId) {
  116. hasSong = true;
  117. }
  118. }
  119. playlist.hasSong = hasSong; // eslint-disable-line no-param-reassign
  120. this.playlists[playlist._id] = playlist;
  121. return playlist;
  122. });
  123. }
  124. }
  125. };
  126. </script>
  127. <style lang="scss" scoped>
  128. @import "styles/global.scss";
  129. .icon.is-small {
  130. margin-right: 10px !important;
  131. }
  132. .songTitle {
  133. font-size: 22px;
  134. padding: 0 10px;
  135. }
  136. .songArtist {
  137. font-size: 19px;
  138. font-weight: 200;
  139. padding: 0 10px;
  140. }
  141. .menu-label {
  142. font-size: 16px;
  143. }
  144. </style>