Compare commits
No commits in common. "6816e1a2d753821ee16ffcc3dab996df61df2808" and "c01fbca5c9ac078f0fe0552c243c18a4126149a2" have entirely different histories.
6816e1a2d7
...
c01fbca5c9
|
|
@ -46,39 +46,21 @@ export default function KennzahlenTable({
|
||||||
}: KennzahlenTableProps) {
|
}: KennzahlenTableProps) {
|
||||||
const [editingIndex, setEditingIndex] = useState<string>("");
|
const [editingIndex, setEditingIndex] = useState<string>("");
|
||||||
const [editValue, setEditValue] = useState("");
|
const [editValue, setEditValue] = useState("");
|
||||||
const [editingPageIndex, setEditingPageIndex] = useState<string>("");
|
|
||||||
const [editPageValue, setEditPageValue] = useState("");
|
|
||||||
const [hoveredPageIndex, setHoveredPageIndex] = useState<string>("");
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
const { mutate } = useMutation({
|
const { mutate } = useMutation({
|
||||||
mutationFn: (params: { id: string; newValue?: string; newPage?: number }) => {
|
mutationFn: (id: string) => {
|
||||||
const { id, newValue, newPage } = params;
|
|
||||||
const key = id.toUpperCase();
|
const key = id.toUpperCase();
|
||||||
const updatedData = { ...data };
|
const updatedData = { ...data };
|
||||||
|
updatedData[key] = data[key]?.map((item) => ({
|
||||||
if (data[key] && data[key].length > 0) {
|
...item,
|
||||||
updatedData[key] = data[key].map((item) => ({
|
entity: editValue,
|
||||||
...item,
|
})) || [{ label: key, entity: editValue }];
|
||||||
...(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);
|
return fetchPutKPI(Number(pdfId), updatedData);
|
||||||
},
|
},
|
||||||
onMutate: async (params: { id: string; newValue?: string; newPage?: number }) => {
|
onMutate: async (id: string) => {
|
||||||
const { id, newValue, newPage } = params;
|
|
||||||
await queryClient.cancelQueries({
|
await queryClient.cancelQueries({
|
||||||
queryKey: ["pitchBookKPI", pdfId],
|
queryKey: ["pitchBookKPI", pdfId],
|
||||||
});
|
});
|
||||||
|
|
@ -89,23 +71,10 @@ export default function KennzahlenTable({
|
||||||
|
|
||||||
queryClient.setQueryData(["pitchBookKPI", pdfId], () => {
|
queryClient.setQueryData(["pitchBookKPI", pdfId], () => {
|
||||||
const updatedData = { ...data };
|
const updatedData = { ...data };
|
||||||
|
updatedData[key] = data[key]?.map((item) => ({
|
||||||
if (data[key] && data[key].length > 0) {
|
...item,
|
||||||
updatedData[key] = data[key].map((item) => ({
|
entity: editValue,
|
||||||
...item,
|
})) || [{ label: key, entity: editValue }];
|
||||||
...(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 updatedData;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -130,39 +99,19 @@ export default function KennzahlenTable({
|
||||||
setEditValue(value);
|
setEditValue(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const startPageEditing = (value: number, index: string) => {
|
|
||||||
setEditingPageIndex(index);
|
|
||||||
setEditPageValue(value.toString());
|
|
||||||
};
|
|
||||||
|
|
||||||
// Bearbeitung beenden und Wert speichern
|
// Bearbeitung beenden und Wert speichern
|
||||||
const handleSave = async (index: string) => {
|
const handleSave = async (index: string) => {
|
||||||
mutate({ id: index, newValue: editValue });
|
// await updateKennzahl(rows[index].label, editValue);
|
||||||
|
mutate(index);
|
||||||
setEditingIndex("");
|
setEditingIndex("");
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePageSave = async (index: string) => {
|
|
||||||
const pageNumber = parseInt(editPageValue);
|
|
||||||
if (!isNaN(pageNumber) && pageNumber > 0) {
|
|
||||||
mutate({ id: index, newPage: pageNumber });
|
|
||||||
}
|
|
||||||
setEditingPageIndex("");
|
|
||||||
};
|
|
||||||
|
|
||||||
// Tastatureingaben verarbeiten
|
// Tastatureingaben verarbeiten
|
||||||
const handleKeyPress = (e: KeyboardEvent<HTMLDivElement>, index: string) => {
|
const handleKeyPress = (e: KeyboardEvent<HTMLDivElement>, index: string) => {
|
||||||
if (e.key === "Enter") {
|
if (e.key === "Enter") {
|
||||||
handleSave(index);
|
handleSave(index);
|
||||||
} else if (e.key === "Escape") {
|
} else if (e.key === "Escape") {
|
||||||
setEditingIndex("");
|
setEditingIndex("null");
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handlePageKeyPress = (e: KeyboardEvent<HTMLDivElement>, index: string) => {
|
|
||||||
if (e.key === "Enter") {
|
|
||||||
handlePageSave(index);
|
|
||||||
} else if (e.key === "Escape") {
|
|
||||||
setEditingPageIndex("");
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -189,9 +138,7 @@ export default function KennzahlenTable({
|
||||||
<strong>Wert</strong>
|
<strong>Wert</strong>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell align="center">
|
<TableCell align="center">
|
||||||
<Box sx={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 1 }}>
|
<strong>Seite</strong>
|
||||||
<strong>Seite</strong>
|
|
||||||
</Box>
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
|
|
@ -218,10 +165,6 @@ export default function KennzahlenTable({
|
||||||
borderColor = "#f6ed48";
|
borderColor = "#f6ed48";
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentPage = row.extractedValues.at(0)?.page ?? 0;
|
|
||||||
const isPageHovered = hoveredPageIndex === row.setting.name;
|
|
||||||
const canEditPage = !hasMultipleValues;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableRow key={row.setting.name}>
|
<TableRow key={row.setting.name}>
|
||||||
<TableCell>{row.setting.name}</TableCell>
|
<TableCell>{row.setting.name}</TableCell>
|
||||||
|
|
@ -357,115 +300,21 @@ export default function KennzahlenTable({
|
||||||
)}
|
)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell align="center">
|
<TableCell align="center">
|
||||||
{editingPageIndex === row.setting.name ? (
|
{(row.extractedValues.at(0)?.page ?? 0) > 0 ? (
|
||||||
<TextField
|
<Link
|
||||||
value={editPageValue}
|
component="button"
|
||||||
onChange={(e) => {
|
onClick={() => {
|
||||||
const value = e.target.value;
|
const extractedValue = row.extractedValues.at(0);
|
||||||
if (value === '' || /^\d+$/.test(value) && parseInt(value) > 0) {
|
if (extractedValue?.page && extractedValue.page > 0) {
|
||||||
setEditPageValue(value);
|
onPageClick?.(Number(extractedValue.page), extractedValue.entity || "");
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onKeyDown={(e) => handlePageKeyPress(e, row.setting.name)}
|
sx={{ cursor: "pointer" }}
|
||||||
onBlur={() => handlePageSave(row.setting.name)}
|
>
|
||||||
autoFocus
|
{row.extractedValues.at(0)?.page}
|
||||||
size="small"
|
</Link>
|
||||||
variant="standard"
|
|
||||||
sx={{
|
|
||||||
width: "60px",
|
|
||||||
"& .MuiInput-input": {
|
|
||||||
textAlign: "center"
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
inputProps={{
|
|
||||||
min: 0,
|
|
||||||
style: { textAlign: 'center' }
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : (
|
) : (
|
||||||
<>
|
""
|
||||||
{currentPage > 0 ? (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
position: "relative",
|
|
||||||
cursor: canEditPage ? "pointer" : "default",
|
|
||||||
borderRadius: "4px",
|
|
||||||
minHeight: "32px",
|
|
||||||
minWidth: "100px",
|
|
||||||
transition: "all 0.2s ease",
|
|
||||||
}}
|
|
||||||
onMouseEnter={() => canEditPage && setHoveredPageIndex(row.setting.name)}
|
|
||||||
onMouseLeave={() => setHoveredPageIndex("")}
|
|
||||||
onClick={() => {
|
|
||||||
if (canEditPage) {
|
|
||||||
startPageEditing(currentPage, row.setting.name);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Link
|
|
||||||
component="button"
|
|
||||||
onClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
const extractedValue = row.extractedValues.at(0);
|
|
||||||
if (extractedValue?.page && extractedValue.page > 0) {
|
|
||||||
onPageClick?.(Number(extractedValue.page), extractedValue.entity || "");
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
sx={{ cursor: "pointer" }}
|
|
||||||
>
|
|
||||||
{currentPage}
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
{isPageHovered && canEditPage && (
|
|
||||||
<EditIcon
|
|
||||||
fontSize="small"
|
|
||||||
sx={{
|
|
||||||
position: "absolute",
|
|
||||||
left: "70px",
|
|
||||||
color: "#666",
|
|
||||||
opacity: 0.7,
|
|
||||||
transition: "opacity 0.2s ease",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
) : canEditPage ? (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
position: "relative",
|
|
||||||
cursor: "pointer",
|
|
||||||
minHeight: "32px",
|
|
||||||
minWidth: "100px",
|
|
||||||
borderRadius: "4px",
|
|
||||||
backgroundColor: isPageHovered ? "#f8f9fa" : "transparent",
|
|
||||||
}}
|
|
||||||
onMouseEnter={() => setHoveredPageIndex(row.setting.name)}
|
|
||||||
onMouseLeave={() => setHoveredPageIndex("")}
|
|
||||||
onClick={() => startPageEditing(0, row.setting.name)}
|
|
||||||
>
|
|
||||||
<span style={{ color: "#999" }}>...</span>
|
|
||||||
<EditIcon
|
|
||||||
fontSize="small"
|
|
||||||
sx={{
|
|
||||||
position: "absolute",
|
|
||||||
left: "70px",
|
|
||||||
color: "#555",
|
|
||||||
cursor: "pointer",
|
|
||||||
opacity: 0.7,
|
|
||||||
transition: "opacity 0.2s ease",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
) : (
|
|
||||||
""
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
@ -475,4 +324,4 @@ export default function KennzahlenTable({
|
||||||
</Table>
|
</Table>
|
||||||
</TableContainer>
|
</TableContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
|
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
|
||||||
import EditIcon from "@mui/icons-material/Edit";
|
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
|
|
@ -28,7 +27,6 @@ import {
|
||||||
} from "@tanstack/react-query";
|
} from "@tanstack/react-query";
|
||||||
import { createFileRoute, useNavigate } from "@tanstack/react-router";
|
import { createFileRoute, useNavigate } from "@tanstack/react-router";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import type { KeyboardEvent } from "react";
|
|
||||||
import PDFViewer from "../components/pdfViewer";
|
import PDFViewer from "../components/pdfViewer";
|
||||||
import { fetchPutKPI } from "../util/api";
|
import { fetchPutKPI } from "../util/api";
|
||||||
import { kpiQueryOptions } from "../util/query";
|
import { kpiQueryOptions } from "../util/query";
|
||||||
|
|
@ -67,23 +65,13 @@ function ExtractedResultsPage() {
|
||||||
const [showConfirmDialog, setShowConfirmDialog] = useState(false);
|
const [showConfirmDialog, setShowConfirmDialog] = useState(false);
|
||||||
const [hasChanges, setHasChanges] = useState(false);
|
const [hasChanges, setHasChanges] = useState(false);
|
||||||
const [customValue, setCustomValue] = useState("");
|
const [customValue, setCustomValue] = useState("");
|
||||||
const [customPage, setCustomPage] = useState("");
|
|
||||||
const [editingCustomPage, setEditingCustomPage] = useState(false);
|
|
||||||
|
|
||||||
const originalValue = kpiValues[0]?.entity || "";
|
const originalValue = kpiValues[0]?.entity || "";
|
||||||
const originalPage = kpiValues[0]?.page || 0;
|
|
||||||
const selectedValue =
|
const selectedValue =
|
||||||
selectedIndex === -1 ? customValue : kpiValues[selectedIndex]?.entity || "";
|
selectedIndex === -1 ? customValue : kpiValues[selectedIndex]?.entity || "";
|
||||||
const selectedPage =
|
|
||||||
selectedIndex === -1
|
|
||||||
? (parseInt(customPage) > 0 ? parseInt(customPage) : 1)
|
|
||||||
: kpiValues[selectedIndex]?.page || 1;
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const valueChanged = selectedValue !== originalValue;
|
setHasChanges(selectedValue !== originalValue);
|
||||||
const pageChanged = selectedPage !== originalPage;
|
}, [selectedValue, originalValue]);
|
||||||
setHasChanges(valueChanged || pageChanged);
|
|
||||||
}, [selectedValue, selectedPage, originalValue, originalPage]);
|
|
||||||
|
|
||||||
const { mutate: updateKPI } = useMutation({
|
const { mutate: updateKPI } = useMutation({
|
||||||
mutationFn: () => {
|
mutationFn: () => {
|
||||||
|
|
@ -95,7 +83,7 @@ function ExtractedResultsPage() {
|
||||||
baseObject = {
|
baseObject = {
|
||||||
label: kpi.toUpperCase(),
|
label: kpi.toUpperCase(),
|
||||||
entity: selectedValue,
|
entity: selectedValue,
|
||||||
page: selectedPage,
|
page: 0,
|
||||||
status: "single-source",
|
status: "single-source",
|
||||||
source: "manual",
|
source: "manual",
|
||||||
};
|
};
|
||||||
|
|
@ -104,7 +92,6 @@ function ExtractedResultsPage() {
|
||||||
{
|
{
|
||||||
...baseObject,
|
...baseObject,
|
||||||
entity: selectedValue,
|
entity: selectedValue,
|
||||||
page: selectedPage,
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
return fetchPutKPI(Number(pitchBook), updatedData);
|
return fetchPutKPI(Number(pitchBook), updatedData);
|
||||||
|
|
@ -133,7 +120,6 @@ function ExtractedResultsPage() {
|
||||||
setSelectedIndex(index);
|
setSelectedIndex(index);
|
||||||
setCurrentPage(kpiValues[index].page);
|
setCurrentPage(kpiValues[index].page);
|
||||||
setCustomValue("");
|
setCustomValue("");
|
||||||
setCustomPage("");
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -145,21 +131,10 @@ function ExtractedResultsPage() {
|
||||||
setSelectedIndex(-1);
|
setSelectedIndex(-1);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCustomPageChange = (
|
|
||||||
event: React.ChangeEvent<HTMLInputElement>,
|
|
||||||
) => {
|
|
||||||
const value = event.target.value;
|
|
||||||
// Allow empty string or positive numbers only (no 0)
|
|
||||||
if (value === '' || (/^\d+$/.test(value) && parseInt(value) > 0)) {
|
|
||||||
setCustomPage(value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleRowClick = (index: number) => {
|
const handleRowClick = (index: number) => {
|
||||||
setCurrentPage(kpiValues[index].page);
|
setCurrentPage(kpiValues[index].page);
|
||||||
setSelectedIndex(index);
|
setSelectedIndex(index);
|
||||||
setCustomValue("");
|
setCustomValue("");
|
||||||
setCustomPage("");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleBackClick = () => {
|
const handleBackClick = () => {
|
||||||
|
|
@ -191,18 +166,6 @@ function ExtractedResultsPage() {
|
||||||
updateKPI();
|
updateKPI();
|
||||||
};
|
};
|
||||||
|
|
||||||
const startCustomPageEditing = () => {
|
|
||||||
setEditingCustomPage(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCustomPageKeyPress = (e: KeyboardEvent<HTMLDivElement>) => {
|
|
||||||
if (e.key === "Enter") {
|
|
||||||
setEditingCustomPage(false);
|
|
||||||
} else if (e.key === "Escape") {
|
|
||||||
setEditingCustomPage(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box p={4}>
|
<Box p={4}>
|
||||||
<Box sx={{ display: "flex", alignItems: "center", mb: 3 }}>
|
<Box sx={{ display: "flex", alignItems: "center", mb: 3 }}>
|
||||||
|
|
@ -355,60 +318,6 @@ function ExtractedResultsPage() {
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell align="center">
|
|
||||||
{editingCustomPage ? (
|
|
||||||
<TextField
|
|
||||||
value={customPage}
|
|
||||||
onChange={handleCustomPageChange}
|
|
||||||
onKeyDown={handleCustomPageKeyPress}
|
|
||||||
onBlur={() => setEditingCustomPage(false)}
|
|
||||||
autoFocus
|
|
||||||
size="small"
|
|
||||||
variant="standard"
|
|
||||||
sx={{
|
|
||||||
width: "60px",
|
|
||||||
"& .MuiInput-input": {
|
|
||||||
textAlign: "center"
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
inputProps={{
|
|
||||||
min: 0,
|
|
||||||
style: { textAlign: 'center' }
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
gap: 1,
|
|
||||||
cursor: "pointer",
|
|
||||||
minHeight: "24px",
|
|
||||||
minWidth: "100px",
|
|
||||||
margin: "0 auto",
|
|
||||||
}}
|
|
||||||
onClick={(e: React.MouseEvent) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
startCustomPageEditing();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span>{customPage || "..."}</span>
|
|
||||||
<EditIcon
|
|
||||||
fontSize="small"
|
|
||||||
sx={{
|
|
||||||
color: "#666",
|
|
||||||
opacity: 0.7,
|
|
||||||
transition: "opacity 0.2s ease",
|
|
||||||
}}
|
|
||||||
onClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
startCustomPageEditing();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue