[31388f42] Restructure Lead Engine UI: vertical layout with 2-column top section for source data

This commit is contained in:
2026-03-02 13:35:18 +00:00
parent 0734256c11
commit 7579c78f3a

View File

@@ -129,120 +129,105 @@ if not df.empty:
except:
pass
with st.expander(f"{date_str} | {row['company_name']} ({row['status']})"):
# Quality Warning
with st.expander(f"{date_str} | {row['company_name']}"):
# Metadata Parsing
meta = {}
if row.get('lead_metadata'):
try: meta = json.loads(row['lead_metadata'])
except: pass
# --- TOP SECTION: QUALITY WARNING ---
if meta.get('is_low_quality'):
st.warning("⚠️ Low Quality Lead detected (Free-mail or missing company). Use for reclamation if applicable.")
st.warning("⚠️ **Low Quality Lead detected** (Free-mail or missing company).")
# --- SECTION 1: LEAD INFO (2 Columns) ---
st.markdown("### 📋 Lead Data")
c1, c2 = st.columns(2)
# --- Left Column: Lead Data ---
c1.write(f"**Contact:** {row['contact_name']}")
c1.write(f"**Email:** {row['email']}")
# Metadata Display
meta = {}
if row.get('lead_metadata'):
try:
meta = json.loads(row['lead_metadata'])
except:
pass
role = meta.get('role')
if role:
c1.info(f"**Role:** {role}")
else:
if c1.button("🔍 Find Role (SerpAPI)", key=f"role_{row['id']}"):
from enrich import enrich_contact_role
with st.spinner("Searching LinkedIn via Google..."):
found_role = enrich_contact_role(row)
if found_role:
st.success(f"Found: {found_role}")
st.rerun()
else:
st.error("No role found.")
if meta:
c1.write("---")
c1.write(f"**Area:** {meta.get('area', '-')}")
c1.write(f"**Purpose:** {meta.get('purpose', '-')}")
c1.write(f"**Location:** {meta.get('zip', '')} {meta.get('city', '')}")
# Manual Sync Button for individual lead
if row['status'] == 'new':
if c1.button("🚀 Sync to Company Explorer", key=f"sync_single_{row['id']}"):
with st.spinner("Processing lead (Role + CE Sync)..."):
res = sync_single_lead(row['id'])
if res.get('status') != 'error':
st.success("Lead synced successfully!")
st.rerun()
else:
st.error(f"Sync failed: {res.get('message')}")
else:
if c1.button("🔄 Reset Status to New", key=f"reset_{row['id']}"):
reset_lead(row['id'])
st.toast("Lead status reset.")
st.rerun()
with c1.expander("Show Original Email Content"):
st.text(clean_html_to_text(row['raw_body']))
if st.checkbox("Show Raw HTML", key=f"raw_{row['id']}"):
st.code(row['raw_body'], language="html")
# --- Right Column: Enrichment & Response ---
enrichment = json.loads(row['enrichment_data']) if row['enrichment_data'] else {}
if enrichment:
c2.write("--- Integration Status ---")
ce_id = enrichment.get('ce_id')
with c1:
st.write(f"**Contact:** {row['contact_name']}")
st.write(f"**Email:** {row['email']}")
if ce_id:
c2.success(f"✅ Linked to Company Explorer (ID: {ce_id})")
# CE Data Display
ce_data = enrichment.get('ce_data', {})
# Support both names (CE uses industry_ai internally)
vertical = ce_data.get('industry_ai') or ce_data.get('vertical')
summary = ce_data.get('research_dossier') or ce_data.get('summary')
if vertical and vertical != 'None':
c2.info(f"**Industry:** {vertical}")
else:
c2.warning("Industry Analysis pending...")
if summary:
with c2.expander("Show Analysis Summary"):
st.write(summary)
# Refresh Button
if c2.button("🔄 Refresh Analysis Data", key=f"refresh_{row['id']}"):
with st.spinner("Fetching latest data from Company Explorer..."):
new_data = refresh_ce_data(row['id'], ce_id)
st.toast("Data refreshed!")
st.rerun()
# Generate Reply Button (only if we have data)
c2.write("--- Response Generation ---")
if c2.button("✨ Generate Expert Reply", key=f"gen_{row['id']}"):
with st.spinner("Generating draft with Gemini..."):
# Prepare lead data dict from row
lead_dict = row.to_dict()
draft = generate_email_draft(lead_dict, ce_data)
# Store draft in session state to persist
st.session_state[f"draft_{row['id']}"] = draft
# Display Draft
if f"draft_{row['id']}" in st.session_state:
c2.text_area("Draft Email", value=st.session_state[f"draft_{row['id']}"], height=300)
role = meta.get('role')
if role:
st.info(f"**Role:** {role}")
else:
c2.warning("⚠️ Not yet synced or failed")
c2.info(f"Log: {enrichment.get('message')}")
if st.button("🔍 Find Role", key=f"role_{row['id']}"):
from enrich import enrich_contact_role
with st.spinner("Searching..."):
found_role = enrich_contact_role(row)
if found_role: st.success(f"Found: {found_role}"); st.rerun()
else: st.error("No role found.")
with c2:
st.write(f"**Area:** {meta.get('area', '-')}")
st.write(f"**Purpose:** {meta.get('purpose', '-')}")
st.write(f"**Location:** {meta.get('zip', '')} {meta.get('city', '')}")
with st.expander("Original Body Preview"):
st.text(clean_html_to_text(row['raw_body']))
if st.checkbox("Show HTML", key=f"raw_{row['id']}"):
st.code(row['raw_body'], language="html")
st.divider()
# --- SECTION 2: INTELLIGENCE (CE) ---
st.markdown("### 🔍 Intelligence (CE)")
enrichment = json.loads(row['enrichment_data']) if row['enrichment_data'] else {}
ce_id = enrichment.get('ce_id')
if ce_id:
st.success(f"✅ Linked to Company Explorer (ID: {ce_id})")
ce_data = enrichment.get('ce_data', {})
vertical = ce_data.get('industry_ai') or ce_data.get('vertical')
summary = ce_data.get('research_dossier') or ce_data.get('summary')
intel_col1, intel_col2 = st.columns([1, 2])
with intel_col1:
if vertical and vertical != 'None':
st.info(f"**Industry:** {vertical}")
else:
st.warning("Industry Analysis pending...")
if st.button("🔄 Refresh CE Data", key=f"refresh_{row['id']}"):
with st.spinner("Fetching..."):
refresh_ce_data(row['id'], ce_id)
st.rerun()
with intel_col2:
if summary:
with st.expander("Show AI Research Dossier", expanded=True):
st.write(summary)
else:
st.warning("⚠️ Not synced with Company Explorer yet")
if st.button("🚀 Sync to Company Explorer", key=f"sync_single_{row['id']}"):
with st.spinner("Syncing..."):
sync_single_lead(row['id'])
st.rerun()
st.divider()
# --- SECTION 3: RESPONSE DRAFT ---
st.markdown("### ✉️ Response Draft")
if row['status'] != 'new' and ce_id:
if st.button("✨ Generate Expert Reply", key=f"gen_{row['id']}", type="primary"):
with st.spinner("Writing email..."):
ce_data = enrichment.get('ce_data', {})
draft = generate_email_draft(row.to_dict(), ce_data)
st.session_state[f"draft_{row['id']}"] = draft
if f"draft_{row['id']}" in st.session_state:
st.text_area("Email Entwurf", value=st.session_state[f"draft_{row['id']}"], height=400)
st.button("📋 Copy to Clipboard", key=f"copy_{row['id']}", on_click=lambda: st.write("Copy functionality simulated"))
else:
st.info("Sync with Company Explorer first to generate a response.")
if row['status'] != 'new':
st.markdown("---")
if st.button("🔄 Reset Lead Status", key=f"reset_{row['id']}", help="Back to 'new' status"):
reset_lead(row['id'])
st.rerun()
else:
st.info("No leads found. Click 'Ingest Emails' in the sidebar.")