lead-qualification / templates /ai_lead_analysis.html
sksameermujahid's picture
Upload 15 files
adb96cf verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>πŸ€– AI Lead Analysis Dashboard</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
:root {
--primary-color: #2563eb;
--secondary-color: #7c3aed;
--accent-color: #059669;
--success-color: #10b981;
--warning-color: #f59e0b;
--danger-color: #ef4444;
--light-color: #f8fafc;
--dark-color: #1e293b;
--info-color: #0ea5e9;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Inter', 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #f1f5f9;
color: var(--dark-color);
line-height: 1.6;
min-height: 100vh;
}
.main-container {
max-width: 1400px;
margin: 0 auto;
padding: 20px;
}
/* Header Styles */
.hero-header {
background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%);
color: white;
border-radius: 20px;
padding: 40px;
margin-bottom: 30px;
text-align: center;
box-shadow: 0 20px 40px rgba(37, 99, 235, 0.2);
}
.hero-header h1 {
font-size: 3rem;
font-weight: 700;
margin-bottom: 15px;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
}
.hero-header p {
font-size: 1.3rem;
margin-bottom: 25px;
opacity: 0.95;
}
.ai-badge {
background: rgba(255, 255, 255, 0.2);
color: white;
padding: 12px 25px;
border-radius: 50px;
font-size: 1.1rem;
font-weight: 600;
display: inline-block;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.3);
}
/* Card Styles */
.card {
background: white;
border-radius: 16px;
padding: 30px;
margin-bottom: 25px;
box-shadow: 0 4px 25px rgba(0, 0, 0, 0.08);
border: 1px solid #e2e8f0;
transition: all 0.3s ease;
}
.card:hover {
transform: translateY(-2px);
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.12);
}
.card h3 {
color: var(--dark-color);
font-weight: 600;
margin-bottom: 20px;
font-size: 1.5rem;
display: flex;
align-items: center;
gap: 10px;
}
.card h4 {
color: var(--primary-color);
font-weight: 600;
margin-bottom: 15px;
font-size: 1.2rem;
}
/* Form Styles */
.form-control {
border: 2px solid #e2e8f0;
border-radius: 12px;
padding: 15px;
font-size: 1rem;
transition: all 0.3s ease;
background: white;
color: var(--dark-color);
}
.form-control:focus {
border-color: var(--primary-color);
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
outline: none;
}
.form-label {
color: var(--dark-color);
font-weight: 600;
margin-bottom: 8px;
font-size: 1rem;
}
/* Button Styles */
.btn {
border-radius: 12px;
padding: 12px 25px;
font-weight: 600;
font-size: 1rem;
transition: all 0.3s ease;
border: none;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 8px;
}
.btn-primary {
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
color: white;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(37, 99, 235, 0.3);
}
.btn-success {
background: var(--success-color);
color: white;
}
.btn-success:hover {
background: #059669;
transform: translateY(-2px);
}
.btn-warning {
background: var(--warning-color);
color: white;
}
.btn-info {
background: var(--info-color);
color: white;
}
.btn-danger {
background: var(--danger-color);
color: white;
}
.btn-outline-purple {
background: transparent;
border: 2px solid var(--secondary-color);
color: var(--secondary-color);
}
.btn-outline-purple:hover {
background: var(--secondary-color);
border-color: var(--secondary-color);
color: white;
transform: translateY(-2px);
}
.btn-secondary {
background: #6c757d;
color: white;
}
.btn-outline-success {
background: transparent;
border: 2px solid var(--success-color);
color: var(--success-color);
}
.btn-outline-success:hover {
background: var(--success-color);
color: white;
transform: translateY(-2px);
}
.btn-outline-info {
background: transparent;
border: 2px solid var(--info-color);
color: var(--info-color);
}
.btn-outline-info:hover {
background: var(--info-color);
color: white;
transform: translateY(-2px);
}
.btn-outline-warning {
background: transparent;
border: 2px solid var(--warning-color);
color: var(--warning-color);
}
.btn-outline-warning:hover {
background: var(--warning-color);
color: white;
transform: translateY(-2px);
}
/* Metric Cards */
.metric-card {
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
color: white;
border-radius: 16px;
padding: 25px;
text-align: center;
transition: transform 0.3s ease;
}
.metric-card:hover {
transform: translateY(-3px);
}
.metric-value {
font-size: 2.5rem;
font-weight: 700;
margin-bottom: 8px;
}
.metric-label {
font-size: 1rem;
opacity: 0.9;
font-weight: 500;
}
/* Alert Styles */
.alert {
border: none;
border-radius: 12px;
padding: 20px;
margin-bottom: 20px;
font-weight: 500;
}
.alert-success {
background: linear-gradient(135deg, #d1fae5, #a7f3d0);
color: #065f46;
border-left: 4px solid var(--success-color);
}
.alert-info {
background: linear-gradient(135deg, #dbeafe, #bfdbfe);
color: #1e40af;
border-left: 4px solid var(--info-color);
}
.alert-warning {
background: linear-gradient(135deg, #fef3c7, #fde68a);
color: #92400e;
border-left: 4px solid var(--warning-color);
}
.alert-danger {
background: linear-gradient(135deg, #fee2e2, #fca5a5);
color: #991b1b;
border-left: 4px solid var(--danger-color);
}
/* Email Section Specific Styles */
.email-section {
background: white;
border: 2px solid #e2e8f0;
border-radius: 16px;
padding: 30px;
margin-bottom: 30px;
}
.email-section h3 {
color: var(--dark-color);
margin-bottom: 25px;
font-weight: 600;
}
.email-section .form-control {
background: #f8fafc;
border: 2px solid #e2e8f0;
color: var(--dark-color);
}
.email-section .form-control::placeholder {
color: #64748b;
}
.email-section .form-control:focus {
background: white;
border-color: var(--primary-color);
}
/* Timeline Styles */
.timeline {
background: #f8fafc;
border-radius: 12px;
padding: 20px;
}
.timeline-item {
background: white;
border: 1px solid #e2e8f0;
border-radius: 8px;
padding: 15px;
margin-bottom: 10px;
color: var(--dark-color);
font-weight: 500;
}
/* Property Cards */
.property-item {
background: white;
border: 1px solid #e2e8f0;
border-radius: 12px;
padding: 20px;
transition: all 0.3s ease;
}
.property-item:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
border-color: var(--primary-color);
}
.property-name {
font-weight: 600;
color: var(--primary-color);
margin-bottom: 10px;
font-size: 1.1rem;
}
.property-details {
color: var(--dark-color);
font-size: 0.95rem;
}
.property-details span {
font-weight: 600;
color: var(--secondary-color);
}
/* Multi-AI Feature Box */
.multi-ai-box {
background: linear-gradient(135deg, #f0f9ff, #e0f2fe);
border: 2px solid #0ea5e9;
border-radius: 16px;
padding: 25px;
margin: 20px 0;
}
.multi-ai-box h6 {
color: var(--info-color);
font-weight: 600;
margin-bottom: 15px;
}
.multi-ai-box ul {
margin: 0;
padding-left: 20px;
}
.multi-ai-box li {
color: var(--dark-color);
margin-bottom: 5px;
font-weight: 500;
}
/* Loading Animation */
.loading {
text-align: center;
padding: 60px;
background: white;
border-radius: 16px;
margin: 20px 0;
}
.loading i {
font-size: 3rem;
color: var(--primary-color);
animation: spin 1s linear infinite;
}
.loading h3 {
color: var(--dark-color);
margin: 20px 0 10px 0;
}
.loading p {
color: #64748b;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Hidden class */
.hidden {
display: none;
}
/* Search Form */
.search-section {
background: white;
border-radius: 16px;
padding: 30px;
margin-bottom: 30px;
border: 2px solid #e2e8f0;
}
.search-form {
display: flex;
gap: 20px;
align-items: end;
justify-content: center;
flex-wrap: wrap;
}
/* Responsive Design */
@media (max-width: 768px) {
.hero-header h1 {
font-size: 2rem;
}
.hero-header p {
font-size: 1.1rem;
}
.search-form {
flex-direction: column;
align-items: stretch;
}
.metric-value {
font-size: 2rem;
}
}
/* Status Badges */
.status-badge {
padding: 8px 16px;
border-radius: 50px;
font-weight: 600;
font-size: 0.9rem;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.status-hot {
background: linear-gradient(135deg, #fee2e2, #fca5a5);
color: #991b1b;
}
.status-warm {
background: linear-gradient(135deg, #fef3c7, #fde68a);
color: #92400e;
}
.status-cold {
background: linear-gradient(135deg, #f1f5f9, #cbd5e1);
color: #475569;
}
/* Progress Bars */
.progress {
height: 12px;
border-radius: 6px;
background-color: #e2e8f0;
overflow: hidden;
}
.progress-bar {
background: linear-gradient(90deg, var(--success-color), var(--accent-color));
border-radius: 6px;
transition: width 0.6s ease;
}
</style>
</head>
<body>
<div class="main-container">
<!-- Hero Header -->
<div class="hero-header">
<h1><i class="fas fa-robot"></i> AI Lead Analysis Dashboard</h1>
<p>Advanced Customer Behavior Analytics with Multi-AI Recommendations</p>
<div class="ai-badge">
<i class="fas fa-brain"></i> Powered by Multiple AI Models
</div>
<div class="mt-4">
<a href="/email-automation" class="btn btn-light btn-lg">
<i class="fas fa-envelope-open-text me-2"></i>
Email Automation Dashboard
</a>
</div>
</div>
<!-- Search Section -->
<div class="search-section">
<h3><i class="fas fa-search"></i> Customer Analysis</h3>
<div class="search-form">
<div class="form-group">
<label for="customerId" class="form-label">Customer ID:</label>
<input type="number" id="customerId" class="form-control" value="144" min="1" placeholder="Enter Customer ID" style="width: 200px;">
</div>
<div class="form-group">
<button type="button" class="btn btn-primary" onclick="analyzeCustomer()">
<i class="fas fa-chart-line"></i> Analyze Customer
</button>
</div>
</div>
</div>
<!-- Loading Section -->
<div id="loadingSection" class="loading hidden">
<i class="fas fa-spinner"></i>
<h3>Analyzing Customer Data...</h3>
<p>Please wait while we process the information with AI models</p>
</div>
<!-- Analysis Results -->
<div id="analysisResults" class="hidden">
<!-- Lead Status Card -->
<div class="card">
<h3><i class="fas fa-user-check"></i> Lead Qualification Status</h3>
<div class="row">
<div class="col-md-8">
<div id="leadStatus"></div>
</div>
<div class="col-md-4">
<div class="metric-card">
<div class="metric-value" id="leadScore">0</div>
<div class="metric-label">Lead Score</div>
</div>
</div>
</div>
<div id="leadFactors" class="mt-4"></div>
<div id="conversionDetails" class="mt-4"></div>
</div>
<!-- Key Metrics -->
<div class="row mb-4">
<div class="col-md-3">
<div class="metric-card">
<div class="metric-value" id="totalViews">0</div>
<div class="metric-label">Total Views</div>
</div>
</div>
<div class="col-md-3">
<div class="metric-card">
<div class="metric-value" id="totalDuration">0h 0m</div>
<div class="metric-label">Total Duration</div>
</div>
</div>
<div class="col-md-3">
<div class="metric-card">
<div class="metric-value" id="engagementScore">0</div>
<div class="metric-label">Engagement Score</div>
</div>
</div>
<div class="col-md-3">
<div class="metric-card">
<div class="metric-value" id="conversionProbability">0%</div>
<div class="metric-label">Conversion Probability</div>
</div>
</div>
</div>
<!-- Property Preferences -->
<div class="card">
<h3><i class="fas fa-home"></i> Property Preferences & Analysis</h3>
<div class="row">
<div class="col-md-4">
<h4><i class="fas fa-tags"></i> Preferred Types</h4>
<div id="propertyPreferences"></div>
</div>
<div class="col-md-4">
<h4><i class="fas fa-clock"></i> Viewing Patterns</h4>
<div id="viewingPatterns"></div>
</div>
<div class="col-md-4">
<h4><i class="fas fa-chart-line"></i> Activity Timeline</h4>
<div id="activityTimeline"></div>
</div>
</div>
</div>
<!-- Price Analysis -->
<div class="card">
<h3><i class="fas fa-money-bill-wave"></i> Price Analysis</h3>
<div id="priceAnalysis"></div>
</div>
<!-- Multi-AI Recommendations System -->
<div class="card">
<h3><i class="fas fa-brain"></i> Multi-AI Recommendations Engine</h3>
<div class="row">
<div class="col-md-6">
<div class="form-group mb-3">
<label for="multiAiEmail" class="form-label">Email Address for Multi-AI Recommendations:</label>
<input type="email" id="multiAiEmail" class="form-control" value="[email protected]">
</div>
<div class="form-group mb-3">
<label for="emailCount" class="form-label">Number of AI Emails to Send:</label>
<select id="emailCount" class="form-control">
<option value="5">5 Emails</option>
<option value="10" selected>10 Emails</option>
<option value="15">15 Emails</option>
</select>
</div>
</div>
<div class="col-md-6">
<div class="multi-ai-box">
<h6><i class="fas fa-info-circle"></i> Multi-AI Features:</h6>
<ul>
<li>🏑 Property-based recommendations</li>
<li>πŸ’° Price-based matching</li>
<li>πŸ“ Location-based suggestions</li>
<li>πŸ” Similarity-based findings</li>
<li>🧠 Behavioral analysis recommendations</li>
<li>⭐ Premium properties collection</li>
<li>πŸ’΅ Budget-friendly options</li>
<li>πŸ“ˆ Trending properties</li>
<li>πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦ Family-oriented properties</li>
<li>πŸ’Ό Investment opportunities</li>
</ul>
</div>
</div>
</div>
<div class="row mt-3">
<div class="col-12">
<button type="button" class="btn btn-primary btn-lg me-3" onclick="sendMultiAIRecommendations()">
<i class="fas fa-robot"></i> Send Multi-AI Recommendations
</button>
<button type="button" class="btn btn-success me-3" onclick="getChromaDBRecommendations()">
<i class="fas fa-database"></i> Get ChromaDB Recommendations
</button>
<button type="button" class="btn btn-info" onclick="fetchAllProperties()">
<i class="fas fa-download"></i> Fetch All Properties to ChromaDB
</button>
</div>
</div>
<!-- Multi-AI Results -->
<div id="multiAiResults" class="mt-4"></div>
<!-- ChromaDB Recommendations Results -->
<div id="chromaDbResults" class="mt-4"></div>
</div>
<!-- Email Testing Section -->
<div class="card">
<h3><i class="fas fa-envelope"></i> Comprehensive Email Testing & Analysis Suite</h3>
<div class="row">
<div class="col-md-6">
<div class="form-group mb-3">
<label for="testEmail" class="form-label">Test Email Address:</label>
<input type="email" id="testEmail" class="form-control" value="[email protected]">
<small class="text-muted">All emails will be sent to this address</small>
</div>
<!-- Main Email Tests -->
<h6><i class="fas fa-envelope"></i> Core Email Functions:</h6>
<div class="d-flex gap-2 flex-wrap mb-3">
<button type="button" class="btn btn-success btn-sm" onclick="testSendGridConnection()">
<i class="fas fa-wifi"></i> Test SendGrid
</button>
<button type="button" class="btn btn-warning btn-sm" onclick="previewAllEmailContent()">
<i class="fas fa-eye"></i> Preview 10 Emails
</button>
</div>
<!-- Analysis & Status -->
<h6><i class="fas fa-chart-line"></i> Analysis & Status:</h6>
<div class="d-flex gap-2 flex-wrap mb-3">
<button type="button" class="btn btn-info btn-sm" onclick="getEmailAnalysisBasis()">
<i class="fas fa-search-plus"></i> Show Analysis Basis
</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="getEmailStatus()">
<i class="fas fa-chart-bar"></i> Email Status
</button>
</div>
</div>
<div class="col-md-6">
<!-- Main Testing Actions -->
<h6><i class="fas fa-rocket"></i> Main Email Actions:</h6>
<div class="d-flex gap-2 flex-wrap mb-2">
<button type="button" class="btn btn-primary" onclick="testAll10Emails()">
<i class="fas fa-envelope-open-text"></i> Send All 10 AI Emails
</button>
</div>
<div class="alert alert-info mb-3">
<small><strong>πŸ“§ Multi-AI Email System:</strong> Each email uses a different AI model to retrieve personalized properties from ChromaDB based on your analysis.</small>
</div>
<!-- Property Management -->
<h6><i class="fas fa-database"></i> Property Management:</h6>
<div class="d-flex gap-2 flex-wrap mb-2">
<button type="button" class="btn btn-info btn-sm" onclick="checkChromaDBStatus()">
<i class="fas fa-heartbeat"></i> Check ChromaDB Status
</button>
<button type="button" class="btn btn-success btn-sm" onclick="fetchAllProperties()">
<i class="fas fa-download"></i> Fetch Properties
</button>
</div>
<div class="d-flex gap-2 flex-wrap mb-4">
<button type="button" class="btn btn-secondary btn-sm" onclick="getChromaDBRecommendations()">
<i class="fas fa-search"></i> Test Recommendations
</button>
</div>
<!-- Saved Emails Management -->
<h6><i class="fas fa-folder-open"></i> Saved Emails:</h6>
<div class="d-flex gap-2 flex-wrap mb-3">
<button type="button" class="btn btn-warning btn-sm" onclick="listSavedEmails()">
<i class="fas fa-folder-open"></i> View Saved Emails
</button>
</div>
<div class="alert alert-warning mb-3">
<small><strong>πŸ“ SendGrid Limit Solution:</strong> When SendGrid limits are exceeded, emails are automatically saved to your local <code>./saved_emails/</code> folder. Click "View Saved Emails" to see and open them.</small>
</div>
<h6>Email Configuration:</h6>
<div class="timeline">
<div class="timeline-item">
<strong>From:</strong> [email protected]
</div>
<div class="timeline-item">
<strong>To:</strong> [email protected]
</div>
<div class="timeline-item">
<strong>2:00 PM Daily</strong> - Peak time recommendations
</div>
<div class="timeline-item">
<strong>6:00 PM Daily</strong> - Evening opportunities
</div>
<div class="timeline-item">
<strong>Every Hour</strong> - System test emails
</div>
</div>
</div>
</div>
</div>
<!-- Customer Analysis & Email Dashboard -->
<div class="card">
<h3><i class="fas fa-user-chart"></i> Customer Analysis & Email Dashboard</h3>
<!-- Customer Tracking Data Analysis -->
<div class="row mb-4">
<div class="col-md-6">
<h5><i class="fas fa-chart-line"></i> Customer Tracking Analysis</h5>
<div id="customerAnalysis" class="alert alert-info">
<p><i class="fas fa-info-circle"></i> Customer analysis will appear here after analyzing a customer.</p>
</div>
</div>
<div class="col-md-6">
<h5><i class="fas fa-robot"></i> AI Analysis Results</h5>
<div id="aiAnalysisResults" class="alert alert-success">
<p><i class="fas fa-brain"></i> AI analysis results will appear here.</p>
</div>
</div>
</div>
<!-- Email Preview Section -->
<div class="row mb-4">
<div class="col-12">
<h5><i class="fas fa-envelope-open"></i> Email Preview Center</h5>
<div class="d-flex gap-2 flex-wrap mb-3">
<button type="button" class="btn btn-primary" onclick="previewAllEmails()">
<i class="fas fa-eye"></i> Preview All 5 Emails
</button>
<button type="button" class="btn btn-success" onclick="previewNewPropertiesEmail()">
<i class="fas fa-home"></i> New Properties
</button>
<button type="button" class="btn btn-info" onclick="previewRecommendationsEmail()">
<i class="fas fa-lightbulb"></i> Recommendations
</button>
<button type="button" class="btn btn-warning" onclick="previewPeakTimeEmail()">
<i class="fas fa-clock"></i> Peak Time
</button>
<button type="button" class="btn btn-secondary" onclick="previewBehavioralEmail()">
<i class="fas fa-user-cog"></i> Behavioral
</button>
</div>
<div id="emailPreviewContainer" class="border rounded p-3" style="min-height: 200px; background-color: #f8f9fa;">
<p class="text-muted text-center"><i class="fas fa-envelope"></i> Select an email type above to preview</p>
</div>
</div>
</div>
<!-- Fixed Email Metrics (No Continuous Updates) -->
<div class="row mb-3">
<div class="col-md-3">
<div class="metric-card">
<div class="metric-value" id="totalEmails">0</div>
<div class="metric-label">Total Emails</div>
</div>
</div>
<div class="col-md-3">
<div class="metric-card">
<div class="metric-value" id="successEmails">0</div>
<div class="metric-label">Successful</div>
</div>
</div>
<div class="col-md-3">
<div class="metric-card">
<div class="metric-value" id="failedEmails">0</div>
<div class="metric-label">Failed</div>
</div>
</div>
<div class="col-md-3">
<div class="metric-card">
<div class="metric-value" id="scheduledEmails">0</div>
<div class="metric-label">Scheduled</div>
</div>
</div>
</div>
<!-- Email Actions -->
<div class="d-flex gap-2 flex-wrap">
<button type="button" class="btn btn-success" onclick="testAllEmailTypes()">
<i class="fas fa-play"></i> Test All Email Types
</button>
<button type="button" class="btn btn-warning" onclick="clearEmailLogs()">
<i class="fas fa-trash"></i> Clear Logs
</button>
<button type="button" class="btn btn-primary" onclick="sendAllIntendedEmails()">
<i class="fas fa-paper-plane"></i> Send All Intended Emails
</button>
<button type="button" class="btn btn-danger" onclick="sendMultiAIEmails()">
<i class="fas fa-robot"></i> Send 10 AI Emails
</button>
</div>
</div>
<!-- Email Logs -->
<div class="card">
<h3><i class="fas fa-list"></i> Email Activity Logs</h3>
<div id="emailLogs"></div>
</div>
<!-- Properties Viewed -->
<div class="card">
<h3><i class="fas fa-eye"></i> Properties Viewed - Detailed Analysis</h3>
<div class="row" id="propertiesViewed"></div>
</div>
<!-- AI Recommendations -->
<div class="card">
<h3><i class="fas fa-robot"></i> AI-Powered Property Recommendations</h3>
<div class="alert alert-info">
<h6><i class="fas fa-lightbulb"></i> Personalized Recommendations</h6>
<div id="aiRecommendations"></div>
</div>
<div id="propertyRecommendations"></div>
</div>
</div>
</div>
<script>
let currentCustomerId = 144;
let analysisData = null;
async function analyzeCustomer() {
const customerId = document.getElementById('customerId').value;
if (!customerId) {
showError('Please enter a Customer ID');
return;
}
currentCustomerId = customerId;
// Show loading
document.getElementById('loadingSection').classList.remove('hidden');
document.getElementById('analysisResults').classList.add('hidden');
try {
const response = await fetch(`/api/lead-analysis/${customerId}`);
const data = await response.json();
if (data.success) {
analysisData = data.data;
displayAnalysis(data.data);
loadEmailLogs();
} else {
showError('Analysis failed: ' + (data.error || 'Unknown error'));
}
} catch (error) {
showError('Error analyzing customer: ' + error.message);
} finally {
document.getElementById('loadingSection').classList.add('hidden');
document.getElementById('analysisResults').classList.remove('hidden');
}
}
function displayAnalysis(data) {
// Lead Status
const leadQual = data.lead_qualification;
document.getElementById('leadStatus').innerHTML = `
<div class="status-badge status-${leadQual.lead_status.toLowerCase()}">
${leadQual.lead_status}
</div>
<p class="mt-3">${leadQual.status_description}</p>
<div class="progress mt-3">
<div class="progress-bar" style="width: ${leadQual.lead_score}%"></div>
</div>
<small class="text-muted mt-2">${leadQual.lead_score}/${leadQual.max_possible_score} points</small>
`;
document.getElementById('leadScore').textContent = leadQual.lead_score;
// Key Metrics
const summary = data.summary;
document.getElementById('totalViews').textContent = summary.total_views;
document.getElementById('totalDuration').textContent = formatDuration(summary.total_duration);
document.getElementById('engagementScore').textContent = Math.round(summary.engagement_score);
const conversionProb = data.analytics.conversion_probability;
document.getElementById('conversionProbability').textContent = Math.round(conversionProb.final_probability) + '%';
// Property Preferences
const analytics = data.analytics;
document.getElementById('propertyPreferences').innerHTML = `
<ul class="list-unstyled">
${analytics.preferred_property_types.map(type => `<li><i class="fas fa-check-circle text-success"></i> ${type}</li>`).join('')}
</ul>
`;
// Update Customer Analysis Section
displayCustomerAnalysis(data);
// Display other sections
displayViewingPatterns(analytics.viewing_patterns);
displayActivityTimeline(analytics.lead_timeline);
displayPriceAnalysis(analytics.price_preferences);
displayPropertiesViewed(data.properties);
displayAIRecommendations(analytics);
}
function displayCustomerAnalysis(data) {
const analytics = data.analytics;
const summary = data.summary;
// Customer Tracking Analysis
document.getElementById('customerAnalysis').innerHTML = `
<div class="row">
<div class="col-md-6">
<h6><i class="fas fa-eye"></i> Viewing Behavior</h6>
<ul class="list-unstyled small">
<li><strong>Total Views:</strong> ${summary.total_views}</li>
<li><strong>Total Duration:</strong> ${formatDuration(summary.total_duration)}</li>
<li><strong>Engagement Score:</strong> ${Math.round(summary.engagement_score)}%</li>
<li><strong>Peak Time:</strong> ${analytics.viewing_patterns.peak_viewing_time}</li>
</ul>
</div>
<div class="col-md-6">
<h6><i class="fas fa-home"></i> Property Preferences</h6>
<ul class="list-unstyled small">
<li><strong>Preferred Types:</strong> ${analytics.preferred_property_types.join(', ')}</li>
<li><strong>Price Range:</strong> $${analytics.price_preferences.min_price.toLocaleString()} - $${analytics.price_preferences.max_price.toLocaleString()}</li>
<li><strong>Avg Price:</strong> $${analytics.price_preferences.avg_price.toLocaleString()}</li>
<li><strong>Conversion Probability:</strong> ${Math.round(analytics.conversion_probability.final_probability)}%</li>
</ul>
</div>
</div>
`;
// AI Analysis Results
document.getElementById('aiAnalysisResults').innerHTML = `
<div class="row">
<div class="col-md-6">
<h6><i class="fas fa-brain"></i> AI Insights</h6>
<ul class="list-unstyled small">
<li><strong>Lead Status:</strong> ${data.lead_qualification.lead_status}</li>
<li><strong>Lead Score:</strong> ${data.lead_qualification.lead_score}/${data.lead_qualification.max_possible_score}</li>
<li><strong>Behavior Pattern:</strong> ${analytics.viewing_patterns.peak_viewing_time} Active</li>
<li><strong>Decision Stage:</strong> ${data.lead_qualification.lead_status}</li>
</ul>
</div>
<div class="col-md-6">
<h6><i class="fas fa-chart-line"></i> Recommendations</h6>
<ul class="list-unstyled small">
<li><i class="fas fa-check text-success"></i> Send new properties matching preferences</li>
<li><i class="fas fa-check text-success"></i> Schedule viewings during peak time</li>
<li><i class="fas fa-check text-success"></i> Focus on ${analytics.preferred_property_types[0]} properties</li>
<li><i class="fas fa-check text-success"></i> Target price range: $${analytics.price_preferences.min_price.toLocaleString()}-${analytics.price_preferences.max_price.toLocaleString()}</li>
</ul>
</div>
</div>
`;
}
function displayViewingPatterns(patterns) {
const patternsHtml = `
<div class="d-flex flex-column gap-2">
<div><strong>Peak Time:</strong> ${patterns.peak_viewing_time}</div>
<div><strong>Morning Views:</strong> ${patterns.morning_views}</div>
<div><strong>Afternoon Views:</strong> ${patterns.afternoon_views}</div>
<div><strong>Evening Views:</strong> ${patterns.evening_views}</div>
</div>
`;
document.getElementById('viewingPatterns').innerHTML = patternsHtml;
}
function displayActivityTimeline(timeline) {
const timelineHtml = timeline.slice(0, 5).map(item => `
<div class="border rounded p-2 mb-2">
<div><strong>${item.property_name}</strong></div>
<small class="text-muted">${item.views} views β€’ ${new Date(item.date).toLocaleDateString()}</small>
</div>
`).join('');
document.getElementById('activityTimeline').innerHTML = timelineHtml;
}
function displayPriceAnalysis(pricePrefs) {
const priceHtml = `
<div class="row">
<div class="col-md-3">
<div class="text-center">
<div class="h4 text-primary">β‚Ή${formatPrice(pricePrefs.avg_price)}</div>
<small>Average Price</small>
</div>
</div>
<div class="col-md-3">
<div class="text-center">
<div class="h4 text-success">β‚Ή${formatPrice(pricePrefs.min_price)}</div>
<small>Min Price</small>
</div>
</div>
<div class="col-md-3">
<div class="text-center">
<div class="h4 text-warning">β‚Ή${formatPrice(pricePrefs.max_price)}</div>
<small>Max Price</small>
</div>
</div>
<div class="col-md-3">
<div class="text-center">
<div class="h4 text-info">β‚Ή${formatPrice(pricePrefs.price_range)}</div>
<small>Price Range</small>
</div>
</div>
</div>
`;
document.getElementById('priceAnalysis').innerHTML = priceHtml;
}
function displayPropertiesViewed(properties) {
const propertiesHtml = properties.slice(0, 6).map(prop => `
<div class="col-md-4 mb-3">
<div class="property-item">
<div class="property-name">${prop.propertyName}</div>
<div class="property-details">
<div><span>Type:</span> ${prop.propertyTypeName}</div>
<div><span>Price:</span> β‚Ή${formatPrice(prop.price)}</div>
<div><span>Views:</span> ${prop.viewCount}</div>
<div><span>Engagement:</span> ${Math.round(prop.engagement_score)}</div>
</div>
</div>
</div>
`).join('');
document.getElementById('propertiesViewed').innerHTML = propertiesHtml;
}
function displayAIRecommendations(analytics) {
const recommendationsHtml = `
<div class="row">
<div class="col-md-6">
<h6>AI Recommendations:</h6>
<ul>
${analytics.recommendations.map(rec => `<li>${rec}</li>`).join('')}
</ul>
</div>
<div class="col-md-6">
<h6>Risk Assessment:</h6>
<div><strong>Risk Level:</strong> ${analytics.risk_assessment.risk_level}</div>
<div><strong>Opportunity Score:</strong> ${Math.round(analytics.opportunity_score)}</div>
</div>
</div>
`;
document.getElementById('aiRecommendations').innerHTML = recommendationsHtml;
}
// Multi-AI Functions
async function sendMultiAIRecommendations() {
const customerId = document.getElementById('customerId').value;
const email = document.getElementById('multiAiEmail').value;
const emailCount = document.getElementById('emailCount').value;
if (!customerId) {
showError('Please enter a customer ID first');
return;
}
try {
showSuccess('πŸ€– Starting Multi-AI recommendation process...');
const response = await fetch(`/api/multi-ai-recommendations/${customerId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: email,
email_count: parseInt(emailCount)
})
});
const result = await response.json();
if (result.success) {
displayMultiAIResults(result);
showSuccess(`βœ… Successfully sent ${result.total_sent} AI recommendation emails!`);
} else {
showError(`Failed to send multi-AI recommendations: ${result.error}`);
}
} catch (error) {
console.error('Error sending multi-AI recommendations:', error);
showError('Error sending multi-AI recommendations. Please try again.');
}
}
function displayMultiAIResults(result) {
const resultsHtml = `
<div class="alert alert-success">
<h5><i class="fas fa-check-circle"></i> Multi-AI Recommendations Results</h5>
<div class="row">
<div class="col-md-6">
<p><strong>Customer ID:</strong> ${result.customer_id}</p>
<p><strong>Recipient:</strong> ${result.recipient_email}</p>
<p><strong>Total Sent:</strong> ${result.total_sent} emails</p>
<p><strong>Total Failed:</strong> ${result.total_failed} emails</p>
</div>
<div class="col-md-6">
<p><strong>AI Insights:</strong></p>
<ul>
<li>Personality: ${result.ai_insights?.personality_type || 'Analytical'}</li>
<li>Urgency: ${result.ai_insights?.urgency_level || 'Medium'}</li>
<li>Decision Style: ${result.ai_insights?.decision_making_style || 'Data-driven'}</li>
</ul>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<h6><i class="fas fa-check"></i> Successfully Sent Emails:</h6>
${result.sent_emails.map(email => `
<div class="alert alert-success">
<strong>${email.type}:</strong> ${email.subject}
<br><small>Recommendations: ${email.recommendations_count}</small>
</div>
`).join('')}
</div>
<div class="col-md-6">
<h6><i class="fas fa-exclamation-triangle"></i> Failed Emails:</h6>
${result.failed_emails.length > 0 ? result.failed_emails.map(email => `
<div class="alert alert-warning">
<strong>${email.type}:</strong> ${email.error}
</div>
`).join('') : '<div class="alert alert-success">No failed emails!</div>'}
</div>
</div>
`;
document.getElementById('multiAiResults').innerHTML = resultsHtml;
}
async function getChromaDBRecommendations() {
const customerId = document.getElementById('customerId').value;
if (!customerId) {
showError('Please enter a customer ID first');
return;
}
try {
showSuccess('πŸ” Getting ChromaDB recommendations...');
const response = await fetch(`/api/chromadb-recommendations/${customerId}`);
const result = await response.json();
if (result.success) {
displayChromaDBResults(result);
showSuccess('βœ… ChromaDB recommendations loaded successfully!');
} else {
showError(`Failed to get ChromaDB recommendations: ${result.error}`);
}
} catch (error) {
console.error('Error getting ChromaDB recommendations:', error);
showError('Error getting ChromaDB recommendations. Please try again.');
}
}
function displayChromaDBResults(result) {
const resultsHtml = `
<div class="alert alert-info">
<h5><i class="fas fa-database"></i> ChromaDB Recommendations Results</h5>
<p><strong>Total Recommendations:</strong> ${result.total_recommendations}</p>
<p><strong>Customer ID:</strong> ${result.customer_id}</p>
</div>
<div class="row">
${Object.entries(result.recommendations).map(([type, recs]) => `
<div class="col-md-4">
<div class="card">
<div class="card-header">
<h6><i class="fas fa-star"></i> ${type.replace('_', ' ').toUpperCase()}</h6>
</div>
<div class="card-body">
${recs.slice(0, 3).map(rec => `
<div class="property-item mb-2">
<div class="property-name">${rec.property_name || 'Property'}</div>
<div class="property-details">
<span>Price:</span> β‚Ή${formatPrice(rec.price || 0)}<br>
<span>Type:</span> ${rec.property_type || 'N/A'}<br>
<span>AI Score:</span> ${(rec.ai_score || 0).toFixed(2)}
</div>
${rec.ai_explanation ? `<small class="text-muted">${rec.ai_explanation}</small>` : ''}
</div>
`).join('')}
${recs.length > 3 ? `<small class="text-muted">... and ${recs.length - 3} more</small>` : ''}
</div>
</div>
</div>
`).join('')}
</div>
`;
document.getElementById('chromaDbResults').innerHTML = resultsHtml;
}
async function fetchAllProperties() {
try {
showSuccess('πŸ“₯ Starting property fetch to ChromaDB...');
const response = await fetch('/api/fetch-all-properties?workers=10&page_size=100&max_pages=10');
const result = await response.json();
if (result.success) {
showSuccess(`βœ… Successfully fetched ${result.total_properties} properties to ChromaDB!`);
} else {
showError(`Failed to fetch properties: ${result.error}`);
}
} catch (error) {
console.error('Error fetching properties:', error);
showError('Error fetching properties. Please try again.');
}
}
// Email Functions
async function sendTestEmail() {
const email = document.getElementById('testEmail').value;
if (!email) {
showError('Please enter an email address');
return;
}
try {
const response = await fetch('/api/test-email', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
customer_id: currentCustomerId,
email_type: 'test_email',
recipient_email: email
})
});
const data = await response.json();
if (data.success) {
showSuccess('Test email sent successfully!');
loadEmailLogs();
} else {
showError('Email send failed: ' + (data.error || 'Unknown error'));
}
} catch (error) {
showError('Error sending email: ' + error.message);
}
}
async function testEmailTriggers() {
try {
const response = await fetch(`/api/test-automated-emails/${currentCustomerId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
const data = await response.json();
if (data.success) {
showSuccess('Email triggers test successful!');
loadEmailLogs();
} else {
showError('Email triggers test failed: ' + (data.error || 'Unknown error'));
}
} catch (error) {
showError('Error testing email triggers: ' + error.message);
}
}
async function sendDirectTestEmail() {
const recipient = document.getElementById('testEmail').value;
if (!recipient) {
showError('Please enter a test email address');
return;
}
try {
const response = await fetch('/api/test-email-simple', {
method: 'GET'
});
const data = await response.json();
if (data.success) {
showSuccess('Direct test email sent successfully!');
loadEmailLogs();
} else {
showError('Direct test email failed: ' + (data.error || 'Unknown error'));
}
} catch (error) {
showError('Error sending direct test email: ' + error.message);
}
}
// Email Preview Functions
async function previewAllEmails() {
if (!analysisData) {
showError('Please analyze a customer first to preview emails');
return;
}
document.getElementById('emailPreviewContainer').innerHTML = '<div class="text-center"><i class="fas fa-spinner fa-spin"></i> Loading all email previews...</div>';
try {
const response = await fetch(`/api/email-automation/${currentCustomerId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: '[email protected]',
email_type: 'all'
})
});
const data = await response.json();
if (data.success) {
displayEmailPreviews(data.results, 'All 5 Email Types');
} else {
showError('Failed to preview emails: ' + (data.error || 'Unknown error'));
}
} catch (error) {
showError('Error previewing emails: ' + error.message);
}
}
async function previewNewPropertiesEmail() {
if (!analysisData) {
showError('Please analyze a customer first to preview emails');
return;
}
document.getElementById('emailPreviewContainer').innerHTML = '<div class="text-center"><i class="fas fa-spinner fa-spin"></i> Loading new properties email preview...</div>';
try {
const response = await fetch(`/api/email-automation/${currentCustomerId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: '[email protected]',
email_type: 'new_properties'
})
});
const data = await response.json();
if (data.success) {
displayEmailPreviews(data.results, 'New Properties Email');
} else {
showError('Failed to preview new properties email: ' + (data.error || 'Unknown error'));
}
} catch (error) {
showError('Error previewing new properties email: ' + error.message);
}
}
async function previewRecommendationsEmail() {
if (!analysisData) {
showError('Please analyze a customer first to preview emails');
return;
}
document.getElementById('emailPreviewContainer').innerHTML = '<div class="text-center"><i class="fas fa-spinner fa-spin"></i> Loading recommendations email preview...</div>';
try {
const response = await fetch(`/api/email-automation/${currentCustomerId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: '[email protected]',
email_type: 'recommendations'
})
});
const data = await response.json();
if (data.success) {
displayEmailPreviews(data.results, 'AI Recommendations Email');
} else {
showError('Failed to preview recommendations email: ' + (data.error || 'Unknown error'));
}
} catch (error) {
showError('Error previewing recommendations email: ' + error.message);
}
}
async function previewPeakTimeEmail() {
if (!analysisData) {
showError('Please analyze a customer first to preview emails');
return;
}
document.getElementById('emailPreviewContainer').innerHTML = '<div class="text-center"><i class="fas fa-spinner fa-spin"></i> Loading peak time email preview...</div>';
try {
const response = await fetch(`/api/email-automation/${currentCustomerId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: '[email protected]',
email_type: 'peak_time'
})
});
const data = await response.json();
if (data.success) {
displayEmailPreviews(data.results, 'Peak Time Engagement Email');
} else {
showError('Failed to preview peak time email: ' + (data.error || 'Unknown error'));
}
} catch (error) {
showError('Error previewing peak time email: ' + error.message);
}
}
async function previewBehavioralEmail() {
if (!analysisData) {
showError('Please analyze a customer first to preview emails');
return;
}
document.getElementById('emailPreviewContainer').innerHTML = '<div class="text-center"><i class="fas fa-spinner fa-spin"></i> Loading behavioral email preview...</div>';
try {
const response = await fetch(`/api/test-automated-emails/${currentCustomerId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
const data = await response.json();
if (data.success) {
displayBehavioralEmailPreview(data, 'Behavioral Trigger Email');
} else {
showError('Failed to preview behavioral email: ' + (data.error || 'Unknown error'));
}
} catch (error) {
showError('Error previewing behavioral email: ' + error.message);
}
}
function displayEmailPreviews(results, title) {
let html = `<h5><i class="fas fa-envelope"></i> ${title} Preview</h5>`;
if (results && results.length > 0) {
results.forEach((result, index) => {
html += `
<div class="card mb-3">
<div class="card-header d-flex justify-content-between align-items-center">
<h6 class="mb-0">
<i class="fas fa-envelope"></i> ${result.type ? result.type.replace('_', ' ').toUpperCase() : 'Email'} ${index + 1}
</h6>
<span class="badge ${result.success ? 'bg-success' : 'bg-danger'}">
${result.success ? 'SUCCESS' : 'FAILED'}
</span>
</div>
<div class="card-body">
${result.success ? `
<div class="row">
<div class="col-md-6">
<h6>Email Details:</h6>
<ul class="list-unstyled">
<li><strong>Type:</strong> ${result.type || 'N/A'}</li>
<li><strong>Properties Count:</strong> ${result.properties_count || 0}</li>
<li><strong>Recommendations Count:</strong> ${result.recommendations_count || 0}</li>
<li><strong>Peak Time:</strong> ${result.peak_time || 'N/A'}</li>
<li><strong>Engagement Level:</strong> ${result.engagement_level || 'N/A'}</li>
</ul>
</div>
<div class="col-md-6">
<h6>AI Insights:</h6>
<ul class="list-unstyled">
<li><strong>Personality Type:</strong> ${result.ai_insights?.personality_type || 'N/A'}</li>
<li><strong>Decision Style:</strong> ${result.ai_insights?.decision_making_style || 'N/A'}</li>
<li><strong>Urgency Level:</strong> ${result.ai_insights?.urgency_level || 'N/A'}</li>
<li><strong>Peak Activity:</strong> ${result.ai_insights?.peak_time || 'N/A'}</li>
</ul>
</div>
</div>
<div class="mt-3">
<h6>Email Content Preview:</h6>
${result.html_content ? `
<div class="email-preview-container" style="max-height: 400px; overflow-y: auto; border: 1px solid #ddd; border-radius: 8px; padding: 15px; background: white;">
<div class="email-preview-header mb-3">
<strong>Subject:</strong> ${result.subject || 'N/A'}<br>
<strong>Properties:</strong> ${result.recommendations_count || 0} recommendations<br>
<strong>AI Insights:</strong> ${result.ai_insights ? `
Personality: ${result.ai_insights.personality_type || 'N/A'} |
Urgency: ${result.ai_insights.urgency_level || 'N/A'} |
Peak Time: ${result.ai_insights.peak_activity || 'N/A'}
` : 'N/A'}
</div>
<div class="email-content-preview">
${result.html_content}
</div>
</div>
` : `
<div class="alert alert-light">
<small>This email would be sent to the customer based on their tracking data and AI analysis. The content is personalized based on their viewing behavior, preferences, and engagement patterns.</small>
</div>
`}
</div>
` : `
<div class="alert alert-danger">
<strong>Error:</strong> ${result.error || 'Unknown error occurred'}
</div>
`}
</div>
</div>
`;
});
} else {
html += '<div class="alert alert-warning">No email previews available</div>';
}
document.getElementById('emailPreviewContainer').innerHTML = html;
}
function displayBehavioralEmailPreview(data, title) {
let html = `<h5><i class="fas fa-envelope"></i> ${title} Preview</h5>`;
html += `
<div class="card">
<div class="card-header">
<h6 class="mb-0">
<i class="fas fa-user-cog"></i> Behavioral Trigger Email
</h6>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<h6>Trigger Details:</h6>
<ul class="list-unstyled">
<li><strong>Trigger Type:</strong> ${data.trigger_type || 'Behavioral'}</li>
<li><strong>Customer ID:</strong> ${data.customer_id || currentCustomerId}</li>
<li><strong>Status:</strong> ${data.success ? 'SUCCESS' : 'FAILED'}</li>
</ul>
</div>
<div class="col-md-6">
<h6>Analysis Basis:</h6>
<ul class="list-unstyled">
<li><strong>Viewing Behavior:</strong> Based on customer's property viewing patterns</li>
<li><strong>Engagement Level:</strong> ${analysisData?.summary?.engagement_score || 'N/A'}%</li>
<li><strong>Peak Time:</strong> ${analysisData?.analytics?.viewing_patterns?.peak_viewing_time || 'N/A'}</li>
</ul>
</div>
</div>
<div class="mt-3">
<h6>Email Content Preview:</h6>
<div class="alert alert-light">
<small>This behavioral email is triggered based on the customer's activity patterns and engagement level. It provides personalized recommendations and follow-up actions based on their browsing behavior.</small>
</div>
</div>
</div>
</div>
`;
document.getElementById('emailPreviewContainer').innerHTML = html;
}
async function loadEmailLogs() {
try {
const response = await fetch('/api/list-emails');
const data = await response.json();
if (data.success) {
const emails = data.emails || [];
// Update email dashboard metrics (fixed values, no continuous updates)
document.getElementById('totalEmails').textContent = emails.length;
document.getElementById('successEmails').textContent = emails.filter(e => e.success !== false).length;
document.getElementById('failedEmails').textContent = emails.filter(e => e.success === false).length;
document.getElementById('scheduledEmails').textContent = emails.filter(e => e.email_type === 'scheduled').length;
document.getElementById('emailLogs').innerHTML = `
${emails.slice(0, 5).map(email => `
<div class="alert ${email.success !== false ? 'alert-success' : 'alert-danger'}">
<div class="d-flex justify-content-between">
<strong>${email.filename || 'Email Log'}</strong>
<small>${new Date(email.created || Date.now()).toLocaleString()}</small>
</div>
<div>Size: ${email.size ? (email.size/1024).toFixed(1) + ' KB' : 'N/A'}</div>
</div>
`).join('')}
${emails.length === 0 ? '<div class="alert alert-info">No email logs found</div>' : ''}
`;
} else {
document.getElementById('emailLogs').innerHTML = '<div class="alert alert-danger">Failed to load email logs</div>';
}
} catch (error) {
document.getElementById('emailLogs').innerHTML = '<div class="alert alert-danger">Error loading email logs</div>';
}
}
async function testAllEmailTypes() {
showSuccess('Testing all email types... This may take a moment.');
// Implementation for testing all email types
}
async function clearEmailLogs() {
if (confirm('Are you sure you want to clear all email logs?')) {
showSuccess('Email logs cleared successfully!');
loadEmailLogs();
}
}
async function sendAllIntendedEmails() {
showSuccess('Sending all intended emails...');
// Implementation for sending all intended emails
}
async function sendMultiAIEmails() {
showSuccess('Starting Multi-AI email campaign...');
// Implementation for sending multi-AI emails
}
// New Email Testing Functions
async function testSendGridConnection() {
try {
showSuccess('Testing SendGrid connection...');
const response = await fetch('/api/test-sendgrid-connection');
const result = await response.json();
if (result.success) {
showSuccess(`βœ… SendGrid connection successful: ${result.message}`);
document.getElementById('multiAiResults').innerHTML = `
<div class="alert alert-success">
<h5><i class="fas fa-check-circle"></i> SendGrid Connection Test</h5>
<p><strong>Status:</strong> Connected βœ…</p>
<p><strong>Details:</strong> ${JSON.stringify(result.details, null, 2)}</p>
<p><strong>Timestamp:</strong> ${result.timestamp}</p>
</div>
`;
} else {
showError(`❌ SendGrid connection failed: ${result.error}`);
}
} catch (error) {
showError(`❌ Error testing SendGrid: ${error.message}`);
}
}
async function getEmailAnalysisBasis() {
try {
const customerId = document.getElementById('customerId').value || 144;
showSuccess('Getting email analysis basis...');
const response = await fetch(`/api/email-analysis-basis/${customerId}`);
const result = await response.json();
if (result.success) {
document.getElementById('multiAiResults').innerHTML = `
<div class="alert alert-info">
<h5><i class="fas fa-search-plus"></i> Email Analysis Basis for Customer ${customerId}</h5>
<div class="row">
<div class="col-md-6">
<h6>Customer Preferences:</h6>
<pre>${JSON.stringify(result.analysis_basis.customer_preferences, null, 2)}</pre>
</div>
<div class="col-md-6">
<h6>Email Triggers:</h6>
${Object.entries(result.email_triggers).map(([type, trigger]) =>
`<p><strong>${type}:</strong> ${trigger}</p>`
).join('')}
</div>
</div>
<div class="row mt-3">
<div class="col-12">
<h6>AI Insights Summary:</h6>
<p><strong>Engagement Level:</strong> ${result.analysis_basis.engagement_level}</p>
<p><strong>Conversion Probability:</strong> ${(result.analysis_basis.conversion_probability * 100).toFixed(1)}%</p>
</div>
</div>
</div>
`;
showSuccess('βœ… Email analysis basis retrieved successfully');
} else {
showError(`❌ Failed to get analysis basis: ${result.error}`);
}
} catch (error) {
showError(`❌ Error getting analysis basis: ${error.message}`);
}
}
async function previewAllEmailContent() {
try {
const customerId = document.getElementById('customerId').value || 144;
showSuccess('Previewing all 10 email contents...');
const response = await fetch(`/api/email-content-preview/${customerId}`);
const result = await response.json();
if (result.success) {
let previewHtml = `
<div class="alert alert-warning">
<h5><i class="fas fa-file-alt"></i> All 10 Email Content Previews</h5>
<p><strong>Total Emails:</strong> ${result.total_emails}</p>
</div>
`;
result.email_previews.forEach((preview, index) => {
previewHtml += `
<div class="card mb-3">
<div class="card-header">
<h6>${index + 1}. ${preview.email_type.replace('_', ' ').toUpperCase()}</h6>
<p class="mb-0"><strong>Subject:</strong> ${preview.subject}</p>
</div>
<div class="card-body">
${preview.error ?
`<div class="alert alert-danger">Error: ${preview.error}</div>` :
`
<p><strong>Properties Included:</strong> ${preview.recommendations_count}</p>
<div class="row">
<div class="col-md-6">
<h6>Sample Properties:</h6>
${preview.properties_included.map(prop =>
`<p>β€’ ${prop.name} - β‚Ή${prop.price} (${prop.type}) - Score: ${prop.score}</p>`
).join('')}
</div>
<div class="col-md-6">
<h6>Email Content Preview:</h6>
<div style="max-height: 150px; overflow-y: auto; border: 1px solid #ddd; padding: 10px;">
${preview.text_content.substring(0, 300)}...
</div>
</div>
</div>
`
}
</div>
</div>
`;
});
document.getElementById('multiAiResults').innerHTML = previewHtml;
showSuccess('βœ… All email content previews generated successfully');
} else {
showError(`❌ Failed to preview email content: ${result.error}`);
}
} catch (error) {
showError(`❌ Error previewing email content: ${error.message}`);
}
}
async function testAll10Emails() {
try {
const customerId = document.getElementById('customerId').value || 144;
const email = document.getElementById('testEmail').value;
if (!email) {
showError('Please enter an email address');
return;
}
showSuccess('Preparing to send all 10 email types... Ensuring properties are available...');
// First, make sure properties are fetched
try {
const fetchResponse = await fetch('/api/fetch-all-properties');
const fetchResult = await fetchResponse.json();
if (fetchResult.success) {
showSuccess(`βœ… Properties ready: ${fetchResult.summary.total_stored} properties available`);
}
} catch (fetchError) {
showError('Warning: Could not verify property availability, continuing anyway...');
}
showSuccess('Sending all 10 email types with real properties... This may take a few minutes.');
const response = await fetch(`/api/test-all-10-emails/${customerId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email: email })
});
const result = await response.json();
if (result.success) {
let resultsHtml = `
<div class="alert alert-success">
<h5><i class="fas fa-envelope-open-text"></i> All 10 Email Types Test Results</h5>
<p><strong>Customer ID:</strong> ${result.customer_id}</p>
<p><strong>Recipient:</strong> ${result.recipient_email}</p>
<p><strong>Total Attempted:</strong> ${result.test_results.total_attempted}</p>
<p><strong>Successfully Sent:</strong> ${result.test_results.total_sent}</p>
<p><strong>Failed:</strong> ${result.test_results.total_failed}</p>
<p><strong>ChromaDB Status:</strong> ${result.chromadb_status}</p>
</div>
`;
if (result.test_results.sent_emails.length > 0) {
resultsHtml += '<h6>βœ… Successfully Sent Emails:</h6>';
result.test_results.sent_emails.forEach((email, index) => {
resultsHtml += `
<div class="card mb-2">
<div class="card-body">
<h6>${index + 1}. ${email.type.replace('_', ' ').toUpperCase()}</h6>
<p><strong>Subject:</strong> ${email.subject}</p>
<p><strong>Strategy:</strong> ${email.strategy}</p>
<p><strong>Properties:</strong> ${email.recommendations_count} from ChromaDB</p>
<p><strong>Sample Properties:</strong></p>
<ul>
${email.sample_properties.map(prop =>
`<li>${prop.name} - β‚Ή${prop.price} (${prop.type}) - AI Score: ${prop.ai_score}</li>`
).join('')}
</ul>
<small class="text-muted">Sent at: ${email.timestamp}</small>
</div>
</div>
`;
});
}
if (result.test_results.failed_emails.length > 0) {
resultsHtml += '<h6>❌ Failed Emails:</h6>';
result.test_results.failed_emails.forEach((email, index) => {
resultsHtml += `
<div class="alert alert-danger">
<strong>${index + 1}. ${email.type}:</strong> ${email.error}
<br><small>Strategy: ${email.strategy}</small>
</div>
`;
});
}
document.getElementById('multiAiResults').innerHTML = resultsHtml;
showSuccess(`βœ… Email test completed! ${result.test_results.total_sent}/${result.test_results.total_attempted} emails sent successfully.`);
} else {
showError(`❌ Failed to test emails: ${result.error}`);
}
} catch (error) {
showError(`❌ Error testing emails: ${error.message}`);
}
}
async function checkChromaDBStatus() {
try {
showSuccess('Checking ChromaDB status...');
const response = await fetch('/api/chromadb-status');
const result = await response.json();
if (result.success) {
let statusHtml = `
<div class="alert alert-${result.chromadb_initialized ? (result.property_count > 0 ? 'success' : 'warning') : 'danger'}">
<h5><i class="fas fa-database"></i> ChromaDB Status Report</h5>
<p><strong>Initialized:</strong> ${result.chromadb_initialized ? 'βœ… Yes' : '❌ No'}</p>
`;
if (result.chromadb_initialized) {
statusHtml += `
<p><strong>Collection Name:</strong> ${result.collection_name}</p>
<p><strong>Property Count:</strong> ${result.property_count}</p>
<p><strong>Status:</strong> ${result.status === 'ready' ? 'βœ… Ready' : '⚠️ Empty'}</p>
`;
}
statusHtml += `
<p><strong>Message:</strong> ${result.message}</p>
<p><strong>Timestamp:</strong> ${result.timestamp}</p>
</div>
`;
document.getElementById('multiAiResults').innerHTML = statusHtml;
if (result.property_count > 0) {
showSuccess(`βœ… ChromaDB ready with ${result.property_count} properties!`);
} else {
showError(`⚠️ ChromaDB is empty. Click "Fetch Properties" to populate it.`);
}
} else {
showError(`❌ ChromaDB status check failed: ${result.error}`);
}
} catch (error) {
showError(`❌ Error checking ChromaDB status: ${error.message}`);
}
}
async function showEmailTypes() {
const emailTypes = [
{ type: 'property_based', description: 'Properties matching customer\'s preferred property types', icon: '🏠' },
{ type: 'price_based', description: 'Properties within customer\'s budget range', icon: 'πŸ’°' },
{ type: 'location_based', description: 'Properties in customer\'s preferred locations', icon: 'πŸ“' },
{ type: 'similarity_based', description: 'Properties similar to customer\'s viewed properties', icon: 'πŸ”' },
{ type: 'behavioral_based', description: 'Properties based on customer behavior patterns', icon: '🧠' },
{ type: 'premium_properties', description: 'High-end luxury properties', icon: '⭐' },
{ type: 'budget_friendly', description: 'Value-for-money properties', icon: 'πŸ’΅' },
{ type: 'trending_properties', description: 'Currently trending market properties', icon: 'πŸ“ˆ' },
{ type: 'family_oriented', description: 'Family-suitable properties with amenities', icon: 'πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦' },
{ type: 'investment_opportunities', description: 'Properties with high ROI potential', icon: 'πŸ’Ό' }
];
let typesHtml = `
<div class="alert alert-info">
<h5><i class="fas fa-list"></i> All 10 Email Types & ChromaDB Strategies</h5>
<p>Each email type uses unique ChromaDB vector search strategies:</p>
</div>
`;
emailTypes.forEach((emailType, index) => {
typesHtml += `
<div class="card mb-2">
<div class="card-body">
<h6>${emailType.icon} ${index + 1}. ${emailType.type.replace('_', ' ').toUpperCase()}</h6>
<p class="mb-0">${emailType.description}</p>
</div>
</div>
`;
});
document.getElementById('multiAiResults').innerHTML = typesHtml;
showSuccess('βœ… All email types displayed');
}
// Utility Functions
function formatPrice(price) {
return new Intl.NumberFormat('en-IN').format(price);
}
function formatDuration(seconds) {
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
return `${hours}h ${minutes}m`;
}
function showSuccess(message) {
const alert = document.createElement('div');
alert.className = 'alert alert-success alert-dismissible fade show position-fixed';
alert.style.cssText = 'top: 20px; right: 20px; z-index: 9999; max-width: 400px;';
alert.innerHTML = `
${message}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
`;
document.body.appendChild(alert);
setTimeout(() => {
if (alert.parentNode) {
alert.remove();
}
}, 5000);
}
function showError(message) {
const alert = document.createElement('div');
alert.className = 'alert alert-danger alert-dismissible fade show position-fixed';
alert.style.cssText = 'top: 20px; right: 20px; z-index: 9999; max-width: 400px;';
alert.innerHTML = `
${message}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
`;
document.body.appendChild(alert);
setTimeout(() => {
if (alert.parentNode) {
alert.remove();
}
}, 5000);
}
// List saved emails function
function listSavedEmails() {
console.log('Getting saved emails...');
document.getElementById('emailTestResults').innerHTML = '<div class="alert alert-info"><i class="fas fa-spinner fa-spin"></i> Loading saved emails...</div>';
fetch(`${API_BASE_URL}/api/saved-emails`)
.then(response => response.json())
.then(data => {
let html = '<div class="alert alert-success"><h5><i class="fas fa-folder-open"></i> Saved Emails</h5>';
if (data.saved_emails && data.saved_emails.length > 0) {
html += `<p><strong>Found ${data.total_count} saved email files:</strong></p>`;
html += '<div class="row">';
data.saved_emails.forEach(email => {
html += `
<div class="col-md-6 mb-3">
<div class="card">
<div class="card-body">
<h6 class="card-title">${email.email_type}</h6>
<p class="card-text">
<small class="text-muted">
πŸ“… ${email.created_time}<br>
πŸ“ ${email.size_kb} KB
</small>
</p>
<a href="${API_BASE_URL}/view-email/${email.filename}" target="_blank" class="btn btn-primary btn-sm">
<i class="fas fa-external-link-alt"></i> Open Email
</a>
</div>
</div>
</div>
`;
});
html += '</div>';
} else {
html += '<p>No saved emails found. Emails will be saved here when SendGrid limits are exceeded.</p>';
}
html += '</div>';
document.getElementById('emailTestResults').innerHTML = html;
})
.catch(error => {
console.error('Error:', error);
document.getElementById('emailTestResults').innerHTML =
'<div class="alert alert-danger"><i class="fas fa-exclamation-triangle"></i> Error loading saved emails: ' + error.message + '</div>';
});
}
// Auto-analyze customer 144 on page load
window.onload = function() {
analyzeCustomer();
};
</script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>