import type { Kennzahl } from "@/types/kpi"; import EditIcon from "@mui/icons-material/Edit"; import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline"; import SearchIcon from "@mui/icons-material/Search"; import { Box, Link, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TextField, Tooltip, } from "@mui/material"; import { useMutation, useQueryClient } from "@tanstack/react-query"; import { useNavigate } from "@tanstack/react-router"; import { useState } from "react"; import type { KeyboardEvent } from "react"; import { fetchPutKPI } from "../util/api"; interface KennzahlenTableProps { onPageClick?: (page: number, text: string) => void; pdfId: string; settings: Kennzahl[]; data: { [key: string]: { label: string; entity: string; page: number; status: string; source: string; }[]; }; from?: string; } export default function KennzahlenTable({ onPageClick, data, pdfId, settings, from, }: KennzahlenTableProps) { const [editingIndex, setEditingIndex] = useState(""); const [editValue, setEditValue] = useState(""); const [editingPageIndex, setEditingPageIndex] = useState(""); const [editPageValue, setEditPageValue] = useState(""); const [hoveredPageIndex, setHoveredPageIndex] = useState(""); const navigate = useNavigate(); const queryClient = useQueryClient(); const { mutate } = useMutation({ mutationFn: (params: { id: string; newValue?: string; newPage?: number }) => { const { id, newValue, newPage } = params; const key = id.toUpperCase(); const updatedData = { ...data }; if (data[key] && data[key].length > 0) { updatedData[key] = data[key].map((item) => ({ ...item, ...(newValue !== undefined && { entity: newValue }), ...(newPage !== undefined && { page: newPage }), })); } else { updatedData[key] = [{ label: key, entity: newValue || "", page: newPage || 0, status: "single-source", source: "manual" }]; } return fetchPutKPI(Number(pdfId), updatedData); }, onMutate: async (params: { id: string; newValue?: string; newPage?: number }) => { const { id, newValue, newPage } = params; await queryClient.cancelQueries({ queryKey: ["pitchBookKPI", pdfId], }); const snapshot = queryClient.getQueryData(["pitchBookKPI", pdfId]); const key = id.toUpperCase(); queryClient.setQueryData(["pitchBookKPI", pdfId], () => { const updatedData = { ...data }; if (data[key] && data[key].length > 0) { updatedData[key] = data[key].map((item) => ({ ...item, ...(newValue !== undefined && { entity: newValue }), ...(newPage !== undefined && { page: newPage }), })); } else { updatedData[key] = [{ label: key, entity: newValue || "", page: newPage || 0, status: "single-source", source: "manual" }]; } return updatedData; }); return () => { queryClient.setQueryData(["pitchBookKPI", pdfId], snapshot); }; }, onError: (error, _variables, rollback) => { console.log("error", error); rollback?.(); }, onSettled: () => { return queryClient.invalidateQueries({ queryKey: ["pitchBookKPI", pdfId], }); }, }); // Bearbeitung starten const startEditing = (value: string, index: string) => { setEditingIndex(index); setEditValue(value); }; const startPageEditing = (value: number, index: string) => { setEditingPageIndex(index); setEditPageValue(value.toString()); }; // Bearbeitung beenden und Wert speichern const handleSave = async (index: string) => { mutate({ id: index, newValue: editValue }); setEditingIndex(""); }; const handlePageSave = async (index: string) => { const pageNumber = parseInt(editPageValue); if (editPageValue === "" || pageNumber === 0) { mutate({ id: index, newPage: 0 }); } else if (!isNaN(pageNumber) && pageNumber > 0) { mutate({ id: index, newPage: pageNumber }); } setEditingPageIndex(""); }; // Tastatureingaben verarbeiten const handleKeyPress = (e: KeyboardEvent, index: string) => { if (e.key === "Enter") { handleSave(index); } else if (e.key === "Escape") { setEditingIndex(""); } }; const handlePageKeyPress = (e: KeyboardEvent, index: string) => { if (e.key === "Enter") { handlePageSave(index); } else if (e.key === "Escape") { setEditingPageIndex(""); } }; const handleNavigateToDetail = (settingName: string) => { navigate({ to: "/extractedResult/$pitchBook/$kpi", params: { pitchBook: pdfId, kpi: settingName, }, search: { from: from ?? undefined }, }); }; return ( Kennzahl Wert Seite {settings .filter((setting) => setting.active) .sort((a, b) => a.position - b.position) .map((setting) => ({ setting: setting, extractedValues: data[setting.name.toUpperCase()] || [], })) .map((row) => { let borderColor = "transparent"; const hasMultipleValues = row.extractedValues.length > 1; const hasNoValue = row.setting.mandatory && (row.extractedValues.length === 0 || row.extractedValues.at(0)?.entity === ""); if (hasNoValue) { borderColor = "red"; } else if (hasMultipleValues) { borderColor = "#f6ed48"; } const currentPage = row.extractedValues.at(0)?.page ?? 0; const isPageHovered = hoveredPageIndex === row.setting.name; const canEditPage = !hasMultipleValues; return ( {row.setting.name} {row.setting.mandatory && ( * )} { // Only allow inline editing for non-multiple value cells if (!hasMultipleValues) { startEditing( row.extractedValues.at(0)?.entity || "", row.setting.name, ); } else { // Navigate to detail page for multiple values handleNavigateToDetail(row.setting.name); } }} > {hasMultipleValues ? ( Problem
Mehrere Werte für die Kennzahl gefunden. } placement="bottom" arrow > {row.extractedValues.at(0)?.entity || "—"}
) : ( Problem
Es wurden keine Kennzahlen gefunden. Bitte ergänzen! ) : ( "" ) } placement="bottom" arrow > {hasNoValue && ( )} {editingIndex === row.setting.name ? ( setEditValue(e.target.value)} onKeyDown={(e) => handleKeyPress(e, row.setting.name) } onBlur={() => handleSave(row.setting.name)} autoFocus size="small" fullWidth variant="standard" sx={{ margin: "-8px 0" }} /> ) : ( {row.extractedValues.at(0)?.entity || "—"} )} { e.stopPropagation(); startEditing( row.extractedValues.at(0)?.entity || "", row.setting.name, ); }} />
)}
{editingPageIndex === row.setting.name ? ( { const value = e.target.value; if (value === '' || /^\d+$/.test(value)) { setEditPageValue(value); } }} onKeyDown={(e) => handlePageKeyPress(e, row.setting.name)} onBlur={() => handlePageSave(row.setting.name)} autoFocus size="small" variant="standard" sx={{ width: "60px", "& .MuiInput-input": { textAlign: "center" } }} inputProps={{ min: 0, style: { textAlign: 'center' } }} /> ) : ( <> {currentPage > 0 ? ( { if (canEditPage) { startPageEditing(currentPage, row.setting.name); } }} > { e.stopPropagation(); const extractedValue = row.extractedValues.at(0); if (extractedValue?.page && extractedValue.page > 0) { onPageClick?.(Number(extractedValue.page), extractedValue.entity || ""); } }} sx={{ cursor: "pointer" }} > {currentPage} ) : canEditPage ? ( setHoveredPageIndex(row.setting.name)} onMouseLeave={() => setHoveredPageIndex("")} onClick={() => startPageEditing(0, row.setting.name)} > ... ) : ( "" )} )}
); })}
); }