403Webshell
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 :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/u390967363/domains/aibenproperties.com/public_html/app/executive-allocations.php
<?php
require_once 'includes/db.php';
require_once 'includes/functions.php';

$role = $_SESSION['user_role'] ?? 'guest';
$role_norm = strtolower(str_replace([' ', '-'], '_', (string)$role));
// Allow broader executive roles
if (!in_array($role_norm, ['chairman_ceo','chairman','ceo','executive','executives','super_admin','super_admins'])) {
    include 'includes/header.php';
    echo "<div class='container p-4'><div class='alert alert-danger'>Access denied.</div></div>";
    include 'includes/footer.php';
    exit;
}

$notice = $_GET['notice'] ?? null;
$type = $_GET['type'] ?? 'success';
$companyId = getCurrentCompanyId();
$isSuperAdminRole = in_array($role_norm, ['super_admin','super_admins'], true);
$isImpersonatingCompany = $isSuperAdminRole && !empty($_SESSION['impersonate_company_id']);

// Demo seed handler
if (isset($_GET['create_demo']) && $_GET['create_demo'] === '1') {
    try {
        $pdo->beginTransaction();
        // Create or find demo client
        $clientId = null;
        $emailDemo = 'demo.client@aiben.local';
        $st = $pdo->prepare("SELECT id FROM users WHERE email = ? LIMIT 1");
        try { $st->execute([$emailDemo]); $clientId = (int)$st->fetchColumn(); } catch (Exception $e) { $clientId = null; }
        if (!$clientId) {
            $cols = ['name','role','email','created_at'];
            $vals = ['Demo Client','client',$emailDemo,date('Y-m-d H:i:s')];
            if (function_exists('tableHasColumn') && tableHasColumn('users','password')) { $cols[]='password'; $vals[]=password_hash('demo123', PASSWORD_DEFAULT); }
            if (function_exists('tableHasColumn') && tableHasColumn('users','username')) { $cols[]='username'; $vals[]='demo.client'; }
            if (function_exists('tableHasColumn') && tableHasColumn('users','phone')) { $cols[]='phone'; $vals[]='0000000000'; }
            if (function_exists('tableHasColumn') && tableHasColumn('users','status')) { $cols[]='status'; $vals[]='active'; }
            if (function_exists('tableHasColumn') && tableHasColumn('users','is_active')) { $cols[]='is_active'; $vals[]=1; }
            if (function_exists('tableHasColumn') && tableHasColumn('users','updated_at')) { $cols[]='updated_at'; $vals[] = date('Y-m-d H:i:s'); }
            if (function_exists('tableHasColumn') && tableHasColumn('users','created_by')) { $cols[]='created_by'; $vals[]=(int)($_SESSION['user_id'] ?? 0); }
            if (function_exists('tableHasColumn') && tableHasColumn('users','company_id') && $companyId) { $cols[]='company_id'; $vals[]=$companyId; }
            $sql = "INSERT INTO users (".implode(',', $cols).") VALUES (".implode(',', array_fill(0,count($cols),'?')).")";
            $stmt = $pdo->prepare($sql);
            $stmt->execute($vals);
            $clientId = (int)$pdo->lastInsertId();
        }
        // Create or find demo property
        $propertyId = null;
        $st2 = $pdo->prepare("SELECT id FROM properties WHERE title = ? LIMIT 1");
        try { $st2->execute(['Demo Plot A']); $propertyId = (int)$st2->fetchColumn(); } catch (Exception $e) { $propertyId = null; }
        if (!$propertyId) {
            $cols = ['title','price','location','created_at'];
            $vals = ['Demo Plot A',1500000,'Demo Estate',date('Y-m-d H:i:s')];
            if (function_exists('tableHasColumn') && tableHasColumn('properties','status')) { $cols[]='status'; $vals[]='available'; }
            if (function_exists('tableHasColumn') && tableHasColumn('properties','available_units')) { $cols[]='available_units'; $vals[]=1; }
            if (function_exists('tableHasColumn') && tableHasColumn('properties','code')) { $cols[]='code'; $vals[]='DEMO-PLOT-A'; }
            if (function_exists('tableHasColumn') && tableHasColumn('properties','updated_at')) { $cols[]='updated_at'; $vals[] = date('Y-m-d H:i:s'); }
            if (function_exists('tableHasColumn') && tableHasColumn('properties','created_by')) { $cols[]='created_by'; $vals[]=(int)($_SESSION['user_id'] ?? 0); }
            if (function_exists('tableHasColumn') && tableHasColumn('properties','company_id') && $companyId) { $cols[]='company_id'; $vals[]=$companyId; }
            $sql2 = "INSERT INTO properties (".implode(',', $cols).") VALUES (".implode(',', array_fill(0,count($cols),'?')).")";
            $stmt2 = $pdo->prepare($sql2);
            $stmt2->execute($vals);
            $propertyId = (int)$pdo->lastInsertId();
        }
        // Create demo allocation
        $colsA = ['user_id','property_id','status','created_at'];
        $valsA = [$clientId,$propertyId,'pending_executive_approval',date('Y-m-d H:i:s')];
        $priceVal = 1500000;
        if (function_exists('tableHasColumn') && tableHasColumn('allocations','total_price')) { $colsA[]='total_price'; $valsA[]=$priceVal; }
        elseif (function_exists('tableHasColumn') && tableHasColumn('allocations','amount')) { $colsA[]='amount'; $valsA[]=$priceVal; }
        elseif (function_exists('tableHasColumn') && tableHasColumn('allocations','price')) { $colsA[]='price'; $valsA[]=$priceVal; }
        elseif (function_exists('tableHasColumn') && tableHasColumn('allocations','final_price')) { $colsA[]='final_price'; $valsA[]=$priceVal; }
        elseif (function_exists('tableHasColumn') && tableHasColumn('allocations','sale_price')) { $colsA[]='sale_price'; $valsA[]=$priceVal; }
        if (function_exists('tableHasColumn') && tableHasColumn('allocations','reference')) { $colsA[]='reference'; $valsA[]='DEMO-ALLO-'.substr(uniqid('', true), -6); }
        if (function_exists('tableHasColumn') && tableHasColumn('allocations','updated_at')) { $colsA[]='updated_at'; $valsA[] = date('Y-m-d H:i:s'); }
        if (function_exists('tableHasColumn') && tableHasColumn('allocations','created_by')) { $colsA[]='created_by'; $valsA[]=(int)($_SESSION['user_id'] ?? 0); }
        if (function_exists('tableHasColumn') && tableHasColumn('allocations','company_id') && $companyId) { $colsA[]='company_id'; $valsA[]=$companyId; }
        $sqlA = "INSERT INTO allocations (".implode(',', $colsA).") VALUES (".implode(',', array_fill(0,count($colsA),'?')).")";
        $stmtA = $pdo->prepare($sqlA);
        $stmtA->execute($valsA);
        $allocId = (int)$pdo->lastInsertId();
        $pdo->commit();
        header("Location: executive-allocations.php?notice=" . urlencode("Demo allocation created (#$allocId).") . "&type=success");
        exit;
    } catch (Exception $e) {
        try { $pdo->rollBack(); } catch (Exception $e2) {}
        $msg = substr((string)$e->getMessage(), 0, 180);
        header("Location: executive-allocations.php?notice=" . urlencode("Failed to create demo allocation: ".$msg) . "&type=danger");
        exit;
    }
}


