<?php $config = require __DIR__ . '/config.php'; session_start(); if (isset($_GET['logout'])) { session_destroy(); header('Location: index.php'); exit; } if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['login_user'])) { if ( hash_equals($config['dashboard_user'], $_POST['login_user']) && hash_equals($config['dashboard_pass'], $_POST['login_pass'] ?? '') ) { $_SESSION['auth'] = true; header('Location: index.php'); exit; } $loginError = 'Invalid credentials'; } if (empty($_SESSION['auth'])): ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Leads Login  BoostSlash</title> <link rel="stylesheet" href="assets/style.css"> </head> <body class="login-body"> <form class="login-card" method="post"> <h1>Lead Automaton</h1> <p class="muted">BoostSlash · LogisticSlash · Hijrat CRM</p> <?php if (!empty($loginError)): ?><p class="error"><?= htmlspecialchars($loginError) ?></p><?php endif; ?> <label>User</label> <input name="login_user" required autocomplete="username"> <label>Password</label> <input name="login_pass" type="password" required autocomplete="current-password"> <button type="submit">Open dashboard</button> </form> </body> </html> <?php exit; endif; mysqli_report(MYSQLI_REPORT_OFF); $conn = new mysqli($config['db_host'], $config['db_user'], $config['db_pass'], $config['db_name']); if ($conn->connect_error) { die('Database connection failed. Import schema.sql via phpMyAdmin first.'); } $conn->set_charset('utf8mb4'); // Status update if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['lead_id'], $_POST['new_status'])) { $id = (int)$_POST['lead_id']; $status = $_POST['new_status']; $allowed = ['new','qualified','contacted','in_conversation','won','lost','ignored']; if (in_array($status, $allowed, true)) { $stmt = $conn->prepare('UPDATE prospects SET status=?, last_touched_at=NOW(), notes=CONCAT(IFNULL(notes,""), ?) WHERE id=?'); $noteAdd = ''; if (!empty($_POST['note'])) { $noteAdd = "\n[" . date('Y-m-d H:i') . "] " . trim($_POST['note']); } $stmt->bind_param('ssi', $status, $noteAdd, $id); $stmt->execute(); $stmt->close(); } header('Location: index.php?' . http_build_query(array_filter([ 'status' => $_GET['status'] ?? '', 'product' => $_GET['product'] ?? '', 'platform' => $_GET['platform'] ?? '', 'q' => $_GET['q'] ?? '', ]))); exit; } $statusFilter = $_GET['status'] ?? 'new'; $productFilter = $_GET['product'] ?? ''; $platformFilter = $_GET['platform'] ?? ''; $q = trim($_GET['q'] ?? ''); $where = ['1=1']; $types = ''; $params = []; if ($statusFilter !== '' && $statusFilter !== 'all') { $where[] = 'status = ?'; $types .= 's'; $params[] = $statusFilter; } if ($productFilter !== '') { $where[] = 'target_product = ?'; $types .= 's'; $params[] = $productFilter; } if ($platformFilter !== '') { $where[] = 'platform = ?'; $types .= 's'; $params[] = $platformFilter; } if ($q !== '') { $where[] = '(extracted_pain_point LIKE ? OR title LIKE ? OR snippet LIKE ? OR direct_id_link LIKE ?)'; $types .= 'ssss'; $like = '%' . $q . '%'; array_push($params, $like, $like, $like, $like); } $sqlWhere = implode(' AND ', $where); // Stats $stats = [ 'today' => 0, 'new' => 0, 'contacted' => 0, 'won' => 0, 'total' => 0, ]; $res = $conn->query("SELECT COUNT(*) AS total, SUM(status='new') AS new_count, SUM(status='contacted') AS contacted_count, SUM(status='won') AS won_count, SUM(DATE(date_found)=CURDATE()) AS today_count FROM prospects"); if ($row = $res->fetch_assoc()) { $stats['total'] = (int)$row['total']; $stats['new'] = (int)$row['new_count']; $stats['contacted'] = (int)$row['contacted_count']; $stats['won'] = (int)$row['won_count']; $stats['today'] = (int)$row['today_count']; } $byProduct = []; $rp = $conn->query('SELECT product_name, COUNT(*) c FROM prospects GROUP BY product_name ORDER BY c DESC'); while ($r = $rp->fetch_assoc()) { $byProduct[] = $r; } $byPlatform = []; $rf = $conn->query('SELECT platform, COUNT(*) c FROM prospects GROUP BY platform ORDER BY c DESC'); while ($r = $rf->fetch_assoc()) { $byPlatform[] = $r; } $listSql = "SELECT * FROM prospects WHERE $sqlWhere ORDER BY relevance_score DESC, date_found DESC LIMIT 100"; $stmt = $conn->prepare($listSql); if ($types !== '') { $stmt->bind_param($types, ...$params); } $stmt->execute(); $leads = $stmt->get_result()->fetch_all(MYSQLI_ASSOC); $stmt->close(); $products = $conn->query('SELECT DISTINCT target_product, product_name FROM prospects ORDER BY product_name')->fetch_all(MYSQLI_ASSOC); $platforms = $conn->query('SELECT DISTINCT platform FROM prospects ORDER BY platform')->fetch_all(MYSQLI_ASSOC); $lastSync = $conn->query('SELECT MAX(date_found) AS last_sync FROM prospects')->fetch_assoc()['last_sync'] ?? null; ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Lead Automaton Dashboard</title> <link rel="stylesheet" href="assets/style.css"> </head> <body> <header class="top"> <div> <h1>Lead Automaton</h1> <p class="muted">leads.boostslash.com · last sync <?= htmlspecialchars($lastSync ?? ' ') ?></p> </div> <a class="btn ghost" href="?logout=1">Logout</a> </header> <section class="stats"> <div class="stat"><span>Today</span><strong><?= $stats['today'] ?></strong></div> <div class="stat"><span>New</span><strong><?= $stats['new'] ?></strong></div> <div class="stat"><span>Contacted</span><strong><?= $stats['contacted'] ?></strong></div> <div class="stat"><span>Won</span><strong><?= $stats['won'] ?></strong></div> <div class="stat"><span>Total</span><strong><?= $stats['total'] ?></strong></div> </section> <section class="split"> <div class="panel"> <h2>By product</h2> <ul class="bars"> <?php foreach ($byProduct as $p): ?> <li><span><?= htmlspecialchars($p['product_name'] ?: ' ') ?></span><b><?= (int)$p['c'] ?></b></li> <?php endforeach; ?> <?php if (!$byProduct): ?><li class="muted">No data yet</li><?php endif; ?> </ul> </div> <div class="panel"> <h2>By platform</h2> <ul class="bars"> <?php foreach ($byPlatform as $p): ?> <li><span><?= htmlspecialchars($p['platform']) ?></span><b><?= (int)$p['c'] ?></b></li> <?php endforeach; ?> <?php if (!$byPlatform): ?><li class="muted">No data yet</li><?php endif; ?> </ul> </div> </section> <form class="filters" method="get"> <select name="status"> <?php foreach (['new','all','qualified','contacted','in_conversation','won','lost','ignored'] as $s): ?> <option value="<?= $s ?>" <?= $statusFilter === $s ? 'selected' : '' ?>><?= $s ?></option> <?php endforeach; ?> </select> <select name="product"> <option value="">All products</option> <?php foreach ($products as $p): ?> <option value="<?= htmlspecialchars($p['target_product']) ?>" <?= $productFilter === $p['target_product'] ? 'selected' : '' ?>> <?= htmlspecialchars($p['product_name'] ?: $p['target_product']) ?> </option> <?php endforeach; ?> </select> <select name="platform"> <option value="">All platforms</option> <?php foreach ($platforms as $p): ?> <option value="<?= htmlspecialchars($p['platform']) ?>" <?= $platformFilter === $p['platform'] ? 'selected' : '' ?>> <?= htmlspecialchars($p['platform']) ?> </option> <?php endforeach; ?> </select> <input name="q" placeholder="Search pain / title& " value="<?= htmlspecialchars($q) ?>"> <button type="submit">Filter</button> </form> <section class="table-wrap"> <table> <thead> <tr> <th>Score</th> <th>Product</th> <th>Platform</th> <th>Pain / context</th> <th>Found</th> <th>Action</th> </tr> </thead> <tbody> <?php foreach ($leads as $lead): ?> <tr> <td><span class="score"><?= (int)$lead['relevance_score'] ?></span></td> <td><span class="badge"><?= htmlspecialchars($lead['product_name'] ?: $lead['target_product']) ?></span></td> <td><?= htmlspecialchars($lead['platform']) ?></td> <td> <div class="pain"><?= htmlspecialchars($lead['extracted_pain_point']) ?></div> <div class="muted small"><?= htmlspecialchars(mb_strimwidth($lead['title'] ?: $lead['snippet'], 0, 120, '& ')) ?></div> <a class="link" href="<?= htmlspecialchars($lead['direct_id_link']) ?>" target="_blank" rel="noopener">Open source ’!</a> </td> <td class="small"><?= htmlspecialchars($lead['date_found']) ?></td> <td> <form method="post" class="action-form"> <input type="hidden" name="lead_id" value="<?= (int)$lead['id'] ?>"> <select name="new_status"> <?php foreach (['qualified','contacted','in_conversation','won','lost','ignored','new'] as $s): ?> <option value="<?= $s ?>" <?= $lead['status'] === $s ? 'selected' : '' ?>><?= $s ?></option> <?php endforeach; ?> </select> <input name="note" placeholder="Note (optional)"> <button type="submit">Save</button> </form> <div class="muted small">Status: <?= htmlspecialchars($lead['status']) ?></div> </td> </tr> <?php endforeach; ?> <?php if (!$leads): ?> <tr><td colspan="6" class="muted">No leads match these filters. Run the crawler or widen filters.</td></tr> <?php endif; ?> </tbody> </table> </section> </body> </html> <?php $conn->close(); ?>