From 05a92208cee25dab9f1412b84f8013523fb7ce7c Mon Sep 17 00:00:00 2001 From: chark1es Date: Sat, 15 Feb 2025 03:27:33 -0800 Subject: [PATCH] fix preview errors --- .../dashboard/Officer_EventManagement.astro | 23 +- .../Officer_EventManagement/EventEditor.tsx | 561 +++++++++--------- .../Officer_EventManagement/FilePreview.tsx | 171 ++++++ 3 files changed, 466 insertions(+), 289 deletions(-) create mode 100644 src/components/dashboard/Officer_EventManagement/FilePreview.tsx diff --git a/src/components/dashboard/Officer_EventManagement.astro b/src/components/dashboard/Officer_EventManagement.astro index d58b5ba..b892496 100644 --- a/src/components/dashboard/Officer_EventManagement.astro +++ b/src/components/dashboard/Officer_EventManagement.astro @@ -3,7 +3,7 @@ import { Icon } from "astro-icon/components"; import { Get } from "../pocketbase/Get"; import { Authentication } from "../pocketbase/Authentication"; import EventEditor from "./Officer_EventManagement/EventEditor"; -import FilePreview from "../modals/FilePreview"; +import FilePreview from "./Officer_EventManagement/FilePreview"; // Get instances const get = Get.getInstance(); @@ -714,7 +714,7 @@ const currentPage = eventResponse.page; import { Update } from "../pocketbase/Update"; import { FileManager } from "../pocketbase/FileManager"; import { SendLog } from "../pocketbase/SendLog"; - import FilePreview from "../modals/FilePreview"; + import FilePreview from "./Officer_EventManagement/FilePreview"; // Add file storage const selectedFileStorage = new Map(); @@ -1832,12 +1832,8 @@ const currentPage = eventResponse.page; const modal = document.getElementById("filePreviewModal") as HTMLDialogElement; const filePreview = document.getElementById("universalFilePreview") as any; const previewFileName = document.getElementById("previewFileName"); - const loadingSpinner = document.getElementById("previewLoadingSpinner"); - if (filePreview && modal && previewFileName && loadingSpinner) { - // Show loading spinner - loadingSpinner.classList.remove("hidden"); - + if (filePreview && modal && previewFileName) { // Update the filename display previewFileName.textContent = filename; @@ -1847,27 +1843,20 @@ const currentPage = eventResponse.page; // Update the preview component filePreview.setAttribute("url", url); filePreview.setAttribute("filename", filename); - - // Hide loading spinner after a short delay - setTimeout(() => { - loadingSpinner.classList.add("hidden"); - }, 500); } }; // Close file preview window.closeFilePreview = function () { const modal = document.getElementById("filePreviewModal") as HTMLDialogElement; - const filePreview = document.getElementById("universalFilePreview"); + const filePreview = document.getElementById("universalFilePreview") as any; const previewFileName = document.getElementById("previewFileName"); const filesContent = document.getElementById("filesContent"); if (modal && filePreview && previewFileName) { // Reset the preview - const event = new CustomEvent("updateFilePreview", { - detail: { url: "", filename: "" }, - }); - filePreview.dispatchEvent(event); + filePreview.setAttribute("url", ""); + filePreview.setAttribute("filename", ""); previewFileName.textContent = ""; modal.close(); diff --git a/src/components/dashboard/Officer_EventManagement/EventEditor.tsx b/src/components/dashboard/Officer_EventManagement/EventEditor.tsx index 956ba58..cf7ad82 100644 --- a/src/components/dashboard/Officer_EventManagement/EventEditor.tsx +++ b/src/components/dashboard/Officer_EventManagement/EventEditor.tsx @@ -4,7 +4,7 @@ import { Authentication } from "../../pocketbase/Authentication"; import { Update } from "../../pocketbase/Update"; import { FileManager } from "../../pocketbase/FileManager"; import { SendLog } from "../../pocketbase/SendLog"; -import FilePreview from "../../modals/FilePreview"; +import FilePreview from "./FilePreview"; // Extend Window interface declare global { @@ -129,6 +129,7 @@ export default function EventEditor({ onEventSaved }: EventEditorProps) { setPreviewFilename(filename); setShowPreview(true); }; + // Handle form submission const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); @@ -256,290 +257,306 @@ export default function EventEditor({ onEventSaved }: EventEditorProps) { } }; - // Add preview section - const previewSection = showPreview && event?.id && ( - { - setShowPreview(false); - const modal = document.getElementById('filePreviewModal') as HTMLDialogElement; - if (modal) { - modal.close(); - } - }} - /> - ); - return ( - {/* Preview Section */} - {previewSection} -
- {/* Main Edit Form Section */} -
-

Edit Event

