// ECO-PANNEAU.FR - __react/socle/_socle_editeur_entite.jsx window.pano_EntityEditorModal = ({ editingEntity, setEditingEntity, saveEditedEntity, showToast, onClose, clientUid, panneauId }) => { const { useState } = React; const [isSaving, setIsSaving] = useState(false); // 1. - SÉCURITÉ ANTI-FUITE DE MÉMOIRE ET RACE CONDITIONS (Zéro-Dette) const { isMounted, safeFetch } = window.pano_useSafeFetch(); // 2. - Composants et Icônes const { Modal, Button, FormInput } = window.pano_getComponents(); const { UploadCloudIcon, Trash2Icon, SearchIcon } = window.pano_getIcons(); // 3. - Logique métier const isLot = editingEntity.location.type === 'lot'; const isIntervenant = editingEntity.location.type === 'intervenant'; const predefinedRoles = ["Architecte", "Maître d'œuvre", "Bureau d'études", "Bureau de contrôle", "CSPS"]; const isCustomRole = editingEntity.data.role && !predefinedRoles.includes(editingEntity.data.role); const [roleType, setRoleType] = useState(isCustomRole ? "Personnalisé" : (editingEntity.data.role || "")); // Suivi de l'état initial pour l'alerte anti-perte de données const [initialDataStr] = useState(JSON.stringify(editingEntity.data)); const isDirty = initialDataStr !== JSON.stringify(editingEntity.data); const handleSiretLookup = async () => { const siret = editingEntity.data.siret; if (!siret || siret.length < 9) { if (showToast) showToast("Veuillez saisir un SIREN (9) ou SIRET (14) valide.", "error"); return; } const payload = { siret }; if (window.pano_CURRENT_DELEGATE_TOKEN) { payload.delegate_token = window.pano_CURRENT_DELEGATE_TOKEN; } const d = await safeFetch('systeme/siret_lookup', { body: payload, setLoading: setIsSaving, successMessage: "Informations récupérées avec succès." }); if (!isMounted.current) return; if (d) { setEditingEntity(prev => prev ? { ...prev, data: { ...prev.data, name: d.data.name || prev.data.address, address: d.data.address || prev.data.address, siret: d.data.siret || prev.data.siret } } : prev); } }; const handleFileUpload = async (e) => { const file = e.target.files[0]; if (e.target) e.target.value = null; if (!file) return; setIsSaving(true); const reader = new FileReader(); reader.onload = async (event) => { if (!isMounted.current) return; const base64Url = event.target.result; setEditingEntity(prev => prev ? { ...prev, data: { ...prev.data, logoUrl: base64Url } } : prev); try { // uploadFile reste une fonction métier externe, on garde donc setIsSaving manuel ici const fileId = await window.pano_uploadFile(file, 'image', null, false, false, clientUid, panneauId); if (!isMounted.current) return; setEditingEntity(prev => prev ? { ...prev, data: { ...prev.data, logoId: fileId.id || fileId } } : prev); } catch (err) { if (!isMounted.current) return; if (showToast) showToast(err, "error"); else if (window.pano_logFallback) window.pano_logFallback("Erreur d'upload du logo de l'entité ignorée car showToast est introuvable."); setEditingEntity(prev => prev ? { ...prev, data: { ...prev.data, logoUrl: '' } } : prev); } finally { if (isMounted.current) setIsSaving(false); } }; reader.readAsDataURL(file); }; const handleSubmit = (e) => { e.preventDefault(); saveEditedEntity(); }; let title = "Modifier l'élément"; if (isLot) title = editingEntity.location.index !== undefined ? "Modifier le lot" : "Nouveau lot"; else if (isIntervenant) title = editingEntity.location.index !== undefined ? "Modifier l'intervenant" : "Nouvel intervenant"; else title = editingEntity.location.index !== undefined ? "Modifier l'entreprise" : "Nouvelle entreprise"; // 4. - Rendu UI return ( { setEditingEntity(null); if (onClose) onClose(); }} isSaving={isSaving} isDirty={isDirty} formId="entity-form" zIndex="z-[250]" >
{!isLot && (
setEditingEntity(prev => prev ? {...prev, data: {...prev.data, siret: e.target.value.replace(/\s/g, '')}} : prev)} placeholder="Saisir SIRET pour auto-remplir" className="flex-1 min-w-0 border-2 border-slate-200 rounded-xl p-3 focus:border-emerald-500 outline-none transition font-bold" maxLength={14} disabled={isSaving} />
)}
setEditingEntity(prev => prev ? {...prev, data: {...prev.data, name: e.target.value}} : prev)} className="w-full border-2 border-slate-200 rounded-xl p-3 focus:border-emerald-500 outline-none transition font-bold" required autoFocus disabled={isSaving} />
{isIntervenant && (
{roleType === 'Personnalisé' && ( setEditingEntity(prev => prev ? {...prev, data: {...prev.data, role: e.target.value}} : prev)} placeholder="Précisez la fonction" className="w-full border-2 border-emerald-200 rounded-xl p-3 mt-2 focus:border-emerald-500 outline-none transition font-bold bg-emerald-50" required disabled={isSaving} /> )}
)} {!isLot && (
Coordonnées (optionnel)
setEditingEntity(prev => prev ? {...prev, data: {...prev.data, address: e.target.value}} : prev)} className="w-full border border-slate-200 rounded-lg p-2.5 text-sm focus:border-emerald-500 outline-none transition font-medium" disabled={isSaving} />
setEditingEntity(prev => prev ? {...prev, data: {...prev.data, phone: e.target.value}} : prev)} className="w-full border border-slate-200 rounded-lg p-2.5 text-sm focus:border-emerald-500 outline-none transition font-medium" disabled={isSaving} />
setEditingEntity(prev => prev ? {...prev, data: {...prev.data, email: e.target.value}} : prev)} className="w-full border border-slate-200 rounded-lg p-2.5 text-sm focus:border-emerald-500 outline-none transition font-medium" disabled={isSaving} />
setEditingEntity(prev => prev ? {...prev, data: {...prev.data, website: e.target.value}} : prev)} className="w-full border border-slate-200 rounded-lg p-2.5 text-sm focus:border-emerald-500 outline-none transition font-medium" disabled={isSaving} />
{(editingEntity.data.logoUrl || editingEntity.data.logoId) && (
Logo {Button && Trash2Icon && !isSaving && (
)}
)}
); }; /* EOF ========== [__react/socle/_socle_editeur_entite.jsx] */