#24-PDF-Anzeigen #41

Merged
1924466 merged 3 commits from #24-PDF-Anzeigen into main 2025-05-30 07:36:32 +02:00
5 changed files with 221 additions and 6 deletions

Binary file not shown.

View File

@ -26,7 +26,7 @@ export default function UploadPage() {
px={2}
>
<IconButton onClick={() => navigate({ to: '/config' })}>
<SettingsIcon fontSize="large" />
<SettingsIcon fontSize="large"/>
</IconButton>
</Box>
<Paper
@ -91,7 +91,7 @@ export default function UploadPage() {
backgroundColor: '#383838',
}}
disabled={files.length === 0}
onClick={() => alert('Kein Backend, aber Button klickbar')}
onClick={() => navigate({ to: '/extractedResult' })}
>
Kennzahlen extrahieren
</Button>

View File

@ -0,0 +1,91 @@
import { Document, Page, pdfjs } from "react-pdf";
import { useState, useRef, useEffect } from 'react';
import 'react-pdf/dist/esm/Page/AnnotationLayer.css';
import 'react-pdf/dist/esm/Page/TextLayer.css';
import { Box, IconButton } from '@mui/material';
import ArrowCircleLeftIcon from '@mui/icons-material/ArrowCircleLeft';
import ArrowCircleRightIcon from '@mui/icons-material/ArrowCircleRight';
import testPDF from '/example.pdf';
pdfjs.GlobalWorkerOptions.workerSrc = new URL(
"pdfjs-dist/build/pdf.worker.min.mjs",
import.meta.url,
).toString();
export default function PDFViewer() {
const [numPages, setNumPages] = useState<number | null>(null);
const [pageNumber, setPageNumber] = useState(1);
const [containerWidth, setContainerWidth] = useState<number | null>(null);
const containerRef = useRef<HTMLDivElement>(null);
const onDocumentLoadSuccess = ({ numPages }: { numPages: number }) => {
setNumPages(numPages);
};
useEffect(() => {
const updateWidth = () => {
if (containerRef.current) {
setContainerWidth(containerRef.current.offsetWidth);
}
};
updateWidth();
window.addEventListener('resize', updateWidth);
return () => window.removeEventListener('resize', updateWidth);
}, []);
return (
<Box
display="flex"
flexDirection="column"
justifyContent="center"
alignItems="center"
width="100%"
height="100%"
p={2}
>
<Box
ref={containerRef}
sx={{
width: '100%',
maxHeight: '90vh',
overflow: 'auto',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
>
<Document file={testPDF}
onLoadSuccess={onDocumentLoadSuccess}
onLoadError={(error) => console.error('Es gab ein Fehler beim Laden des PDFs:', error)}
onSourceError={(error) => console.error('Ungültige PDF:', error)}>
{containerWidth && (
<Page
pageNumber={pageNumber}
width={containerWidth * 0.8}
/>
)}
</Document>
</Box>
<Box
mt={2}
display="flex"
alignItems="center"
justifyContent="center"
gap={1}
>
<IconButton disabled={pageNumber <= 1} onClick={() => setPageNumber(p => p - 1)}>
<ArrowCircleLeftIcon fontSize="large" />
</IconButton>
<span>{pageNumber} / {numPages}</span>
<IconButton
disabled={pageNumber >= (numPages || 1)}
onClick={() => setPageNumber(p => p + 1)}
>
<ArrowCircleRightIcon fontSize="large" />
</IconButton>
</Box>
</Box>
);
}

View File

@ -11,11 +11,18 @@
// Import Routes
import { Route as rootRoute } from './routes/__root'
import { Route as ExtractedResultImport } from './routes/extractedResult'
import { Route as ConfigImport } from './routes/config'
import { Route as IndexImport } from './routes/index'
// Create/Update Routes
const ExtractedResultRoute = ExtractedResultImport.update({
id: '/extractedResult',
path: '/extractedResult',
getParentRoute: () => rootRoute,
} as any)
const ConfigRoute = ConfigImport.update({
id: '/config',
path: '/config',
@ -46,6 +53,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof ConfigImport
parentRoute: typeof rootRoute
}
'/extractedResult': {
id: '/extractedResult'
path: '/extractedResult'
fullPath: '/extractedResult'
preLoaderRoute: typeof ExtractedResultImport
parentRoute: typeof rootRoute
}
}
}
@ -54,36 +68,41 @@ declare module '@tanstack/react-router' {
export interface FileRoutesByFullPath {
'/': typeof IndexRoute
'/config': typeof ConfigRoute
'/extractedResult': typeof ExtractedResultRoute
}
export interface FileRoutesByTo {
'/': typeof IndexRoute
'/config': typeof ConfigRoute
'/extractedResult': typeof ExtractedResultRoute
}
export interface FileRoutesById {
__root__: typeof rootRoute
'/': typeof IndexRoute
'/config': typeof ConfigRoute
'/extractedResult': typeof ExtractedResultRoute
}
export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
fullPaths: '/' | '/config'
fullPaths: '/' | '/config' | '/extractedResult'
fileRoutesByTo: FileRoutesByTo
to: '/' | '/config'
id: '__root__' | '/' | '/config'
to: '/' | '/config' | '/extractedResult'
id: '__root__' | '/' | '/config' | '/extractedResult'
fileRoutesById: FileRoutesById
}
export interface RootRouteChildren {
IndexRoute: typeof IndexRoute
ConfigRoute: typeof ConfigRoute
ExtractedResultRoute: typeof ExtractedResultRoute
}
const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute,
ConfigRoute: ConfigRoute,
ExtractedResultRoute: ExtractedResultRoute,
}
export const routeTree = rootRoute
@ -97,7 +116,8 @@ export const routeTree = rootRoute
"filePath": "__root.tsx",
"children": [
"/",
"/config"
"/config",
"/extractedResult"
]
},
"/": {
@ -105,6 +125,9 @@ export const routeTree = rootRoute
},
"/config": {
"filePath": "config.tsx"
},
"/extractedResult": {
"filePath": "extractedResult.tsx"
}
}
}

