anycoder-b738a38b / index.html
defaultdolphin's picture
Upload folder using huggingface_hub
96fe1b5 verified
Raw
History Blame Contribute Delete
43.7 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mortgage Leads & Expense Manager</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--primary: #2563eb;
--primary-dark: #1d4ed8;
--secondary: #7c3aed;
--success: #10b981;
--warning: #f59e0b;
--danger: #ef4444;
--dark: #1e293b;
--light: #f8fafc;
--gray: #64748b;
--white: #ffffff;
--shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
--gradient: linear-gradient(135deg, #2563eb 0%, #7c3aed 100%);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
}
body {
background: linear-gradient(135deg, #0f172a 0%, #1e293b 50%, #0f172a 100%);
min-height: 100vh;
color: var(--white);
overflow-x: hidden;
}
/* Background Pattern */
body::before {
content: '';
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image:
radial-gradient(circle at 20% 80%, rgba(37, 99, 235, 0.1) 0%, transparent 50%),
radial-gradient(circle at 80% 20%, rgba(124, 58, 237, 0.1) 0%, transparent 50%);
pointer-events: none;
z-index: -1;
}
/* Header */
header {
background: rgba(30, 41, 59, 0.8);
backdrop-filter: blur(20px);
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
padding: 1rem 2rem;
position: sticky;
top: 0;
z-index: 100;
}
.header-content {
max-width: 1400px;
margin: 0 auto;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 1rem;
}
.logo {
display: flex;
align-items: center;
gap: 0.75rem;
}
.logo-icon {
width: 42px;
height: 42px;
background: var(--gradient);
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.25rem;
box-shadow: var(--shadow);
}
.logo h1 {
font-size: 1.5rem;
font-weight: 700;
background: var(--gradient);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.header-links {
display: flex;
gap: 1.5rem;
align-items: center;
}
.header-links a {
color: var(--gray);
text-decoration: none;
font-weight: 500;
transition: color 0.3s;
}
.header-links a:hover {
color: var(--white);
}
.anycoder-link {
background: rgba(255, 255, 255, 0.1);
padding: 0.5rem 1rem;
border-radius: 8px;
font-size: 0.875rem;
color: var(--gray);
text-decoration: none;
transition: all 0.3s;
}
.anycoder-link:hover {
background: var(--primary);
color: var(--white);
}
/* Main Container */
.container {
max-width: 1400px;
margin: 0 auto;
padding: 2rem;
}
/* Stats Cards */
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 1.5rem;
margin-bottom: 2rem;
}
.stat-card {
background: rgba(30, 41, 59, 0.6);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 16px;
padding: 1.5rem;
transition: transform 0.3s, box-shadow 0.3s;
}
.stat-card:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-lg);
}
.stat-card-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 1rem;
}
.stat-icon {
width: 48px;
height: 48px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.25rem;
}
.stat-icon.blue { background: rgba(37, 99, 235, 0.2); color: #3b82f6; }
.stat-icon.green { background: rgba(16, 185, 129, 0.2); color: #10b981; }
.stat-icon.purple { background: rgba(124, 58, 237, 0.2); color: #8b5cf6; }
.stat-icon.orange { background: rgba(245, 158, 11, 0.2); color: #f59e0b; }
.stat-trend {
font-size: 0.875rem;
padding: 0.25rem 0.5rem;
border-radius: 6px;
}
.stat-trend.up { background: rgba(16, 185, 129, 0.2); color: #10b981; }
.stat-trend.down { background: rgba(239, 68, 68, 0.2); color: #ef4444; }
.stat-value {
font-size: 2rem;
font-weight: 700;
margin-bottom: 0.25rem;
}
.stat-label {
color: var(--gray);
font-size: 0.875rem;
}
/* Main Grid */
.main-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1.5rem;
}
@media (max-width: 1024px) {
.main-grid {
grid-template-columns: 1fr;
}
}
/* Cards */
.card {
background: rgba(30, 41, 59, 0.6);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 16px;
overflow: hidden;
}
.card-header {
padding: 1.25rem 1.5rem;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
display: flex;
justify-content: space-between;
align-items: center;
}
.card-title {
font-size: 1.125rem;
font-weight: 600;
display: flex;
align-items: center;
gap: 0.75rem;
}
.card-title i {
color: var(--primary);
}
.card-body {
padding: 1.5rem;
}
/* Tabs */
.tabs {
display: flex;
gap: 0.5rem;
padding: 0.5rem;
background: rgba(0, 0, 0, 0.2);
border-radius: 10px;
margin-bottom: 1.5rem;
}
.tab {
flex: 1;
padding: 0.75rem 1rem;
border: none;
background: transparent;
color: var(--gray);
font-size: 0.875rem;
font-weight: 500;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s;
}
.tab.active {
background: var(--gradient);
color: var(--white);
}
.tab:hover:not(.active) {
color: var(--white);
}
/* Forms */
.form-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
}
@media (max-width: 600px) {
.form-grid {
grid-template-columns: 1fr;
}
}
.form-group {
margin-bottom: 1rem;
}
.form-group.full-width {
grid-column: 1 / -1;
}
.form-label {
display: block;
font-size: 0.875rem;
font-weight: 500;
margin-bottom: 0.5rem;
color: var(--gray);
}
.form-input, .form-select {
width: 100%;
padding: 0.75rem 1rem;
background: rgba(0, 0, 0, 0.2);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 10px;
color: var(--white);
font-size: 0.9rem;
transition: border-color 0.3s, box-shadow 0.3s;
}
.form-input:focus, .form-select:focus {
outline: none;
border-color: var(--primary);
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.2);
}
.form-input::placeholder {
color: var(--gray);
}
.form-select option {
background: var(--dark);
}
/* Buttons */
.btn {
padding: 0.75rem 1.5rem;
border: none;
border-radius: 10px;
font-size: 0.9rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
}
.btn-primary {
background: var(--gradient);
color: var(--white);
box-shadow: var(--shadow);
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: var(--shadow-lg);
}
.btn-secondary {
background: rgba(255, 255, 255, 0.1);
color: var(--white);
}
.btn-secondary:hover {
background: rgba(255, 255, 255, 0.2);
}
.btn-danger {
background: rgba(239, 68, 68, 0.2);
color: #ef4444;
}
.btn-danger:hover {
background: #ef4444;
color: var(--white);
}
.btn-group {
display: flex;
gap: 0.75rem;
margin-top: 1.5rem;
}
/* Expense Table */
.expense-table {
width: 100%;
border-collapse: collapse;
}
.expense-table th,
.expense-table td {
padding: 1rem;
text-align: left;
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}
.expense-table th {
font-size: 0.75rem;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--gray);
font-weight: 600;
}
.expense-table td {
font-size: 0.9rem;
}
.expense-table tbody tr {
transition: background 0.2s;
}
.expense-table tbody tr:hover {
background: rgba(255, 255, 255, 0.05);
}
.expense-category {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.25rem 0.75rem;
border-radius: 6px;
font-size: 0.8rem;
font-weight: 500;
}
.expense-category.mortgage { background: rgba(37, 99, 235, 0.2); color: #3b82f6; }
.expense-category.taxes { background: rgba(124, 58, 237, 0.2); color: #8b5cf6; }
.expense-category.insurance { background: rgba(16, 185, 129, 0.2); color: #10b981; }
.expense-category.maintenance { background: rgba(245, 158, 11, 0.2); color: #f59e0b; }
.expense-category.utilities { background: rgba(236, 72, 153, 0.2); color: #ec4899; }
.status-badge {
padding: 0.25rem 0.75rem;
border-radius: 20px;
font-size: 0.75rem;
font-weight: 600;
}
.status-badge.new { background: rgba(37, 99, 235, 0.2); color: #3b82f6; }
.status-badge.contacted { background: rgba(245, 158, 11, 0.2); color: #f59e0b; }
.status-badge.qualified { background: rgba(16, 185, 129, 0.2); color: #10b981; }
.status-badge.closed { background: rgba(124, 58, 237, 0.2); color: #8b5cf6; }
/* Calculator Result */
.calculator-result {
background: rgba(0, 0, 0, 0.3);
border-radius: 12px;
padding: 1.5rem;
margin-top: 1.5rem;
}
.result-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.75rem 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}
.result-row:last-child {
border-bottom: none;
}
.result-label {
color: var(--gray);
font-size: 0.9rem;
}
.result-value {
font-weight: 600;
font-size: 1.1rem;
}
.result-value.highlight {
color: var(--success);
font-size: 1.5rem;
}
/* Lead List */
.lead-list {
max-height: 400px;
overflow-y: auto;
}
.lead-item {
display: flex;
align-items: center;
gap: 1rem;
padding: 1rem;
background: rgba(0, 0, 0, 0.2);
border-radius: 10px;
margin-bottom: 0.75rem;
transition: all 0.3s;
}
.lead-item:hover {
background: rgba(0, 0, 0, 0.3);
}
.lead-avatar {
width: 44px;
height: 44px;
border-radius: 10px;
background: var(--gradient);
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
font-size: 1rem;
flex-shrink: 0;
}
.lead-info {
flex: 1;
min-width: 0;
}
.lead-name {
font-weight: 600;
margin-bottom: 0.25rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.lead-detail {
font-size: 0.8rem;
color: var(--gray);
}
.lead-actions {
display: flex;
gap: 0.5rem;
}
.lead-actions button {
width: 32px;
height: 32px;
border: none;
border-radius: 8px;
cursor: pointer;
transition: all 0.3s;
display: flex;
align-items: center;
justify-content: center;
}
.lead-actions .view-btn {
background: rgba(37, 99, 235, 0.2);
color: #3b82f6;
}
.lead-actions .delete-btn {
background: rgba(239, 68, 68, 0.2);
color: #ef4444;
}
.lead-actions button:hover {
transform: scale(1.1);
}
/* Chart Placeholder */
.chart-container {
height: 200px;
display: flex;
align-items: flex-end;
gap: 0.5rem;
padding: 1rem 0;
}
.chart-bar {
flex: 1;
background: var(--gradient);
border-radius: 6px 6px 0 0;
transition: height 0.5s ease;
position: relative;
}
.chart-bar::after {
content: attr(data-label);
position: absolute;
bottom: -25px;
left: 50%;
transform: translateX(-50%);
font-size: 0.7rem;
color: var(--gray);
white-space: nowrap;
}
/* Empty State */
.empty-state {
text-align: center;
padding: 3rem;
color: var(--gray);
}
.empty-state i {
font-size: 3rem;
margin-bottom: 1rem;
opacity: 0.5;
}
/* Animations */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
.fade-in {
animation: fadeIn 0.4s ease forwards;
}
/* Modal */
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.7);
backdrop-filter: blur(4px);
display: none;
align-items: center;
justify-content: center;
z-index: 1000;
padding: 1rem;
}
.modal-overlay.active {
display: flex;
}
.modal {
background: var(--dark);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 16px;
max-width: 500px;
width: 100%;
max-height: 90vh;
overflow-y: auto;
animation: fadeIn 0.3s ease;
}
.modal-header {
padding: 1.25rem 1.5rem;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
display: flex;
justify-content: space-between;
align-items: center;
}
.modal-header h3 {
font-size: 1.125rem;
}
.modal-close {
width: 32px;
height: 32px;
border: none;
background: rgba(255, 255, 255, 0.1);
color: var(--white);
border-radius: 8px;
cursor: pointer;
transition: background 0.3s;
}
.modal-close:hover {
background: rgba(239, 68, 68, 0.5);
}
.modal-body {
padding: 1.5rem;
}
/* Scrollbar */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0.2);
border-radius: 4px;
}
::-webkit-scrollbar-thumb {
background: var(--gray);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--primary);
}
/* Responsive */
@media (max-width: 768px) {
.header-content {
flex-direction: column;
text-align: center;
}
.header-links {
width: 100%;
justify-content: center;
flex-wrap: wrap;
}
.container {
padding: 1rem;
}
.stats-grid {
grid-template-columns: 1fr 1fr;
}
.stat-card {
padding: 1rem;
}
.stat-value {
font-size: 1.5rem;
}
.btn-group {
flex-direction: column;
}
.lead-item {
flex-wrap: wrap;
}
}
@media (max-width: 480px) {
.stats-grid {
grid-template-columns: 1fr;
}
.tabs {
flex-direction: column;
}
.form-grid {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<header>
<div class="header-content">
<div class="logo">
<div class="logo-icon">
<i class="fas fa-home"></i>
</div>
<h1>MortgageHub</h1>
</div>
<div class="header-links">
<a href="#" onclick="showTab('leads')"><i class="fas fa-users"></i> Leads</a>
<a href="#" onclick="showTab('expenses')"><i class="fas fa-calculator"></i> Expenses</a>
<a href="#" onclick="showTab('calculator')"><i class="fas fa-chart-line"></i> Calculator</a>
<a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">
<i class="fas fa-code"></i> Built with anycoder
</a>
</div>
</div>
</header>
<div class="container">
<!-- Stats Grid -->
<div class="stats-grid">
<div class="stat-card">
<div class="stat-card-header">
<div class="stat-icon blue">
<i class="fas fa-users"></i>
</div>
<span class="stat-trend up"><i class="fas fa-arrow-up"></i> 12%</span>
</div>
<div class="stat-value" id="totalLeads">0</div>
<div class="stat-label">Total Leads</div>
</div>
<div class="stat-card">
<div class="stat-card-header">
<div class="stat-icon green">
<i class="fas fa-check-circle"></i>
</div>
<span class="stat-trend up"><i class="fas fa-arrow-up"></i> 8%</span>
</div>
<div class="stat-value" id="qualifiedLeads">0</div>
<div class="stat-label">Qualified Leads</div>
</div>
<div class="stat-card">
<div class="stat-card-header">
<div class="stat-icon purple">
<i class="fas fa-dollar-sign"></i>
</div>
</div>
<div class="stat-value" id="totalExpenses">$0</div>
<div class="stat-label">Total Monthly Expenses</div>
</div>
<div class="stat-card">
<div class="stat-card-header">
<div class="stat-icon orange">
<i class="fas fa-file-invoice-dollar"></i>
</div>
</div>
<div class="stat-value" id="avgMortgage">$0</div>
<div class="stat-label">Avg. Mortgage Payment</div>
</div>
</div>
<!-- Main Grid -->
<div class="main-grid">
<!-- Lead Generation Form -->
<div class="card">
<div class="card-header">
<h2 class="card-title">
<i class="fas fa-user-plus"></i>
Generate New Lead
</h2>
</div>
<div class="card-body">
<form id="leadForm">
<div class="form-grid">
<div class="form-group">
<label class="form-label">Full Name</label>
<input type="text" class="form-input" id="leadName" placeholder="John Doe" required>
</div>
<div class="form-group">
<label class="form-label">Email Address</label>
<input type="email" class="form-input" id="leadEmail" placeholder="john@example.com" required>
</div>
<div class="form-group">
<label class="form-label">Phone Number</label>
<input type="tel" class="form-input" id="leadPhone" placeholder="(555) 123-4567" required>
</div>
<div class="form-group">
<label class="form-label">Property Type</label>
<select class="form-select" id="leadPropertyType">
<option value="single-family">Single Family Home</option>
<option value="condo">Condo</option>
<option value="townhouse">Townhouse</option>
<option value="multi-family">Multi-Family</option>
<option value="commercial">Commercial</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Loan Amount Needed</label>
<input type="number" class="form-input" id="leadLoanAmount" placeholder="250000" required>
</div>
<div class="form-group">
<label class="form-label">Property Value</label>
<input type="number" class="form-input" id="leadPropertyValue" placeholder="350000" required>
</div>
<div class="form-group">
<label class="form-label">Annual Income</label>
<input type="number" class="form-input" id="leadIncome" placeholder="75000" required>
</div>
<div class="form-group">
<label class="form-label">Credit Score</label>
<select class="form-select" id="leadCreditScore">
<option value="excellent">Excellent (750+)</option>
<option value="good">Good (700-749)</option>
<option value="fair">Fair (650-699)</option>
<option value="poor">Poor (<650)</option>
</select>
</div>
</div>
<div class="btn-group">
<button type="submit" class="btn btn-primary">
<i class="fas fa-plus-circle"></i> Generate Lead
</button>
<button type="reset" class="btn btn-secondary">
<i class="fas fa-redo"></i> Reset
</button>
</div>
</form>
</div>
</div>
<!-- Expense Tracker -->
<div class="card">
<div class="card-header">
<h2 class="card-title">
<i class="fas fa-wallet"></i>
Expense Tracker
</h2>
<button class="btn btn-primary" onclick="openExpenseModal()">
<i class="fas fa-plus"></i> Add Expense
</button>
</div>
<div class="card-body">
<div class="tabs">
<button class="tab active" onclick="filterExpenses('all')">All</button>
<button class="tab" onclick="filterExpenses('mortgage')">Mortgage</button>
<button class="tab" onclick="filterExpenses('taxes')">Taxes</button>
<button class="tab" onclick="filterExpenses('insurance')">Insurance</button>
</div>
<div id="expenseList">
<table class="expense-table">
<thead>
<tr>
<th>Description</th>
<th>Category</th>
<th>Amount</th>
<th>Due Date</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="expenseTableBody">
<!-- Expenses will be added here -->
</tbody>
</table>
<div class="empty-state" id="expenseEmptyState">
<i class="fas fa-receipt"></i>
<p>No expenses added yet</p>
</div>
</div>
</div>
</div>
</div>
<!-- Leads List -->
<div class="card" style="margin-top: 1.5rem;">
<div class="card-header">
<h2 class="card-title">
<i class="fas fa-list"></i>
Recent Leads
</h2>
<div>
<button class="btn btn-secondary" onclick="exportLeads()">
<i class="fas fa-download"></i> Export
</button>
</div>
</div>
<div class="card-body">
<div class="lead-list" id="leadList">
<div class="empty-state" id="leadEmptyState">
<i class="fas fa-user-friends"></i>
<p>No leads generated yet</p>
</div>
</div>
</div>
</div>
<!-- Mortgage Calculator -->
<div class="card" style="margin-top: 1.5rem;">
<div class="card-header">
<h2 class="card-title">
<i class="fas fa-calculator"></i>
Mortgage Calculator
</h2>
</div>
<div class="card-body">
<div class="form-grid">
<div class="form-group">
<label class="form-label">Home Price ($)</label>
<input type="number" class="form-input" id="calcHomePrice" value="350000" oninput="calculateMortgage()">
</div>
<div class="form-group">
<label class="form-label">Down Payment ($)</label>
<input type="number" class="form-input" id="calcDownPayment" value="70000" oninput="calculateMortgage()">
</div>
<div class="form-group">
<label class="form-label">Interest Rate (%)</label>
<input type="number" class="form-input" id="calcInterestRate" value="6.5" step="0.1" oninput="calculateMortgage()">
</div>
<div class="form-group">
<label class="form-label">Loan Term (Years)</label>
<select class="form-select" id="calcLoanTerm" onchange="calculateMortgage()">
<option value="15">15 Years</option>
<option value="20">20 Years</option>
<option value="30" selected>30 Years</option>
</select>
</div>
</div>
<div class="calculator-result" id="calcResult">
<div class="result-row">
<span class="result-label">Loan Amount</span>
<span class="result-value" id="resultLoanAmount">$280,000</span>
</div>
<div class="result-row">
<span class="result-label">Monthly Principal & Interest</span>
<span class="result-value highlight" id="resultMonthlyPayment">$1,772</span>
</div>
<div class="result-row">
<span class="result-label">Total Interest Paid</span>
<span class="result-value" id="resultTotalInterest">$357,920</span>
</div>
<div class="result-row">
<span class="result-label">Total Amount Paid</span>
<span class="result-value" id="resultTotalAmount">$637,920</span>
</div>
</div>
</div>
</div>
</div>
<!-- Expense Modal -->
<div class="modal-overlay" id="expenseModal">
<div class="modal">
<div class="modal-header">
<h3>Add New Expense</h3>
<button class="modal-close" onclick="closeExpenseModal()">
<i class="fas fa-times"></i>
</button>
</div>
<div class="modal-body">
<form id="expenseForm">
<div class="form-group">
<label class="form-label">Description</label>
<input type="text" class="form-input" id="expenseDescription" placeholder="Monthly mortgage payment" required>
</div>
<div class="form-group">
<label class="form-label">Category</label>
<select class="form-select" id="expenseCategory">
<option value="mortgage">Mortgage</option>
<option value="taxes">Property Taxes</option>
<option value="insurance">Home Insurance</option>
<option value="maintenance">Maintenance</option>
<option value="utilities">Utilities</option>
</select>
</div>
<div class="form-group">
<label class="form-label">Amount ($)</label>
<input type="number" class="form-input" id="expenseAmount" placeholder="1500" required>
</div>
<div class="form-group">
<label class="form-label">Due Date</label>
<input type="date" class="form-input" id="expenseDueDate" required>
</div>
<div class="btn-group">
<button type="submit" class="btn btn-primary" style="width: 100%;">
<i class="fas fa-plus"></i> Add Expense
</button>
</div>
</form>
</div>
</div>
</div>
<script>
// Data Storage
let leads = [];
let expenses = [];
let expenseFilter = 'all';
// Initialize
document.addEventListener('DOMContentLoaded', () => {
loadFromStorage();
updateStats();
renderLeads();
renderExpenses();
calculateMortgage();
// Set default date to today
document.getElementById('expenseDueDate').valueAsDate = new Date();
});
// Storage Functions
function saveToStorage() {
localStorage.setItem('mortgageLeads', JSON.stringify(leads));
localStorage.setItem('mortgageExpenses', JSON.stringify(expenses));
}
function loadFromStorage() {
const storedLeads = localStorage.getItem('mortgageLeads');
const storedExpenses = localStorage.getItem('mortgageExpenses');
if (storedLeads) leads = JSON.parse(storedLeads);
if (storedExpenses) expenses = JSON.parse(storedExpenses);
}
// Lead Form Handler
document.getElementById('leadForm').addEventListener('submit', (e) => {
e.preventDefault();
const lead = {
id: Date.now(),
name: document.getElementById('leadName').value,
email: document.getElementById('leadEmail').value,
phone: document.getElementById('leadPhone').value,
propertyType: document.getElementById('leadPropertyType').value,
loanAmount: parseFloat(document.getElementById('leadLoanAmount').value),
propertyValue: parseFloat(document.getElementById('leadPropertyValue').value),
income: parseFloat(document.getElementById('leadIncome').value),
creditScore: document.getElementById('leadCreditScore').value,
status: 'new',
date: new Date().toLocaleDateString()
};
// Calculate LTV and DTI
lead.ltv = (lead.loanAmount / lead.propertyValue * 100).toFixed(1);
lead.dti = ((lead.loanAmount * 0.04) / (lead.income / 12) * 100).toFixed(1); // Estimated
leads.unshift(lead);
saveToStorage();
updateStats();
renderLeads();
// Auto-add estimated mortgage as expense
const estimatedPayment = (lead.loanAmount * 0.005).toFixed(0); // Rough estimate
if (confirm(`Lead added! Would you like to add estimated monthly mortgage payment ($${estimatedPayment}) as an expense?`)) {
addExpense({
description: `Mortgage - ${lead.name}`,
category: 'mortgage',
amount: parseFloat(estimatedPayment),
dueDate: new Date().toISOString().split('T')[0]
});
}
e.target.reset();
});
// Expense Form Handler
document.getElementById('expenseForm').addEventListener('submit', (e) => {
e.preventDefault();
const expense = {
id: Date.now(),
description: document.getElementById('expenseDescription').value,
category: document.getElementById('expenseCategory').value,
amount: parseFloat(document.getElementById('expenseAmount').value),
dueDate: document.getElementById('expenseDueDate').value,
date: new Date().toLocaleDateString()
};
addExpense(expense);
closeExpenseModal();
e.target.reset();
});
function addExpense(expense) {
expenses.unshift(expense);
saveToStorage();
updateStats();
renderExpenses();
}
// Render Leads
function renderLeads() {
const container = document.getElementById('leadList');
const emptyState = document.getElementById('leadEmptyState');
if (leads.length === 0) {
container.innerHTML = '';
container.appendChild(emptyState);
emptyState.style.display = 'block';
return;
}
emptyState.style.display = 'none';
container.innerHTML = leads.map((lead, index) => `
<div class="lead-item fade-in" style="animation-delay: ${index * 0.05}s">
<div class="lead-avatar">${lead.name.split(' ').map(n => n[0]).join('')}</div>
<div class="lead-info">
<div class="lead-name">${lead.name}</div>
<div class="lead-detail">
<i class="fas fa-phone"></i> ${lead.phone} |
<i class="fas fa-home"></i> ${lead.propertyType} |
<i class="fas fa-dollar-sign"></i> $${lead.loanAmount.toLocaleString()}
</div>
<div class="lead-detail">
<span class="status-badge ${lead.status}">${lead.status.toUpperCase()}</span>
<span style="margin-left: 0.5rem; color: var(--gray);">LTV: ${lead.ltv}% | DTI: ${lead.dti}%</span>
</div>
</div>
<div class="lead-actions">
<button class="view-btn" onclick="viewLead(${lead.id})" title="View Details">
<i class="fas fa-eye"></i>
</button>
<button class="delete-btn" onclick="deleteLead(${lead.id})" title="Delete">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
`).join('');
}
// Render Expenses
function renderExpenses() {
const tbody = document.getElementById('expenseTableBody');
const emptyState = document.getElementById('expenseEmptyState');
let filteredExpenses = expenseFilter === 'all'
? expenses
: expenses.filter(e => e.category === expenseFilter);
if (filteredExpenses.length === 0) {
tbody.innerHTML = '';
emptyState.style.display = 'block';
return;
}
emptyState.style.display = 'none';
tbody.innerHTML = filteredExpenses.map(expense => `
<tr class="fade-in">
<td>${expense.description}</td>
<td><span class="expense-category ${expense.category}">${expense.category}</span></td>
<td>$${expense.amount.toLocaleString()}</td>
<td>${new Date(expense.dueDate).toLocaleDateString()}</td>
<td>
<button class="btn btn-danger" style="padding: 0.25rem 0.5rem; font-size: 0.75rem;" onclick="deleteExpense(${expense.id})">
<i class="fas fa-trash"></i>
</button>
</td>
</tr>
`).join('');
}
// Filter Expenses
function filterExpenses(category) {
expenseFilter = category;
document.querySelectorAll('.tabs .tab').forEach(tab => {
tab.classList.remove('active');
if (tab.textContent.toLowerCase().includes(category) || (category === 'all' && tab.textContent === 'All')) {
tab.classList.add('active');
}
});
renderExpenses();
}
// Update Stats
function updateStats() {
document.getElementById('totalLeads').textContent = leads.length;
document.getElementById('qualifiedLeads').textContent = leads.filter(l => l.status === 'qualified' || l.status === 'closed').length;
const totalExpenses = expenses.reduce((sum, e) => sum + e.amount, 0);
document.getElementById('totalExpenses').textContent = '$' + totalExpenses.toLocaleString();
const mortgageExpenses = expenses.filter(e => e.category === 'mortgage');
const avgMortgage = mortgageExpenses.length > 0
? mortgageExpenses.reduce((sum, e) => sum + e.amount, 0) / mortgageExpenses.length
: 0;
document.getElementById('avgMortgage').textContent = '$' + Math.round(avgMortgage).toLocaleString();
}
// Mortgage Calculator
function calculateMortgage() {
const homePrice = parseFloat(document.getElementById('calcHomePrice').value) || 0;
const downPayment = parseFloat(document.getElementById('calcDownPayment').value) || 0;
const interestRate = parseFloat(document.getElementById('calcInterestRate').value) || 0;
const loanTerm = parseInt(document.getElementById('calcLoanTerm').value) || 30;
const loanAmount = homePrice - downPayment;
const monthlyRate = interestRate / 100 / 12;
const numPayments = loanTerm * 12;
let monthlyPayment;
if (monthlyRate === 0) {
monthlyPayment = loanAmount / numPayments;
} else {
monthlyPayment = loanAmount * (monthlyRate * Math.pow(1