feat: add inline editing for extracted data and autocomplete for tagging
- Add EditableField component for inline editing of any field - Update DataRow, LocataireCard, OperationCard to support inline editing - Add CRUD operations for locataires and operations (add/remove) - Update JsonViewer to propagate changes via v-model - Add TagAutocomplete component with search/filter functionality - Replace select dropdown with autocomplete in TaggingStep
This commit is contained in:
@@ -66,38 +66,38 @@
|
||||
<div class="grid grid-cols-1 gap-3">
|
||||
<!-- Editeur -->
|
||||
<DataCard title="Editeur" icon="building">
|
||||
<DataRow label="Nom" :value="data.data?.metadata?.editeur?.nom" />
|
||||
<DataRow label="Adresse" :value="data.data?.metadata?.editeur?.adresse" />
|
||||
<DataRow label="Telephone" :value="data.data?.metadata?.editeur?.telephone" />
|
||||
<DataRow label="SIRET" :value="data.data?.metadata?.editeur?.siret" />
|
||||
<DataRow label="Nom" :value="data.data?.metadata?.editeur?.nom" @update:value="updateMetadata('editeur.nom', $event)" />
|
||||
<DataRow label="Adresse" :value="data.data?.metadata?.editeur?.adresse" @update:value="updateMetadata('editeur.adresse', $event)" />
|
||||
<DataRow label="Telephone" :value="data.data?.metadata?.editeur?.telephone" @update:value="updateMetadata('editeur.telephone', $event)" />
|
||||
<DataRow label="SIRET" :value="data.data?.metadata?.editeur?.siret" @update:value="updateMetadata('editeur.siret', $event)" />
|
||||
</DataCard>
|
||||
|
||||
<!-- Destinataire -->
|
||||
<DataCard title="Destinataire" icon="user">
|
||||
<DataRow label="Nom" :value="data.data?.metadata?.destinataire?.nom" />
|
||||
<DataRow label="Adresse" :value="data.data?.metadata?.destinataire?.adresse" />
|
||||
<DataRow label="Nom" :value="data.data?.metadata?.destinataire?.nom" @update:value="updateMetadata('destinataire.nom', $event)" />
|
||||
<DataRow label="Adresse" :value="data.data?.metadata?.destinataire?.adresse" @update:value="updateMetadata('destinataire.adresse', $event)" />
|
||||
</DataCard>
|
||||
|
||||
<!-- Document -->
|
||||
<DataCard title="Document" icon="document">
|
||||
<DataRow label="Reference" :value="data.data?.metadata?.document?.reference" />
|
||||
<DataRow label="Date" :value="data.data?.metadata?.document?.date" />
|
||||
<DataRow label="Type" :value="data.data?.metadata?.document?.type" />
|
||||
<DataRow label="Reference" :value="data.data?.metadata?.document?.reference" @update:value="updateMetadata('document.reference', $event)" />
|
||||
<DataRow label="Date" :value="data.data?.metadata?.document?.date" type="date" @update:value="updateMetadata('document.date', $event)" />
|
||||
<DataRow label="Type" :value="data.data?.metadata?.document?.type" @update:value="updateMetadata('document.type', $event)" />
|
||||
</DataCard>
|
||||
|
||||
<!-- Immeuble -->
|
||||
<DataCard title="Immeuble" icon="home">
|
||||
<DataRow label="Code" :value="data.data?.metadata?.immeuble?.code" />
|
||||
<DataRow label="Adresse" :value="data.data?.metadata?.immeuble?.adresse" />
|
||||
<DataRow label="Ville" :value="data.data?.metadata?.immeuble?.ville" />
|
||||
<DataRow label="Code postal" :value="data.data?.metadata?.immeuble?.code_postal" />
|
||||
<DataRow label="Code" :value="data.data?.metadata?.immeuble?.code" @update:value="updateMetadata('immeuble.code', $event)" />
|
||||
<DataRow label="Adresse" :value="data.data?.metadata?.immeuble?.adresse" @update:value="updateMetadata('immeuble.adresse', $event)" />
|
||||
<DataRow label="Ville" :value="data.data?.metadata?.immeuble?.ville" @update:value="updateMetadata('immeuble.ville', $event)" />
|
||||
<DataRow label="Code postal" :value="data.data?.metadata?.immeuble?.code_postal" @update:value="updateMetadata('immeuble.code_postal', $event)" />
|
||||
</DataCard>
|
||||
|
||||
<!-- Solde -->
|
||||
<DataCard title="Solde" icon="currency">
|
||||
<DataRow label="Montant" :value="formatCurrency(data.data?.metadata?.solde?.montant)" highlight />
|
||||
<DataRow label="Type" :value="data.data?.metadata?.solde?.type" />
|
||||
<DataRow label="Date arrete" :value="data.data?.metadata?.solde?.date_arrete" />
|
||||
<DataRow label="Montant" :value="data.data?.metadata?.solde?.montant" type="currency" highlight @update:value="updateMetadata('solde.montant', $event)" />
|
||||
<DataRow label="Type" :value="data.data?.metadata?.solde?.type" @update:value="updateMetadata('solde.type', $event)" />
|
||||
<DataRow label="Date arrete" :value="data.data?.metadata?.solde?.date_arrete" type="date" @update:value="updateMetadata('solde.date_arrete', $event)" />
|
||||
</DataCard>
|
||||
</div>
|
||||
</DataSection>
|
||||
@@ -115,7 +115,20 @@
|
||||
:key="idx"
|
||||
:locataire="loc"
|
||||
:index="idx"
|
||||
@update:locataire="updateLocataire(idx, $event)"
|
||||
@remove="removeLocataire(idx)"
|
||||
/>
|
||||
|
||||
<!-- Bouton ajouter locataire -->
|
||||
<button
|
||||
@click="addLocataire"
|
||||
class="w-full flex items-center justify-center gap-2 px-3 py-2 text-sm text-blue-600 hover:bg-blue-50 border border-dashed border-blue-300 rounded-lg transition-colors"
|
||||
>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
|
||||
</svg>
|
||||
Ajouter un locataire
|
||||
</button>
|
||||
</div>
|
||||
</DataSection>
|
||||
|
||||
@@ -132,7 +145,19 @@
|
||||
:key="idx"
|
||||
:categorie="group.categorie"
|
||||
:operations="group.operations"
|
||||
@update:operations="updateOperationsGroup(group.categorie, $event)"
|
||||
/>
|
||||
|
||||
<!-- Bouton ajouter operation -->
|
||||
<button
|
||||
@click="addOperation"
|
||||
class="w-full flex items-center justify-center gap-2 px-3 py-2 text-sm text-blue-600 hover:bg-blue-50 border border-dashed border-blue-300 rounded-lg transition-colors"
|
||||
>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
|
||||
</svg>
|
||||
Ajouter une operation
|
||||
</button>
|
||||
</div>
|
||||
</DataSection>
|
||||
</div>
|
||||
@@ -159,6 +184,8 @@ const props = defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:data'])
|
||||
|
||||
// Grouper les operations par categorie pour l'affichage
|
||||
const operationsGroupedByCategory = computed(() => {
|
||||
const operations = props.data?.data?.recapitulatif_operations
|
||||
@@ -203,11 +230,6 @@ function collapseAll() {
|
||||
expandedSections.operations = false
|
||||
}
|
||||
|
||||
function formatCurrency(value) {
|
||||
if (value === null || value === undefined) return '-'
|
||||
return new Intl.NumberFormat('fr-FR', { style: 'currency', currency: 'EUR' }).format(value)
|
||||
}
|
||||
|
||||
async function copyJson() {
|
||||
if (!props.data) return
|
||||
|
||||
@@ -221,4 +243,122 @@ async function copyJson() {
|
||||
console.error('Failed to copy:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// ===== FONCTIONS DE MISE A JOUR =====
|
||||
|
||||
// Helper pour creer une copie profonde des donnees
|
||||
function cloneData() {
|
||||
return JSON.parse(JSON.stringify(props.data))
|
||||
}
|
||||
|
||||
// Helper pour setter une valeur nested
|
||||
function setNestedValue(obj, path, value) {
|
||||
const parts = path.split('.')
|
||||
let current = obj
|
||||
for (let i = 0; i < parts.length - 1; i++) {
|
||||
if (!current[parts[i]]) {
|
||||
current[parts[i]] = {}
|
||||
}
|
||||
current = current[parts[i]]
|
||||
}
|
||||
current[parts[parts.length - 1]] = value
|
||||
}
|
||||
|
||||
// Mettre a jour les metadonnees
|
||||
function updateMetadata(path, value) {
|
||||
const updated = cloneData()
|
||||
if (!updated.data) updated.data = {}
|
||||
if (!updated.data.metadata) updated.data.metadata = {}
|
||||
|
||||
setNestedValue(updated.data.metadata, path, value)
|
||||
emit('update:data', updated)
|
||||
}
|
||||
|
||||
// Mettre a jour un locataire
|
||||
function updateLocataire(index, locataire) {
|
||||
const updated = cloneData()
|
||||
if (!updated.data) updated.data = {}
|
||||
if (!updated.data.situation_locataires) updated.data.situation_locataires = []
|
||||
|
||||
updated.data.situation_locataires[index] = locataire
|
||||
emit('update:data', updated)
|
||||
}
|
||||
|
||||
// Ajouter un locataire
|
||||
function addLocataire() {
|
||||
const updated = cloneData()
|
||||
if (!updated.data) updated.data = {}
|
||||
if (!updated.data.situation_locataires) updated.data.situation_locataires = []
|
||||
|
||||
updated.data.situation_locataires.push({
|
||||
lot: {
|
||||
numero: '',
|
||||
type: ''
|
||||
},
|
||||
locataire: {
|
||||
nom: 'Nouveau locataire'
|
||||
},
|
||||
lignes: [],
|
||||
totaux: {
|
||||
solde_anterieur: 0,
|
||||
loyers: 0,
|
||||
taxes: 0,
|
||||
provisions: 0,
|
||||
divers: 0,
|
||||
total: 0,
|
||||
regles: 0,
|
||||
impayes: 0
|
||||
}
|
||||
})
|
||||
|
||||
emit('update:data', updated)
|
||||
}
|
||||
|
||||
// Supprimer un locataire
|
||||
function removeLocataire(index) {
|
||||
const updated = cloneData()
|
||||
updated.data.situation_locataires.splice(index, 1)
|
||||
emit('update:data', updated)
|
||||
}
|
||||
|
||||
// Mettre a jour un groupe d'operations (par categorie)
|
||||
function updateOperationsGroup(categorie, updatedGroupOperations) {
|
||||
const updated = cloneData()
|
||||
if (!updated.data) updated.data = {}
|
||||
if (!updated.data.recapitulatif_operations) updated.data.recapitulatif_operations = []
|
||||
|
||||
// Reconstruire la liste complete des operations
|
||||
// 1. Filtrer toutes les operations de cette categorie
|
||||
const otherOperations = updated.data.recapitulatif_operations.filter(op => op.categorie !== categorie)
|
||||
|
||||
// 2. Combiner avec les operations mises a jour
|
||||
updated.data.recapitulatif_operations = [...otherOperations, ...updatedGroupOperations]
|
||||
|
||||
emit('update:data', updated)
|
||||
}
|
||||
|
||||
// Ajouter une operation
|
||||
function addOperation() {
|
||||
const updated = cloneData()
|
||||
if (!updated.data) updated.data = {}
|
||||
if (!updated.data.recapitulatif_operations) updated.data.recapitulatif_operations = []
|
||||
|
||||
updated.data.recapitulatif_operations.push({
|
||||
categorie: 'AUTRES',
|
||||
sous_categorie: null,
|
||||
fournisseur: 'Nouveau fournisseur',
|
||||
description: null,
|
||||
lot_concerne: null,
|
||||
lot_numero: null,
|
||||
montants: {
|
||||
debit: 0,
|
||||
credit: 0,
|
||||
tva: 0,
|
||||
locatif: 0,
|
||||
deductible: 0
|
||||
}
|
||||
})
|
||||
|
||||
emit('update:data', updated)
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user