View File

@ -0,0 +1,101 @@
import { Box, Paper, Typography, Button } from '@mui/material';
import {createFileRoute, useNavigate} from '@tanstack/react-router';
import PDFViewer from '../components/pdfViewer';
import ContentPasteIcon from '@mui/icons-material/ContentPaste';
export const Route = createFileRoute('/extractedResult')({
component: ExtractedResultsPage,
});
function ExtractedResultsPage() {
const navigate = useNavigate();
const status: 'green' | 'yellow' | 'red' = 'red';
const statusColor = {
red: '#f43131',
yellow: '#f6ed48',
green: '#3fd942',
}[status];
return (
<Box p={4}>
<Box display="flex" alignItems="center" gap={3}>
<Box
sx={{
width: 45,
height: 45,
borderRadius: '50%',
backgroundColor: statusColor,
top: 32,
left: 32,
}}
/>
<Typography variant="h5" gutterBottom>
Kennzahlen extrahiert aus: <br/><strong>FONDSNAME: TODO</strong>
</Typography>
</Box>
<Box
display="flex"
gap={4}
sx={{
width: '100vw',
maxWidth: '100%',
height: '80vh',
mt: 4,
}}
>
<Paper
elevation={2}
sx={{
width: '45%',
height: '100%',
borderRadius: 2,
backgroundColor: '#eeeeee',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<Typography color="textSecondary">To-do: Table hierhin</Typography>
</Paper>
<Box
display="flex"
flexDirection="column"
justifyContent="space-between"
gap={5}
sx={{ width: '55%', height: '95%' }}
>
<Paper
elevation={2}
sx={{
height: '100%',
borderRadius: 2,
backgroundColor: '#eeeeee',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<PDFViewer/>
</Paper>
<Box mt={2} display="flex" justifyContent="flex-end" gap={2}>
<Button
variant="contained"
sx={{ backgroundColor: '#383838' }}
>
<ContentPasteIcon sx={{ fontSize: 18, mr: 1 }} />
Kennzahlenzeile kopieren
</Button>
<Button
variant="contained"
sx={{ backgroundColor: '#383838' }}
onClick={() => navigate({ to: '/' })}
>
Neu hochladen
</Button>
</Box>
</Box>
</Box>
</Box>
);
}