ImmoGuardIA / index.html
jcalbornoz's picture
Update index.html
111d50d verified
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>InmoGuard V35</title>
<style>
:root { --p: #0f172a; --a: #3b82f6; --s: #10b981; --d: #ef4444; --w: #f59e0b; --bg: #f8fafc; }
body { font-family: 'Segoe UI', sans-serif; background: var(--bg); padding: 20px; color: #334155; }
.container { max-width: 1450px; margin: 0 auto; }
.header { text-align: center; margin-bottom: 25px; }
.header h1 { margin: 0; color: var(--p); font-size: 2rem; }
.header span { color: var(--a); }
.dropzone { background: white; border: 2px dashed #cbd5e1; padding: 30px; text-align: center; cursor: pointer; border-radius: 10px; transition: 0.3s; }
.dropzone:hover { border-color: var(--a); background: #eff6ff; }
.btn-group { text-align: center; margin-top: 20px; }
button { padding: 12px 25px; border: none; border-radius: 6px; font-weight: bold; cursor: pointer; margin: 5px; color: white; font-size: 1rem; }
.btn-go { background: var(--a); }
.btn-pdf { background: var(--d); display: none; }
.btn-json { background: #8b5cf6; display: none; }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); gap: 20px; margin-top: 30px; display: none; }
.card { background: white; padding: 20px; border-radius: 8px; border-top: 5px solid #94a3b8; box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1); }
.card h3 { margin-top: 0; color: var(--p); border-bottom: 1px solid #e2e8f0; padding-bottom: 10px; font-size: 1.15rem; }
/* COLORES */
.c-sae { border-top-color: var(--d); background: #fff5f5; }
.c-hist { border-top-color: var(--a); grid-column: span 2; }
.c-vur { border-top-color: var(--w); grid-column: 1 / -1; }
.c-amb { border-top-color: var(--s); }
.c-riesgo { border-top-color: var(--p); }
.lbl { font-weight: bold; font-size: 0.85rem; color: #64748b; display: block; margin-top: 8px; text-transform: uppercase; }
.val { font-weight: 500; font-size: 1rem; color: #1e293b; }
/* RIESGOS */
.risk-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 5px; font-size: 0.9em; }
.bar-bg { flex: 1; height: 8px; background: #e2e8f0; border-radius: 4px; margin-left: 10px; overflow: hidden; }
.bar-fill { height: 100%; transition: width 0.5s; }
.bg-low { background: var(--s); width: 33%; }
.bg-med { background: var(--w); width: 66%; }
.bg-high { background: var(--d); width: 100%; }
table { width: 100%; border-collapse: collapse; font-size: 0.9rem; margin-top: 10px; }
th { text-align: left; padding: 8px; background: #f8fafc; color: #475569; border-bottom: 2px solid #e2e8f0; }
td { padding: 8px; border-bottom: 1px solid #e2e8f0; }
.tag-vig { color: #b91c1c; font-weight: bold; background: #fee2e2; padding: 2px 6px; border-radius: 4px; }
.tag-cancel { color: #15803d; background: #dcfce7; padding: 2px 6px; border-radius: 4px; font-style: italic; }
iframe { width: 100%; height: 250px; border: none; background: #e2e8f0; border-radius: 6px; }
#status { text-align: center; margin-top: 15px; font-weight: bold; color: #64748b; }
#err-box { background: #fee2e2; color: #b91c1c; padding: 15px; border-radius: 8px; margin-top: 20px; display: none; text-align: center; border: 1px solid #fecaca; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>🛡️ InmoGuard <span>AI V35</span></h1>
<p style="color:#64748b">Análisis Multi-Activo & Localización Profunda</p>
</div>
<div class="dropzone" onclick="document.getElementById('files').click()">
<h3>📂 Cargar Expediente</h3>
<p id="prev-txt">Soporta PDFs y Fotos</p>
<input type="file" id="files" multiple style="display:none" onchange="document.getElementById('prev-txt').innerText = `${this.files.length} Archivos`">
</div>
<div class="btn-group">
<button class="btn-go" id="btnGo" onclick="run()">🔍 Analizar Completo</button>
<button class="btn-pdf" id="btnPdf" onclick="dl('pdf')">📄 PDF</button>
<button class="btn-json" id="btnJson" onclick="dl('json')">💾 JSON</button>
</div>
<div id="status"></div>
<div id="err-box"></div>
<div id="dash" class="grid">
<div class="card" style="border-top-color: #3b82f6;">
<h3>🏠 Identificación Legal</h3>
<span class="lbl">FMI / Matrículas Detectadas:</span>
<span class="val" id="fmi" style="color:var(--a); font-weight:bold; display:block; margin-top:5px; line-height:1.4;"></span>
<span class="lbl">Cédula Catastral:</span> <span class="val" id="cedula" style="font-weight:bold;"></span>
<span class="lbl">Dirección:</span> <span class="val" id="dir"></span>
</div>
<div class="card c-riesgo">
<h3>🚥 Tablero de Riesgos</h3>
<div id="risk-box"></div>
</div>
<div class="card c-sae">
<h3>⚖️ Análisis Ley 1708 (SAE)</h3>
<span class="lbl">Estado:</span> <span class="val" id="sae-st"></span>
<span class="lbl">Concepto Legal:</span> <p class="val" id="sae-leg" style="font-size:0.9rem; font-style:italic"></p>
<span class="lbl">Viabilidad FRISCO:</span> <span class="val" id="sae-via" style="font-weight:bold;"></span>
</div>
<div class="card c-hist">
<h3>📜 Historial de Propiedad (Cadena)</h3>
<div id="hist-table"></div>
</div>
<div class="card c-amb">
<h3>🌳 Ambiental & Urbanístico</h3>
<span class="lbl">Restricciones:</span> <span class="val" id="amb-res"></span>
<span class="lbl">Autoridad:</span> <span class="val" id="amb-aut"></span>
</div>
<div class="card c-vur">
<h3>📑 VUR Detallado</h3>
<div id="vur-table"></div>
<div style="margin-top:15px; padding:10px; background:#fff7ed; border-radius:5px">
<span class="lbl" style="color:#c2410c; margin:0">Falsa Tradición:</span> <span class="val" id="falsa"></span>
</div>
</div>
<div class="card c-fisc">
<h3>💰 Fiscal Detallado</h3>
<span class="lbl">Municipal:</span><span class="val" id="fisc-mun"></span>
<span class="lbl">Departamental:</span><span class="val" id="fisc-dep"></span>
<span class="lbl">Avalúo:</span><span class="val" id="fisc-ava"></span>
</div>
<div class="card"><h3>🏢 Corporativo</h3><span class="lbl">Rep Legal:</span><span class="val" id="rep"></span></div>
<div class="card"><h3>🚨 LAFT</h3><span class="val" id="alertas"></span></div>
<div class="card"><h3>📍 Mapa</h3><div id="map-box"></div></div>
<div class="card c-res" style="grid-column: 1 / -1; background:#e2e8f0; border-top-color:var(--p)">
<h3>🏁 Dictamen Final</h3>
<h2 id="res-t" style="text-align:center;"></h2>
<p id="res-d" style="padding:0 15px; font-size:1.05rem; line-height:1.6"></p>
</div>
</div>
</div>
<script>
let gData = null;
async function run() {
let f = document.getElementById('files').files;
if(!f.length) return alert("Sube archivos");
document.getElementById('status').innerText = "⏳ Consultando Ley 1708, VUR y FMI Múltiples...";
document.getElementById('btnGo').disabled = true;
document.getElementById('err-box').style.display = 'none';
let fd = new FormData();
for(let x of f) fd.append('files', x);
try {
let req = await fetch('/analyze', { method: 'POST', body: fd });
let res = await req.json();
if(res.error) {
document.getElementById('err-box').innerText = "❌ " + res.msg;
document.getElementById('err-box').style.display = 'block';
document.getElementById('status').innerText = "";
} else {
gData = res;
render(res);
document.getElementById('status').innerText = "✅ Análisis Completado";
}
} catch(e) {
document.getElementById('err-box').innerText = "❌ Error Red: " + e.message;
document.getElementById('err-box').style.display = 'block';
}
document.getElementById('btnGo').disabled = false;
}
function render(d) {
document.getElementById('dash').style.display = 'grid';
document.getElementById('btnPdf').style.display = 'inline-block';
document.getElementById('btnJson').style.display = 'inline-block';
const get = (o, k) => (o && o[k]) ? o[k] : '---';
const m=d.meta||{}, sae=d.analisis_sae_ley||{}, hist=d.historial_propiedad||[], amb=d.ambiental||{}, fisc=d.fiscal_completo||{};
const v=d.vur||{}, end=d.dic||{}, c=d.corp||{}, l=d.laft||{}, val=d.val||{}, sem=d.semaforo_riesgos||{};
document.getElementById('fmi').innerText = get(m,'fmi');
// FIX CÉDULA OBJECT
let ced = m.cedula_catastral;
document.getElementById('cedula').innerText = (typeof ced === 'object') ? JSON.stringify(ced) : (ced || '---');
document.getElementById('dir').innerText = get(m,'dir_legal');
// Riesgos Visuales
let rHtml = "";
for(let k in sem) {
let s = (sem[k]||"BAJO").toUpperCase();
let cls = s.includes("ALTO")?"bg-high":(s.includes("MEDIO")?"bg-med":"bg-low");
rHtml += `<div class="risk-row"><span>${k.toUpperCase()}</span><div class="bar-bg"><div class="bar-fill ${cls}"></div></div></div>`;
}
document.getElementById('risk-box').innerHTML = rHtml;
// SAE
document.getElementById('sae-st').innerText = get(sae,'estado_proceso');
document.getElementById('sae-leg').innerText = get(sae,'fundamento_legal');
document.getElementById('sae-via').innerText = get(sae,'viabilidad_comercializacion');
// Ambiental
document.getElementById('amb-res').innerText = get(amb,'restricciones');
document.getElementById('amb-aut').innerText = get(amb,'autoridad');
// Historial
let hh = "<table style='width:100%'><tr><th>Fecha</th><th>Acto</th><th>Detalle</th></tr>";
hist.forEach(x => hh+=`<tr><td>${x.fecha||''}</td><td>${x.acto||''}</td><td>${x.detalles||''}</td></tr>`);
document.getElementById('hist-table').innerHTML = hh + "</table>";
// VUR
document.getElementById('falsa').innerText = get(v,'falsa_tradicion');
let hv = "<table><tr><th>Nro</th><th>Desc</th><th>Estado</th></tr>";
(v.anotaciones_detalle||[]).forEach(x => {
let st = x.estado || '---';
let cls = st.toUpperCase().includes('VIGENTE') ? 'tag-vig' : 'tag-cancel';
hv += `<tr><td>${x.nro}</td><td>${x.desc}</td><td><span class="${cls}">${st}</span></td></tr>`;
});
document.getElementById('vur-table').innerHTML = hv + "</table>";
// Fiscal
document.getElementById('fisc-mun').innerText = get(fisc,'municipal');
document.getElementById('fisc-dep').innerText = get(fisc,'departamental');
document.getElementById('fisc-ava').innerText = get(fisc,'avaluo');
// Otros
document.getElementById('rep').innerText = get(c,'rep');
document.getElementById('alertas').innerText = get(l,'alertas');
if(d.mapa) {
let fr = document.createElement('iframe'); fr.srcdoc = d.mapa;
document.getElementById('map-box').innerHTML = ''; document.getElementById('map-box').appendChild(fr);
} else document.getElementById('map-box').innerHTML = '<div style="padding:30px; text-align:center; color:#94a3b8">Ubicación no encontrada</div>';
let r = get(end,'res');
let el = document.getElementById('res-t');
el.innerText = r;
el.style.color = r.includes('NO') ? 'var(--d)' : 'var(--s)';
document.getElementById('res-d').innerText = get(end,'txt');
}
async function dl(t) {
if(!gData) return;
try {
let ep = t === 'pdf' ? '/print-pdf' : '/download-json';
let req = await fetch(ep, {method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify(gData)});
let b = await req.blob();
let url = window.URL.createObjectURL(b);
let a = document.createElement('a'); a.href=url; a.download=`Informe.${t}`; a.click();
} catch(e) { alert("Error descarga"); }
}
</script>
</body>
</html>