Compare commits
4 Commits
74d08d3c39
...
416c2ceefd
| Author | SHA1 | Date |
|---|---|---|
|
|
416c2ceefd | |
|
|
efcf4fb831 | |
|
|
f99700c696 | |
|
|
676728021e |
Binary file not shown.
|
|
@ -91,7 +91,7 @@ export default function UploadPage() {
|
||||||
backgroundColor: '#383838',
|
backgroundColor: '#383838',
|
||||||
}}
|
}}
|
||||||
disabled={files.length === 0}
|
disabled={files.length === 0}
|
||||||
onClick={() => alert('Kein Backend, aber Button klickbar')}
|
onClick={() => navigate({ to: '/extractedResult' })}
|
||||||
>
|
>
|
||||||
Kennzahlen extrahieren
|
Kennzahlen extrahieren
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -11,11 +11,18 @@
|
||||||
// Import Routes
|
// Import Routes
|
||||||
|
|
||||||
import { Route as rootRoute } from './routes/__root'
|
import { Route as rootRoute } from './routes/__root'
|
||||||
|
import { Route as ExtractedResultImport } from './routes/extractedResult'
|
||||||
import { Route as ConfigImport } from './routes/config'
|
import { Route as ConfigImport } from './routes/config'
|
||||||
import { Route as IndexImport } from './routes/index'
|
import { Route as IndexImport } from './routes/index'
|
||||||
|
|
||||||
// Create/Update Routes
|
// Create/Update Routes
|
||||||
|
|
||||||
|
const ExtractedResultRoute = ExtractedResultImport.update({
|
||||||
|
id: '/extractedResult',
|
||||||
|
path: '/extractedResult',
|
||||||
|
getParentRoute: () => rootRoute,
|
||||||
|
} as any)
|
||||||
|
|
||||||
const ConfigRoute = ConfigImport.update({
|
const ConfigRoute = ConfigImport.update({
|
||||||
id: '/config',
|
id: '/config',
|
||||||
path: '/config',
|
path: '/config',
|
||||||
|
|
@ -46,6 +53,13 @@ declare module '@tanstack/react-router' {
|
||||||
preLoaderRoute: typeof ConfigImport
|
preLoaderRoute: typeof ConfigImport
|
||||||
parentRoute: typeof rootRoute
|
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 {
|
export interface FileRoutesByFullPath {
|
||||||
'/': typeof IndexRoute
|
'/': typeof IndexRoute
|
||||||
'/config': typeof ConfigRoute
|
'/config': typeof ConfigRoute
|
||||||
|
'/extractedResult': typeof ExtractedResultRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FileRoutesByTo {
|
export interface FileRoutesByTo {
|
||||||
'/': typeof IndexRoute
|
'/': typeof IndexRoute
|
||||||
'/config': typeof ConfigRoute
|
'/config': typeof ConfigRoute
|
||||||
|
'/extractedResult': typeof ExtractedResultRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FileRoutesById {
|
export interface FileRoutesById {
|
||||||
__root__: typeof rootRoute
|
__root__: typeof rootRoute
|
||||||
'/': typeof IndexRoute
|
'/': typeof IndexRoute
|
||||||
'/config': typeof ConfigRoute
|
'/config': typeof ConfigRoute
|
||||||
|
'/extractedResult': typeof ExtractedResultRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FileRouteTypes {
|
export interface FileRouteTypes {
|
||||||
fileRoutesByFullPath: FileRoutesByFullPath
|
fileRoutesByFullPath: FileRoutesByFullPath
|
||||||
fullPaths: '/' | '/config'
|
fullPaths: '/' | '/config' | '/extractedResult'
|
||||||
fileRoutesByTo: FileRoutesByTo
|
fileRoutesByTo: FileRoutesByTo
|
||||||
to: '/' | '/config'
|
to: '/' | '/config' | '/extractedResult'
|
||||||
id: '__root__' | '/' | '/config'
|
id: '__root__' | '/' | '/config' | '/extractedResult'
|
||||||
fileRoutesById: FileRoutesById
|
fileRoutesById: FileRoutesById
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RootRouteChildren {
|
export interface RootRouteChildren {
|
||||||
IndexRoute: typeof IndexRoute
|
IndexRoute: typeof IndexRoute
|
||||||
ConfigRoute: typeof ConfigRoute
|
ConfigRoute: typeof ConfigRoute
|
||||||
|
ExtractedResultRoute: typeof ExtractedResultRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
const rootRouteChildren: RootRouteChildren = {
|
const rootRouteChildren: RootRouteChildren = {
|
||||||
IndexRoute: IndexRoute,
|
IndexRoute: IndexRoute,
|
||||||
ConfigRoute: ConfigRoute,
|
ConfigRoute: ConfigRoute,
|
||||||
|
ExtractedResultRoute: ExtractedResultRoute,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const routeTree = rootRoute
|
export const routeTree = rootRoute
|
||||||
|
|
@ -97,7 +116,8 @@ export const routeTree = rootRoute
|
||||||
"filePath": "__root.tsx",
|
"filePath": "__root.tsx",
|
||||||
"children": [
|
"children": [
|
||||||
"/",
|
"/",
|
||||||
"/config"
|
"/config",
|
||||||
|
"/extractedResult"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"/": {
|
"/": {
|
||||||
|
|
@ -105,6 +125,9 @@ export const routeTree = rootRoute
|
||||||
},
|
},
|
||||||
"/config": {
|
"/config": {
|
||||||
"filePath": "config.tsx"
|
"filePath": "config.tsx"
|
||||||
|
},
|
||||||
|
"/extractedResult": {
|
||||||
|
"filePath": "extractedResult.tsx"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue