4NK_IA_front/src/views/AnalyseView.tsx

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>
)
}