import ArrowBackIcon from "@mui/icons-material/ArrowBack"; import EditIcon from "@mui/icons-material/Edit"; import { Box, Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, IconButton, Link, Paper, Radio, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TextField, Typography, } from "@mui/material"; import { useMutation, useQueryClient, useSuspenseQuery, } from "@tanstack/react-query"; import { createFileRoute, useNavigate } from "@tanstack/react-router"; import { useEffect, useState, type KeyboardEvent } from "react"; import PDFViewer from "../components/pdfViewer"; import { fetchPutKPI } from "../util/api"; import { kpiQueryOptions } from "../util/query"; import { redirect } from "@tanstack/react-router"; export const Route = createFileRoute("/extractedResult_/$pitchBook/$kpi")({ component: ExtractedResultsPage, validateSearch: (search: Record) => { return { from: typeof search.from === "string" ? search.from : undefined, }; }, loader: async ({ context: { queryClient }, params: { pitchBook } }) => { try { return await queryClient.ensureQueryData(kpiQueryOptions(pitchBook)); } catch (err) { throw redirect({ to: "/" }); } }, }); function ExtractedResultsPage() { const params = Route.useParams() as { pitchBook: string; kpi: string }; const { pitchBook, kpi } = params; const navigate = useNavigate(); const queryClient = useQueryClient(); const { from } = Route.useSearch(); const { data: kpiData } = useSuspenseQuery(kpiQueryOptions(pitchBook)); const kpiValues = kpiData[kpi.toUpperCase()] || []; const [selectedIndex, setSelectedIndex] = useState(0); const [currentPage, setCurrentPage] = useState(kpiValues[0]?.page || 1); const [showConfirmDialog, setShowConfirmDialog] = useState(false); const [hasChanges, setHasChanges] = useState(false); const [customValue, setCustomValue] = useState(""); const [customPage, setCustomPage] = useState(""); const [editingCustomPage, setEditingCustomPage] = useState(false); const originalValue = kpiValues[0]?.entity || ""; const originalPage = kpiValues[0]?.page || 0; function groupKpiValues(values: Array<{ entity: string; page: number; [key: string]: any }>): Array<{ entity: string; pages: number[]; [key: string]: any }> { const map = new Map(); values.forEach((item: { entity: string; page: number; [key: string]: any }) => { const key = item.entity.toLowerCase(); if (!map.has(key)) { map.set(key, { ...item, pages: [item.page] }); } else { const existingEntry = map.get(key)!; if (!existingEntry.pages.includes(item.page)) { existingEntry.pages.push(item.page); } } }); return Array.from(map.values()); } const groupedKpiValues: Array<{ entity: string; pages: number[]; [key: string]: any }> = groupKpiValues(kpiValues); const selectedValue: string = selectedIndex === -1 ? customValue : groupedKpiValues[selectedIndex]?.entity || ""; const selectedPage = selectedIndex === -1 ? (parseInt(customPage) > 0 ? parseInt(customPage) : 1) : groupedKpiValues[selectedIndex]?.pages[0] || 1; const isSelectedValueEmpty = selectedIndex === -1 ? customValue.trim() === "" : !selectedValue; useEffect(() => { const valueChanged = selectedValue !== originalValue; const pageChanged = selectedPage !== originalPage; setHasChanges(valueChanged || pageChanged); }, [selectedValue, selectedPage, originalValue, originalPage]); const { mutate: updateKPI } = useMutation({ mutationFn: () => { const updatedData = { ...kpiData }; let baseObject; if (selectedIndex >= 0) { const original = kpiValues.find(v => v.entity.toLowerCase() === groupedKpiValues[selectedIndex].entity.toLowerCase()) as { status?: string; source?: string } | undefined; baseObject = { label: kpi.toUpperCase(), entity: groupedKpiValues[selectedIndex].entity, page: groupedKpiValues[selectedIndex].pages[0], status: original?.status || "single-source", source: original?.source || "auto", }; } else { baseObject = { label: kpi.toUpperCase(), entity: selectedValue, page: selectedPage, status: "single-source", source: "manual", }; } updatedData[kpi.toUpperCase()] = [ { ...baseObject, entity: selectedValue, page: selectedPage, }, ]; return fetchPutKPI(Number(pitchBook), updatedData); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["pitchBookKPI", pitchBook], }); navigate({ to: "/extractedResult/$pitchBook", params: { pitchBook }, search: from ? { from } : undefined }); }, onError: (error) => { console.error("Error updating KPI:", error); }, }); const handleRadioChange = (event: React.ChangeEvent) => { const value = event.target.value; if (value === "custom") { setSelectedIndex(-1); } else { const index = Number.parseInt(value); setSelectedIndex(index); setCurrentPage(groupedKpiValues[index].pages[0]); setCustomValue(""); setCustomPage(""); } }; const handleCustomValueChange = ( event: React.ChangeEvent, ) => { const value = event.target.value; setCustomValue(value); setSelectedIndex(-1); }; const handleCustomPageChange = ( event: React.ChangeEvent, ) => { const value = event.target.value; if (value === '' || (/^\d+$/.test(value) && parseInt(value) > 0)) { setCustomPage(value); } }; const handleRowClick = (index: number) => { setCurrentPage(groupedKpiValues[index].pages[0]); setSelectedIndex(index); setCustomValue(""); setCustomPage(""); }; const handleBackClick = () => { if (hasChanges) { setShowConfirmDialog(true); } else { navigate({ to: "/extractedResult/$pitchBook", params: { pitchBook }, search: from ? { from } : undefined }); } }; const handleConfirmDiscard = () => { setShowConfirmDialog(false); navigate({ to: "/extractedResult/$pitchBook", params: { pitchBook }, search: from ? { from } : undefined }); }; const handleCancelDiscard = () => { setShowConfirmDialog(false); }; const handleAcceptReview = () => { updateKPI(); }; const startCustomPageEditing = () => { setEditingCustomPage(true); }; const handleCustomPageKeyPress = (e: KeyboardEvent) => { if (e.key === "Enter" || e.key === "Escape") { setEditingCustomPage(false); } }; return ( Überprüfung der Kennzahl: {kpi} Gefundene Werte Seiten {groupedKpiValues.map((item, index) => ( handleRowClick(index)} > {item.entity} {item.pages.map((page: number, i: number) => ( { e.stopPropagation(); setCurrentPage(page); }} sx={{ cursor: "pointer", ml: i > 0 ? 1 : 0 }} > {page} ))} ))} { setSelectedIndex(-1); }} > { e.stopPropagation(); }} error={selectedIndex === -1 && customValue !== "" && customValue.trim() === ""} helperText={selectedIndex === -1 && customValue !== "" && customValue.trim() === "" ? "Der Wert, der angegeben wurde, ist leer." : ""} /> {editingCustomPage ? ( setEditingCustomPage(false)} autoFocus size="small" variant="standard" sx={{ width: "60px", "& .MuiInput-input": { textAlign: "center" } }} inputProps={{ min: 0, style: { textAlign: 'center' } }} /> ) : ( { e.stopPropagation(); startCustomPageEditing(); }} > {customPage || "..."} { e.stopPropagation(); startCustomPageEditing(); }} /> )}
k.pages.map((page: number) => ({ page, text: k.entity }))) .reduce((acc, val) => acc.concat(val), [])} focusHighlight={{ page: groupedKpiValues.at(selectedIndex)?.pages[0] || -1, text: groupedKpiValues.at(selectedIndex)?.entity || "", }} />
Achtung Alle vorgenommenen Änderungen werden verworfen.
); }