| Server IP : 139.59.63.204 / Your IP : 216.73.217.62 Web Server : Apache/2.4.58 (Ubuntu) System : Linux ubuntu-s-1vcpu-1gb-blr1-01 6.8.0-110-generic #110-Ubuntu SMP PREEMPT_DYNAMIC Thu Mar 19 15:09:20 UTC 2026 x86_64 User : root ( 0) PHP Version : 8.3.6 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/efbtechnology.com/web-design-services/ |
Upload File : |
<?php
// ============================================================
// EFB Technology — Leads Admin Panel
// File: admin/leads.php
// Access: yourdomain.com/admin/leads.php
// ============================================================
session_start();
require_once __DIR__ . '/../config/db.php';
// ── Simple login ─────────────────────────────────────────────
$loginError = '';
if (!isset($_SESSION['efb_admin'])) {
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['login'])) {
$pdo = getDB();
$u = trim($_POST['username'] ?? '');
$p = $_POST['password'] ?? '';
$row = $pdo->prepare("SELECT password FROM admin_users WHERE username = ? LIMIT 1");
$row->execute([$u]);
$hash = $row->fetchColumn();
if ($hash && password_verify($p, $hash)) {
$_SESSION['efb_admin'] = $u;
header('Location: leads.php'); exit;
}
$loginError = 'Invalid username or password.';
}
showLogin($loginError); exit;
}
if (isset($_GET['logout'])) { session_destroy(); header('Location: leads.php'); exit; }
// ── Filters & Pagination ─────────────────────────────────────
$pdo = getDB();
$page = max(1, (int)($_GET['page'] ?? 1));
$perPage = 20;
$offset = ($page - 1) * $perPage;
$status = $_GET['status'] ?? '';
$planF = $_GET['plan'] ?? '';
$search = trim($_GET['q'] ?? '');
$where = '1=1';
$params = [];
if ($status) { $where .= ' AND status = :status'; $params[':status'] = $status; }
if ($planF) { $where .= ' AND plan = :plan'; $params[':plan'] = $planF; }
if ($search) {
$where .= ' AND (name LIKE :q OR email LIKE :q OR phone LIKE :q OR business LIKE :q)';
$params[':q'] = '%' . $search . '%';
}
$total = $pdo->prepare("SELECT COUNT(*) FROM leads WHERE $where");
$total->execute($params);
$totalRows = (int)$total->fetchColumn();
$totalPages = (int)ceil($totalRows / $perPage);
$stmt = $pdo->prepare("SELECT * FROM leads WHERE $where ORDER BY created_at DESC LIMIT $perPage OFFSET $offset");
$stmt->execute($params);
$leads = $stmt->fetchAll();
// Stats
$stats = $pdo->query("SELECT status, COUNT(*) as cnt FROM leads GROUP BY status")->fetchAll();
$statMap = array_column($stats, 'cnt', 'status');
// Update status via AJAX
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['update_status'])) {
header('Content-Type: application/json');
$id = (int)$_POST['id'];
$s = in_array($_POST['new_status'], ['new','contacted','converted','lost']) ? $_POST['new_status'] : 'new';
$pdo->prepare("UPDATE leads SET status=? WHERE id=?")->execute([$s, $id]);
echo json_encode(['success' => true]); exit;
}
// Export CSV
if (isset($_GET['export']) && $_GET['export'] === 'csv') {
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="efb_leads_' . date('Y-m-d') . '.csv"');
$out = fopen('php://output', 'w');
fputcsv($out, ['ID','Name','Phone','Email','Business','Plan','Message','UTM Source','UTM Campaign','Status','Date']);
$all = $pdo->prepare("SELECT id,name,phone,email,business,plan,message,utm_source,utm_campaign,status,created_at FROM leads WHERE $where ORDER BY created_at DESC");
$all->execute($params);
while ($row = $all->fetch()) fputcsv($out, $row);
fclose($out); exit;
}
function badge(string $s): string {
$map = ['new'=>'#3b82f6','contacted'=>'#f59e0b','converted'=>'#10b981','lost'=>'#ef4444'];
$c = $map[$s] ?? '#6b7280';
return "<span style='background:{$c};color:#fff;padding:2px 10px;border-radius:20px;font-size:0.75rem;font-weight:600;text-transform:uppercase'>{$s}</span>";
}
function planBadge(string $p): string {
$map = ['basic'=>'#64748b','standard'=>'#0099e6','premium'=>'#7c3aed','custom'=>'#059669'];
$c = $map[$p] ?? '#64748b';
return $p ? "<span style='background:{$c};color:#fff;padding:2px 10px;border-radius:20px;font-size:0.72rem;font-weight:600'>{$p}</span>" : '—';
}
function showLogin(string $err): void { ?>
<!DOCTYPE html><html><head><meta charset="UTF-8"><title>EFB Admin Login</title>
<style>*{box-sizing:border-box;margin:0;padding:0}body{background:#06080f;display:flex;align-items:center;justify-content:center;min-height:100vh;font-family:system-ui,sans-serif}.box{background:#0c1220;border:1px solid rgba(0,153,230,.2);border-radius:16px;padding:2.5rem;width:360px}.logo{color:#00c6ff;font-size:1.4rem;font-weight:800;margin-bottom:2rem;text-align:center}.logo span{color:#fff}h2{color:#e8f4ff;font-size:1rem;margin-bottom:1.5rem;text-align:center}label{display:block;color:#7a9ab8;font-size:.8rem;text-transform:uppercase;letter-spacing:.05em;margin-bottom:.4rem}input{width:100%;background:rgba(0,153,230,.05);border:1px solid rgba(0,153,230,.15);border-radius:8px;color:#e8f4ff;padding:.75rem 1rem;font-size:.95rem;margin-bottom:1rem;outline:none}input:focus{border-color:rgba(0,153,230,.5)}button{width:100%;background:linear-gradient(135deg,#0099e6,#00c6ff);color:#fff;border:none;padding:.9rem;border-radius:8px;font-size:1rem;font-weight:600;cursor:pointer}.err{background:rgba(239,68,68,.1);border:1px solid rgba(239,68,68,.3);color:#fca5a5;padding:.7rem 1rem;border-radius:8px;font-size:.85rem;margin-bottom:1rem;text-align:center}</style></head>
<body><div class="box"><div class="logo">EFB <span>Technology</span></div><h2>Leads Admin Panel</h2>
<?php if($err) echo '<div class="err">'.$err.'</div>'; ?>
<form method="post"><label>Username</label><input name="username" type="text" autocomplete="username" required>
<label>Password</label><input name="password" type="password" autocomplete="current-password" required>
<button name="login" value="1">Login →</button></form></div></body></html><?php }
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>EFB Technology — Leads Panel</title>
<style>
*{box-sizing:border-box;margin:0;padding:0}
body{background:#06080f;color:#e8f4ff;font-family:system-ui,sans-serif;font-size:14px}
a{color:#00c6ff;text-decoration:none}a:hover{text-decoration:underline}
header{background:#080d18;border-bottom:1px solid rgba(0,153,230,.15);padding:.9rem 2rem;display:flex;align-items:center;justify-content:space-between}
.brand{font-weight:800;font-size:1.1rem;color:#00c6ff}.brand span{color:#e8f4ff}
.logout{background:rgba(239,68,68,.1);border:1px solid rgba(239,68,68,.2);color:#fca5a5;padding:.4rem .9rem;border-radius:6px;font-size:.8rem}
.container{max-width:1280px;margin:0 auto;padding:1.5rem 2rem}
.stat-row{display:grid;grid-template-columns:repeat(4,1fr);gap:1rem;margin-bottom:1.5rem}
.stat-card{background:#0c1220;border:1px solid rgba(0,153,230,.1);border-radius:12px;padding:1.2rem 1.5rem}
.stat-num{font-size:2rem;font-weight:800;line-height:1}.stat-label{color:#7a9ab8;font-size:.78rem;text-transform:uppercase;letter-spacing:.08em;margin-top:.3rem}
.toolbar{display:flex;gap:.75rem;margin-bottom:1.2rem;flex-wrap:wrap;align-items:center}
.toolbar input,.toolbar select{background:#0c1220;border:1px solid rgba(0,153,230,.15);color:#e8f4ff;padding:.5rem .9rem;border-radius:8px;font-size:.85rem;outline:none}
.toolbar input:focus,.toolbar select:focus{border-color:rgba(0,153,230,.5)}
.btn{background:linear-gradient(135deg,#0099e6,#00c6ff);color:#fff;border:none;padding:.5rem 1.1rem;border-radius:8px;font-size:.85rem;font-weight:600;cursor:pointer}
.btn-outline{background:rgba(0,153,230,.08);border:1px solid rgba(0,153,230,.25);color:#00c6ff;padding:.5rem 1.1rem;border-radius:8px;font-size:.85rem;cursor:pointer}
table{width:100%;border-collapse:collapse;background:#0c1220;border-radius:12px;overflow:hidden;border:1px solid rgba(0,153,230,.1)}
thead{background:#080d18}th{padding:.8rem 1rem;text-align:left;font-size:.75rem;text-transform:uppercase;letter-spacing:.08em;color:#7a9ab8;font-weight:600;border-bottom:1px solid rgba(0,153,230,.1)}
td{padding:.8rem 1rem;border-bottom:1px solid rgba(255,255,255,.03);vertical-align:top}
tr:last-child td{border-bottom:none}tr:hover td{background:rgba(0,153,230,.04)}
.msg-cell{max-width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#7a9ab8}
.status-sel{background:#0c1220;border:1px solid rgba(0,153,230,.2);color:#e8f4ff;padding:3px 6px;border-radius:6px;font-size:.78rem;cursor:pointer}
.pagination{display:flex;gap:.5rem;margin-top:1.2rem;align-items:center}
.page-btn{background:#0c1220;border:1px solid rgba(0,153,230,.15);color:#e8f4ff;padding:.4rem .85rem;border-radius:6px;font-size:.85rem;cursor:pointer;text-decoration:none}
.page-btn.active{background:#0099e6;border-color:#0099e6;color:#fff}
.toast{position:fixed;top:1.2rem;right:1.2rem;background:#10b981;color:#fff;padding:.7rem 1.3rem;border-radius:8px;font-weight:600;font-size:.88rem;display:none;z-index:999}
</style>
</head>
<body>
<header>
<div class="brand">EFB <span>Technology</span> — Leads Panel</div>
<div style="display:flex;align-items:center;gap:1rem">
<span style="color:#7a9ab8">👤 <?= htmlspecialchars($_SESSION['efb_admin']) ?></span>
<a href="?logout=1" class="logout">Logout</a>
</div>
</header>
<div class="container">
<!-- Stats -->
<div class="stat-row">
<div class="stat-card"><div class="stat-num" style="color:#00c6ff"><?= $totalRows ?></div><div class="stat-label">Total Leads</div></div>
<div class="stat-card"><div class="stat-num" style="color:#3b82f6"><?= $statMap['new'] ?? 0 ?></div><div class="stat-label">New</div></div>
<div class="stat-card"><div class="stat-num" style="color:#10b981"><?= $statMap['converted'] ?? 0 ?></div><div class="stat-label">Converted</div></div>
<div class="stat-card"><div class="stat-num" style="color:#f59e0b"><?= $statMap['contacted'] ?? 0 ?></div><div class="stat-label">Contacted</div></div>
</div>
<!-- Toolbar -->
<form method="get" class="toolbar">
<input name="q" type="search" placeholder="🔍 Search name, email, phone..." value="<?= htmlspecialchars($search) ?>">
<select name="status"><option value="">All Status</option><?php foreach(['new','contacted','converted','lost'] as $s): ?><option value="<?=$s?>"<?= $status===$s?' selected':''?>><?= ucfirst($s) ?></option><?php endforeach; ?></select>
<select name="plan"><option value="">All Plans</option><?php foreach(['basic','standard','premium','custom'] as $pl): ?><option value="<?=$pl?>"<?= $planF===$pl?' selected':''?>><?= ucfirst($pl) ?></option><?php endforeach; ?></select>
<button type="submit" class="btn">Filter</button>
<a href="leads.php" class="btn-outline">Reset</a>
<a href="?<?= http_build_query(array_merge($_GET, ['export'=>'csv'])) ?>" class="btn-outline" style="margin-left:auto">⬇ Export CSV</a>
</form>
<!-- Table -->
<table>
<thead><tr>
<th>#</th><th>Name</th><th>Phone</th><th>Email</th><th>Business</th>
<th>Plan</th><th>Message</th><th>UTM</th><th>Status</th><th>Date</th>
</tr></thead>
<tbody>
<?php if (empty($leads)): ?>
<tr><td colspan="10" style="text-align:center;color:#7a9ab8;padding:2rem">No leads found.</td></tr>
<?php else: foreach ($leads as $l): ?>
<tr>
<td style="color:#7a9ab8">#<?= $l['id'] ?></td>
<td><strong><?= htmlspecialchars($l['name']) ?></strong></td>
<td><a href="tel:<?= htmlspecialchars($l['phone']) ?>"><?= htmlspecialchars($l['phone']) ?></a></td>
<td><a href="mailto:<?= htmlspecialchars($l['email']) ?>"><?= htmlspecialchars($l['email']) ?></a></td>
<td><?= htmlspecialchars($l['business'] ?: '—') ?></td>
<td><?= planBadge($l['plan'] ?? '') ?></td>
<td class="msg-cell" title="<?= htmlspecialchars($l['message']) ?>"><?= htmlspecialchars($l['message'] ?: '—') ?></td>
<td style="color:#7a9ab8;font-size:.78rem"><?= $l['utm_source'] ? htmlspecialchars($l['utm_source'].'/'.$l['utm_campaign']) : '—' ?></td>
<td>
<select class="status-sel" data-id="<?= $l['id'] ?>" onchange="updateStatus(this)">
<?php foreach(['new','contacted','converted','lost'] as $s): ?>
<option value="<?=$s?>"<?= $l['status']===$s?' selected':''?>><?= ucfirst($s) ?></option>
<?php endforeach; ?>
</select>
</td>
<td style="color:#7a9ab8;white-space:nowrap"><?= date('d M Y H:i', strtotime($l['created_at'])) ?></td>
</tr>
<?php endforeach; endif; ?>
</tbody>
</table>
<!-- Pagination -->
<?php if ($totalPages > 1): ?>
<div class="pagination">
<span style="color:#7a9ab8;font-size:.85rem"><?= $totalRows ?> records · Page <?= $page ?> of <?= $totalPages ?></span>
<?php for ($i = 1; $i <= $totalPages; $i++): ?>
<a href="?<?= http_build_query(array_merge($_GET, ['page'=>$i])) ?>" class="page-btn <?= $i===$page?'active':'' ?>"><?= $i ?></a>
<?php endfor; ?>
</div>
<?php endif; ?>
</div>
<div class="toast" id="toast">✓ Status updated</div>
<script>
function updateStatus(sel) {
const id = sel.dataset.id;
fetch('leads.php', {
method: 'POST',
headers: {'Content-Type':'application/x-www-form-urlencoded'},
body: 'update_status=1&id=' + id + '&new_status=' + sel.value
})
.then(r => r.json())
.then(d => {
if (d.success) {
const t = document.getElementById('toast');
t.style.display = 'block';
setTimeout(() => t.style.display = 'none', 2000);
}
});
}
</script>
</body>
</html>