| Server IP : 72.60.21.38 / Your IP : 216.73.216.25 Web Server : LiteSpeed System : Linux uk-fast-web1372.main-hosting.eu 4.18.0-553.121.1.lve.el8.x86_64 #1 SMP Thu Apr 30 16:40:41 UTC 2026 x86_64 User : u390967363 ( 390967363) PHP Version : 8.2.30 Disable Function : system, exec, shell_exec, passthru, mysql_list_dbs, ini_alter, dl, symlink, link, chgrp, leak, popen, apache_child_terminate, virtual, mb_send_mail MySQL : OFF | cURL : ON | WGET : ON | Perl : OFF | Python : OFF | Sudo : OFF | Pkexec : OFF Directory : /home/u390967363/domains/aibenproperties.com/public_html/app/ |
Upload File : |
<?php
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
require_once __DIR__ . '/includes/db.php';
require_once __DIR__ . '/includes/functions.php';
$role = $_SESSION['user_role'] ?? 'guest';
$roleLower = strtolower((string)$role);
$is_admin_tier = in_array($roleLower, ['super_admin','admin'], true);
$is_agent_tier = in_array($roleLower, ['agent','sales_agent','marketing','sales'], true);
$is_marketing_role = in_array($roleLower, ['marketing','marketer','sales_agent','sales','agent'], true);
$viewMode = strtolower(trim((string)($_GET['view'] ?? ($_GET['as'] ?? ($_GET['variant'] ?? '')))));
$is_marketing_view = $is_marketing_role || ($is_admin_tier && $viewMode === 'marketing');
if (!$is_admin_tier && !$is_agent_tier) {
header("Location: dashboard.php");
exit;
}
$companyId = function_exists('getCurrentCompanyId') ? getCurrentCompanyId() : 0;
if (isset($_GET['action']) && $_GET['action'] === 'payment_history') {
header('Content-Type: application/json');
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Expires: 0');
$email = strtolower(trim((string)($_GET['email'] ?? '')));
if ($email === '' || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
echo json_encode(['ok' => false, 'items' => [], 'msg' => 'invalid_email']);
exit;
}
try {
if (!$is_admin_tier && $is_agent_tier) {
$q = "SELECT 1 FROM clients WHERE agent_id = ? AND LOWER(TRIM(email)) = ?";
$p = [(int)($_SESSION['user_id'] ?? 0), $email];
if (tableHasColumn('clients', 'company_id') && $companyId) { $q .= " AND company_id = ?"; $p[] = $companyId; }
$q .= " LIMIT 1";
$chk = $pdo->prepare($q);
$chk->execute($p);
if (!$chk->fetchColumn()) {
echo json_encode(['ok' => false, 'items' => [], 'msg' => 'forbidden']);
exit;
}
}
$dtParts = [];
if (function_exists('tableHasColumn') && tableHasColumn('payments', 'verified_at')) { $dtParts[] = "NULLIF(p.verified_at, '0000-00-00 00:00:00')"; }
if (function_exists('tableHasColumn') && tableHasColumn('payments', 'approval_date')) { $dtParts[] = "NULLIF(p.approval_date, '0000-00-00 00:00:00')"; }
if (function_exists('tableHasColumn') && tableHasColumn('payments', 'payment_date')) { $dtParts[] = "NULLIF(p.payment_date, '0000-00-00')"; }
if (function_exists('tableHasColumn') && tableHasColumn('payments', 'date')) { $dtParts[] = "NULLIF(p.date, '0000-00-00 00:00:00')"; }
if (function_exists('tableHasColumn') && tableHasColumn('payments', 'created_at')) { $dtParts[] = "NULLIF(p.created_at, '0000-00-00 00:00:00')"; }
if (function_exists('tableHasColumn') && tableHasColumn('payments', 'updated_at')) { $dtParts[] = "NULLIF(p.updated_at, '0000-00-00 00:00:00')"; }
if (empty($dtParts)) { $dtParts[] = 'NOW()'; }
$dateExpr = 'COALESCE(' . implode(',', $dtParts) . ')';
$statusExpr = "p.status";
if (function_exists('tableHasColumn') && !tableHasColumn('payments', 'status') && tableHasColumn('payments', 'payment_status')) { $statusExpr = 'p.payment_status'; }
elseif (function_exists('tableHasColumn') && !tableHasColumn('payments', 'status') && !tableHasColumn('payments', 'payment_status')) { $statusExpr = "''"; }
$joins = "";
$selectUserEmail = "'' AS user_email";
$whereParts = [];
$params = [];
if (function_exists('tableHasColumn') && tableHasColumn('payments', 'user_id') && tableHasColumn('users', 'email')) {
$joins .= " LEFT JOIN users u ON p.user_id = u.id";
$selectUserEmail = "COALESCE(u.email,'') AS user_email";
$whereParts[] = "LOWER(TRIM(u.email)) = ?";
$params[] = $email;
}
if (function_exists('tableHasColumn') && tableHasColumn('payments', 'client_email')) {
$whereParts[] = "LOWER(TRIM(p.client_email)) = ?";
$params[] = $email;
}
if (function_exists('tableHasColumn') && tableHasColumn('payments', 'payer_email')) {
$whereParts[] = "LOWER(TRIM(p.payer_email)) = ?";
$params[] = $email;
}
if (function_exists('tableHasColumn') && tableHasColumn('payments', 'email')) {
$whereParts[] = "LOWER(TRIM(p.email)) = ?";
$params[] = $email;
}
if (function_exists('tableHasColumn') && tableHasColumn('payments', 'meta_json')) {
$whereParts[] = "p.meta_json LIKE ?";
$params[] = '%' . $email . '%';
}
if (empty($whereParts)) {
echo json_encode(['ok' => true, 'items' => []]);
exit;
}
$selectProp = "'' AS property_title";
if (function_exists('tableHasColumn') && tableHasColumn('payments', 'allocation_id') && tableHasColumn('allocations', 'property_id') && tableHasColumn('properties', 'title')) {
$joins .= " LEFT JOIN allocations a ON p.allocation_id = a.id LEFT JOIN properties pr ON a.property_id = pr.id";
$selectProp = "COALESCE(pr.title,'') AS property_title";
}
$sql = "SELECT p.id, p.amount"
. (function_exists('tableHasColumn') && tableHasColumn('payments', 'reference') ? ", p.reference" : ", '' AS reference")
. ", DATE_FORMAT({$dateExpr}, '%Y-%m-%d') AS dt, {$statusExpr} AS st, "
. (function_exists('tableHasColumn') && tableHasColumn('payments', 'meta_json') ? "p.meta_json" : "NULL AS meta_json")
. ", {$selectUserEmail}, {$selectProp}
FROM payments p
{$joins}
WHERE (" . implode(" OR ", $whereParts) . ")";
$final = function_exists('kpiPaymentFinalizedStatuses') ? (array)kpiPaymentFinalizedStatuses() : ['verified','approved','paid','completed','success'];
$final = array_values(array_filter(array_map(function($v){ return strtolower(trim((string)$v)); }, $final), function($v){ return $v !== ''; }));
if (empty($final)) { $final = ['approved']; }
if (function_exists('tableHasColumn') && tableHasColumn('payments', 'status')) {
$in = implode(',', array_fill(0, count($final), '?'));
$sql .= " AND LOWER(TRIM(p.status)) IN ($in)";
$params = array_merge($params, $final);
} elseif (function_exists('tableHasColumn') && tableHasColumn('payments', 'payment_status')) {
$in = implode(',', array_fill(0, count($final), '?'));
$sql .= " AND LOWER(TRIM(p.payment_status)) IN ($in)";
$params = array_merge($params, $final);
} elseif (function_exists('tableHasColumn') && tableHasColumn('payments', 'verified_at')) {
$sql .= " AND p.verified_at IS NOT NULL";
} elseif (function_exists('tableHasColumn') && tableHasColumn('payments', 'approval_date')) {
$sql .= " AND p.approval_date IS NOT NULL";
} elseif (function_exists('tableHasColumn') && tableHasColumn('payments', 'confirmation_status')) {
$in = implode(',', array_fill(0, count($final), '?'));
$sql .= " AND LOWER(TRIM(p.confirmation_status)) IN ($in)";
$params = array_merge($params, $final);
}
if (function_exists('tableHasColumn') && tableHasColumn('payments', 'company_id') && $companyId) { $sql .= " AND (p.company_id = ? OR p.company_id IS NULL)"; $params[] = $companyId; }
$sql .= " ORDER BY dt DESC LIMIT 1000";
$st = $pdo->prepare($sql);
$st->execute($params);
$rows = $st->fetchAll(PDO::FETCH_ASSOC) ?: [];
$items = [];
foreach ($rows as $r) {
$meta = [];
if (!empty($r['meta_json'])) {
try { $meta = json_decode((string)$r['meta_json'], true) ?: []; } catch (Throwable $eMeta) { $meta = []; }
}
$metaEmail = strtolower(trim((string)($meta['client_email'] ?? '')));
$userEmail = strtolower(trim((string)($r['user_email'] ?? '')));
if ($metaEmail !== $email && $userEmail !== $email) { continue; }
$stLower = strtolower(trim((string)($r['st'] ?? '')));
if (!empty($final) && $stLower !== '' && !in_array($stLower, $final, true)) { continue; }
$label = (string)($meta['project_desc'] ?? ($meta['property_title'] ?? ($meta['property'] ?? ($r['property_title'] ?? ''))));
$label = trim($label);
if ($label === '') {
$ref = trim((string)($r['reference'] ?? ''));
if (strtoupper($ref) === 'FORM_FEE') { $label = 'Form Fee'; }
elseif ($ref !== '') { $label = $ref; }
else { $label = 'Payment'; }
}
$items[] = [
'id' => (int)($r['id'] ?? 0),
'dt' => (string)($r['dt'] ?? ''),
'amount' => (float)($r['amount'] ?? 0),
'status' => (string)($r['st'] ?? ''),
'reference' => (string)($r['reference'] ?? ''),
'project' => $label,
];
}
echo json_encode(['ok' => true, 'items' => $items]);
exit;
} catch (Throwable $e) {
echo json_encode(['ok' => false, 'items' => [], 'msg' => 'failed']);
exit;
}
}
include 'includes/header.php';
$success_msg = '';
$error_msg = '';
// Handle Add Client
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_client'])) {
if ($is_marketing_view) {
$error_msg = "You are not allowed to add clients from this page.";
} else {
$first_name = trim($_POST['first_name']);
$last_name = trim($_POST['last_name']);
$email = trim($_POST['email']);
$phone = trim($_POST['phone']);
$status = $_POST['status'];
$notes = isset($_POST['notes']) ? trim($_POST['notes']) : '';
if (empty($first_name) || empty($last_name) || empty($email)) {
$error_msg = "Please fill in all required fields.";
} else {
try {
// Check if email exists
$stmt = $pdo->prepare("SELECT id FROM clients WHERE email = ?");
$stmt->execute([$email]);
if ($stmt->fetch()) {
$error_msg = "A client with this email already exists.";
} else {
$stmt = $pdo->prepare("INSERT INTO clients (agent_id, first_name, last_name, email, phone, status, notes, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, NOW())");
if ($stmt->execute([$_SESSION['user_id'], $first_name, $last_name, $email, $phone, $status, $notes])) {
$success_msg = "Client added successfully!";
logActivity($_SESSION['user_id'], "Client Added", "Added client: $first_name $last_name");
} else {
$error_msg = "Failed to add client.";
}
}
} catch (PDOException $e) {
$error_msg = "Database error: " . $e->getMessage();
}
}
}
}
$clients = [];
$agentIdFilter = null;
if ($is_agent_tier) {
$agentIdFilter = (int)($_SESSION['user_id'] ?? 0);
} elseif (isset($_GET['agent_id']) && ctype_digit($_GET['agent_id'])) {
$agentIdFilter = (int)$_GET['agent_id'];
}
if ($agentIdFilter) {
$q = "SELECT * FROM clients WHERE agent_id = ? AND status != 'lead' ORDER BY created_at DESC";
if (tableHasColumn('clients', 'company_id') && $companyId) $q = "SELECT * FROM clients WHERE agent_id = ? AND status != 'lead' AND company_id = ? ORDER BY created_at DESC";
$stmt = $pdo->prepare($q);
$params = tableHasColumn('clients', 'company_id') && $companyId ? [$agentIdFilter, $companyId] : [$agentIdFilter];
$stmt->execute($params);
$clients = $stmt->fetchAll();
} else {
$q = "SELECT * FROM clients WHERE status != 'lead' ORDER BY created_at DESC";
$params = [];
if (tableHasColumn('clients', 'company_id') && $companyId) { $q = "SELECT * FROM clients WHERE status != 'lead' AND company_id = ? ORDER BY created_at DESC"; $params = [$companyId]; }
$stmt = $pdo->prepare($q);
$stmt->execute($params);
$clients = $stmt->fetchAll();
}
?>
<div class="container-fluid px-4">
<div class="d-flex flex-column flex-sm-row justify-content-between align-items-stretch align-items-sm-center gap-2 mt-4 mb-4">
<h1 class="h3 mb-0 text-gray-800"><i class="fa-solid fa-users me-2"></i>My Deals</h1>
<?php if (!$is_marketing_view): ?>
<div class="d-grid d-sm-block">
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addClientModal">
<i class="fa-solid fa-user-plus me-2"></i>Add New Client
</button>
</div>
<?php endif; ?>
</div>
<?php if ($success_msg): ?>
<div class="alert alert-success alert-dismissible fade show" role="alert">
<i class="fa-solid fa-check-circle me-2"></i><?= htmlspecialchars($success_msg) ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<?php if ($error_msg): ?>
<div class="alert alert-danger alert-dismissible fade show" role="alert">
<i class="fa-solid fa-exclamation-circle me-2"></i><?= htmlspecialchars($error_msg) ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<!-- Stats Cards -->
<div class="row mb-4">
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-left-success shadow h-100 py-2">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">Active Clients</div>
<div class="h5 mb-0 font-weight-bold text-gray-800"><?= count($clients) ?></div>
</div>
<div class="col-auto">
<i class="fas fa-user-check fa-2x text-gray-300"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card shadow mb-4">
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
<h6 class="m-0 font-weight-bold text-navy">Client List</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover align-middle table-sm table-stackable" id="clientsTable" width="100%" cellspacing="0">
<thead class="table-light">
<tr>
<th>Name</th>
<th>Contact</th>
<?php if (!$is_marketing_view): ?>
<th>Status</th>
<th>Date Added</th>
<th>Actions</th>
<?php else: ?>
<th>Transaction History</th>
<?php endif; ?>
</tr>
</thead>
<tbody>
<?php if (empty($clients)): ?>
<tr>
<td colspan="<?= $is_marketing_view ? 3 : 5 ?>" class="text-center py-4">No clients found.</td>
</tr>
<?php else: ?>
<?php foreach ($clients as $client): ?>
<tr>
<td data-label="Name">
<div class="d-flex align-items-center">
<div class="avatar-sm me-2 bg-light rounded-circle d-flex align-items-center justify-content-center" style="width: 40px; height: 40px;">
<i class="fa-solid fa-user text-navy"></i>
</div>
<div>
<div class="fw-bold"><?= htmlspecialchars($client['first_name'] . ' ' . $client['last_name']) ?></div>
</div>
</div>
</td>
<td data-label="Contact">
<?php
$cEmail = trim((string)($client['email'] ?? ''));
$cPhone = trim((string)($client['phone'] ?? ''));
?>
<div class="small text-break lh-sm"><i class="fa-solid fa-envelope me-1 text-muted"></i><?= htmlspecialchars($cEmail !== '' ? $cEmail : '-') ?></div>
<?php if (!$is_marketing_view): ?>
<div class="small text-break lh-sm"><i class="fa-solid fa-phone me-1 text-muted"></i><?= htmlspecialchars($cPhone !== '' ? $cPhone : '-') ?></div>
<?php endif; ?>
</td>
<?php if (!$is_marketing_view): ?>
<td data-label="Status">
<?php
$statusClass = 'bg-secondary';
if ($client['status'] === 'active') $statusClass = 'bg-success';
elseif ($client['status'] === 'inactive') $statusClass = 'bg-danger';
elseif ($client['status'] === 'prospect') $statusClass = 'bg-warning text-dark';
?>
<span class="badge <?= $statusClass ?>"><?= ucfirst($client['status']) ?></span>
</td>
<td data-label="Date Added"><?= date('M j, Y', strtotime($client['created_at'])) ?></td>
<td data-label="Actions">
<div class="d-flex flex-wrap gap-1">
<a class="btn btn-sm btn-outline-primary" title="View Details"
href="client-profile.php?client_id=<?= (int)($client['id'] ?? 0) ?>">
<i class="fa-solid fa-eye"></i>
</a>
<button class="btn btn-sm btn-outline-success js-payments-history" type="button" title="Payment History"
data-bs-toggle="modal" data-bs-target="#paymentHistoryModal"
data-email="<?= htmlspecialchars((string)($client['email'] ?? '')) ?>"
data-name="<?= htmlspecialchars(trim((string)($client['first_name'] . ' ' . $client['last_name']))) ?>">
<i class="fa-solid fa-receipt"></i>
</button>
<a class="btn btn-sm btn-outline-secondary" title="Edit"
href="client-edit.php?client_id=<?= (int)($client['id'] ?? 0) ?>">
<i class="fa-solid fa-pen"></i>
</a>
</div>
</td>
<?php else: ?>
<td data-label="Transaction History">
<div class="d-grid d-sm-block">
<button class="btn btn-sm btn-outline-success js-payments-history" type="button"
data-bs-toggle="modal" data-bs-target="#paymentHistoryModal"
data-email="<?= htmlspecialchars((string)($client['email'] ?? '')) ?>"
data-name="<?= htmlspecialchars(trim((string)($client['first_name'] . ' ' . $client['last_name']))) ?>">
<i class="fa-solid fa-receipt me-1"></i><span>View</span>
</button>
</div>
</td>
<?php endif; ?>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- Payment History Modal -->
<div class="modal fade" id="paymentHistoryModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><i class="fa-solid fa-receipt me-2"></i>Transaction History</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="small text-muted mb-2" id="payHistMeta"></div>
<div class="table-responsive">
<table class="table table-sm table-hover align-middle mb-0 table-stackable">
<thead class="table-light">
<tr>
<th>Date</th>
<th>Project</th>
<th class="text-end">Amount</th>
<th>Status</th>
</tr>
</thead>
<tbody id="payHistBody">
<tr><td colspan="4" class="text-center py-4 text-muted">Select a client to view transaction history.</td></tr>
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<!-- Add Client Modal -->
<?php if (!$is_marketing_view): ?>
<div class="modal fade" id="addClientModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><i class="fa-solid fa-user-plus me-2"></i>Add New Client</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form method="POST">
<div class="modal-body">
<input type="hidden" name="add_client" value="1">
<div class="row g-3">
<div class="col-md-6">
<label class="form-label">First Name</label>
<input type="text" class="form-control" name="first_name" required>
</div>
<div class="col-md-6">
<label class="form-label">Last Name</label>
<input type="text" class="form-control" name="last_name" required>
</div>
<div class="col-12">
<label class="form-label">Email</label>
<input type="email" class="form-control" name="email" required>
</div>
<div class="col-12">
<label class="form-label">Phone</label>
<input type="text" class="form-control" name="phone">
</div>
<div class="col-12">
<label class="form-label">Status</label>
<select class="form-select" name="status">
<option value="active">Active</option>
<option value="inactive">Inactive</option>
<option value="prospect">Prospect</option>
</select>
</div>
<div class="col-12">
<label class="form-label">Notes</label>
<textarea class="form-control" name="notes" rows="3"></textarea>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary">Save Client</button>
</div>
</form>
</div>
</div>
</div>
<?php endif; ?>
<script>
(function(){
function fmtMoney(n){
var x = Number(n || 0);
return '₦' + x.toLocaleString('en-NG', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}
function escapeHtml(s){
return String(s || '').replace(/[&<>"']/g, function(c){
return ({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]);
});
}
var modalEl = document.getElementById('paymentHistoryModal');
var bodyEl = document.getElementById('payHistBody');
var metaEl = document.getElementById('payHistMeta');
if (!modalEl || !bodyEl) return;
var bsModal = null;
try { bsModal = bootstrap.Modal.getOrCreateInstance(modalEl); } catch (e) { bsModal = null; }
function setLoading(name){
if (metaEl) metaEl.textContent = name ? ('Client: ' + name) : '';
bodyEl.innerHTML = '<tr><td colspan="4" class="text-center py-4 text-muted">Loading...</td></tr>';
}
function setEmpty(){
bodyEl.innerHTML = '<tr><td colspan="4" class="text-center py-4 text-muted">No approved transactions found for this client.</td></tr>';
}
function setRows(items){
if (!Array.isArray(items) || !items.length) { setEmpty(); return; }
bodyEl.innerHTML = items.map(function(it){
var rawDt = String(it.dt || '').trim();
if (!rawDt || rawDt.indexOf('0000-00-00') === 0) rawDt = '-';
var dt = escapeHtml(rawDt);
var proj = escapeHtml(it.project || '-');
var amt = fmtMoney(it.amount || 0);
var st = escapeHtml(it.status || '');
return '<tr>'
+ '<td data-label="Date" class="text-muted small">' + dt + '</td>'
+ '<td data-label="Project" class="text-break">' + proj + '</td>'
+ '<td data-label="Amount" class="text-end fw-bold">' + amt + '</td>'
+ '<td data-label="Status"><span class="badge bg-light text-dark border">' + st + '</span></td>'
+ '</tr>';
}).join('');
}
document.addEventListener('click', function(e){
var btn = e.target && (e.target.closest ? e.target.closest('.js-payments-history') : null);
if (!btn) return;
var email = (btn.getAttribute('data-email') || '').trim();
var name = (btn.getAttribute('data-name') || '').trim();
setLoading(name);
if (bsModal) bsModal.show();
var url = 'agent-clients.php?action=payment_history&email=' + encodeURIComponent(email);
fetch(url, { credentials: 'same-origin' })
.then(function(r){ return r.json(); })
.then(function(data){
if (!data || data.ok !== true) { setEmpty(); return; }
setRows(data.items || []);
})
.catch(function(){ setEmpty(); });
});
})();
</script>
<?php include 'includes/footer.php'; ?>