feat(submissions): add small file preview before submitting

This commit is contained in:
2026-10-16 02:24:41 +02:00
parent 1daf2757b8
commit 60d730a683
+32 -4
View File
@@ -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>