CreatePlaylist.vue 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. <script setup lang="ts">
  2. import { defineAsyncComponent, ref, onBeforeUnmount } from "vue";
  3. import Toast from "toasters";
  4. import validation from "@/validation";
  5. import { useWebsocketsStore } from "@/stores/websockets";
  6. import { useModalsStore } from "@/stores/modals";
  7. const Modal = defineAsyncComponent(() => import("@/components/Modal.vue"));
  8. defineProps({
  9. modalUuid: { type: String, default: "" }
  10. });
  11. const playlist = ref({
  12. displayName: "",
  13. privacy: "public",
  14. songs: []
  15. });
  16. const { openModal, closeCurrentModal } = useModalsStore();
  17. const { socket } = useWebsocketsStore();
  18. const createPlaylist = () => {
  19. const { displayName } = playlist.value;
  20. if (!validation.isLength(displayName, 2, 32))
  21. return new Toast("Display name must have between 2 and 32 characters.");
  22. if (!validation.regex.ascii.test(displayName))
  23. return new Toast(
  24. "Invalid display name format. Only ASCII characters are allowed."
  25. );
  26. return socket.dispatch("playlists.create", playlist.value, res => {
  27. new Toast(res.message);
  28. if (res.status === "success") {
  29. closeCurrentModal();
  30. if (!window.addToPlaylistDropdown) {
  31. openModal({
  32. modal: "editPlaylist",
  33. data: { playlistId: res.data.playlistId }
  34. });
  35. }
  36. }
  37. });
  38. };
  39. onBeforeUnmount(() => {
  40. if (window.addToPlaylistDropdown)
  41. window.addToPlaylistDropdown.tippy.setProps({
  42. zIndex: 9999,
  43. hideOnClick: true
  44. });
  45. window.addToPlaylistDropdown = null;
  46. });
  47. </script>
  48. <template>
  49. <modal title="Create Playlist" :size="'slim'">
  50. <template #body>
  51. <p class="control is-expanded">
  52. <label class="label">Display Name</label>
  53. <input
  54. v-model="playlist.displayName"
  55. class="input"
  56. type="text"
  57. placeholder="Enter display name..."
  58. autofocus
  59. @keyup.enter="createPlaylist()"
  60. />
  61. </p>
  62. <div class="control" id="privacy-selection">
  63. <label class="label">Privacy</label>
  64. <p class="control is-expanded select">
  65. <select v-model="playlist.privacy">
  66. <option value="private">Private</option>
  67. <option value="public" selected>Public</option>
  68. </select>
  69. </p>
  70. </div>
  71. </template>
  72. <template #footer>
  73. <a class="button is-info" @click="createPlaylist()"
  74. ><i class="material-icons icon-with-button">create</i>Create
  75. Playlist</a
  76. >
  77. </template>
  78. </modal>
  79. </template>