ux(review): spinner, tooltip, chip en cours et snackbar sur Révision IA
This commit is contained in:
parent
4bed3562b1
commit
1e207f734e
@ -8,6 +8,8 @@ import {
|
||||
Skeleton,
|
||||
Alert,
|
||||
Button,
|
||||
Snackbar,
|
||||
Alert as MuiAlert,
|
||||
Chip,
|
||||
List,
|
||||
ListItem,
|
||||
@ -50,7 +52,7 @@ import type { Document } from '../types'
|
||||
import { confirmDetectedAddress, deleteFolderFile, reviewFileWithAI } from '../services/folderApi'
|
||||
|
||||
// Composant mémorisé pour les items de la liste
|
||||
const DocumentListItem = memo(({ doc, index, onPreview, onDelete, onReplace, onConfirmAddress, onReview, onOpenCorrections, totalCount }: {
|
||||
const DocumentListItem = memo(({ doc, index, onPreview, onDelete, onReplace, onConfirmAddress, onReview, onOpenCorrections, isReviewing, totalCount }: {
|
||||
doc: Document,
|
||||
index: number,
|
||||
onPreview: (doc: Document) => void,
|
||||
@ -59,6 +61,7 @@ const DocumentListItem = memo(({ doc, index, onPreview, onDelete, onReplace, onC
|
||||
onConfirmAddress: (doc: Document) => void,
|
||||
onReview: (doc: Document) => void,
|
||||
onOpenCorrections: (doc: Document, corrections: any[]) => void,
|
||||
isReviewing: boolean,
|
||||
totalCount: number
|
||||
}) => {
|
||||
const getFileIcon = (mimeType: string) => {
|
||||
@ -151,6 +154,9 @@ const DocumentListItem = memo(({ doc, index, onPreview, onDelete, onReplace, onC
|
||||
variant="outlined"
|
||||
/>
|
||||
)}
|
||||
{isReviewing && (
|
||||
<Chip color="default" label="Révision IA en cours…" size="small" />
|
||||
)}
|
||||
{(() => {
|
||||
const anyDoc: any = doc as any
|
||||
const score: number | undefined =
|
||||
@ -223,14 +229,18 @@ const DocumentListItem = memo(({ doc, index, onPreview, onDelete, onReplace, onC
|
||||
>
|
||||
Aperçu
|
||||
</Button>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => onReview(doc)}
|
||||
disabled={doc.status !== 'completed'}
|
||||
fullWidth
|
||||
>
|
||||
Révision IA
|
||||
</Button>
|
||||
<Tooltip title="Analyse IA (Ollama): calcule un score de fiabilité, propose des corrections, ajoute un avis.">
|
||||
<span>
|
||||
<Button
|
||||
size="small"
|
||||
onClick={() => onReview(doc)}
|
||||
disabled={doc.status !== 'completed' || isReviewing}
|
||||
fullWidth
|
||||
>
|
||||
{isReviewing ? 'Révision IA…' : 'Révision IA'}
|
||||
</Button>
|
||||
</span>
|
||||
</Tooltip>
|
||||
<Button
|
||||
size="small"
|
||||
color="error"
|
||||
@ -276,6 +286,8 @@ export default function UploadView() {
|
||||
const [reviewDialogOpen, setReviewDialogOpen] = useState(false)
|
||||
const [reviewDoc, setReviewDoc] = useState<Document | null>(null)
|
||||
const [reviewCorrections, setReviewCorrections] = useState<any[]>([])
|
||||
const [reviewingId, setReviewingId] = useState<string | null>(null)
|
||||
const [snack, setSnack] = useState<{ open: boolean; severity: 'success' | 'error'; message: string }>({ open: false, severity: 'success', message: '' })
|
||||
|
||||
const handleConfirmAddress = useCallback((doc: Document) => {
|
||||
try {
|
||||
@ -308,10 +320,15 @@ export default function UploadView() {
|
||||
const handleReview = useCallback(async (doc: Document) => {
|
||||
if (!currentFolderHash) return
|
||||
try {
|
||||
setReviewingId(doc.id)
|
||||
await reviewFileWithAI(currentFolderHash, doc.id)
|
||||
await dispatch(loadFolderResults(currentFolderHash)).unwrap()
|
||||
setSnack({ open: true, severity: 'success', message: 'Révision IA terminée: score et corrections mis à jour.' })
|
||||
} catch (e) {
|
||||
console.error('❌ Révision IA:', e)
|
||||
setSnack({ open: true, severity: 'error', message: "Échec de la révision IA. Réessaie plus tard." })
|
||||
} finally {
|
||||
setReviewingId(null)
|
||||
}
|
||||
}, [currentFolderHash, dispatch])
|
||||
|
||||
@ -581,6 +598,7 @@ export default function UploadView() {
|
||||
onConfirmAddress={handleConfirmAddress}
|
||||
onReview={handleReview}
|
||||
onOpenCorrections={(d, corr) => { setReviewDoc(d); setReviewCorrections(corr); setReviewDialogOpen(true) }}
|
||||
isReviewing={reviewingId === doc.id}
|
||||
totalCount={memoizedDocuments.length}
|
||||
/>
|
||||
))}
|
||||
@ -780,6 +798,18 @@ export default function UploadView() {
|
||||
<Button onClick={() => setReviewDialogOpen(false)}>Fermer</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
||||
{/* Snackbar feedback */}
|
||||
<Snackbar
|
||||
open={snack.open}
|
||||
autoHideDuration={3000}
|
||||
onClose={() => setSnack({ ...snack, open: false })}
|
||||
anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
|
||||
>
|
||||
<MuiAlert onClose={() => setSnack({ ...snack, open: false })} severity={snack.severity} variant="filled" sx={{ width: '100%' }}>
|
||||
{snack.message}
|
||||
</MuiAlert>
|
||||
</Snackbar>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user