if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['exec_action'])) {
    $allocId = isset($_POST['allocation_id']) && ctype_digit($_POST['allocation_id']) ? (int)$_POST['allocation_id'] : 0;
    $decision = $_POST['decision'] ?? '';
    $comment = trim($_POST['comment'] ?? '');
    if ($allocId <= 0 || !in_array($decision, ['approve','reject'])) {
        header("Location: executive-allocations.php?notice=" . urlencode("Invalid request") . "&type=danger");
        exit;
    }
    if ($comment === '') {
        header("Location: executive-allocations.php?notice=" . urlencode("Comment is required") . "&type=danger");
        exit;
    }
    try {
        $params = [];
        $sql = "UPDATE allocations SET status = ? ";
        $newStatus = $decision === 'approve' ? 'executive_approved' : 'rejected';
        $params[] = $newStatus;
        if (function_exists('tableHasColumn') && tableHasColumn('allocations','exec_comment')) {
            $sql .= ", exec_comment = ? ";
            $params[] = $comment;
        }
        if (function_exists('tableHasColumn') && tableHasColumn('allocations','exec_decided_by')) {
            $sql .= ", exec_decided_by = ? ";
            $params[] = (int)($_SESSION['user_id'] ?? 0);
        }
        if (function_exists('tableHasColumn') && tableHasColumn('allocations','exec_decided_at')) {
            $sql .= ", exec_decided_at = NOW() ";
        }
        if (function_exists('tableHasColumn') && tableHasColumn('allocations','locked')) {
            $sql .= ", locked = 1 ";
        }
        $sql .= " WHERE id = ? ";
        $params[] = $allocId;
        if ((!$isSuperAdminRole || $isImpersonatingCompany) && $companyId && function_exists('tableHasColumn') && tableHasColumn('allocations','company_id')) {
            $sql .= " AND company_id = ? ";
            $params[] = $companyId;
        }
        $st = $pdo->prepare($sql);
        $st->execute($params);
        if (function_exists('logActivity') && isset($_SESSION['user_id'])) {
            $details = ['allocation_id'=>$allocId,'decision'=>$decision,'comment'=>$comment];
            if ($companyId) { $details['company_id'] = $companyId; }
            logActivity($_SESSION['user_id'], 'EXEC_ALLOCATION_DECISION', json_encode($details));
        }
        header("Location: executive-allocations.php?notice=" . urlencode("Allocation ".($decision==='approve'?'executive approved':'rejected')) . "&type=success");
        exit;
    } catch (Exception $e) {
        header("Location: executive-allocations.php?notice=" . urlencode("Action failed") . "&type=danger");
        exit;
    }
}

