feat: Agente-Marketing initial commit
This commit is contained in:
@@ -0,0 +1,224 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}{{ prop.address }} — Casa Hunter FL{% endblock %}
|
||||
{% block content %}
|
||||
|
||||
<nav aria-label="breadcrumb" class="mb-3">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="/">Dashboard</a></li>
|
||||
<li class="breadcrumb-item"><a href="/properties">Propiedades</a></li>
|
||||
<li class="breadcrumb-item active">Detalle</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<div class="row g-4">
|
||||
<!-- Left Column -->
|
||||
<div class="col-12 col-lg-8">
|
||||
<div class="card mb-3">
|
||||
{% if prop.image_url %}
|
||||
<img src="{{ prop.image_url }}" class="card-img-top" style="height:280px;object-fit:cover;border-radius:12px 12px 0 0" alt="">
|
||||
{% else %}
|
||||
<div style="height:180px;background:linear-gradient(135deg,#1a3a5c,#2d6a9f);border-radius:12px 12px 0 0;display:flex;align-items:center;justify-content:center">
|
||||
<i class="fas fa-home fa-4x text-white opacity-40"></i>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="card-body">
|
||||
<div class="d-flex flex-wrap justify-content-between align-items-start gap-2 mb-3">
|
||||
<div>
|
||||
<span class="source-tag me-2">{{ prop.source }}</span>
|
||||
<span class="badge bg-secondary">{{ prop.status }}</span>
|
||||
</div>
|
||||
<span class="score-badge {% if prop.score >= 75 %}score-high{% elif prop.score >= 50 %}score-mid{% else %}score-low{% endif %} fs-6">
|
||||
Score: {{ prop.score }}/100
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<h3 class="prop-price mb-1">${{ "{:,.0f}".format(prop.price) }}</h3>
|
||||
<p class="text-muted mb-1"><i class="fas fa-map-marker-alt me-1"></i>{{ prop.address }}</p>
|
||||
<p class="text-muted small mb-3">{{ prop.city }}{% if prop.county %}, {{ prop.county }} County{% endif %}, FL {{ prop.zipcode }}</p>
|
||||
|
||||
<div class="row text-center g-2 mb-3">
|
||||
{% if prop.beds %}
|
||||
<div class="col-4">
|
||||
<div class="border rounded p-2">
|
||||
<i class="fas fa-bed text-muted d-block mb-1"></i>
|
||||
<strong>{{ prop.beds }}</strong><br><small class="text-muted">Habitaciones</small>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if prop.baths %}
|
||||
<div class="col-4">
|
||||
<div class="border rounded p-2">
|
||||
<i class="fas fa-bath text-muted d-block mb-1"></i>
|
||||
<strong>{{ prop.baths }}</strong><br><small class="text-muted">Baños</small>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if prop.sqft %}
|
||||
<div class="col-4">
|
||||
<div class="border rounded p-2">
|
||||
<i class="fas fa-ruler-combined text-muted d-block mb-1"></i>
|
||||
<strong>{{ prop.sqft }}</strong><br><small class="text-muted">Sq Ft</small>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="d-flex gap-2 flex-wrap">
|
||||
{% if prop.url %}
|
||||
<a href="{{ prop.url }}" target="_blank" class="btn btn-primary"><i class="fas fa-external-link-alt me-2"></i>Ver en {{ prop.source }}</a>
|
||||
{% endif %}
|
||||
<button class="btn {% if prop.is_favorite %}btn-warning{% else %}btn-outline-warning{% endif %}" onclick="toggleFav({{ prop.id }}, this)">
|
||||
<i class="fas fa-star me-1"></i>{% if prop.is_favorite %}Guardada{% else %}Guardar{% endif %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AI Analysis -->
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<h6 class="fw-bold mb-3" style="color:var(--primary)"><i class="fas fa-robot me-2" style="color:var(--accent)"></i>Análisis con IA (qwen2.5)</h6>
|
||||
<div id="ai-result">
|
||||
{% if prop.ai_analysis %}
|
||||
<div class="action-kit">{{ prop.ai_analysis }}</div>
|
||||
{% else %}
|
||||
<p class="text-muted">Aún no se ha analizado esta propiedad.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<button class="btn btn-sm btn-primary mt-3" onclick="runAnalysis({{ prop.id }})">
|
||||
<i class="fas fa-magic me-1"></i>{% if prop.ai_analysis %}Re-analizar{% else %}Analizar con IA{% endif %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Notes -->
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h6 class="fw-bold mb-2" style="color:var(--primary)"><i class="fas fa-sticky-note me-2"></i>Mis Notas</h6>
|
||||
<textarea class="form-control mb-2" id="notes" rows="3" placeholder="Agrega notas sobre esta propiedad...">{{ prop.notes or '' }}</textarea>
|
||||
<button class="btn btn-sm btn-outline-primary" onclick="saveNotes({{ prop.id }})"><i class="fas fa-save me-1"></i>Guardar Notas</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Right Column: Action Kit -->
|
||||
<div class="col-12 col-lg-4">
|
||||
<!-- Action Kit -->
|
||||
<div class="card mb-3" style="border-left:4px solid var(--accent)">
|
||||
<div class="card-body">
|
||||
<h6 class="fw-bold mb-3" style="color:var(--primary)"><i class="fas fa-clipboard-list me-2" style="color:var(--accent)"></i>Kit de Acción</h6>
|
||||
|
||||
<p class="small fw-bold text-muted mb-2">DOCUMENTOS A PREPARAR</p>
|
||||
<ul class="small mb-3">
|
||||
<li>Green card o visa + pasaporte</li>
|
||||
<li>12-24 meses de estados de cuenta bancarios</li>
|
||||
<li>Comprobante de ingresos (facturas de trabajo)</li>
|
||||
<li>Carta del landlord confirmando pagos de renta</li>
|
||||
<li>Carta explicando tu situación laboral (self-employed)</li>
|
||||
<li>Evidencia de los $50,000 disponibles (bank statement)</li>
|
||||
</ul>
|
||||
|
||||
<p class="small fw-bold text-muted mb-2">PASOS A SEGUIR</p>
|
||||
<ol class="small mb-3">
|
||||
<li>Llama a 2-3 lenders de la lista (empieza con Heart Mortgage y Jhenesis)</li>
|
||||
<li>Pide una pre-qualification letter</li>
|
||||
<li>Contrata un inspector de propiedades ($300-500)</li>
|
||||
<li>Si es HUD/Fannie Mae, necesitas un agente de bienes raíces aprobado</li>
|
||||
<li>Presenta oferta con pre-qual letter y prueba de fondos</li>
|
||||
</ol>
|
||||
|
||||
<div class="bg-light rounded p-2 small">
|
||||
<strong><i class="fas fa-calculator me-1"></i>Estimado para esta propiedad:</strong><br>
|
||||
Down payment (25%): <strong>${{ "{:,.0f}".format(prop.price * 0.25) }}</strong><br>
|
||||
Préstamo estimado: <strong>${{ "{:,.0f}".format(prop.price * 0.75) }}</strong><br>
|
||||
Cuota aprox (7.5%, 30 años): <strong>${{ "{:,.0f}".format(prop.price * 0.75 * 0.007) }}/mes</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Recommended Lenders -->
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h6 class="fw-bold mb-3" style="color:var(--primary)"><i class="fas fa-handshake me-2" style="color:var(--accent)"></i>Lenders para Esta Compra</h6>
|
||||
{% for l in lenders[:4] %}
|
||||
<div class="border rounded p-2 mb-2">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<strong class="small">{{ l.name }}</strong>
|
||||
<span class="badge" style="background:var(--accent);color:#fff">{{ l.match_score }}%</span>
|
||||
</div>
|
||||
<small class="text-muted">{{ l.loan_type }}</small><br>
|
||||
<a href="{{ l.website }}" target="_blank" class="btn btn-xs btn-outline-primary btn-sm mt-1" style="font-size:.7rem;padding:2px 8px">
|
||||
<i class="fas fa-globe me-1"></i>Visitar
|
||||
</a>
|
||||
<button class="btn btn-xs btn-outline-secondary btn-sm mt-1 ms-1" style="font-size:.7rem;padding:2px 8px"
|
||||
onclick="showScript('{{ l.name|e }}', `{{ l.contact_script|e }}`)">
|
||||
<i class="fas fa-phone me-1"></i>Script
|
||||
</button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<a href="/lenders" class="btn btn-sm btn-outline-primary w-100 mt-1">Ver todos los lenders</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Script Modal -->
|
||||
<div class="modal fade" id="scriptModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h6 class="modal-title fw-bold" id="scriptTitle"></h6>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p class="text-muted small mb-2">Usa este guión cuando los contactes:</p>
|
||||
<div class="action-kit" id="scriptContent"></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button onclick="copyScript()" class="btn btn-sm btn-primary"><i class="fas fa-copy me-1"></i>Copiar</button>
|
||||
<button type="button" class="btn btn-sm btn-secondary" data-bs-dismiss="modal">Cerrar</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
<script>
|
||||
function toggleFav(id, btn) {
|
||||
fetch(`/property/${id}/favorite`, {method:'POST'})
|
||||
.then(r=>r.json())
|
||||
.then(d => {
|
||||
btn.className = d.is_favorite ? 'btn btn-warning' : 'btn btn-outline-warning';
|
||||
btn.innerHTML = `<i class="fas fa-star me-1"></i>${d.is_favorite ? 'Guardada' : 'Guardar'}`;
|
||||
});
|
||||
}
|
||||
function runAnalysis(id) {
|
||||
document.getElementById('ai-result').innerHTML = '<div class="text-center py-3"><div class="spinner-border spinner-border-sm me-2"></div>Analizando con qwen2.5...</div>';
|
||||
fetch(`/property/${id}/analyze`, {method:'POST'})
|
||||
.then(r=>r.json())
|
||||
.then(d => {
|
||||
const container = document.createElement('div');
|
||||
container.className = 'action-kit';
|
||||
container.textContent = d.analysis;
|
||||
const wrapper = document.getElementById('ai-result');
|
||||
wrapper.innerHTML = '';
|
||||
wrapper.appendChild(container);
|
||||
});
|
||||
}
|
||||
function saveNotes(id) {
|
||||
const notes = document.getElementById('notes').value;
|
||||
fetch(`/property/${id}/notes`, {method:'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({notes})})
|
||||
.then(()=>alert('Notas guardadas'));
|
||||
}
|
||||
function showScript(name, script) {
|
||||
document.getElementById('scriptTitle').textContent = 'Script: ' + name;
|
||||
document.getElementById('scriptContent').textContent = script;
|
||||
new bootstrap.Modal(document.getElementById('scriptModal')).show();
|
||||
}
|
||||
function copyScript() {
|
||||
navigator.clipboard.writeText(document.getElementById('scriptContent').textContent);
|
||||
alert('Script copiado al portapapeles');
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user