fix(extraction): brouillons immutables pour champs description (corrige object non extensible)
This commit is contained in:
parent
db2de72ad7
commit
32a15e29e6
@ -1,4 +1,4 @@
|
||||
import { useState } from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import { Box, Typography, Paper, Card, CardContent, Chip, Button, List, ListItem, ListItemText, ListItemButton, Tooltip, Alert, Accordion, AccordionSummary, AccordionDetails, CircularProgress } from '@mui/material'
|
||||
import { Person, LocationOn, Business, Description, Language, Verified, ExpandMore, TextFields, Assessment } from '@mui/icons-material'
|
||||
import { useAppDispatch, useAppSelector } from '../store'
|
||||
@ -17,6 +17,26 @@ export default function ExtractionView() {
|
||||
// Utiliser les résultats du dossier pour la navigation
|
||||
const currentResult = folderResults[currentIndex]
|
||||
const [savingKey, setSavingKey] = useState<string | null>(null)
|
||||
const [personsDraft, setPersonsDraft] = useState<any[]>([])
|
||||
const [addressesDraft, setAddressesDraft] = useState<any[]>([])
|
||||
const [companiesDraft, setCompaniesDraft] = useState<any[]>([])
|
||||
|
||||
// Initialiser les brouillons à chaque changement de résultat courant
|
||||
React.useEffect(() => {
|
||||
if (!currentResult) {
|
||||
setPersonsDraft([]); setAddressesDraft([]); setCompaniesDraft([])
|
||||
return
|
||||
}
|
||||
try {
|
||||
const ents = currentResult.extraction?.entities || {}
|
||||
setPersonsDraft((ents.persons || []).map((p: any) => ({ id: p.id, firstName: p.firstName || '', lastName: p.lastName || '', description: p.description || '' })))
|
||||
setAddressesDraft((ents.addresses || []).map((a: any) => ({ id: a.id, street: a.street || '', postalCode: a.postalCode || '', city: a.city || '', country: a.country || '', description: a.description || '' })))
|
||||
setCompaniesDraft((ents.companies || []).map((c: any) => ({ id: c.id, name: c.name || '', description: c.description || '' })))
|
||||
} catch {
|
||||
setPersonsDraft([]); setAddressesDraft([]); setCompaniesDraft([])
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [currentResult?.fileHash])
|
||||
|
||||
const gotoResult = (index: number) => {
|
||||
if (index >= 0 && index < folderResults.length) {
|
||||
@ -188,28 +208,28 @@ export default function ExtractionView() {
|
||||
{/* Entités extraites */}
|
||||
<Box sx={{ display: 'flex', gap: 3, flexWrap: 'wrap' }}>
|
||||
{/* Personnes */}
|
||||
{extraction.extraction.entities.persons.length > 0 && (
|
||||
{personsDraft.length > 0 && (
|
||||
<Card sx={{ flex: '1 1 300px' }}>
|
||||
<CardContent>
|
||||
<Typography variant="h6" gutterBottom>
|
||||
<Person sx={{ mr: 1, verticalAlign: 'middle' }} />
|
||||
Personnes ({extraction.extraction.entities.persons.length})
|
||||
Personnes ({personsDraft.length})
|
||||
</Typography>
|
||||
<List dense>
|
||||
{extraction.extraction.entities.persons.map((p: any, i: number) => (
|
||||
{personsDraft.map((p: any, i: number) => (
|
||||
<ListItem key={`p-${i}`} disableGutters sx={{ py: 0.5 }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 2, width: '100%', flexWrap: 'wrap' }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, flex: '1 1 auto', minWidth: 0, flexWrap: 'wrap' }}>
|
||||
<input style={{ padding: 4, width: 140 }} placeholder="Prénom" defaultValue={p.firstName} onChange={(e)=> (p.firstName=e.target.value)} />
|
||||
<input style={{ padding: 4, width: 160 }} placeholder="Nom" defaultValue={p.lastName} onChange={(e)=> (p.lastName=e.target.value)} />
|
||||
<input style={{ padding: 4, width: 260 }} placeholder="Description" defaultValue={p.description || ''} onChange={(e)=> (p.description=e.target.value)} />
|
||||
<input style={{ padding: 4, width: 140 }} placeholder="Prénom" value={p.firstName} onChange={(e)=> setPersonsDraft((prev)=>{ const c=[...prev]; c[i]={...c[i], firstName:e.target.value}; return c})} />
|
||||
<input style={{ padding: 4, width: 160 }} placeholder="Nom" value={p.lastName} onChange={(e)=> setPersonsDraft((prev)=>{ const c=[...prev]; c[i]={...c[i], lastName:e.target.value}; return c})} />
|
||||
<input style={{ padding: 4, width: 260 }} placeholder="Description" value={p.description} onChange={(e)=> setPersonsDraft((prev)=>{ const c=[...prev]; c[i]={...c[i], description:e.target.value}; return c})} />
|
||||
</Box>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, flexShrink: 0, whiteSpace: 'nowrap' }}>
|
||||
<Button size="small" variant="outlined" disabled={savingKey===`p-${i}`}
|
||||
onClick={async ()=>{
|
||||
try{
|
||||
setSavingKey(`p-${i}`)
|
||||
await updateEntity(currentFolderHash!, extraction.fileHash, 'person', { index: i, id: p.id, patch: { firstName: p.firstName, lastName: p.lastName, description: p.description || '' } })
|
||||
await updateEntity(currentFolderHash!, extraction.fileHash, 'person', { index: i, id: p.id, patch: { firstName: p.firstName, lastName: p.lastName, description: p.description || '' } })
|
||||
} finally { setSavingKey(null) }
|
||||
}}>Enregistrer</Button>
|
||||
<Button size="small" color="error"
|
||||
@ -226,23 +246,23 @@ export default function ExtractionView() {
|
||||
)}
|
||||
|
||||
{/* Adresses */}
|
||||
{extraction.extraction.entities.addresses.length > 0 && (
|
||||
{addressesDraft.length > 0 && (
|
||||
<Card sx={{ flex: '1 1 300px' }}>
|
||||
<CardContent>
|
||||
<Typography variant="h6" gutterBottom>
|
||||
<LocationOn sx={{ mr: 1, verticalAlign: 'middle' }} />
|
||||
Adresses ({extraction.extraction.entities.addresses.length})
|
||||
Adresses ({addressesDraft.length})
|
||||
</Typography>
|
||||
<List dense>
|
||||
{extraction.extraction.entities.addresses.map((a: any, i: number) => (
|
||||
{addressesDraft.map((a: any, i: number) => (
|
||||
<ListItem key={`a-${i}`} disableGutters sx={{ py: 0.5 }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 2, width: '100%', flexWrap: 'wrap' }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, flex: '1 1 auto', minWidth: 0, flexWrap: 'wrap' }}>
|
||||
<input style={{ padding: 4, width: 240 }} placeholder="Rue" defaultValue={a.street} onChange={(e)=> (a.street=e.target.value)} />
|
||||
<input style={{ padding: 4, width: 100 }} placeholder="CP" defaultValue={a.postalCode} onChange={(e)=> (a.postalCode=e.target.value)} />
|
||||
<input style={{ padding: 4, width: 180 }} placeholder="Ville" defaultValue={a.city} onChange={(e)=> (a.city=e.target.value)} />
|
||||
<input style={{ padding: 4, width: 140 }} placeholder="Pays" defaultValue={a.country||''} onChange={(e)=> (a.country=e.target.value)} />
|
||||
<input style={{ padding: 4, width: 260 }} placeholder="Description" defaultValue={a.description || ''} onChange={(e)=> (a.description=e.target.value)} />
|
||||
<input style={{ padding: 4, width: 240 }} placeholder="Rue" value={a.street} onChange={(e)=> setAddressesDraft((prev)=>{ const c=[...prev]; c[i]={...c[i], street:e.target.value}; return c})} />
|
||||
<input style={{ padding: 4, width: 100 }} placeholder="CP" value={a.postalCode} onChange={(e)=> setAddressesDraft((prev)=>{ const c=[...prev]; c[i]={...c[i], postalCode:e.target.value}; return c})} />
|
||||
<input style={{ padding: 4, width: 180 }} placeholder="Ville" value={a.city} onChange={(e)=> setAddressesDraft((prev)=>{ const c=[...prev]; c[i]={...c[i], city:e.target.value}; return c})} />
|
||||
<input style={{ padding: 4, width: 140 }} placeholder="Pays" value={a.country} onChange={(e)=> setAddressesDraft((prev)=>{ const c=[...prev]; c[i]={...c[i], country:e.target.value}; return c})} />
|
||||
<input style={{ padding: 4, width: 260 }} placeholder="Description" value={a.description} onChange={(e)=> setAddressesDraft((prev)=>{ const c=[...prev]; c[i]={...c[i], description:e.target.value}; return c})} />
|
||||
</Box>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, flexShrink: 0, whiteSpace: 'nowrap' }}>
|
||||
<Button size="small" variant="outlined" disabled={savingKey===`a-${i}`}
|
||||
@ -266,20 +286,20 @@ export default function ExtractionView() {
|
||||
)}
|
||||
|
||||
{/* Entreprises */}
|
||||
{extraction.extraction.entities.companies.length > 0 && (
|
||||
{companiesDraft.length > 0 && (
|
||||
<Card sx={{ flex: '1 1 300px' }}>
|
||||
<CardContent>
|
||||
<Typography variant="h6" gutterBottom>
|
||||
<Business sx={{ mr: 1, verticalAlign: 'middle' }} />
|
||||
Entreprises ({extraction.extraction.entities.companies.length})
|
||||
Entreprises ({companiesDraft.length})
|
||||
</Typography>
|
||||
<List dense>
|
||||
{extraction.extraction.entities.companies.map((c: any, i: number) => (
|
||||
{companiesDraft.map((c: any, i: number) => (
|
||||
<ListItem key={`c-${i}`} disableGutters sx={{ py: 0.5 }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 2, width: '100%', flexWrap: 'wrap' }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, flex: '1 1 auto', minWidth: 0, flexWrap: 'wrap' }}>
|
||||
<input style={{ padding: 4, width: 300 }} placeholder="Raison sociale" defaultValue={c.name} onChange={(e)=> (c.name=e.target.value)} />
|
||||
<input style={{ padding: 4, width: 260 }} placeholder="Description" defaultValue={c.description || ''} onChange={(e)=> (c.description=e.target.value)} />
|
||||
<input style={{ padding: 4, width: 300 }} placeholder="Raison sociale" value={c.name} onChange={(e)=> setCompaniesDraft((prev)=>{ const x=[...prev]; x[i]={...x[i], name:e.target.value}; return x})} />
|
||||
<input style={{ padding: 4, width: 260 }} placeholder="Description" value={c.description} onChange={(e)=> setCompaniesDraft((prev)=>{ const x=[...prev]; x[i]={...x[i], description:e.target.value}; return x})} />
|
||||
</Box>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1, flexShrink: 0, whiteSpace: 'nowrap' }}>
|
||||
<Button size="small" variant="outlined" disabled={savingKey===`c-${i}`}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user