186 lines
8.0 KiB
TypeScript
186 lines
8.0 KiB
TypeScript
import { Box, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Typography, CircularProgress, Chip } from "@mui/material";
|
|
import { useSuspenseQuery } from "@tanstack/react-query";
|
|
import { useNavigate } from "@tanstack/react-router";
|
|
import { pitchBooksQueryOptions } from "../util/query";
|
|
import PictureAsPdfIcon from '@mui/icons-material/PictureAsPdf';
|
|
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
|
import HourglassEmptyIcon from '@mui/icons-material/HourglassEmpty';
|
|
|
|
interface PitchBook {
|
|
id: number;
|
|
filename: string;
|
|
created_at: string;
|
|
kpi?: string | {
|
|
[key: string]: {
|
|
label: string;
|
|
entity: string;
|
|
page: number;
|
|
status: string;
|
|
source: string;
|
|
}[];
|
|
};
|
|
status?: 'processing' | 'completed';
|
|
}
|
|
|
|
export function PitchBooksTable() {
|
|
const navigate = useNavigate();
|
|
const { data: pitchBooks, isLoading } = useSuspenseQuery(pitchBooksQueryOptions());
|
|
|
|
const handleRowClick = (pitchBookId: number) => {
|
|
navigate({
|
|
to: "/extractedResult/$pitchBook",
|
|
params: { pitchBook: pitchBookId.toString() },
|
|
search: { from: "overview" }
|
|
});
|
|
};
|
|
|
|
const getKPIValue = (pitchBook: PitchBook, fieldName: string): string => {
|
|
if (!pitchBook.kpi || typeof pitchBook.kpi === 'string') {
|
|
try {
|
|
const parsedKPI = JSON.parse(pitchBook.kpi as string);
|
|
// Convert array to object format if needed
|
|
const kpiObj = Array.isArray(parsedKPI) ?
|
|
parsedKPI.reduce((acc: any, item: any) => {
|
|
if (!acc[item.label]) acc[item.label] = [];
|
|
acc[item.label].push(item);
|
|
return acc;
|
|
}, {}) : parsedKPI;
|
|
|
|
return kpiObj[fieldName]?.[0]?.entity || 'N/A';
|
|
} catch {
|
|
return 'N/A';
|
|
}
|
|
}
|
|
|
|
return (pitchBook.kpi as any)[fieldName]?.[0]?.entity || 'N/A';
|
|
};
|
|
|
|
const getStatus = (pitchBook: PitchBook) => {
|
|
if (pitchBook.kpi &&
|
|
((typeof pitchBook.kpi === 'string' && pitchBook.kpi !== '{}') ||
|
|
(typeof pitchBook.kpi === 'object' && Object.keys(pitchBook.kpi).length > 0))) {
|
|
return 'completed';
|
|
}
|
|
return 'processing';
|
|
};
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<Box display="flex" justifyContent="center" alignItems="center" height="400px">
|
|
<CircularProgress sx={{ color: "#383838" }} />
|
|
</Box>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<TableContainer
|
|
component={Paper}
|
|
sx={{
|
|
width: "85%",
|
|
maxWidth: 1200,
|
|
boxShadow: "0 2px 8px rgba(0,0,0,0.1)",
|
|
}}
|
|
>
|
|
<Table>
|
|
<TableHead>
|
|
<TableRow sx={{ backgroundColor: "#f5f5f5" }}>
|
|
<TableCell sx={{ width: "60px" }}></TableCell>
|
|
<TableCell sx={{ fontWeight: "bold" }}>Fondsname</TableCell>
|
|
<TableCell sx={{ fontWeight: "bold" }}>Fondsmanager</TableCell>
|
|
<TableCell sx={{ fontWeight: "bold" }}>Dateiname</TableCell>
|
|
<TableCell sx={{ fontWeight: "bold", width: "120px" }}>Status</TableCell>
|
|
</TableRow>
|
|
</TableHead>
|
|
<TableBody>
|
|
{pitchBooks.map((pitchBook: PitchBook) => {
|
|
const status = getStatus(pitchBook);
|
|
const fundName = getKPIValue(pitchBook, 'FONDSNAME') ||
|
|
getKPIValue(pitchBook, 'FUND_NAME') ||
|
|
getKPIValue(pitchBook, 'NAME');
|
|
|
|
const manager = getKPIValue(pitchBook, 'FONDSMANAGER') ||
|
|
getKPIValue(pitchBook, 'MANAGER') ||
|
|
getKPIValue(pitchBook, 'PORTFOLIO_MANAGER');
|
|
|
|
return (
|
|
<TableRow
|
|
key={pitchBook.id}
|
|
onClick={() => handleRowClick(pitchBook.id)}
|
|
sx={{
|
|
cursor: "pointer",
|
|
"&:hover": {
|
|
backgroundColor: "#f9f9f9",
|
|
},
|
|
}}
|
|
>
|
|
<TableCell>
|
|
<Box
|
|
sx={{
|
|
width: 40,
|
|
height: 50,
|
|
backgroundColor: "#f0f0f0",
|
|
borderRadius: 1,
|
|
display: "flex",
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
border: "1px solid #e0e0e0",
|
|
}}
|
|
>
|
|
<PictureAsPdfIcon fontSize="small" sx={{ color: "#666" }} />
|
|
</Box>
|
|
</TableCell>
|
|
<TableCell>
|
|
<Typography variant="body2" fontWeight="medium">
|
|
{fundName}
|
|
</Typography>
|
|
</TableCell>
|
|
<TableCell>{manager}</TableCell>
|
|
<TableCell>
|
|
<Typography variant="body2" color="text.secondary" fontSize="0.875rem">
|
|
{pitchBook.filename}
|
|
</Typography>
|
|
</TableCell>
|
|
<TableCell>
|
|
{status === 'completed' ? (
|
|
<Chip
|
|
icon={<CheckCircleIcon />}
|
|
label="Abgeschlossen"
|
|
size="small"
|
|
sx={{
|
|
backgroundColor: "#e8f5e9",
|
|
color: "#2e7d32",
|
|
"& .MuiChip-icon": {
|
|
color: "#2e7d32",
|
|
},
|
|
}}
|
|
/>
|
|
) : (
|
|
<Chip
|
|
icon={<HourglassEmptyIcon />}
|
|
label="In Bearbeitung"
|
|
size="small"
|
|
sx={{
|
|
backgroundColor: "#fff3e0",
|
|
color: "#e65100",
|
|
"& .MuiChip-icon": {
|
|
color: "#e65100",
|
|
},
|
|
}}
|
|
/>
|
|
)}
|
|
</TableCell>
|
|
</TableRow>
|
|
);
|
|
})}
|
|
</TableBody>
|
|
</Table>
|
|
{pitchBooks.length === 0 && (
|
|
<Box p={4} textAlign="center">
|
|
<Typography color="text.secondary">
|
|
Keine Pitch Books vorhanden
|
|
</Typography>
|
|
</Box>
|
|
)}
|
|
</TableContainer>
|
|
);
|
|
} |