From 0dd3785fdd038ac0478d872c827662f40435ddf7 Mon Sep 17 00:00:00 2001
From: Abdulraahman Dabbagh <1924466@stud.hs-mannheim.de>
Date: Mon, 2 Jun 2025 12:11:53 +0200
Subject: [PATCH 1/5] =?UTF-8?q?Implementiere=20PDF-Highlighting=20f=C3=BCr?=
=?UTF-8?q?=20Kennzahlen=20(Ticket=20#31)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/components/HighlightOverlay.tsx | 30 ++++++++++++
.../src/components/KennzahlenTable.tsx | 16 ++++++-
.../frontend/src/components/highlightData.ts | 21 +++++++++
project/frontend/src/components/pdfViewer.tsx | 46 +++++++++++++++----
.../frontend/src/routes/extractedResult.tsx | 7 ++-
5 files changed, 106 insertions(+), 14 deletions(-)
create mode 100644 project/frontend/src/components/HighlightOverlay.tsx
create mode 100644 project/frontend/src/components/highlightData.ts
diff --git a/project/frontend/src/components/HighlightOverlay.tsx b/project/frontend/src/components/HighlightOverlay.tsx
new file mode 100644
index 0000000..2f30aa5
--- /dev/null
+++ b/project/frontend/src/components/HighlightOverlay.tsx
@@ -0,0 +1,30 @@
+import { Box } from '@mui/material';
+
+type Props = {
+ x: number;
+ y: number;
+ width: number;
+ height: number;
+ type: 'all' | 'selected';
+};
+
+// Eine farbige Box, die über dem PDF angezeigt wird
+export default function HighlightOverlay({ x, y, width, height, type }: Props) {
+ return (
+
+ );
+}
diff --git a/project/frontend/src/components/KennzahlenTable.tsx b/project/frontend/src/components/KennzahlenTable.tsx
index 420ed8f..4d20e22 100644
--- a/project/frontend/src/components/KennzahlenTable.tsx
+++ b/project/frontend/src/components/KennzahlenTable.tsx
@@ -8,6 +8,7 @@ import {
import SearchIcon from '@mui/icons-material/Search';
import EditIcon from '@mui/icons-material/Edit';
import { useState } from 'react';
+ import { Dispatch, SetStateAction } from 'react';
// Beispiel-Daten
@@ -19,7 +20,12 @@ import {
];
// React-Komponente
- export default function KennzahlenTable() {
+
+ type Props = {
+ setSelectedLabel: Dispatch>;
+ };
+ export default function KennzahlenTable({ setSelectedLabel }: Props) {
+
// Zustand für bearbeitbare Daten
const [rows, setRows] = useState(exampleData);
@@ -67,7 +73,13 @@ import {
else if (row.status === 'warning') borderColor = '#f6ed48';
return (
-
+ setSelectedLabel(row.label)}
+ hover
+ sx={{ cursor: 'pointer' }}
+ >
+
{/* Kennzahl */}
{row.label}
diff --git a/project/frontend/src/components/highlightData.ts b/project/frontend/src/components/highlightData.ts
new file mode 100644
index 0000000..536a633
--- /dev/null
+++ b/project/frontend/src/components/highlightData.ts
@@ -0,0 +1,21 @@
+// Beispielhafte Highlight-Daten mit Labels
+export const highlightData = [
+ {
+ label: 'Risikoprofil',
+ page: 1,
+ x: 100,
+ y: 200,
+ width: 120,
+ height: 20,
+ type: 'all', // gelb
+ },
+ {
+ label: 'Risikoprofil',
+ page: 1,
+ x: 100,
+ y: 300,
+ width: 140,
+ height: 25,
+ type: 'selected', // orange (nur wenn ausgewählt)
+ }
+];
diff --git a/project/frontend/src/components/pdfViewer.tsx b/project/frontend/src/components/pdfViewer.tsx
index 2e8f7d1..bc7ced8 100644
--- a/project/frontend/src/components/pdfViewer.tsx
+++ b/project/frontend/src/components/pdfViewer.tsx
@@ -6,13 +6,22 @@ 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';
+import HighlightOverlay from './HighlightOverlay';
+import { highlightData } from './highlightData';
+
+
+
pdfjs.GlobalWorkerOptions.workerSrc = new URL(
"pdfjs-dist/build/pdf.worker.min.mjs",
import.meta.url,
).toString();
-export default function PDFViewer() {
+type Props = {
+ selectedLabel: string | null;
+ };
+
+ export default function PDFViewer({ selectedLabel }: Props) {
const [numPages, setNumPages] = useState(null);
const [pageNumber, setPageNumber] = useState(1);
const [containerWidth, setContainerWidth] = useState(null);
@@ -56,17 +65,34 @@ export default function PDFViewer() {
alignItems: 'center',
}}
>
- console.error('Es gab ein Fehler beim Laden des PDFs:', error)}
- onSourceError={(error) => console.error('Ungültige PDF:', error)}>
- {containerWidth && (
- console.error('Fehler beim Laden:', error)}
+ onSourceError={(error) => console.error('Ungültige PDF:', error)}
+ >
+ {containerWidth && (
+
+
+
+ {/* Highlights einfügen */}
+ {highlightData
+ .filter((h) => h.page === pageNumber)
+ .map((h, idx) => (
+
- )}
+
+ ))}
+
+ )}
+
(null);
const navigate = useNavigate();
const status: 'green' | 'yellow' | 'red' = 'red';
@@ -57,7 +59,8 @@ function ExtractedResultsPage() {
overflow: 'auto', // Scrollen falls Tabelle zu lang
}}
>
-
+
+
-
+
)}
--
2.43.0
From 9ac2ff22263da6cdcea2e4c42cffeeb87fa97bbe Mon Sep 17 00:00:00 2001
From: Abdulraahman Dabbagh <1924466@stud.hs-mannheim.de>
Date: Wed, 4 Jun 2025 22:46:36 +0200
Subject: [PATCH 3/5] Fix: Mergekonflikt bereinigt & Wort-Highlighting im PDF
integriert
---
project/frontend/src/components/pdfViewer.tsx | 309 +++++++-----------
1 file changed, 110 insertions(+), 199 deletions(-)
diff --git a/project/frontend/src/components/pdfViewer.tsx b/project/frontend/src/components/pdfViewer.tsx
index b524c68..b1069fb 100644
--- a/project/frontend/src/components/pdfViewer.tsx
+++ b/project/frontend/src/components/pdfViewer.tsx
@@ -1,220 +1,131 @@
-<<<<<<< HEAD
+import { useEffect, useRef, useState, useCallback } from "react";
import { Document, Page, pdfjs } from "react-pdf";
-import { useState, useRef, useEffect, useCallback } 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();
-
-type Props = {
- selectedLabel: string | null;
- };
-
- export default function PDFViewer({ selectedLabel }: Props) {
- const [numPages, setNumPages] = useState(null);
- const [pageNumber, setPageNumber] = useState(1);
- const [containerWidth, setContainerWidth] = useState(null);
-=======
-import { useEffect, useRef, useState } from "react";
-import { Document, Page } from "react-pdf";
import "react-pdf/dist/esm/Page/AnnotationLayer.css";
import "react-pdf/dist/esm/Page/TextLayer.css";
import ArrowCircleLeftIcon from "@mui/icons-material/ArrowCircleLeft";
import ArrowCircleRightIcon from "@mui/icons-material/ArrowCircleRight";
import { Box, IconButton } from "@mui/material";
+pdfjs.GlobalWorkerOptions.workerSrc = new URL(
+ "pdfjs-dist/build/pdf.worker.min.mjs",
+ import.meta.url
+).toString();
+
interface PDFViewerProps {
- pitchBookId: string;
+ pitchBookId: string;
+ currentPage?: number;
}
-export default function PDFViewer({ pitchBookId }: PDFViewerProps) {
- const [numPages, setNumPages] = useState(null);
- const [pageNumber, setPageNumber] = useState(1);
- const [containerWidth, setContainerWidth] = useState(null);
- const containerRef = useRef(null);
- const onDocumentLoadSuccess = ({ numPages }: { numPages: number }) => {
- setNumPages(numPages);
- };
->>>>>>> origin/main
+export default function PDFViewer({ pitchBookId, currentPage }: PDFViewerProps) {
+ const [numPages, setNumPages] = useState(null);
+ const [pageNumber, setPageNumber] = useState(currentPage || 1);
+ const [containerWidth, setContainerWidth] = useState(null);
+ const containerRef = useRef(null);
- useEffect(() => {
- const updateWidth = () => {
- if (containerRef.current) {
- setContainerWidth(containerRef.current.offsetWidth);
- }
- };
+ const [highlightLabels, setHighlightLabels] = useState([]);
- updateWidth();
- window.addEventListener("resize", updateWidth);
- return () => window.removeEventListener("resize", updateWidth);
- }, []);
+ const onDocumentLoadSuccess = ({ numPages }: { numPages: number }) => {
+ setNumPages(numPages);
+ };
-<<<<<<< HEAD
- const [highlightLabels, setHighlightLabels] = useState([]);
+ // Aktuelle Containergröße berechnen
+ useEffect(() => {
+ const updateWidth = () => {
+ if (containerRef.current) {
+ setContainerWidth(containerRef.current.offsetWidth);
+ }
+ };
+ updateWidth();
+ window.addEventListener("resize", updateWidth);
+ return () => window.removeEventListener("resize", updateWidth);
+ }, []);
- // Funktion zum Einfärben von Text
- function highlightPattern(text: string, patterns: string[]) {
- for (const word of patterns) {
- const regex = new RegExp(`(${word})`, 'gi');
- text = text.replace(regex, '$1');
- }
- return text;
+ // Seite ändern, wenn prop sich ändert
+ useEffect(() => {
+ if (currentPage && currentPage !== pageNumber) {
+ setPageNumber(currentPage);
}
+ }, [currentPage]);
- // TextRenderer für PDF
- const textRenderer = useCallback(
+ // Highlight-Logik
+ useEffect(() => {
+ setHighlightLabels(["LTV", "Fondsmanager", "Risikoprofil"]);
+ }, []);
+
+ function highlightPattern(text: string, patterns: string[]) {
+ for (const word of patterns) {
+ const regex = new RegExp(`(${word})`, "gi");
+ text = text.replace(regex, "$1");
+ }
+ return text;
+ }
+
+ const textRenderer = useCallback(
(textItem: { str: string }) => highlightPattern(textItem.str, highlightLabels),
[highlightLabels]
- );
+ );
- // Beispielanzatz zum Einfärben von Text
- useEffect(() => {
- setHighlightLabels(['LTV']);
- }, []);
-
-
- useEffect(() => {
- const updateWidth = () => {
- if (containerRef.current) {
- setContainerWidth(containerRef.current.offsetWidth);
- }
- };
-
- updateWidth();
- window.addEventListener('resize', updateWidth);
- return () => window.removeEventListener('resize', updateWidth);
- }, []);
-
- return (
-
+
+
+ console.error("Es gab ein Fehler beim Laden des PDFs:", error)
+ }
+ onSourceError={(error) => console.error("Ungültige PDF:", error)}
>
-
- console.error('Fehler beim Laden:', error)}
- onSourceError={(error) => console.error('Ungültige PDF:', error)}
- >
- {containerWidth && (
-
-
-
-
- )}
-
-
-
-
- setPageNumber(p => p - 1)}>
-
-
- {pageNumber} / {numPages}
- = (numPages || 1)}
- onClick={() => setPageNumber(p => p + 1)}
- >
-
-
-
-
- );
+ {containerWidth && (
+
+ )}
+
+
+
+ setPageNumber((p) => p - 1)}
+ >
+
+
+
+ {pageNumber} / {numPages}
+
+ = (numPages || 1)}
+ onClick={() => setPageNumber((p) => p + 1)}
+ >
+
+
+
+
+ );
}
-=======
- return (
-
-
-
- console.error("Es gab ein Fehler beim Laden des PDFs:", error)
- }
- onSourceError={(error) => console.error("Ungültige PDF:", error)}
- >
- {containerWidth && (
-
- )}
-
-
-
- setPageNumber((p) => p - 1)}
- >
-
-
-
- {pageNumber} / {numPages}
-
- = (numPages || 1)}
- onClick={() => setPageNumber((p) => p + 1)}
- >
-
-
-
-
- );
-}
->>>>>>> origin/main
--
2.43.0
From 08eb77d9d7d7d52f37dde8aa3fe20915b3883d96 Mon Sep 17 00:00:00 2001
From: Abdulraahman Dabbagh <1924466@stud.hs-mannheim.de>
Date: Wed, 4 Jun 2025 23:09:30 +0200
Subject: [PATCH 4/5] Fix: Mergekonflikt in pdfViewer.tsx bereinigt HOFFENTLICH
---
project/frontend/src/components/pdfViewer.tsx | 34 ++++++++-----------
1 file changed, 15 insertions(+), 19 deletions(-)
diff --git a/project/frontend/src/components/pdfViewer.tsx b/project/frontend/src/components/pdfViewer.tsx
index b1069fb..d872aa4 100644
--- a/project/frontend/src/components/pdfViewer.tsx
+++ b/project/frontend/src/components/pdfViewer.tsx
@@ -2,9 +2,9 @@ import { useEffect, useRef, useState, useCallback } from "react";
import { Document, Page, pdfjs } from "react-pdf";
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 { Box, IconButton } from "@mui/material";
pdfjs.GlobalWorkerOptions.workerSrc = new URL(
"pdfjs-dist/build/pdf.worker.min.mjs",
@@ -20,34 +20,28 @@ export default function PDFViewer({ pitchBookId, currentPage }: PDFViewerProps)
const [numPages, setNumPages] = useState(null);
const [pageNumber, setPageNumber] = useState(currentPage || 1);
const [containerWidth, setContainerWidth] = useState(null);
- const containerRef = useRef(null);
-
const [highlightLabels, setHighlightLabels] = useState([]);
+ const containerRef = useRef(null);
+
const onDocumentLoadSuccess = ({ numPages }: { numPages: number }) => {
setNumPages(numPages);
};
- // Aktuelle Containergröße berechnen
+ // Update PDF width on resize
useEffect(() => {
const updateWidth = () => {
if (containerRef.current) {
setContainerWidth(containerRef.current.offsetWidth);
}
};
+
updateWidth();
window.addEventListener("resize", updateWidth);
return () => window.removeEventListener("resize", updateWidth);
}, []);
- // Seite ändern, wenn prop sich ändert
- useEffect(() => {
- if (currentPage && currentPage !== pageNumber) {
- setPageNumber(currentPage);
- }
- }, [currentPage]);
-
- // Highlight-Logik
+ // Highlight search logic
useEffect(() => {
setHighlightLabels(["LTV", "Fondsmanager", "Risikoprofil"]);
}, []);
@@ -65,6 +59,13 @@ export default function PDFViewer({ pitchBookId, currentPage }: PDFViewerProps)
[highlightLabels]
);
+ // Update page if prop changes
+ useEffect(() => {
+ if (currentPage && currentPage !== pageNumber) {
+ setPageNumber(currentPage);
+ }
+ }, [currentPage]);
+
return (
- console.error("Es gab ein Fehler beim Laden des PDFs:", error)
- }
+ onLoadError={(error) => console.error("Fehler beim Laden:", error)}
onSourceError={(error) => console.error("Ungültige PDF:", error)}
>
{containerWidth && (
@@ -110,10 +109,7 @@ export default function PDFViewer({ pitchBookId, currentPage }: PDFViewerProps)
justifyContent="center"
gap={1}
>
- setPageNumber((p) => p - 1)}
- >
+ setPageNumber((p) => p - 1)}>
--
2.43.0
From 053922f8a2d7e74f063be11c4637a9a691770adf Mon Sep 17 00:00:00 2001
From: s8613
Date: Thu, 5 Jun 2025 12:59:29 +0200
Subject: [PATCH 5/5] deleted file
---
.../frontend/src/routes/extractedResult.tsx | 106 ------------------
1 file changed, 106 deletions(-)
delete mode 100644 project/frontend/src/routes/extractedResult.tsx
diff --git a/project/frontend/src/routes/extractedResult.tsx b/project/frontend/src/routes/extractedResult.tsx
deleted file mode 100644
index abf86eb..0000000
--- a/project/frontend/src/routes/extractedResult.tsx
+++ /dev/null
@@ -1,106 +0,0 @@
-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';
-import KennzahlenTable from "../components/KennzahlenTable";
-import { useState } from 'react';
-
-
-export const Route = createFileRoute('/extractedResult')({
- component: ExtractedResultsPage,
-});
-
-function ExtractedResultsPage() {
- const [selectedLabel, setSelectedLabel] = useState(null);
- const navigate = useNavigate();
- const status: 'green' | 'yellow' | 'red' = 'red';
-
- const statusColor = {
- red: '#f43131',
- yellow: '#f6ed48',
- green: '#3fd942',
- }[status];
-
- return (
-
-
-
-
- Kennzahlen extrahiert aus:
FONDSNAME: TODO
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
\ No newline at end of file
--
2.43.0