
- Suppression du bouton 'Analyser' à côté de l'aperçu - Correction des erreurs JavaScript dans ExtractionView - Amélioration de la gestion des erreurs dans l'API - Alignement avec les endpoints du backend
288 lines
9.7 KiB
TypeScript
288 lines
9.7 KiB
TypeScript
import { useEffect } from 'react'
|
|
import {
|
|
Box,
|
|
Typography,
|
|
Paper,
|
|
Card,
|
|
CardContent,
|
|
Chip,
|
|
List,
|
|
ListItem,
|
|
ListItemText,
|
|
Alert,
|
|
CircularProgress,
|
|
} from '@mui/material'
|
|
import {
|
|
Person,
|
|
LocationOn,
|
|
Home,
|
|
Description,
|
|
Language,
|
|
Verified,
|
|
} from '@mui/icons-material'
|
|
import { useAppDispatch, useAppSelector } from '../store'
|
|
import { extractDocument } from '../store/documentSlice'
|
|
import { Layout } from '../components/Layout'
|
|
|
|
export default function ExtractionView() {
|
|
const dispatch = useAppDispatch()
|
|
const { currentDocument, extractionResult, loading } = useAppSelector(
|
|
(state) => state.document
|
|
)
|
|
|
|
useEffect(() => {
|
|
if (currentDocument && !extractionResult) {
|
|
dispatch(extractDocument(currentDocument.id))
|
|
}
|
|
}, [currentDocument, extractionResult, dispatch])
|
|
|
|
if (!currentDocument) {
|
|
return (
|
|
<Layout>
|
|
<Alert severity="info">
|
|
Veuillez d'abord téléverser et sélectionner un document.
|
|
</Alert>
|
|
</Layout>
|
|
)
|
|
}
|
|
|
|
if (loading) {
|
|
return (
|
|
<Layout>
|
|
<Box sx={{ display: 'flex', justifyContent: 'center', mt: 4 }}>
|
|
<CircularProgress />
|
|
<Typography sx={{ ml: 2 }}>Extraction en cours...</Typography>
|
|
</Box>
|
|
</Layout>
|
|
)
|
|
}
|
|
|
|
if (!extractionResult) {
|
|
return (
|
|
<Layout>
|
|
<Alert severity="warning">
|
|
Aucun résultat d'extraction disponible.
|
|
</Alert>
|
|
</Layout>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<Layout>
|
|
<Typography variant="h4" gutterBottom>
|
|
Extraction des données
|
|
</Typography>
|
|
|
|
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
|
|
{/* Informations générales */}
|
|
<Paper sx={{ p: 2 }}>
|
|
<Typography variant="h6" gutterBottom>
|
|
Informations générales
|
|
</Typography>
|
|
<Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}>
|
|
<Chip
|
|
icon={<Language />}
|
|
label={`Langue: ${extractionResult.language}`}
|
|
color="primary"
|
|
variant="outlined"
|
|
/>
|
|
<Chip
|
|
icon={<Description />}
|
|
label={`Type: ${extractionResult.documentType}`}
|
|
color="secondary"
|
|
variant="outlined"
|
|
/>
|
|
<Chip
|
|
icon={<Verified />}
|
|
label={`Confiance: ${(extractionResult.confidence * 100).toFixed(1)}%`}
|
|
color={extractionResult.confidence > 0.8 ? 'success' : 'warning'}
|
|
variant="outlined"
|
|
/>
|
|
</Box>
|
|
</Paper>
|
|
|
|
<Box sx={{ display: 'flex', gap: 3, flexWrap: 'wrap' }}>
|
|
{/* Identités */}
|
|
<Box sx={{ flex: '1 1 300px' }}>
|
|
<Card>
|
|
<CardContent>
|
|
<Typography variant="h6" gutterBottom>
|
|
<Person sx={{ mr: 1, verticalAlign: 'middle' }} />
|
|
Identités ({extractionResult.identities?.length || 0})
|
|
</Typography>
|
|
<List dense>
|
|
{(extractionResult.identities || []).map((identity, index) => (
|
|
<ListItem key={index}>
|
|
<ListItemText
|
|
primary={
|
|
identity.type === 'person'
|
|
? `${identity.firstName} ${identity.lastName}`
|
|
: identity.companyName
|
|
}
|
|
secondary={
|
|
<Box>
|
|
<Typography variant="caption" display="block">
|
|
Type: {identity.type}
|
|
</Typography>
|
|
{identity.birthDate && (
|
|
<Typography variant="caption" display="block">
|
|
Naissance: {identity.birthDate}
|
|
</Typography>
|
|
)}
|
|
{identity.nationality && (
|
|
<Typography variant="caption" display="block">
|
|
Nationalité: {identity.nationality}
|
|
</Typography>
|
|
)}
|
|
<Typography variant="caption" display="block">
|
|
Confiance: {(identity.confidence * 100).toFixed(1)}%
|
|
</Typography>
|
|
</Box>
|
|
}
|
|
/>
|
|
</ListItem>
|
|
))}
|
|
</List>
|
|
</CardContent>
|
|
</Card>
|
|
</Box>
|
|
|
|
{/* Adresses */}
|
|
<Box sx={{ flex: '1 1 300px' }}>
|
|
<Card>
|
|
<CardContent>
|
|
<Typography variant="h6" gutterBottom>
|
|
<LocationOn sx={{ mr: 1, verticalAlign: 'middle' }} />
|
|
Adresses ({extractionResult.addresses?.length || 0})
|
|
</Typography>
|
|
<List dense>
|
|
{(extractionResult.addresses || []).map((address, index) => (
|
|
<ListItem key={index}>
|
|
<ListItemText
|
|
primary={`${address.street}, ${address.city}`}
|
|
secondary={`${address.postalCode} ${address.country}`}
|
|
/>
|
|
</ListItem>
|
|
))}
|
|
</List>
|
|
</CardContent>
|
|
</Card>
|
|
</Box>
|
|
</Box>
|
|
|
|
<Box sx={{ display: 'flex', gap: 3, flexWrap: 'wrap' }}>
|
|
{/* Biens */}
|
|
<Box sx={{ flex: '1 1 300px' }}>
|
|
<Card>
|
|
<CardContent>
|
|
<Typography variant="h6" gutterBottom>
|
|
<Home sx={{ mr: 1, verticalAlign: 'middle' }} />
|
|
Biens ({extractionResult.properties?.length || 0})
|
|
</Typography>
|
|
<List dense>
|
|
{(extractionResult.properties || []).map((property, index) => (
|
|
<ListItem key={index}>
|
|
<ListItemText
|
|
primary={`${property.type} - ${property.address.city}`}
|
|
secondary={
|
|
<Box>
|
|
<Typography variant="caption" display="block">
|
|
{property.address.street}
|
|
</Typography>
|
|
{property.surface && (
|
|
<Typography variant="caption" display="block">
|
|
Surface: {property.surface} m²
|
|
</Typography>
|
|
)}
|
|
{property.cadastralReference && (
|
|
<Typography variant="caption" display="block">
|
|
Cadastre: {property.cadastralReference}
|
|
</Typography>
|
|
)}
|
|
</Box>
|
|
}
|
|
/>
|
|
</ListItem>
|
|
))}
|
|
</List>
|
|
</CardContent>
|
|
</Card>
|
|
</Box>
|
|
|
|
{/* Contrats */}
|
|
<Box sx={{ flex: '1 1 300px' }}>
|
|
<Card>
|
|
<CardContent>
|
|
<Typography variant="h6" gutterBottom>
|
|
<Description sx={{ mr: 1, verticalAlign: 'middle' }} />
|
|
Contrats ({extractionResult.contracts?.length || 0})
|
|
</Typography>
|
|
<List dense>
|
|
{(extractionResult.contracts || []).map((contract, index) => (
|
|
<ListItem key={index}>
|
|
<ListItemText
|
|
primary={`${contract.type} - ${contract.amount ? `${contract.amount}€` : 'Montant non spécifié'}`}
|
|
secondary={
|
|
<Box>
|
|
<Typography variant="caption" display="block">
|
|
Parties: {contract.parties.length}
|
|
</Typography>
|
|
{contract.date && (
|
|
<Typography variant="caption" display="block">
|
|
Date: {contract.date}
|
|
</Typography>
|
|
)}
|
|
<Typography variant="caption" display="block">
|
|
Clauses: {contract.clauses.length}
|
|
</Typography>
|
|
</Box>
|
|
}
|
|
/>
|
|
</ListItem>
|
|
))}
|
|
</List>
|
|
</CardContent>
|
|
</Card>
|
|
</Box>
|
|
</Box>
|
|
|
|
{/* Signatures */}
|
|
<Card>
|
|
<CardContent>
|
|
<Typography variant="h6" gutterBottom>
|
|
Signatures détectées ({extractionResult.signatures?.length || 0})
|
|
</Typography>
|
|
<List dense>
|
|
{(extractionResult.signatures || []).map((signature, index) => (
|
|
<ListItem key={index}>
|
|
<ListItemText primary={signature} />
|
|
</ListItem>
|
|
))}
|
|
</List>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Texte extrait */}
|
|
<Card>
|
|
<CardContent>
|
|
<Typography variant="h6" gutterBottom>
|
|
Texte extrait
|
|
</Typography>
|
|
<Paper
|
|
sx={{
|
|
p: 2,
|
|
bgcolor: 'grey.50',
|
|
maxHeight: 300,
|
|
overflow: 'auto',
|
|
}}
|
|
>
|
|
<Typography variant="body2" sx={{ whiteSpace: 'pre-wrap' }}>
|
|
{extractionResult.text}
|
|
</Typography>
|
|
</Paper>
|
|
</CardContent>
|
|
</Card>
|
|
</Box>
|
|
</Layout>
|
|
)
|
|
} |