255 lines
8.1 KiB
TypeScript
255 lines
8.1 KiB
TypeScript
import { useEffect } from 'react'
|
|
import {
|
|
Box,
|
|
Typography,
|
|
Paper,
|
|
Card,
|
|
CardContent,
|
|
Chip,
|
|
List,
|
|
ListItem,
|
|
ListItemText,
|
|
ListItemIcon,
|
|
Alert,
|
|
LinearProgress,
|
|
} from '@mui/material'
|
|
import {
|
|
CheckCircle,
|
|
Error,
|
|
Warning,
|
|
Flag,
|
|
Security,
|
|
Assessment,
|
|
Info,
|
|
} from '@mui/icons-material'
|
|
import type { ChipProps, LinearProgressProps } from '@mui/material'
|
|
import { useAppDispatch, useAppSelector } from '../store'
|
|
import { analyzeDocument } from '../store/documentSlice'
|
|
import { Layout } from '../components/Layout'
|
|
|
|
export default function AnalyseView() {
|
|
const dispatch = useAppDispatch()
|
|
const { currentDocument, analysisResult, loading } = useAppSelector(
|
|
(state) => state.document
|
|
)
|
|
|
|
useEffect(() => {
|
|
if (currentDocument && !analysisResult) {
|
|
dispatch(analyzeDocument(currentDocument.id))
|
|
}
|
|
}, [currentDocument, analysisResult, 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', flexDirection: 'column', alignItems: 'center', mt: 4 }}>
|
|
<LinearProgress sx={{ width: '100%', mb: 2 }} />
|
|
<Typography>Analyse en cours...</Typography>
|
|
</Box>
|
|
</Layout>
|
|
)
|
|
}
|
|
|
|
if (!analysisResult) {
|
|
return (
|
|
<Layout>
|
|
<Alert severity="warning">
|
|
Aucun résultat d'analyse disponible.
|
|
</Alert>
|
|
</Layout>
|
|
)
|
|
}
|
|
|
|
const getScoreColor = (score: number): ChipProps['color'] => {
|
|
if (score >= 0.8) return 'success'
|
|
if (score >= 0.6) return 'warning'
|
|
return 'error'
|
|
}
|
|
|
|
const getScoreIcon = (score: number) => {
|
|
if (score >= 0.8) return <CheckCircle color="success" />
|
|
if (score >= 0.6) return <Warning color="warning" />
|
|
return <Error color="error" />
|
|
}
|
|
|
|
return (
|
|
<Layout>
|
|
<Typography variant="h4" gutterBottom>
|
|
Analyse du document
|
|
</Typography>
|
|
|
|
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
|
|
{/* Résumé général */}
|
|
<Paper sx={{ p: 2 }}>
|
|
<Typography variant="h6" gutterBottom>
|
|
Résumé de l'analyse
|
|
</Typography>
|
|
<Box sx={{ display: 'flex', gap: 2, flexWrap: 'wrap', alignItems: 'center' }}>
|
|
<Chip
|
|
icon={<Assessment />}
|
|
label={`Score de vraisemblance: ${(analysisResult.credibilityScore * 100).toFixed(1)}%`}
|
|
color={getScoreColor(analysisResult.credibilityScore)}
|
|
variant="filled"
|
|
/>
|
|
<Chip
|
|
icon={<Info />}
|
|
label={`Type: ${analysisResult.documentType}`}
|
|
color="primary"
|
|
variant="outlined"
|
|
/>
|
|
{analysisResult.isCNI && (
|
|
<Chip
|
|
icon={<Flag />}
|
|
label={`Pays: ${analysisResult.country}`}
|
|
color="secondary"
|
|
variant="outlined"
|
|
/>
|
|
)}
|
|
</Box>
|
|
</Paper>
|
|
|
|
{/* Cas CNI */}
|
|
{analysisResult.isCNI && (
|
|
<Card>
|
|
<CardContent>
|
|
<Typography variant="h6" gutterBottom>
|
|
<Security sx={{ mr: 1, verticalAlign: 'middle' }} />
|
|
Vérification CNI
|
|
</Typography>
|
|
{analysisResult.verificationResult && (
|
|
<List>
|
|
<ListItem>
|
|
<ListItemIcon>
|
|
{analysisResult.verificationResult.numberValid ? (
|
|
<CheckCircle color="success" />
|
|
) : (
|
|
<Error color="error" />
|
|
)}
|
|
</ListItemIcon>
|
|
<ListItemText
|
|
primary="Numéro valide"
|
|
secondary={
|
|
analysisResult.verificationResult.numberValid
|
|
? 'Le numéro de CNI est valide'
|
|
: 'Le numéro de CNI est invalide'
|
|
}
|
|
/>
|
|
</ListItem>
|
|
<ListItem>
|
|
<ListItemIcon>
|
|
{analysisResult.verificationResult.formatValid ? (
|
|
<CheckCircle color="success" />
|
|
) : (
|
|
<Error color="error" />
|
|
)}
|
|
</ListItemIcon>
|
|
<ListItemText
|
|
primary="Format valide"
|
|
secondary={
|
|
analysisResult.verificationResult.formatValid
|
|
? 'Le format du numéro est correct'
|
|
: 'Le format du numéro est incorrect'
|
|
}
|
|
/>
|
|
</ListItem>
|
|
<ListItem>
|
|
<ListItemIcon>
|
|
{analysisResult.verificationResult.checksumValid ? (
|
|
<CheckCircle color="success" />
|
|
) : (
|
|
<Error color="error" />
|
|
)}
|
|
</ListItemIcon>
|
|
<ListItemText
|
|
primary="Checksum valide"
|
|
secondary={
|
|
analysisResult.verificationResult.checksumValid
|
|
? 'La somme de contrôle est correcte'
|
|
: 'La somme de contrôle est incorrecte'
|
|
}
|
|
/>
|
|
</ListItem>
|
|
</List>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
)}
|
|
|
|
<Box sx={{ display: 'flex', gap: 3, flexWrap: 'wrap' }}>
|
|
{/* Score de vraisemblance */}
|
|
<Box sx={{ flex: '1 1 300px' }}>
|
|
<Card>
|
|
<CardContent>
|
|
<Typography variant="h6" gutterBottom>
|
|
Score de vraisemblance
|
|
</Typography>
|
|
<Box sx={{ display: 'flex', alignItems: 'center', mb: 2 }}>
|
|
{getScoreIcon(analysisResult.credibilityScore)}
|
|
<Typography variant="h4" sx={{ ml: 2 }}>
|
|
{(analysisResult.credibilityScore * 100).toFixed(1)}%
|
|
</Typography>
|
|
</Box>
|
|
<LinearProgress
|
|
variant="determinate"
|
|
value={analysisResult.credibilityScore * 100}
|
|
color={getScoreColor(analysisResult.credibilityScore) as LinearProgressProps['color']}
|
|
sx={{ height: 10, borderRadius: 5 }}
|
|
/>
|
|
<Typography variant="body2" color="text.secondary" sx={{ mt: 1 }}>
|
|
{analysisResult.credibilityScore >= 0.8
|
|
? 'Document très fiable'
|
|
: analysisResult.credibilityScore >= 0.6
|
|
? 'Document moyennement fiable'
|
|
: 'Document peu fiable - vérification recommandée'}
|
|
</Typography>
|
|
</CardContent>
|
|
</Card>
|
|
</Box>
|
|
|
|
{/* Synthèse */}
|
|
<Box sx={{ flex: '1 1 300px' }}>
|
|
<Card>
|
|
<CardContent>
|
|
<Typography variant="h6" gutterBottom>
|
|
Synthèse
|
|
</Typography>
|
|
<Typography variant="body1" sx={{ whiteSpace: 'pre-wrap' }}>
|
|
{analysisResult.summary}
|
|
</Typography>
|
|
</CardContent>
|
|
</Card>
|
|
</Box>
|
|
</Box>
|
|
|
|
{/* Recommandations */}
|
|
<Card>
|
|
<CardContent>
|
|
<Typography variant="h6" gutterBottom>
|
|
Recommandations
|
|
</Typography>
|
|
<List>
|
|
{analysisResult.recommendations.map((recommendation, index) => (
|
|
<ListItem key={index}>
|
|
<ListItemIcon>
|
|
<Info color="primary" />
|
|
</ListItemIcon>
|
|
<ListItemText primary={recommendation} />
|
|
</ListItem>
|
|
))}
|
|
</List>
|
|
</CardContent>
|
|
</Card>
|
|
</Box>
|
|
</Layout>
|
|
)
|
|
} |