// Fetch pending for executive decision
$rows = [];
$showPending = (($_GET['show'] ?? '') === 'pending');
try {
    $hasRef = function_exists('tableHasColumn') && tableHasColumn('allocations', 'reference');
    $hasRefNo = function_exists('tableHasColumn') && tableHasColumn('allocations', 'ref_no');
    $refExpr = $hasRef ? 'a.reference' : ($hasRefNo ? 'a.ref_no' : "CONCAT('ALC-', a.id)");

    $createdExpr = 'NULL';
    if (function_exists('tableHasColumn')) {
        if (tableHasColumn('allocations', 'created_at')) { $createdExpr = 'a.created_at'; }
        elseif (tableHasColumn('allocations', 'date_created')) { $createdExpr = 'a.date_created'; }
        elseif (tableHasColumn('allocations', 'created_on')) { $createdExpr = 'a.created_on'; }
        elseif (tableHasColumn('allocations', 'created')) { $createdExpr = 'a.created'; }
    }

    $priceCandidates = [];
    if (function_exists('tableHasColumn')) {
        foreach (['total_price','amount','price','final_price','sale_price'] as $pc) {
            if (tableHasColumn('allocations', $pc)) { $priceCandidates[] = 'a.' . $pc; }
        }
    }
    $totalExpr = !empty($priceCandidates) ? ('COALESCE(' . implode(', ', $priceCandidates) . ')') : '0';

    $userNameExpr = (function_exists('tableHasColumn') && tableHasColumn('users', 'name')) ? 'u.name' : ((function_exists('tableHasColumn') && tableHasColumn('users', 'fullname')) ? 'u.fullname' : "CONCAT('User#', u.id)");
    $propertyTitleExpr = (function_exists('tableHasColumn') && tableHasColumn('properties', 'title')) ? 'p.title' : ((function_exists('tableHasColumn') && tableHasColumn('properties', 'name')) ? 'p.name' : "CONCAT('Property#', p.id)");

    $baseSelect = "SELECT a.id, {$refExpr} AS reference, {$userNameExpr} AS client, {$propertyTitleExpr} AS property,
                          {$totalExpr} AS total_price, a.status, {$createdExpr} AS created_at
                   FROM allocations a
                   LEFT JOIN users u ON a.user_id = u.id
                   LEFT JOIN properties p ON a.property_id = p.id
                   WHERE 1=1";

    $sql = $baseSelect;
    $params = [];
    if ($showPending) {
        $sql .= " AND a.status IN ('pending','admin_approved','approved','pending_executive_approval','pending_chairman_approval','plot_assigned_pending_chairman_approval','executive_review','awaiting_chairman_approval','pending_head_admin_review','draft_prepared','returned_for_correction')";
    }
    if ((!$isSuperAdminRole || $isImpersonatingCompany) && $companyId && function_exists('tableHasColumn') && tableHasColumn('allocations','company_id')) {
        $sql .= " AND (a.company_id = ? OR a.company_id IS NULL OR a.company_id = 0) ";
        $params[] = $companyId;
    }
    $sql .= " ORDER BY a.created_at DESC LIMIT 100";
    $st = $pdo->prepare($sql);
    $st->execute($params);
    $rows = $st->fetchAll(PDO::FETCH_ASSOC);
    if (empty($rows) && $showPending) {
        $sql2 = $baseSelect;
        $params2 = [];
        if ((!$isSuperAdminRole || $isImpersonatingCompany) && $companyId && function_exists('tableHasColumn') && tableHasColumn('allocations','company_id')) {
            $sql2 .= " AND (a.company_id = ? OR a.company_id IS NULL OR a.company_id = 0) ";
            $params2[] = $companyId;
        }
        $sql2 .= " ORDER BY a.created_at DESC LIMIT 50";
        $st2 = $pdo->prepare($sql2);
        $st2->execute($params2);
        $rows = $st2->fetchAll(PDO::FETCH_ASSOC);
        $notice = $notice ?: "No items pending executive decision. Showing recent allocations.";
        $type = 'warning';
    }
} catch (Exception $e) {}
// Fallback to payment queue if still empty
$payRows = [];
if (empty($rows)) {
    try {
        $sqlp = "SELECT p.id, p.amount, p.status, p.created_at, p.transaction_id
                 FROM payments p
                 WHERE p.status IN ('pending_confirmation','verified')";
        $paramsp = [];
        if ((!$isSuperAdminRole || $isImpersonatingCompany) && $companyId && function_exists('tableHasColumn') && tableHasColumn('payments','company_id')) {
            $sqlp .= " AND p.company_id = ? ";
            $paramsp[] = $companyId;
        }
        $sqlp .= " ORDER BY p.created_at DESC LIMIT 50";
        $stp = $pdo->prepare($sqlp);
        $stp->execute($paramsp);
        $payRows = $stp->fetchAll(PDO::FETCH_ASSOC);
        if (!empty($payRows)) {
            $notice = $notice ?: "No allocations found. Showing payment queue.";
            $type = 'warning';
        }
    } catch (Exception $e) {}
}
// Try to surface latest demo allocation if no rows
$demo = null;
if (empty($rows)) {
    try {
        $demoRefExpr = $hasRef ? 'a.reference' : ($hasRefNo ? 'a.ref_no' : "CONCAT('ALC-', a.id)");
        $sqld = $baseSelect . " AND (
                     ({$demoRefExpr} LIKE 'DEMO-ALLO-%') OR
                     (u.email = 'demo.client@aiben.local') OR
                     ({$propertyTitleExpr} = 'Demo Plot A') OR
                     (p.code = 'DEMO-PLOT-A')
                 )";
        $paramsd = [];
        if ((!$isSuperAdminRole || $isImpersonatingCompany) && $companyId && function_exists('tableHasColumn') && tableHasColumn('allocations','company_id')) {
            $sqld .= " AND a.company_id = ? ";
            $paramsd[] = $companyId;
        }
        $sqld .= " ORDER BY a.created_at DESC LIMIT 1";
        $std = $pdo->prepare($sqld);
        $std->execute($paramsd);
        $demo = $std->fetch(PDO::FETCH_ASSOC);
        if ($demo) {
            $notice = $notice ?: "Showing latest demo allocation to test letter generation.";
            $type = 'info';
        } else {
            $sqla = $baseSelect;
            $paramsa = [];
            if ((!$isSuperAdminRole || $isImpersonatingCompany) && $companyId && function_exists('tableHasColumn') && tableHasColumn('allocations','company_id')) {
                $sqla .= " AND a.company_id = ? ";
                $paramsa[] = $companyId;
            }
            $sqla .= " ORDER BY a.created_at DESC LIMIT 1";
            $sta = $pdo->prepare($sqla);
            $sta->execute($paramsa);
            $demo = $sta->fetch(PDO::FETCH_ASSOC) ?: null;
            if ($demo) {
                $notice = $notice ?: "No pending items. Showing latest allocation for testing.";
                $type = 'info';
            }
        }
    } catch (Exception $e) {}
}
$isChairmanQueue = in_array($role_norm, ['chairman_ceo','chairman','ceo','super_admin','super_admins'], true);
$pageTitle = $isChairmanQueue ? 'Chairman Allocation Queue' : 'Executive Allocation Queue';
$pageSubtitle = $isChairmanQueue ? 'Final verification and release-ready allocations waiting for chairman action.' : 'Review pending allocations and make executive approval decisions.';
$queueCount = count($rows);
$latestQueueDate = !empty($rows[0]['created_at']) ? date('M d, Y', strtotime((string)$rows[0]['created_at'])) : '—';
$totalQueueValue = 0.0;
foreach ($rows as $queueRow) {
    $totalQueueValue += (float)($queueRow['total_price'] ?? 0);
}
include 'includes/header.php';
?>
<style>
.exec-queue-page{background:#f6f8fc}
.exec-queue-page .hero-card,.exec-queue-page .summary-card,.exec-queue-page .queue-card{border:0;border-radius:18px;box-shadow:0 10px 30px rgba(15,23,42,.08)}
.exec-queue-page .hero-card{background:linear-gradient(135deg,#0f172a 0%,#1e3a8a 100%);color:#fff}
.exec-queue-page .hero-card h2{color:#fff}
.exec-queue-page .summary-label{font-size:.78rem;color:#6b7280;text-transform:uppercase;letter-spacing:.04em}
.exec-queue-page .summary-value{font-size:1.8rem;font-weight:800;color:#111827;line-height:1.1}
.exec-queue-page .hero-card .summary-label,.exec-queue-page .hero-card .summary-value{color:#fff}
.exec-queue-page .hero-muted{color:rgba(255,255,255,.8)}
.exec-queue-page .status-pill{display:inline-flex;align-items:center;gap:.4rem;border-radius:999px;padding:.4rem .75rem;font-size:.78rem;font-weight:600}
.exec-queue-page .status-pill.pending{background:#fff7ed;color:#c2410c}
.exec-queue-page .queue-actions{display:flex;flex-wrap:wrap;gap:.5rem}
.exec-queue-page .empty-box{padding:3rem 1.5rem;text-align:center}
.exec-queue-page .execq-table-scroll{display:block;width:100%;max-width:100%;overflow:auto !important;overflow-x:auto !important;overflow-y:hidden;-webkit-overflow-scrolling:touch;touch-action:pan-x pan-y;cursor:grab}
.exec-queue-page .execq-table-scroll.execq-grabbing{cursor:grabbing}
.exec-queue-page .table-responsive.execq-table-scroll{overflow:auto !important;overflow-x:auto !important;overflow-y:hidden}
.exec-queue-page .execq-table{width:max-content;min-width:980px}
.exec-queue-page .execq-table th,.exec-queue-page .execq-table td{white-space:nowrap !important;vertical-align:middle}
.exec-queue-page .execq-table td.execq-primary{white-space:normal !important;min-width:220px;max-width:360px}
.exec-queue-page .queue-hint{display:none}
@media (max-width: 991.98px){
  .exec-queue-page .queue-hint{display:block}
}
@media (max-width: 1199.98px){
  .exec-queue-page .execq-table{width:100%;min-width:0;table-layout:fixed}
  .exec-queue-page .execq-table th,.exec-queue-page .execq-table td{white-space:normal !important}
  .exec-queue-page .execq-table td{word-break:break-word}
  .exec-queue-page .execq-table td.execq-primary{min-width:0;max-width:none}
}
@media (max-width:576px){
  .exec-queue-page .queue-actions{gap:.35rem}
  .exec-queue-page .queue-actions .btn{padding:.25rem .45rem}
}
</style>
<div class="container-fluid py-4 exec-queue-page">
    <div class="hero-card card mb-4">
        <div class="card-body p-4">
            <div class="d-flex flex-wrap justify-content-between gap-3 align-items-start">
                <div>
                    <div class="summary-label mb-2"><?= $isChairmanQueue ? 'Chairman Verification Desk' : 'Executive Approval Desk' ?></div>
                    <h2 class="mb-2"><?= htmlspecialchars($pageTitle) ?></h2>
                    <p class="hero-muted mb-0"><?= htmlspecialchars($pageSubtitle) ?></p>
                </div>
                <div class="queue-actions">
                    <a href="executive-dashboard.php" class="btn btn-light btn-sm">Back to Dashboard</a>
                    <?php if ($showPending): ?>
                    <a href="executive-allocations.php" class="btn btn-outline-light btn-sm">Show All</a>
                    <?php else: ?>
                    <a href="executive-allocations.php?show=pending" class="btn btn-outline-light btn-sm">Pending Only</a>
                    <?php endif; ?>
                    <a href="allocation-letters.php" class="btn btn-outline-light btn-sm">Allocation Letters</a>
                    <?php if ($isChairmanQueue): ?>
                    <a href="chairman-approval.php" class="btn btn-warning btn-sm">Open Verification Desk</a>
                    <?php endif; ?>
                </div>
            </div>
        </div>
    </div>
    <?php if ($notice): ?>
        <div class="alert alert-<?= htmlspecialchars($type) ?>"><?= htmlspecialchars($notice) ?></div>
    <?php endif; ?>
    <div class="row g-3 mb-4">
        <div class="col-md-4">
            <div class="summary-card card h-100">
                <div class="card-body">
                    <div class="summary-label">Items In Queue</div>
                    <div class="summary-value"><?= number_format($queueCount) ?></div>
                    <div class="text-muted small mt-2"><?= $showPending ? 'Showing only pending approval items' : 'Showing current approval queue' ?></div>
                </div>
            </div>
        </div>
        <div class="col-md-4">
            <div class="summary-card card h-100">
                <div class="card-body">
                    <div class="summary-label">Queue Value</div>
                    <div class="summary-value"><?= formatCurrency($totalQueueValue) ?></div>
                    <div class="text-muted small mt-2">Total value of visible allocation requests</div>
                </div>
            </div>
        </div>
        <div class="col-md-4">
            <div class="summary-card card h-100">
                <div class="card-body">
                    <div class="summary-label">Latest Submission</div>
                    <div class="summary-value" style="font-size:1.3rem;"><?= htmlspecialchars($latestQueueDate) ?></div>
                    <div class="text-muted small mt-2">Newest request currently in this queue</div>
                </div>
            </div>
        </div>
    </div>
    <div class="queue-card card shadow-sm">
        <div class="card-header bg-white border-0 d-flex justify-content-between align-items-center py-3">
            <div>
                <h5 class="mb-1"><?= $isChairmanQueue ? 'Verification Queue' : 'Approval Queue' ?></h5>
                <div class="text-muted small">Review allocation details, preview letter, then approve or reject.</div>
            </div>
            <span class="status-pill pending"><i class="fa-regular fa-clock"></i><?= $showPending ? 'Pending Only' : 'Queue View' ?></span>
        </div>
        <div class="card-body p-0">
            <div class="queue-hint px-3 py-2 small text-muted border-bottom">Swipe left/right to see all columns.</div>
            <div class="table-responsive execq-table-scroll">
                <table class="table table-hover mb-0 execq-table">
                    <thead class="table-light">
                        <tr>
                            <th>Reference</th>
                            <th>Client</th>
                            <th>Property</th>
                            <th class="text-end">Total</th>
                            <th>Status</th>
                            <th class="d-none d-md-table-cell">Created</th>
                            <th>Action</th>
                        </tr>
                    </thead>
                    <tbody>
                    <?php if (empty($rows)): ?>
                        <tr>
                          <td colspan="7" class="empty-box">
                            <div class="mb-2 fs-5 fw-semibold">No allocation is waiting for review</div>
                            <div class="text-muted mb-3">New approval items will appear here once admin sends them to the executive/chairman queue.</div>
                            <div class="d-inline-flex flex-wrap justify-content-center gap-2">
                              <a href="executive-dashboard.php" class="btn btn-outline-secondary btn-sm">Back to Dashboard</a>
                              <a href="allocation-letters.php?view=executive" class="btn btn-outline-primary btn-sm">Open Allocation Letters</a>
                              <?php if (!$showPending): ?>
                              <a href="executive-allocations.php?show=pending" class="btn btn-outline-warning btn-sm">Pending Only</a>
                              <?php endif; ?>
                            </div>
                          </td>
                        </tr>
                    <?php else: foreach ($rows as $r): ?>
                        <tr>
                            <td>
                                <div class="fw-semibold"><?= htmlspecialchars($r['reference'] ?: ('ALC-' . (int)$r['id'])) ?></div>
                                <div class="text-muted small">#<?= (int)$r['id'] ?></div>
                                <div class="text-muted small d-md-none"><?= !empty($r['created_at']) ? date('M d, Y h:i A', strtotime((string)$r['created_at'])) : '—' ?></div>
                            </td>
                            <td class="execq-primary"><?= htmlspecialchars($r['client'] ?? '—') ?></td>
                            <td class="execq-primary"><?= htmlspecialchars($r['property'] ?? '—') ?></td>
                            <td class="text-end">₦<?= number_format((float)$r['total_price'],2) ?></td>
                            <td><span class="badge bg-warning text-dark"><?= htmlspecialchars($r['status']) ?></span></td>
                            <td class="d-none d-md-table-cell"><?= !empty($r['created_at']) ? date('M d, Y h:i A', strtotime((string)$r['created_at'])) : '—' ?></td>
                            <td>
                                <div class="queue-actions">
                                    <a href="allocation-details.php?id=<?= (int)$r['id'] ?>" class="btn btn-outline-secondary btn-sm">Details</a>
                                    <a href="allocation-letters.php?view=executive&amp;action=preview&amp;allocation_id=<?= (int)$r['id'] ?>" class="btn btn-outline-primary btn-sm" target="_blank">Preview Letter</a>
                                    <?php if ($isChairmanQueue): ?>
                                    <a href="chairman-approval.php?alloc_id=<?= (int)$r['id'] ?>" class="btn btn-dark btn-sm">Verify</a>
                                    <?php endif; ?>
                                    <button class="btn btn-success btn-sm" data-bs-toggle="modal" data-bs-target="#execModal" data-id="<?= (int)$r['id'] ?>" data-decision="approve">Approve</button>
                                    <button class="btn btn-danger btn-sm" data-bs-toggle="modal" data-bs-target="#execModal" data-id="<?= (int)$r['id'] ?>" data-decision="reject">Reject</button>
                                </div>
                            </td>
                        </tr>
                    <?php endforeach; endif; ?>
                    </tbody>
                </table>
            </div>
        </div>
    </div>
</div>

<!-- Comment Modal -->
<div class="modal fade" id="execModal" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog">
    <form method="post" class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Confirm Decision</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <input type="hidden" name="exec_action" value="1">
        <input type="hidden" name="allocation_id" id="allocId">
        <input type="hidden" name="decision" id="allocDecision">
        <div class="mb-3">
            <label class="form-label">Comment (required)</label>
            <textarea name="comment" class="form-control" required rows="3" placeholder="Provide reason"></textarea>
        </div>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
        <button type="submit" class="btn btn-dark">Confirm</button>
      </div>
    </form>
  </div>
</div>

<script>
document.getElementById('execModal').addEventListener('show.bs.modal', function (ev) {
    const btn = ev.relatedTarget;
    const id = btn.getAttribute('data-id');
    const decision = btn.getAttribute('data-decision');
    document.getElementById('allocId').value = id;
    document.getElementById('allocDecision').value = decision;
});
document.querySelector('#execModal form').addEventListener('submit', async function(e){
    const decision = document.getElementById('allocDecision').value;
    const title = decision === 'approve' ? 'Approve Allocation' : 'Reject Allocation';
    const message = decision === 'approve' ? 'Are you sure you want to approve this allocation?' : 'Are you sure you want to reject this allocation?';
    const variant = decision === 'approve' ? 'success' : 'danger';
    const ok = window.showConfirm ? await window.showConfirm({ title, message, confirmText: 'Yes, proceed', variant }) : window.confirm('Are you sure?');
    if (!ok) { e.preventDefault(); return false; }
});
// Auto session timeout (15min)
(function(){
    let t; const logoutAfter=15*60*1000; const reset=()=>{clearTimeout(t);t=setTimeout(()=>location.href='logout.php?reason=idle',logoutAfter);};
    ['click','mousemove','keydown','scroll','touchstart'].forEach(ev=>window.addEventListener(ev,reset,{passive:true}));
    reset();
})();
// Drag-to-scroll fallback (desktop) for the queue table
(function(){
    var el = document.querySelector('.execq-table-scroll');
    if (!el) return;
    var isDown = false;
    var startX = 0;
    var scrollLeft = 0;
    el.addEventListener('mousedown', function(e){
        if (e.button !== 0) return;
        if (e.target && e.target.closest('a,button,input,select,textarea,label,.modal,.dropdown-menu')) return;
        isDown = true;
        el.classList.add('execq-grabbing');
        startX = e.pageX;
        scrollLeft = el.scrollLeft;
    });
    document.addEventListener('mouseup', function(){
        if (!isDown) return;
        isDown = false;
        el.classList.remove('execq-grabbing');
    });
    document.addEventListener('mousemove', function(e){
        if (!isDown) return;
        var walk = (e.pageX - startX);
        el.scrollLeft = scrollLeft - walk;
    });
})();
</script>

<?php include 'includes/footer.php'; ?>

Youez - 2016 - github.com/yon3zu
LinuXploit