PNG IHDR x sBIT|d pHYs + tEXtSoftware www.inkscape.org< ,tEXtComment
<?php
// 🔴 DEBUG MODE ON
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
session_start();
// 1. STRICT SECURITY PERIMETER
if (!isset($_SESSION['admin_id']) || !isset($_SESSION['is_admin']) || $_SESSION['is_admin'] !== true) {
session_destroy();
header("Location: admin-login.php");
exit();
}
$host = 'localhost';
$dbname = 'u264723324_NuDb';
$user = 'u264723324_NuUu';
$pass = '@WdsdsdAq1231';
try {
$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// =======================================================
// AJAX HANDLER: GOD MODE TRANSACTION REVERSAL
// =======================================================
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ajax_action'])) {
header('Content-Type: application/json');
if ($_POST['ajax_action'] === 'reverse_tx') {
$txId = filter_input(INPUT_POST, 'tx_id', FILTER_VALIDATE_INT);
$authKey = filter_input(INPUT_POST, 'auth_key', FILTER_SANITIZE_STRING);
if (!$txId) {
echo json_encode(['success' => false, 'message' => 'Invalid Transaction ID.']);
exit;
}
try {
$pdo->beginTransaction();
// 1. Fetch the exact transaction details
$stmtTx = $pdo->prepare("SELECT account_id, transaction_type, amount, status FROM transactions WHERE id = ? FOR UPDATE");
$stmtTx->execute([$txId]);
$txData = $stmtTx->fetch(PDO::FETCH_ASSOC);
if (!$txData) {
throw new Exception("Transaction not found in ledger.");
}
if ($txData['status'] === 'reversed') {
throw new Exception("Transaction has already been reversed.");
}
// 2. Mathematically reverse the funds on the actual account
// If it was a debit (money left), we add it back (+). If it was a credit, we claw it back (-).
$mathOperator = ($txData['transaction_type'] === 'debit') ? '+' : '-';
$amount = $txData['amount'];
$accId = $txData['account_id'];
$stmtAcc = $pdo->prepare("UPDATE accounts SET balance = balance $mathOperator ? WHERE id = ?");
$stmtAcc->execute([$amount, $accId]);
// 3. Mark the transaction as permanently reversed
$stmtUpdateTx = $pdo->prepare("UPDATE transactions SET status = 'reversed', description = CONCAT(description, ' [REVERSED BY ADMIN]') WHERE id = ?");
$stmtUpdateTx->execute([$txId]);
$pdo->commit();
echo json_encode(['success' => true, 'message' => 'GODMODE: Transaction Reversed and Funds Adjusted.']);
} catch (Exception $e) {
$pdo->rollBack();
echo json_encode(['success' => false, 'message' => 'REVERSAL FAILED: ' . $e->getMessage()]);
}
exit;
}
}
// =======================================================
// FETCH GLOBAL LEDGER (God Eye View)
// =======================================================
// Join transactions with accounts and users to see exactly who did what
$query = "
SELECT
t.id, t.transaction_type, t.amount, t.description, t.status, t.created_at,
a.account_number, a.currency,
u.first_name, u.last_name, u.email
FROM transactions t
JOIN accounts a ON t.account_id = a.id
JOIN users u ON a.user_id = u.id
ORDER BY t.created_at DESC
LIMIT 100
";
$stmtTx = $pdo->query($query);
$ledgerList = $stmtTx->fetchAll(PDO::FETCH_ASSOC);
// Fetch Quick Stats
$stmtVol = $pdo->query("SELECT SUM(amount) FROM transactions WHERE status = 'completed' AND DATE(created_at) = CURDATE()");
$dailyVolume = $stmtVol->fetchColumn() ?: 0;
$stmtRev = $pdo->query("SELECT COUNT(*) FROM transactions WHERE status = 'reversed'");
$reversalCount = $stmtRev->fetchColumn() ?: 0;
} catch (PDOException $e) {
$ledgerList = [];
$dailyVolume = $reversalCount = 0;
$dbError = "Ledger Sync Error. Database missing tables? " . $e->getMessage();
}
$adminName = htmlspecialchars($_SESSION['admin_username']);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Global Ledger - City Prime Admin</title>
<style>
:root {
--bg-deep: #050505; --surface-dark: #0f0f0f; --surface-light: #1a1a1a;
--border-red: #7f1d1d; --danger: #ef4444; --danger-glow: rgba(239, 68, 68, 0.15);
--text-main: #f8fafc; --text-muted: #64748b; --success: #22c55e; --warning: #facc15; --purple: #a855f7;
}
* { margin: 0; padding: 0; box-sizing: border-box; font-family: "Courier New", Courier, monospace; }
body { background-color: var(--bg-deep); color: var(--text-main); display: flex; min-height: 100vh; overflow-x: hidden; }
.grid-bg { position: fixed; width: 100vw; height: 100vh; background-image: linear-gradient(rgba(255,255,255,0.02) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.02) 1px, transparent 1px); background-size: 30px 30px; z-index: 0; pointer-events: none;}
/* SIDEBAR */
.sidebar { width: 260px; background: var(--surface-dark); border-right: 1px solid var(--border-red); height: 100vh; position: sticky; top: 0; display: flex; flex-direction: column; padding: 24px 0; z-index: 10;}
.brand { text-align: center; margin-bottom: 40px; padding: 0 24px;}
.brand h2 { color: var(--danger); letter-spacing: 2px; text-transform: uppercase; font-size: 1.4rem; text-shadow: 0 0 10px rgba(239,68,68,0.4);}
.brand p { color: var(--text-muted); font-size: 0.75rem; letter-spacing: 1px; margin-top: 4px; }
.nav-links { display: flex; flex-direction: column; gap: 8px; padding: 0 16px; flex: 1;}
.nav-links a { text-decoration: none; color: var(--text-muted); padding: 14px 20px; border-radius: 8px; transition: 0.2s; display: flex; align-items: center; gap: 12px; font-weight: bold; letter-spacing: 1px;}
.nav-links a:hover, .nav-links a.active { background: var(--danger-glow); color: var(--danger); border: 1px solid rgba(239,68,68,0.3);}
.logout-box { padding: 0 16px; margin-top: auto;}
.logout-btn { display: block; text-align: center; background: transparent; color: var(--danger); border: 1px solid var(--danger); padding: 14px; border-radius: 8px; text-decoration: none; font-weight: bold; transition: 0.2s; letter-spacing: 1px;}
.logout-btn:hover { background: var(--danger); color: white; box-shadow: 0 0 15px rgba(239,68,68,0.4);}
/* MAIN CONTENT */
.main-content { flex: 1; padding: 32px 40px; position: relative; z-index: 1; max-width: 1400px; margin: 0 auto; width: 100%;}
.top-bar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 40px; border-bottom: 1px solid rgba(255,255,255,0.05); padding-bottom: 24px;}
.page-title h1 { font-size: 1.8rem; font-weight: normal; letter-spacing: 2px;}
.page-title p { color: var(--text-muted); font-size: 0.9rem; margin-top: 8px;}
.godmode-badge { background: rgba(168, 85, 247, 0.1); border: 1px solid var(--purple); color: var(--purple); padding: 8px 16px; border-radius: 20px; font-size: 0.8rem; font-weight: bold; letter-spacing: 2px; text-shadow: 0 0 10px rgba(168,85,247,0.5); box-shadow: inset 0 0 10px rgba(168,85,247,0.2);}
/* STATS GRID */
.stats-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; margin-bottom: 40px;}
.stat-card { background: var(--surface-dark); border: 1px solid rgba(255,255,255,0.05); padding: 24px; border-radius: 16px; position: relative;}
.stat-title { color: var(--text-muted); font-size: 0.85rem; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 12px;}
.stat-value { font-size: 2rem; font-weight: bold;}
.stat-value.green { color: var(--success); }
.stat-value.red { color: var(--danger); }
/* DATA TABLE */
.controls-bar { display: flex; justify-content: space-between; margin-bottom: 24px; gap: 16px;}
.search-box { flex: 1; max-width: 400px; position: relative;}
.search-box input { width: 100%; background: var(--surface-dark); border: 1px solid rgba(255,255,255,0.1); color: var(--text-main); padding: 12px 16px; border-radius: 8px; outline: none; font-family: monospace;}
.search-box input:focus { border-color: var(--danger);}
.data-panel { background: var(--surface-dark); border: 1px solid rgba(255,255,255,0.05); border-radius: 16px; padding: 24px; overflow-x: auto; min-height: 500px;}
table { width: 100%; border-collapse: collapse; min-width: 1000px;}
th { text-align: left; padding: 16px; color: var(--text-muted); font-size: 0.85rem; text-transform: uppercase; border-bottom: 1px solid rgba(255,255,255,0.1); letter-spacing: 1px; font-weight: normal;}
td { padding: 16px; border-bottom: 1px solid rgba(255,255,255,0.02); font-size: 0.95rem; vertical-align: middle;}
tr:last-child td { border-bottom: none;}
tr:hover td { background: rgba(255,255,255,0.02);}
.td-name { font-weight: bold; margin-bottom: 4px; display: block; font-size: 1rem; color: var(--text-main);}
.td-sub { color: var(--text-muted); font-size: 0.8rem;}
.td-txid { font-family: monospace; color: var(--text-muted); font-size: 0.8rem;}
.amt-credit { color: var(--success); font-weight: bold; font-family: monospace; font-size: 1.1rem;}
.amt-debit { color: var(--danger); font-weight: bold; font-family: monospace; font-size: 1.1rem;}
.badge { padding: 4px 10px; border-radius: 20px; font-size: 0.75rem; font-weight: bold; text-transform: uppercase; letter-spacing: 1px; display: inline-block;}
.badge.completed { background: rgba(34, 197, 94, 0.1); color: var(--success); border: 1px solid rgba(34, 197, 94, 0.3);}
.badge.pending { background: rgba(250, 204, 21, 0.1); color: var(--warning); border: 1px solid rgba(250, 204, 21, 0.3);}
.badge.reversed { background: rgba(168, 85, 247, 0.1); color: var(--purple); border: 1px solid rgba(168, 85, 247, 0.3);}
.badge.failed { background: rgba(239, 68, 68, 0.1); color: var(--danger); border: 1px solid rgba(239, 68, 68, 0.3);}
.action-btn { background: rgba(239, 68, 68, 0.1); border: 1px solid rgba(239, 68, 68, 0.3); color: var(--danger); padding: 8px 16px; border-radius: 6px; cursor: pointer; font-size: 0.85rem; transition: 0.2s; font-family: inherit; font-weight: bold;}
.action-btn:hover { background: var(--danger); color: white; box-shadow: 0 0 10px rgba(239,68,68,0.4);}
.action-btn.disabled { opacity: 0.3; cursor: not-allowed; pointer-events: none; border-color: transparent; background: rgba(255,255,255,0.05); color: var(--text-muted);}
/* MODAL (REVERSE TX) */
.modal-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.8); backdrop-filter: blur(5px); display: flex; align-items: center; justify-content: center; opacity: 0; pointer-events: none; transition: 0.3s; z-index: 1000; }
.modal-overlay.active { opacity: 1; pointer-events: all; }
.modal-container { background: var(--surface-dark); width: 100%; max-width: 500px; border-radius: 16px; padding: 32px; border: 1px solid var(--purple); box-shadow: 0 0 30px rgba(168,85,247,0.15); transform: translateY(20px); transition: 0.3s;}
.modal-overlay.active .modal-container { transform: translateY(0); }
.modal-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px; border-bottom: 1px solid rgba(255,255,255,0.1); padding-bottom: 16px;}
.modal-header h3 { font-size: 1.4rem; color: var(--purple); text-transform: uppercase; letter-spacing: 1px;}
.close-btn { background: none; border: none; color: var(--text-muted); font-size: 1.5rem; cursor: pointer; transition: 0.2s;}
.close-btn:hover { color: var(--text-main);}
.tx-details-box { background: var(--bg-deep); padding: 20px; border-radius: 8px; border: 1px dashed var(--danger); margin-bottom: 24px; font-family: monospace;}
.tx-row { display: flex; justify-content: space-between; margin-bottom: 12px; border-bottom: 1px solid rgba(255,255,255,0.05); padding-bottom: 8px;}
.tx-row:last-child { border: none; margin: 0; padding: 0;}
.tx-row span { color: var(--text-muted);}
.tx-row strong { color: white; font-size: 1.1rem;}
.warning-text { color: var(--danger); font-size: 0.85rem; margin-bottom: 24px; line-height: 1.5; font-weight: bold; background: rgba(239,68,68,0.1); padding: 12px; border-left: 3px solid var(--danger);}
.btn-reverse { width: 100%; background: rgba(168, 85, 247, 0.1); color: var(--purple); border: 1px solid var(--purple); padding: 16px; border-radius: 8px; font-size: 1rem; font-weight: bold; cursor: pointer; transition: 0.2s; text-transform: uppercase; letter-spacing: 2px;}
.btn-reverse:hover { background: var(--purple); color: white; box-shadow: 0 0 20px rgba(168,85,247,0.5);}
/* TOAST */
.toast { position: fixed; top: 20px; right: -300px; background: var(--success); color: white; padding: 16px 24px; border-radius: 8px; font-weight: bold; box-shadow: 0 4px 12px rgba(0,0,0,0.3); transition: 0.4s; z-index: 2000; font-family: monospace; letter-spacing: 1px;}
.toast.show { right: 20px; }
.toast.error { background: var(--danger); }
</style>
</head>
<body oncontextmenu="return false;">
<div class="grid-bg"></div>
<aside class="sidebar">
<div class="brand">
<h2>City Prime</h2>
<p>COMMAND CENTER</p>
</div>
<nav class="nav-links">
<a href="admin-dashboard.php"><span>[1]</span> Dashboard</a>
<a href="admin-users.php"><span>[2]</span> User Matrix</a>
<a href="admin-kyc.php"><span>[3]</span> KYC Approvals</a>
<a href="admin-cards.php"><span>[4]</span> Card Requests</a>
<a href="admin-transactions.php" class="active"><span>[5]</span> Ledgers</a>
<a href="admin-settings.php"><span>[6]</span> System Config</a>
</nav>
<div class="logout-box">
<a href="admin-logout.php" class="logout-btn">TERMINATE SESSION</a>
</div>
</aside>
<main class="main-content">
<div class="top-bar">
<div class="page-title">
<h1>Global Ledger</h1>
<p>Live stream of all financial movements across the network.</p>
</div>
<div class="godmode-badge">
STATUS: GODMODE ACTIVE
</div>
</div>
<div class="stats-grid">
<div class="stat-card">
<div class="stat-title">Daily Volume (24h)</div>
<div class="stat-value green">+$<?php echo number_format($dailyVolume, 2); ?></div>
</div>
<div class="stat-card">
<div class="stat-title">Active Nodes</div>
<div class="stat-value">14</div>
</div>
<div class="stat-card">
<div class="stat-title">Total Reversals</div>
<div class="stat-value red" id="reversalCountUi"><?php echo number_format($reversalCount); ?></div>
</div>
</div>
<div class="controls-bar">
<div class="search-box">
<input type="text" id="searchInput" placeholder="Search by TX ID, Account, or Name..." onkeyup="filterTable()">
</div>
</div>
<div class="data-panel">
<?php if (isset($dbError)): ?>
<div style="color: var(--danger); margin-bottom: 16px;"><?php echo $dbError; ?></div>
<?php endif; ?>
<table id="ledgerTable">
<thead>
<tr>
<th>TX ID / Date</th>
<th>Account Info</th>
<th>Description</th>
<th>Amount</th>
<th>Status</th>
<th>Intercept</th>
</tr>
</thead>
<tbody>
<?php if (empty($ledgerList)): ?>
<tr><td colspan="6" style="text-align:center; padding:40px; color:var(--text-muted); font-style:italic;">No transactions found in ledger. (Did you buy a card yet?)</td></tr>
<?php else: ?>
<?php foreach ($ledgerList as $tx):
$isReversed = ($tx['status'] === 'reversed');
$isCredit = ($tx['transaction_type'] === 'credit');
$amtClass = $isCredit ? 'amt-credit' : 'amt-debit';
$amtSign = $isCredit ? '+' : '-';
?>
<tr>
<td>
<span class="td-txid">TXN-<?php echo str_pad($tx['id'], 8, '0', STR_PAD_LEFT); ?></span>
<span class="td-sub" style="display: block; margin-top: 4px;">
<?php echo date('M d, Y H:i:s', strtotime($tx['created_at'])); ?>
</span>
</td>
<td>
<span class="td-name"><?php echo htmlspecialchars($tx['first_name'] . ' ' . $tx['last_name']); ?></span>
<span class="td-sub">ACC: ****<?php echo substr($tx['account_number'], -4); ?></span>
</td>
<td style="max-width: 250px; line-height: 1.4;">
<span id="desc-<?php echo $tx['id']; ?>"><?php echo htmlspecialchars($tx['description']); ?></span>
</td>
<td class="<?php echo $amtClass; ?>" style="white-space: nowrap;">
<?php echo $amtSign; ?>$<?php echo number_format($tx['amount'], 2); ?>
</td>
<td>
<span class="badge <?php echo $tx['status']; ?>" id="badge-<?php echo $tx['id']; ?>">
<?php echo strtoupper($tx['status']); ?>
</span>
</td>
<td>
<button class="action-btn <?php echo $isReversed ? 'disabled' : ''; ?>" id="btn-<?php echo $tx['id']; ?>" onclick="openReverseModal(
<?php echo $tx['id']; ?>,
'<?php echo addslashes($tx['first_name'] . ' ' . $tx['last_name']); ?>',
'<?php echo $amtSign . '$' . number_format($tx['amount'], 2); ?>',
'<?php echo addslashes($tx['description']); ?>',
'<?php echo addslashes($tx['transaction_type']); ?>'
)">REVERSE</button>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</main>
<div class="modal-overlay" id="reverseModal">
<div class="modal-container">
<div class="modal-header">
<h3>Intercept Transaction</h3>
<button class="close-btn" onclick="closeModal()">×</button>
</div>
<div class="tx-details-box">
<div class="tx-row">
<span>Target User:</span>
<strong id="modalUser">NAME</strong>
</div>
<div class="tx-row">
<span>Value:</span>
<strong id="modalAmt" style="color: var(--danger);">AMOUNT</strong>
</div>
<div class="tx-row">
<span>Type:</span>
<strong id="modalType">TYPE</strong>
</div>
<div class="tx-row">
<span>Details:</span>
<strong id="modalDesc" style="font-size: 0.85rem; max-width: 200px; text-align: right;">DESC</strong>
</div>
</div>
<div class="warning-text">
CRITICAL WARNING: Executing a reversal will directly modify the user's live account balance. This action will be permanently logged in the God-Mode audit trail and cannot be undone.
</div>
<input type="hidden" id="modalTxId">
<button class="btn-reverse" id="executeBtn" onclick="executeReversal()">AUTHORIZE REVERSAL</button>
</div>
</div>
<div id="toast" class="toast">Command Executed</div>
<script>
let totalReversals = <?php echo $reversalCount; ?>;
// --- Toast Notification ---
function showToast(msg, isError = false) {
const toast = document.getElementById('toast');
toast.textContent = msg;
toast.className = 'toast show ' + (isError ? 'error' : '');
setTimeout(() => { toast.classList.remove('show'); }, 30
b IDATxytVսϓ22 A@IR:hCiZ[v*E:WũZA ^dQeQ @ !jZ'>gsV仿$|?g)&x-E