Spaces:
Configuration error
Configuration error
| <script setup> | |
| import { ref, watch, computed } from "vue"; | |
| // TODO: handle only video file | |
| const dropzoneInput = ref(null); | |
| const uploadedVideoFile = ref(null); | |
| const isUploaded = computed(() => (uploadedVideoFile.value ? true : false)); | |
| const isDragOver = ref(false); | |
| // Emit events | |
| const emit = defineEmits(["fileUploaded"]); | |
| watch( | |
| () => uploadedVideoFile.value, | |
| (newData, oldData) => { | |
| if (newData) { | |
| emit("fileUploaded", newData); | |
| } | |
| } | |
| ); | |
| // * Handle Drag Events | |
| const removeDragEventDefault = (event) => { | |
| event.preventDefault(); | |
| event.stopPropagation(); | |
| }; | |
| const handleDragOver = (event) => { | |
| removeDragEventDefault(event); | |
| isDragOver.value = true; | |
| }; | |
| const handleDragLeave = (event) => { | |
| removeDragEventDefault(event); | |
| isDragOver.value = false; | |
| }; | |
| const handleDrop = (event) => { | |
| removeDragEventDefault(event); | |
| isDragOver.value = false; | |
| let videoFile = event.dataTransfer.files[0]; | |
| let dataTransfer = new DataTransfer(); | |
| dataTransfer.items.add(videoFile); | |
| let filesToBeAdded = dataTransfer.files; | |
| dropzoneInput.value.files = filesToBeAdded; | |
| uploadedVideoFile.value = videoFile; | |
| }; | |
| // Handle File Input | |
| const openFileInput = () => { | |
| dropzoneInput.value.click(); | |
| }; | |
| const handleClickUpload = (event) => { | |
| const target = event.target; | |
| if (target && target.files) { | |
| uploadedVideoFile.value = target.files[0]; | |
| } | |
| }; | |
| // Other utils func | |
| const byteToMB = (bytes) => { | |
| return Math.round(bytes / 1000000); | |
| }; | |
| </script> | |
| <template> | |
| <div | |
| class="dropzone" | |
| :class="{ 'dropzone-dragging': isDragOver }" | |
| id="dropzone" | |
| @drag="removeDragEventDefault" | |
| @dragstart="removeDragEventDefault" | |
| @dragend="removeDragEventDefault" | |
| @dragover="handleDragOver" | |
| @dragenter="handleDragLeave" | |
| @dragleave="removeDragEventDefault" | |
| @drop="handleDrop" | |
| @click.self="openFileInput" | |
| > | |
| <!-- Initial Stage --> | |
| <template v-if="!isUploaded"> | |
| <i class="fa-solid fa-cloud-arrow-up dropzone-icon"></i> | |
| Drop files or Click here to select files to upload. | |
| </template> | |
| <!-- Uploaded State --> | |
| <template v-else> | |
| <i class="fa-regular fa-file-video dropzone-icon"></i> | |
| {{ uploadedVideoFile.name }} | |
| ({{ byteToMB(uploadedVideoFile.size) }} MB) | |
| </template> | |
| <input | |
| type="file" | |
| name="files" | |
| class="dropzone-input" | |
| ref="dropzoneInput" | |
| @change="handleClickUpload" | |
| /> | |
| </div> | |
| </template> | |
| <style lang="scss" scoped> | |
| .dropzone { | |
| display: flex; | |
| flex-direction: column; | |
| justify-content: center; | |
| align-items: center; | |
| border: 0.2rem dashed var(--primary-color); | |
| padding: 2rem; | |
| border-radius: 0.25rem; | |
| background-color: #fff; | |
| font-size: 1.25rem; | |
| text-align: center; | |
| transition: 0.25s background-color ease-in-out; | |
| cursor: pointer; | |
| &-dragging, | |
| &:hover { | |
| background-color: lighten(#41b883, 38%); | |
| } | |
| &-icon { | |
| display: block; | |
| font-size: 3rem; | |
| margin: 0 auto 1.5rem; | |
| color: var(--primary-color); | |
| } | |
| &-input { | |
| display: none; | |
| } | |
| } | |
| </style> | |