Youtube.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. <script setup lang="ts">
  2. import { storeToRefs } from "pinia";
  3. import { useEditSongStore } from "@/stores/editSong";
  4. import { useSearchYoutube } from "@/composables/useSearchYoutube";
  5. import { useYoutubeDirect } from "@/composables/useYoutubeDirect";
  6. import SearchQueryItem from "../../../SearchQueryItem.vue";
  7. const props = defineProps({
  8. modalUuid: { type: String, required: true },
  9. modalModulePath: { type: String, default: "modals/editSong/MODAL_UUID" }
  10. });
  11. const editSongStore = useEditSongStore({ modalUuid: props.modalUuid });
  12. const { form, newSong } = storeToRefs(editSongStore);
  13. const { updateYoutubeId } = editSongStore;
  14. const { youtubeSearch, searchForSongs, loadMoreSongs } = useSearchYoutube();
  15. const { youtubeDirect, getYoutubeVideoId } = useYoutubeDirect();
  16. const selectSong = (youtubeId, result = null) => {
  17. updateYoutubeId(youtubeId);
  18. if (newSong && result)
  19. form.value.setValue({
  20. title: result.title,
  21. thumbnail: result.thumbnail
  22. });
  23. };
  24. </script>
  25. <template>
  26. <div class="youtube-tab">
  27. <label class="label"> Add a YouTube song from a URL </label>
  28. <div class="control is-grouped input-with-button">
  29. <p class="control is-expanded">
  30. <input
  31. class="input"
  32. type="text"
  33. placeholder="Enter your YouTube song URL here..."
  34. v-model="youtubeDirect"
  35. @keyup.enter="selectSong(getYoutubeVideoId())"
  36. />
  37. </p>
  38. <p class="control">
  39. <a
  40. class="button is-info"
  41. @click="selectSong(getYoutubeVideoId())"
  42. ><i class="material-icons icon-with-button">add</i>Add</a
  43. >
  44. </p>
  45. </div>
  46. <label class="label"> Search for a song from YouTube </label>
  47. <div class="control is-grouped input-with-button">
  48. <p class="control is-expanded">
  49. <input
  50. class="input"
  51. type="text"
  52. placeholder="Enter your YouTube query here..."
  53. v-model="youtubeSearch.songs.query"
  54. autofocus
  55. @keyup.enter="searchForSongs()"
  56. />
  57. </p>
  58. <p class="control">
  59. <button
  60. class="button is-info"
  61. @click.prevent="searchForSongs()"
  62. >
  63. <i class="material-icons icon-with-button">search</i>Search
  64. </button>
  65. </p>
  66. </div>
  67. <div
  68. v-if="youtubeSearch.songs.results.length > 0"
  69. id="song-query-results"
  70. >
  71. <search-query-item
  72. v-for="result in youtubeSearch.songs.results"
  73. :key="result.id"
  74. :result="result"
  75. >
  76. <template #actions>
  77. <i
  78. class="material-icons icon-selected"
  79. v-if="result.id === form.inputs.youtubeId.value"
  80. key="selected"
  81. >radio_button_checked
  82. </i>
  83. <i
  84. class="material-icons icon-not-selected"
  85. v-else
  86. @click.prevent="selectSong(result.id, result)"
  87. key="not-selected"
  88. >radio_button_unchecked
  89. </i>
  90. </template>
  91. </search-query-item>
  92. <button
  93. class="button is-primary load-more-button"
  94. @click.prevent="loadMoreSongs()"
  95. >
  96. Load more...
  97. </button>
  98. </div>
  99. </div>
  100. </template>
  101. <style lang="less" scoped>
  102. .youtube-tab #song-query-results {
  103. height: calc(100% - 74px);
  104. overflow: auto;
  105. .search-query-item {
  106. .icon-selected {
  107. color: var(--green) !important;
  108. }
  109. .icon-not-selected {
  110. color: var(--grey) !important;
  111. }
  112. }
  113. .search-query-item:not(:last-of-type) {
  114. margin-bottom: 10px;
  115. }
  116. .load-more-button {
  117. width: 100%;
  118. margin-top: 10px;
  119. }
  120. }
  121. </style>