Fix: Mergekonflikt bereinigt & Wort-Highlighting im PDF integriert
parent
2d88e793e0
commit
9ac2ff2226
|
|
@ -1,220 +1,131 @@
|
||||||
<<<<<<< HEAD
|
import { useEffect, useRef, useState, useCallback } from "react";
|
||||||
import { Document, Page, pdfjs } from "react-pdf";
|
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<number | null>(null);
|
|
||||||
const [pageNumber, setPageNumber] = useState(1);
|
|
||||||
const [containerWidth, setContainerWidth] = useState<number | null>(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/AnnotationLayer.css";
|
||||||
import "react-pdf/dist/esm/Page/TextLayer.css";
|
import "react-pdf/dist/esm/Page/TextLayer.css";
|
||||||
import ArrowCircleLeftIcon from "@mui/icons-material/ArrowCircleLeft";
|
import ArrowCircleLeftIcon from "@mui/icons-material/ArrowCircleLeft";
|
||||||
import ArrowCircleRightIcon from "@mui/icons-material/ArrowCircleRight";
|
import ArrowCircleRightIcon from "@mui/icons-material/ArrowCircleRight";
|
||||||
import { Box, IconButton } from "@mui/material";
|
import { Box, IconButton } from "@mui/material";
|
||||||
|
|
||||||
|
pdfjs.GlobalWorkerOptions.workerSrc = new URL(
|
||||||
|
"pdfjs-dist/build/pdf.worker.min.mjs",
|
||||||
|
import.meta.url
|
||||||
|
).toString();
|
||||||
|
|
||||||
interface PDFViewerProps {
|
interface PDFViewerProps {
|
||||||
pitchBookId: string;
|
pitchBookId: string;
|
||||||
|
currentPage?: number;
|
||||||
}
|
}
|
||||||
export default function PDFViewer({ pitchBookId }: PDFViewerProps) {
|
|
||||||
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 }) => {
|
export default function PDFViewer({ pitchBookId, currentPage }: PDFViewerProps) {
|
||||||
setNumPages(numPages);
|
const [numPages, setNumPages] = useState<number | null>(null);
|
||||||
};
|
const [pageNumber, setPageNumber] = useState(currentPage || 1);
|
||||||
>>>>>>> origin/main
|
const [containerWidth, setContainerWidth] = useState<number | null>(null);
|
||||||
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
const [highlightLabels, setHighlightLabels] = useState<string[]>([]);
|
||||||
const updateWidth = () => {
|
|
||||||
if (containerRef.current) {
|
|
||||||
setContainerWidth(containerRef.current.offsetWidth);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
updateWidth();
|
const onDocumentLoadSuccess = ({ numPages }: { numPages: number }) => {
|
||||||
window.addEventListener("resize", updateWidth);
|
setNumPages(numPages);
|
||||||
return () => window.removeEventListener("resize", updateWidth);
|
};
|
||||||
}, []);
|
|
||||||
|
|
||||||
<<<<<<< HEAD
|
// Aktuelle Containergröße berechnen
|
||||||
const [highlightLabels, setHighlightLabels] = useState<string[]>([]);
|
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
|
// Seite ändern, wenn prop sich ändert
|
||||||
function highlightPattern(text: string, patterns: string[]) {
|
useEffect(() => {
|
||||||
for (const word of patterns) {
|
if (currentPage && currentPage !== pageNumber) {
|
||||||
const regex = new RegExp(`(${word})`, 'gi');
|
setPageNumber(currentPage);
|
||||||
text = text.replace(regex, '<mark>$1</mark>');
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
}
|
}
|
||||||
|
}, [currentPage]);
|
||||||
|
|
||||||
// TextRenderer für PDF
|
// Highlight-Logik
|
||||||
const textRenderer = useCallback(
|
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, "<mark>$1</mark>");
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
const textRenderer = useCallback(
|
||||||
(textItem: { str: string }) => highlightPattern(textItem.str, highlightLabels),
|
(textItem: { str: string }) => highlightPattern(textItem.str, highlightLabels),
|
||||||
[highlightLabels]
|
[highlightLabels]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Beispielanzatz zum Einfärben von Text
|
return (
|
||||||
useEffect(() => {
|
<Box
|
||||||
setHighlightLabels(['LTV']);
|
display="flex"
|
||||||
}, []);
|
flexDirection="column"
|
||||||
|
justifyContent="center"
|
||||||
|
alignItems="center"
|
||||||
useEffect(() => {
|
width="100%"
|
||||||
const updateWidth = () => {
|
height="100%"
|
||||||
if (containerRef.current) {
|
p={2}
|
||||||
setContainerWidth(containerRef.current.offsetWidth);
|
>
|
||||||
}
|
<Box
|
||||||
};
|
ref={containerRef}
|
||||||
|
sx={{
|
||||||
updateWidth();
|
width: "100%",
|
||||||
window.addEventListener('resize', updateWidth);
|
maxHeight: "90vh",
|
||||||
return () => window.removeEventListener('resize', updateWidth);
|
overflow: "auto",
|
||||||
}, []);
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
return (
|
alignItems: "center",
|
||||||
<Box
|
}}
|
||||||
display="flex"
|
>
|
||||||
flexDirection="column"
|
<Document
|
||||||
justifyContent="center"
|
file={`http://localhost:5050/api/pitch_book/${pitchBookId}/download`}
|
||||||
alignItems="center"
|
onLoadSuccess={onDocumentLoadSuccess}
|
||||||
width="100%"
|
onLoadError={(error) =>
|
||||||
height="100%"
|
console.error("Es gab ein Fehler beim Laden des PDFs:", error)
|
||||||
p={2}
|
}
|
||||||
|
onSourceError={(error) => console.error("Ungültige PDF:", error)}
|
||||||
>
|
>
|
||||||
<Box
|
{containerWidth && (
|
||||||
ref={containerRef}
|
<Page
|
||||||
sx={{
|
pageNumber={pageNumber}
|
||||||
width: '100%',
|
width={containerWidth * 0.8}
|
||||||
maxHeight: '90vh',
|
customTextRenderer={textRenderer}
|
||||||
overflow: 'auto',
|
/>
|
||||||
display: 'flex',
|
)}
|
||||||
justifyContent: 'center',
|
</Document>
|
||||||
alignItems: 'center',
|
</Box>
|
||||||
}}
|
<Box
|
||||||
>
|
mt={2}
|
||||||
<Document
|
display="flex"
|
||||||
file={testPDF}
|
alignItems="center"
|
||||||
onLoadSuccess={onDocumentLoadSuccess}
|
justifyContent="center"
|
||||||
onLoadError={(error) => console.error('Fehler beim Laden:', error)}
|
gap={1}
|
||||||
onSourceError={(error) => console.error('Ungültige PDF:', error)}
|
>
|
||||||
>
|
<IconButton
|
||||||
{containerWidth && (
|
disabled={pageNumber <= 1}
|
||||||
<Box position="relative">
|
onClick={() => setPageNumber((p) => p - 1)}
|
||||||
<Page
|
>
|
||||||
pageNumber={pageNumber}
|
<ArrowCircleLeftIcon fontSize="large" />
|
||||||
width={containerWidth * 0.8}
|
</IconButton>
|
||||||
customTextRenderer={textRenderer}
|
<span>
|
||||||
/>
|
{pageNumber} / {numPages}
|
||||||
|
</span>
|
||||||
</Box>
|
<IconButton
|
||||||
)}
|
disabled={pageNumber >= (numPages || 1)}
|
||||||
</Document>
|
onClick={() => setPageNumber((p) => p + 1)}
|
||||||
|
>
|
||||||
</Box>
|
<ArrowCircleRightIcon fontSize="large" />
|
||||||
<Box
|
</IconButton>
|
||||||
mt={2}
|
</Box>
|
||||||
display="flex"
|
</Box>
|
||||||
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>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
=======
|
|
||||||
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={`http://localhost:5050/api/pitch_book/${pitchBookId}/download`}
|
|
||||||
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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
>>>>>>> origin/main
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue