Update PDF viewer to display user-uploaded documents as slides
Integrates the react-pdf library to render PDF documents page by page as slides, replacing the previous canvas-based rendering approach. Includes necessary setup for the PDF worker and static file serving. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 9a264234-c5d7-4dcc-adf3-a954b149b30d Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3df548ff-50ae-432f-9be4-25d34eccc983/9a264234-c5d7-4dcc-adf3-a954b149b30d/VGhYqEL
This commit is contained in:
@ -11,9 +11,9 @@ import { useState, useEffect, useRef } from "react";
|
||||
import type { MediaOutlet } from "@shared/schema";
|
||||
import Footer from "@/components/Footer";
|
||||
import SearchModal from "@/components/SearchModal";
|
||||
import * as pdfjsLib from 'pdfjs-dist';
|
||||
import { Document, Page, pdfjs } from 'react-pdf';
|
||||
|
||||
pdfjsLib.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjsLib.version}/pdf.worker.min.js`;
|
||||
pdfjs.GlobalWorkerOptions.workerSrc = '/pdf.worker.min.mjs';
|
||||
|
||||
const reportContent: Record<string, { htmlPath: string; pdfPath?: string; pptPath?: string; customComponent?: boolean }> = {
|
||||
'chayan-asli': {
|
||||
@ -32,71 +32,32 @@ const reportContent: Record<string, { htmlPath: string; pdfPath?: string; pptPat
|
||||
};
|
||||
|
||||
function MohamedSalahSlides() {
|
||||
const [currentSlide, setCurrentSlide] = useState(0);
|
||||
const [currentSlide, setCurrentSlide] = useState(1);
|
||||
const [numPages, setNumPages] = useState(0);
|
||||
const [pdfDoc, setPdfDoc] = useState<any>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const loadPdf = async () => {
|
||||
try {
|
||||
const loadingTask = pdfjsLib.getDocument('/attached_assets/mohamed_salah_pdf_en_1760419721874.pdf');
|
||||
const pdf = await loadingTask.promise;
|
||||
setPdfDoc(pdf);
|
||||
setNumPages(pdf.numPages);
|
||||
setLoading(false);
|
||||
} catch (error) {
|
||||
console.error('Error loading PDF:', error);
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
loadPdf();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!pdfDoc || !canvasRef.current) return;
|
||||
|
||||
const renderPage = async () => {
|
||||
const page = await pdfDoc.getPage(currentSlide + 1);
|
||||
const canvas = canvasRef.current!;
|
||||
const context = canvas.getContext('2d')!;
|
||||
|
||||
const containerWidth = canvas.parentElement?.clientWidth || 800;
|
||||
const viewport = page.getViewport({ scale: 1 });
|
||||
const scale = containerWidth / viewport.width;
|
||||
const scaledViewport = page.getViewport({ scale });
|
||||
|
||||
canvas.width = scaledViewport.width;
|
||||
canvas.height = scaledViewport.height;
|
||||
|
||||
await page.render({
|
||||
canvasContext: context,
|
||||
viewport: scaledViewport
|
||||
}).promise;
|
||||
};
|
||||
|
||||
renderPage();
|
||||
}, [pdfDoc, currentSlide]);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="flex items-center justify-center h-96">
|
||||
<p data-testid="text-loading-slides">Loading slides...</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const onDocumentLoadSuccess = ({ numPages }: { numPages: number }) => {
|
||||
setNumPages(numPages);
|
||||
setCurrentSlide(1); // Reset to first slide after load
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<div className="w-full relative overflow-hidden" style={{ paddingTop: '56.25%' }} data-testid="slide-container-16-9">
|
||||
<Card className="absolute inset-0 bg-white">
|
||||
<CardContent className="p-0 h-full w-full flex items-center justify-center">
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
className="max-w-full max-h-full object-contain"
|
||||
data-testid="canvas-pdf-slide"
|
||||
/>
|
||||
<Document
|
||||
file="/attached_assets/mohamed_salah_pdf_en_1760419721874.pdf"
|
||||
onLoadSuccess={onDocumentLoadSuccess}
|
||||
loading={<p data-testid="text-loading-slides">Loading slides...</p>}
|
||||
>
|
||||
<Page
|
||||
pageNumber={currentSlide}
|
||||
width={1200}
|
||||
renderTextLayer={false}
|
||||
renderAnnotationLayer={false}
|
||||
data-testid="canvas-pdf-slide"
|
||||
/>
|
||||
</Document>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
@ -104,19 +65,19 @@ function MohamedSalahSlides() {
|
||||
<div className="flex items-center justify-between">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setCurrentSlide(Math.max(0, currentSlide - 1))}
|
||||
disabled={currentSlide === 0}
|
||||
onClick={() => setCurrentSlide(Math.max(1, currentSlide - 1))}
|
||||
disabled={numPages === 0 || currentSlide === 1}
|
||||
data-testid="button-previous-slide"
|
||||
>
|
||||
Previous
|
||||
</Button>
|
||||
<span className="text-sm text-gray-600" data-testid="text-slide-counter">
|
||||
Slide {currentSlide + 1} of {numPages}
|
||||
Slide {currentSlide} of {numPages}
|
||||
</span>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setCurrentSlide(Math.min(numPages - 1, currentSlide + 1))}
|
||||
disabled={currentSlide === numPages - 1}
|
||||
onClick={() => setCurrentSlide(Math.min(numPages || 1, currentSlide + 1))}
|
||||
disabled={numPages === 0 || currentSlide === numPages}
|
||||
data-testid="button-next-slide"
|
||||
>
|
||||
Next
|
||||
|
||||
Reference in New Issue
Block a user