feat(submissions): add small file preview before submitting
This commit is contained in:
@@ -415,6 +415,26 @@ const removeFile = (index: number) => {
|
||||
uploadedFiles.value.splice(index, 1);
|
||||
};
|
||||
|
||||
// Thumbnails of the selected images, revoked once the file is removed/submitted
|
||||
const thumbnailUrls = new Map<File, string>();
|
||||
const thumbnails = computed(() =>
|
||||
uploadedFiles.value.map((file) => {
|
||||
if (!file.type.startsWith("image/")) return null;
|
||||
if (!thumbnailUrls.has(file)) thumbnailUrls.set(file, URL.createObjectURL(file));
|
||||
return thumbnailUrls.get(file)!;
|
||||
}),
|
||||
);
|
||||
|
||||
const revokeThumbnails = (keep: File[] = []) => {
|
||||
thumbnailUrls.forEach((url, file) => {
|
||||
if (keep.includes(file)) return;
|
||||
URL.revokeObjectURL(url);
|
||||
thumbnailUrls.delete(file);
|
||||
});
|
||||
};
|
||||
|
||||
watch(uploadedFiles, (files) => revokeThumbnails(files), { deep: true });
|
||||
|
||||
const submitSubmission = async () => {
|
||||
if (uploadedFiles.value.length === 0) return;
|
||||
|
||||
@@ -561,6 +581,7 @@ onMounted(async () => {
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('paste', handlePasteOnUploadArea);
|
||||
revokeThumbnails();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -629,17 +650,24 @@ onUnmounted(() => {
|
||||
<!-- Uploaded Files List -->
|
||||
<div v-if="uploadedFiles.length > 0" class="mb-6">
|
||||
<p class="font-semibold mb-3">{{ t("common.selectedFiles") }}</p>
|
||||
<div class="space-y-2">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
|
||||
<div v-for="(file, index) in uploadedFiles" :key="index"
|
||||
class="flex items-center gap-3 bg-base-200 p-3 rounded-lg cursor-pointer hover:bg-base-300 transition-colors group"
|
||||
class="relative bg-base-200 rounded-lg overflow-hidden cursor-pointer hover:bg-base-300 transition-colors group"
|
||||
@click="openFilePreview(file)">
|
||||
<div class="aspect-video bg-base-300 flex items-center justify-center">
|
||||
<img v-if="thumbnails[index]" :src="thumbnails[index]" :alt="file.name"
|
||||
class="w-full h-full object-contain" />
|
||||
<i v-else :class="['mdi text-5xl text-primary', getFileIcon(file)]"></i>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 p-2">
|
||||
<i :class="['mdi text-primary', getFileIcon(file)]"></i>
|
||||
<div class="flex-1 min-w-0">
|
||||
<p class="font-medium truncate group-hover:text-primary">{{ file.name }}</p>
|
||||
<p class="text-sm font-medium truncate group-hover:text-primary" :title="file.name">{{ file.name }}</p>
|
||||
<p class="text-xs text-base-content/70">{{ formatFileSize(file.size) }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<button @click.stop="removeFile(index)"
|
||||
class="btn btn-ghost btn-xs opacity-0 group-hover:opacity-100">
|
||||
class="btn btn-circle btn-xs absolute top-2 right-2 sm:opacity-0 sm:group-hover:opacity-100">
|
||||
<i class="mdi mdi-close"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user