|
1 | 1 | <script setup lang="ts">
|
2 |
| -import { useBase64, useDropZone } from "@vueuse/core"; |
3 |
| -import { ref } from "vue"; |
| 2 | +import { useDropZone, useBase64 } from "@vueuse/core"; |
| 3 | +import { ref, computed } from "vue"; |
| 4 | +import use8baseStorage from "@/composables/use8baseStorage"; |
| 5 | +const props = defineProps<{ |
| 6 | + image?: string; |
| 7 | + loading?: boolean; |
| 8 | +}>(); |
| 9 | +const emit = defineEmits<{ |
| 10 | + (e: "upload", payload: { id: string }): void; |
| 11 | +}>(); |
| 12 | +// data |
| 13 | +const image = ref<string | File | null | undefined>(props.image); |
| 14 | +const dropZoneRef = ref(null); |
4 | 15 |
|
5 |
| -const dropzoneEl = ref<HTMLElement | null>(null); |
6 |
| -const file = ref(); |
7 |
| -const { base64: url } = useBase64(file); |
8 |
| -const { isOverDropZone } = useDropZone(dropzoneEl, (files) => { |
9 |
| - if (!files) return; |
10 |
| - file.value = files[0]; |
11 |
| - console.log(file.value); |
12 |
| -}); |
| 16 | +//@ts-expect-error is checked in src for string type |
| 17 | +const { base64 } = useBase64(image); |
| 18 | +const uploadingToFilestack = ref(false); |
| 19 | +const src = computed(() => |
| 20 | + typeof image.value === "string" ? image.value : base64.value |
| 21 | +); |
13 | 22 |
|
14 |
| -function onFileChange(e: any) { |
15 |
| - file.value = e.target.files[0]; |
16 |
| - console.log(file.value); |
| 23 | +// functions |
| 24 | +function onFileSelect(e: Event) { |
| 25 | + handleFiles((e.target as HTMLInputElement).files); |
17 | 26 | }
|
18 |
| -
|
19 |
| -function reset() { |
20 |
| - file.value = null; |
| 27 | +function onDrop(files: File[] | null) { |
| 28 | + handleFiles(files); |
| 29 | +} |
| 30 | +const { uploadAsset } = use8baseStorage(); |
| 31 | +async function handleFiles(files: FileList | File[] | null) { |
| 32 | + if (!files) return; |
| 33 | + image.value = files[0]; |
| 34 | + uploadingToFilestack.value = true; |
| 35 | + const res = await uploadAsset(files[0]); |
| 36 | + emit("upload", res?.data.fileCreate); |
| 37 | + uploadingToFilestack.value = false; |
21 | 38 | }
|
| 39 | +const { isOverDropZone } = useDropZone(dropZoneRef, onDrop); |
22 | 40 | </script>
|
23 | 41 |
|
24 | 42 | <template>
|
25 | 43 | <div
|
26 |
| - ref="dropzoneEl" |
27 |
| - class="flex m-4" |
| 44 | + class="bg-gray-100 p-2 flex justify-center items-center border-2 border-gray-100 relative" |
28 | 45 | :class="{
|
29 |
| - border: isOverDropZone, |
30 |
| - 'bg-orange-100': isOverDropZone, |
31 |
| - 'border-orange-400': isOverDropZone, |
| 46 | + 'border-blue-200': isOverDropZone, |
| 47 | + 'border-2': isOverDropZone, |
32 | 48 | }"
|
33 |
| - style="width: 300px; height: 200px; background: #3332; position: relative" |
| 49 | + ref="dropZoneRef" |
34 | 50 | >
|
35 |
| - <div class="m-auto opacity-50">Drop a image over or select</div> |
36 |
| - <div v-if="url" class="absolute left-0 top-0 bottom-0 right-0 object-cover"> |
37 |
| - <img :src="url" class="h-full" /> |
38 |
| - </div> |
39 |
| - <input |
40 |
| - class="absolute z-1 left-0 top-0 bottom-0 right-0 opacity-0" |
41 |
| - type="file" |
42 |
| - accept="image/*" |
43 |
| - @input="onFileChange" |
44 |
| - /> |
| 51 | + <label class="absolute top-0 left-0 right-0 bottom-0 block"> |
| 52 | + <input |
| 53 | + accept="image/png, image/jpeg" |
| 54 | + class="hidden" |
| 55 | + type="file" |
| 56 | + @change="onFileSelect" |
| 57 | + /> |
| 58 | + </label> |
| 59 | + <AppImage v-if="image" :src="src" /> |
| 60 | + <template v-else>{{ "Click or drop to upload image" }}</template> |
| 61 | + <AppLoader v-if="loading || uploadingToFilestack" :overlay="true" /> |
45 | 62 | </div>
|
46 |
| - <button @click="reset">Reset</button> |
47 | 63 | </template>
|
0 commit comments