-
- -
- {/* Event Name */} -
- - setEvent(prev => prev ? { ...prev, event_name: e.target.value } : null)} - required - /> -
- - {/* Event Code */} -
- - setEvent(prev => prev ? { ...prev, event_code: e.target.value } : null)} - required - /> -
- - {/* Location */} -
- - setEvent(prev => prev ? { ...prev, location: e.target.value } : null)} - required - /> -
- - {/* Points to Reward */} -
- - setEvent(prev => prev ? { ...prev, points_to_reward: Number(e.target.value) } : null)} - min="0" - required - /> -
- - {/* Start Date */} -
- - setEvent(prev => prev ? { ...prev, start_date: e.target.value } : null)} - required - /> -
- - {/* End Date */} -
- - setEvent(prev => prev ? { ...prev, end_date: e.target.value } : null)} - required - /> -
+ {showPreview ? ( +
+
+
+ +

+ {previewFilename} +

+
+
+ +
+
+ ) : ( +
+ {/* Main Edit Form Section */} +
+

+ {event?.id ? 'Edit Event' : 'Add New Event'} +

+ + +
+ {/* Event Name */} +
+ + setEvent(prev => prev ? { ...prev, event_name: e.target.value } : null)} + required + /> +
- {/* Description */} -
- - -
+ {/* Event Code */} +
+ + setEvent(prev => prev ? { ...prev, event_code: e.target.value } : null)} + required + /> +
- {/* Files */} -
- - -
- {/* New Files */} - {Array.from(selectedFiles.entries()).map(([name, file]) => ( -
- {name} -
-
New
- + {/* Location */} +
+ + setEvent(prev => prev ? { ...prev, location: e.target.value } : null)} + required + /> +
+ + {/* Points to Reward */} +
+ + setEvent(prev => prev ? { ...prev, points_to_reward: Number(e.target.value) } : null)} + min="0" + required + /> +
+ + {/* Start Date */} +
+ + setEvent(prev => prev ? { ...prev, start_date: e.target.value } : null)} + required + /> +
+ + {/* End Date */} +
+ + setEvent(prev => prev ? { ...prev, end_date: e.target.value } : null)} + required + /> +
+
+ + {/* Description */} +
+ + +
+ + {/* Files */} +
+ + +
+ {/* New Files */} + {Array.from(selectedFiles.entries()).map(([name, file]) => ( +
+ {name} +
+
New
+ +
-
- ))} + ))} - {/* Current Files */} - {event?.files && event.files.length > 0 && ( - <> -
Current Files
- {event.files.map((filename) => ( -
- {filename} -
- -
- {filesToDelete.has(filename) ? ( - - ) : ( - - )} + {/* Current Files */} + {event?.files && event.files.length > 0 && ( + <> +
Current Files
+ {event.files.map((filename) => ( +
+ {filename} +
+ +
+ {filesToDelete.has(filename) ? ( + + ) : ( + + )} +
-
- ))} - - )} + ))} + + )} +
-
- {/* Published */} -
- - -
+ {/* Published */} +
+ + +
- {/* Has Food */} -
- - -
- + {/* Has Food */} +
+ + +
+ +
+ +
+ + +
- -
- - -
-
+ )}
diff --git a/src/components/dashboard/Officer_EventManagement/FilePreview.tsx b/src/components/dashboard/Officer_EventManagement/FilePreview.tsx new file mode 100644 index 0000000..bc4e11c --- /dev/null +++ b/src/components/dashboard/Officer_EventManagement/FilePreview.tsx @@ -0,0 +1,171 @@ +import React, { useEffect, useState } from 'react'; + +interface FilePreviewProps { + url: string; + filename: string; +} + +const FilePreview: React.FC = ({ url, filename }) => { + const [content, setContent] = useState(null); + const [error, setError] = useState(null); + const [loading, setLoading] = useState(false); + const [fileType, setFileType] = useState(null); + + useEffect(() => { + if (!url || !filename) { + setContent(null); + setError(null); + setFileType(null); + return; + } + + const loadContent = async () => { + setLoading(true); + setError(null); + + try { + const response = await fetch(url); + const contentType = response.headers.get('content-type'); + setFileType(contentType); + + if (contentType?.startsWith('image/')) { + setContent('image'); + } else if (contentType?.startsWith('video/')) { + setContent('video'); + } else if (contentType?.startsWith('application/pdf')) { + setContent('pdf'); + } else if (contentType?.startsWith('text/')) { + const text = await response.text(); + // Truncate text if it's too long (e.g., more than 100KB) + if (text.length > 100000) { + setContent(text.substring(0, 100000) + '\n\n... Content truncated. Please download the file to view the complete content.'); + } else { + setContent(text); + } + } else if (filename.toLowerCase().endsWith('.mp4')) { + // Fallback for video files when content-type might not be correct + setContent('video'); + } else { + setError(`This file type (${contentType || 'unknown'}) is not supported for preview. Please download the file to view it.`); + } + } catch (err) { + setError('Failed to load file'); + console.error('Error loading file:', err); + } finally { + setLoading(false); + } + }; + + loadContent(); + }, [url, filename]); + + const handleDownload = async () => { + try { + const response = await fetch(url); + const blob = await response.blob(); + const downloadUrl = window.URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = downloadUrl; + link.download = filename; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + window.URL.revokeObjectURL(downloadUrl); + } catch (err) { + console.error('Error downloading file:', err); + alert('Failed to download file. Please try again.'); + } + }; + + return ( +
+ {/* Header with filename and download button */} +
+
+ {filename} + {fileType && ( + {fileType.split('/')[1]} + )} +
+ +
+ + {/* Preview content */} +
+ {loading && ( +
+ +
+ )} + + {error && ( +
+
+ + + +
+
+

Preview Unavailable

+

{error}

+
+ +
+ )} + + {!loading && !error && content === 'image' && ( +
+ {filename} +
+ )} + + {!loading && !error && content === 'video' && ( +
+ +
+ )} + + {!loading && !error && content === 'pdf' && ( +
+ +
+ )} + + {!loading && !error && content && !['image', 'video', 'pdf'].includes(content) && ( +
+
{content}
+
+ )} +
+
+ ); +}; + +export default FilePreview; \ No newline at end of file