fix: display ocr data submissions

This commit is contained in:
2026-05-25 02:00:34 +02:00
parent 11d6fc423a
commit a769d1a0b3
5 changed files with 220 additions and 54 deletions
+157 -4
View File
@@ -30,6 +30,10 @@ const filePreviewUrl = ref<string>("");
const isModalOpen = ref(false);
const userSubmissions = ref<any[]>([]);
const isLoadingSubmissions = ref(false);
const selectedSubmissionFile = ref<any>(null);
const isSubmissionFileModalOpen = ref(false);
const imageAspectRatio = ref<"portrait" | "landscape">("landscape");
const copyFeedback = ref<string>("");
const openFilePreview = async (file: File) => {
selectedFile.value = file;
@@ -58,6 +62,42 @@ const closeModal = () => {
filePreviewUrl.value = "";
};
const openSubmissionFileModal = (file: any) => {
selectedSubmissionFile.value = file;
isSubmissionFileModalOpen.value = true;
// Check image dimensions for aspect ratio
if (file?.content_type?.startsWith("image/")) {
const img = new Image();
img.onload = () => {
imageAspectRatio.value = img.height > img.width ? "portrait" : "landscape";
};
img.src = file.file_url;
}
};
const closeSubmissionFileModal = () => {
isSubmissionFileModalOpen.value = false;
selectedSubmissionFile.value = null;
};
const copyOCRText = async () => {
if (selectedSubmissionFile.value?.ocr_raw_data) {
try {
await navigator.clipboard.writeText(selectedSubmissionFile.value.ocr_raw_data);
copyFeedback.value = "Copied!";
setTimeout(() => {
copyFeedback.value = "";
}, 2000);
} catch (err) {
copyFeedback.value = "Failed to copy";
setTimeout(() => {
copyFeedback.value = "";
}, 2000);
}
}
};
const getGameHeaderImage = () => {
if (props.gameImage) {
return props.gameImage;
@@ -218,7 +258,8 @@ onMounted(() => {
<img :src="getGameHeaderImage()!" :alt="gameName" class="w-full h-full object-cover" />
<div class="absolute inset-0 bg-black/30"></div>
</figure>
<figure v-else class="relative h-48 bg-gradient-to-br from-blue-600 to-blue-400 flex items-center justify-center">
<figure v-else
class="relative h-48 bg-gradient-to-br from-blue-600 to-blue-400 flex items-center justify-center">
<i class="mdi mdi-gamepad-variant text-6xl text-white opacity-30"></i>
</figure>
<div class="card-body">
@@ -265,7 +306,8 @@ onMounted(() => {
<p class="font-medium truncate group-hover:text-primary">{{ file.name }}</p>
<p class="text-xs text-base-content/70">{{ formatFileSize(file.size) }}</p>
</div>
<button @click.stop="removeFile(index)" class="btn btn-ghost btn-xs opacity-0 group-hover:opacity-100">
<button @click.stop="removeFile(index)"
class="btn btn-ghost btn-xs opacity-0 group-hover:opacity-100">
<i class="mdi mdi-close"></i>
</button>
</div>
@@ -407,9 +449,10 @@ onMounted(() => {
<div class="flex flex-col gap-1">
<div v-for="file in submission.files" :key="file.id" class="flex items-center gap-2">
<i :class="['mdi text-primary text-sm', getFileIcon({ type: file.content_type })]"></i>
<a :href="file.file_url" target="_blank" class="link link-primary truncate max-w-xs">
<button @click="openSubmissionFileModal(file)"
class="link link-primary truncate max-w-xs text-left">
{{ file.original_filename }}
</a>
</button>
<span class="text-xs text-base-content/50">({{ formatFileSize(file.file_size) }})</span>
</div>
</div>
@@ -487,5 +530,115 @@ onMounted(() => {
<div class="modal-backdrop" @click="closeModal"></div>
</div>
<!-- Submission File Modal -->
<div :class="['modal', { 'modal-open': isSubmissionFileModalOpen }]">
<div class="modal-box w-11/12 max-w-6xl max-h-[90vh] overflow-hidden">
<h3 class="font-bold text-lg mb-4">
<i :class="['mdi mr-2', getFileIcon({ type: selectedSubmissionFile?.content_type })]"></i>
{{ selectedSubmissionFile?.original_filename }}
</h3>
<!-- Responsive Layout: Portrait images side-by-side (left/right), landscape images and other files stacked (top/bottom) -->
<div :class="['gap-4 h-[70vh]', imageAspectRatio === 'portrait' ? 'grid grid-cols-1 lg:grid-cols-2' : 'flex flex-col']">
<!-- File Display -->
<div class="flex flex-col overflow-hidden" :class="imageAspectRatio === 'portrait' ? 'h-full' : 'flex-1'">
<p class="text-sm text-base-content/70 mb-2">File Preview</p>
<div class="flex-1 overflow-auto border border-base-300 rounded-lg">
<!-- Image Preview -->
<div v-if="selectedSubmissionFile?.content_type.startsWith('image/')"
class="flex items-center justify-center h-full p-4">
<img :src="selectedSubmissionFile.file_url" :alt="selectedSubmissionFile.original_filename"
class="max-w-full max-h-full object-contain rounded" />
</div>
<!-- PDF Preview -->
<div v-else-if="selectedSubmissionFile?.content_type === 'application/pdf'" class="h-full">
<iframe :src="selectedSubmissionFile.file_url" class="w-full h-full border-0 rounded"></iframe>
</div>
<!-- Text Preview -->
<div v-else-if="selectedSubmissionFile?.content_type.startsWith('text/')" class="p-4">
<div class="bg-base-200 p-4 rounded font-mono text-sm whitespace-pre-wrap break-words">
<p class="text-base-content/70">Text content preview not available. Download file to view.</p>
</div>
</div>
<!-- Unsupported Preview -->
<div v-else class="flex items-center justify-center h-full">
<div class="text-center">
<i class="mdi mdi-file-question text-6xl text-base-content/30 mb-4"></i>
<p class="text-base-content/70">Preview not available</p>
<p class="text-sm text-base-content/50">{{ selectedSubmissionFile?.content_type }}</p>
</div>
</div>
</div>
<div class="mt-2">
<a v-if="selectedSubmissionFile?.file_url" :href="selectedSubmissionFile.file_url" download
class="btn btn-sm btn-outline w-full">
<i class="mdi mdi-download mr-2"></i>
Download File
</a>
</div>
</div>
<!-- OCR Data -->
<div class="flex flex-col overflow-hidden" :class="imageAspectRatio === 'portrait' ? 'h-full' : 'flex-1'">
<p class="text-sm text-base-content/70 mb-2">OCR Data</p>
<div class="flex-1 overflow-auto border border-base-300 rounded-lg p-4 bg-base-200">
<div v-if="selectedSubmissionFile?.ocr_status === 'processed' && selectedSubmissionFile.ocr_raw_data">
<div class="space-y-3">
<div>
<p class="text-xs font-semibold text-base-content/70 mb-1">Status:</p>
<span :class="getOCRStatusColor(selectedSubmissionFile.ocr_status)">{{
selectedSubmissionFile.ocr_status }}</span>
</div>
<div class="divider my-2"></div>
<div>
<div class="flex items-center justify-between mb-2">
<p class="text-xs font-semibold text-base-content/70">Extracted Text:</p>
<button @click="copyOCRText" class="btn btn-xs btn-ghost gap-1">
<i class="mdi mdi-content-copy"></i>
{{ copyFeedback || "Copy" }}
</button>
</div>
<div
class="bg-base-100 p-3 rounded text-xs whitespace-pre-wrap break-words font-mono overflow-y-auto h-full">
{{ selectedSubmissionFile.ocr_raw_data }}
</div>
</div>
</div>
</div>
<div v-else-if="selectedSubmissionFile?.ocr_status === 'processing'"
class="flex items-center justify-center h-full">
<div class="text-center">
<span class="loading loading-spinner loading-lg"></span>
<p class="text-base-content/70 mt-4">OCR is being processed...</p>
</div>
</div>
<div v-else-if="selectedSubmissionFile?.ocr_status === 'error'"
class="flex items-center justify-center h-full">
<div class="text-center">
<i class="mdi mdi-alert-circle text-4xl text-error mb-2"></i>
<p class="text-base-content/70">OCR processing failed</p>
</div>
</div>
<div v-else class="flex items-center justify-center h-full">
<div class="text-center">
<i class="mdi mdi-clock-outline text-4xl text-base-content/30 mb-2"></i>
<p class="text-base-content/70">Waiting for OCR processing...</p>
</div>
</div>
</div>
</div>
</div>
<div class="modal-action mt-4">
<button @click="closeSubmissionFileModal" class="btn">Close</button>
</div>
</div>
<div class="modal-backdrop" @click="closeSubmissionFileModal"></div>
</div>
</div>
</template>