PHP WebShell
Текущая директория: /var/www/bitcardoApp/backyard/user/dashboard
Просмотр файла: index.php
<?php
// backyard/user/dashboard/index.php
include '../common/header.php';
$today = date('Y-m-d');
$txTodayQS = 'from='.$today.'&to='.$today;
if (!isset($conn)) {
include_once '../../config/db_config.php';
}
require_once '../../models/dashboard/index.php';
$overview = dash_get_overview($conn);
$wallets = dash_get_platform_wallets($conn, 0); // ALL wallets
$orders = dash_get_recent_giftcard_batches($conn, 10);
$latestTx = dash_get_latest_transactions($conn, 5);
function fmt_num($n, $dec = 0) { return number_format((float)$n, $dec); }
function fmt_money($n, $dec = 2) { return number_format((float)$n, $dec); }
function h($s) { return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
function short_addr($a, $keep = 6) {
$a = (string)$a;
if ($a === '') return '—';
if (strlen($a) <= ($keep * 2 + 3)) return $a;
return substr($a, 0, $keep) . '...' . substr($a, -$keep);
}
function tx_status_badge($status) {
$s = strtoupper(trim((string)$status));
if (in_array($s, ['SUCCESS','COMPLETED','APPROVED'], true)) return 'bg-success text-white';
if (in_array($s, ['PENDING','PROCESSING','INITIATED','QUEUED'], true)) return 'bg-warning text-dark';
if (in_array($s, ['FAILED','DECLINED','REJECTED','CANCELLED','CANCELED','ERROR'], true)) return 'bg-danger text-white';
return 'bg-secondary text-white';
}
// === AJAX endpoint (same file) for live wallet updates ===
if (isset($_GET['ajax']) && $_GET['ajax'] === 'wallets') {
header('Content-Type: application/json; charset=utf-8');
$walletsAjax = dash_get_platform_wallets($conn, 0);
echo json_encode(['ok' => true, 'wallets' => $walletsAjax]);
exit;
}
?>
<style>
.amountx{ color:#000; }
</style>
<div class="nk-content nk-content-fluid mt-5">
<div class="container-xl wide-lg">
<div class="nk-content-body">
<div class="nk-block-head">
<div class="nk-block-head-sub"><span>Welcome!</span></div>
<div class="nk-block-between-md g-4">
<div class="nk-block-head-content">
<h2 class="nk-block-title fw-normal">Olatunbosun Olaniba</h2>
<div class="nk-block-des">
<p>At a glance summary of your platform!</p>
</div>
</div>
<div class="nk-block-head-content">
<ul class="nk-block-tools gx-3">
<li><a href="#" class="btn btn-danger"><span>Freeze Crypto Wallet</span></a></li>
<li><a href="#" class="btn btn-dark"><span>Suspend User</span></a></li>
<li class="opt-menu-md dropdown">
<a href="#" class="btn btn-white btn-light btn-icon" data-bs-toggle="dropdown"><i class="fa fa-cog"></i></a>
<div class="dropdown-menu dropdown-menu-end">
<ul class="link-list-opt no-bdr">
<li><a href="#"><i class="fa fa-money"></i><span>Currency Settings</span></a></li>
<li><a href="#"><i class="fa fa-bell"></i><span>Push Notification</span></a></li>
</ul>
</div>
</li>
</ul>
</div>
</div>
</div>
<div class="nk-block">
<div class="row gy-gs">
<div class="col-lg-5 col-xl-4">
<div class="nk-block">
<div class="nk-block-head-xs">
<div class="nk-block-head-content">
<h5 class="nk-block-title title">Overview</h5>
</div>
</div>
<div class="nk-block">
<div class="card card-bordered text-light is-dark h-100">
<div class="card-inner">
<div class="nk-wg7">
<div class="nk-wg7-stats">
<div class="nk-wg7-title">Today's Transactions</div>
<div class="number-lg amount">
<?= fmt_money($overview['today_tx_amount'] ?? 0, 2); ?>
</div>
</div>
<div class="nk-wg7-stats-group">
<div class="nk-wg7-stats w-50">
<div class="nk-wg7-title">Users</div>
<div class="number"><?= fmt_num($overview['users_count'] ?? 0); ?></div>
<div class="small text-light-70">Users who transacted today</div>
</div>
<div class="nk-wg7-stats w-50">
<div class="nk-wg7-title">Transactions</div>
<div class="number"><?= fmt_num($overview['transactions_count'] ?? 0); ?></div>
<div class="small text-light-70">Transactions today</div>
</div>
</div>
<div class="mt-2 small text-light-70">
</div>
</div>
</div>
</div>
</div><!-- .nk-block -->
</div>
</div>
<div class="col-lg-7 col-xl-8">
<div class="nk-block">
<div class="nk-block-head-xs">
<div class="nk-block-between-md g-2">
<div class="nk-block-head-content">
<h5 class="nk-block-title title">Platform Wallets</h5>
</div>
<div class="nk-block-head-content">
<a href="../wallets/platform-wallets.php" class="btn btn-outline-secondary btn-sm px-1 py-0">See All</a>
</div>
</div>
</div>
<div class="row g-2" id="walletGrid">
<?php if (!empty($wallets)): ?>
<?php foreach ($wallets as $w):
$coin = $w['coin'] ?? '';
$icon = $w['icon'] ?? '';
$status = $w['status'] ?? '';
$platform_balance = (float)($w['platform_balance'] ?? 0);
$user_balance = (float)($w['user_balance'] ?? 0);
$growth = (float)($w['growth_percent'] ?? 0);
$growth_class = ($user_balance > 0 && $growth < 0) ? 'text-danger' : (($user_balance > 0 && $growth >= 0) ? 'text-success' : 'text-muted');
$growth_sign = ($user_balance > 0 && $growth >= 0) ? '+' : '';
$growth_text = ($user_balance > 0) ? ($growth_sign . number_format($growth, 2) . '%') : '—';
$card_class = ($status === 'Active') ? 'bg-light' : 'bg-white border';
?>
<div class="col-md-4">
<div class="card <?= $card_class; ?>">
<div class="nk-wgw sm">
<span class="nk-wgw-inner">
<div class="nk-wgw-name d-flex justify-content-between align-items-center">
<div class="nk-wgw-icon">
<img class="rounded-5" src="../../../assets/icons/<?= h($icon); ?>" alt="<?= h($coin); ?> icon">
</div>
<div class="flex-grow-1 ms-2">
<h5 class="nk-wgw-title title mb-0"><?= h($coin); ?></h5>
</div>
<h6 class="mb-0 js-growth <?= $growth_class; ?>" data-coin="<?= h($coin); ?>">
<?= h($growth_text); ?>
</h6>
</div>
<div class="nk-wgw-balance">
<div class="amountx">
Platform:
<span class="js-wallet-platform" data-coin="<?= h($coin); ?>">
<?= fmt_money($platform_balance, 6); ?>
</span>
</div>
<div class="amountx">
All Users:
<span class="js-wallet-users" data-coin="<?= h($coin); ?>">
<?= fmt_money($user_balance, 6); ?>
</span>
</div>
</div>
</span>
</div>
</div>
</div>
<?php endforeach; ?>
<?php else: ?>
<div class="col-12">
<div class="alert alert-light border">No wallets found.</div>
</div>
<?php endif; ?>
</div><!-- .row -->
<div class="small text-muted mt-2">Balances update automatically.</div>
</div>
</div>
</div>
</div>
<!-- GiftCard Orders -->
<div class="nk-block nk-block-lg">
<div class="card-title mb-4 border-top border-bottom py-3 px-3 d-flex justify-content-between align-items-center">
<h5 class="title mb-0">GiftCard Orders</h5>
<a class="btn btn-sm btn-outline-secondary" href="../giftcards/index.php">See All</a>
</div>
<div class="gy-gs container">
<?php if (!empty($orders)): ?>
<?php
date_default_timezone_set('Africa/Lagos');
foreach ($orders as $b):
$batch = $b['batch_ref'];
$fname = trim(($b['first_name'] ?? '').' '.($b['last_name'] ?? ''));
$payout = number_format((float)$b['total_payout'], 2);
$status = dash_batch_status($b);
$created = $b['last_time'] ? date('M j, Y g:i A', strtotime($b['last_time'])) : '—';
$badgeClass = 'bg-secondary text-white';
$sUp = strtoupper($status);
if ($sUp === 'SUCCESS') $badgeClass = 'bg-success text-white';
elseif ($sUp === 'PENDING') $badgeClass = 'bg-warning text-dark';
elseif ($sUp === 'DECLINED') $badgeClass = 'bg-danger text-white';
elseif ($sUp === 'MIXED') $badgeClass = 'bg-info text-dark';
$href = "../orders/process_order.php?batch=" . urlencode($batch);
?>
<a href="<?= $href; ?>" class="row border rounded-5 px-2 py-3 shadow-sm mx-1 mb-2 text-dark">
<div class="col-md-3 col-7">
<div class="number-sm"><?= h($batch); ?></div>
</div>
<div class="col-md-2 d-none d-md-block">
<div class="number-sm"><?= h($fname !== '' ? $fname : '—'); ?></div>
</div>
<div class="col-md-3 col-5">
<div class="number-sm"><?= $payout; ?> / <span class="currency">₦</span></div>
</div>
<div class="col-md-2 col-6 mt-2 mt-md-0">
<span class="number-sm <?= $badgeClass; ?> py-1 px-2 rounded-3">
<?= h($status); ?>
</span>
</div>
<div class="col-md-2 col-6 mt-2 mt-md-0 text-md-end">
<div class="number-sm"><?= h($created); ?></div>
</div>
</a>
<?php endforeach; ?>
<?php else: ?>
<div class="alert alert-light border mx-1">No recent gift card batches.</div>
<?php endif; ?>
</div>
</div>
<!-- Latest Transactions -->
<div class="nk-block nk-block-lg">
<div class="card-title mb-4 border-top border-bottom py-3 px-3 d-flex justify-content-between align-items-center">
<h5 class="title mb-0">Latest Transactions</h5>
<a class="btn btn-sm btn-outline-secondary" href="../transactions/index.php?<?= h($txTodayQS); ?>">See Today</a>
</div>
<div class="gy-gs container">
<?php if (!empty($latestTx)): ?>
<?php
date_default_timezone_set('Africa/Lagos');
foreach ($latestTx as $t):
$trans_id = (int)($t['trans_id'] ?? 0);
$coin = strtoupper(trim((string)($t['coin'] ?? '')));
$amount = (float)($t['amount'] ?? 0);
$type = (string)($t['type'] ?? '');
$status = (string)($t['status'] ?? 'pending');
$created = !empty($t['created_at']) ? date('M j, Y g:i A', strtotime($t['created_at'])) : '—';
$fname = trim(($t['first_name'] ?? '').' '.($t['last_name'] ?? ''));
if ($fname === '') $fname = $t['email'] ?? '—';
$sender = short_addr($t['sender_address'] ?? '');
$recv = short_addr($t['receiver_address'] ?? '');
$badgeClass = tx_status_badge($status);
$txHref = "../transactions/view.php?trans_id=" . urlencode((string)$trans_id);
?>
<a href="<?= h($txHref); ?>" class="row border rounded-5 px-2 py-3 shadow-sm mx-1 mb-2 text-dark">
<div class="col-md-3 col-7">
<div class="number-sm">#<?= h($trans_id); ?></div>
<div class="small text-muted"><?= h($fname); ?></div>
</div>
<div class="col-md-3 col-5">
<div class="number-sm"><?= fmt_money($amount, 6); ?> <span class="currency"><?= h($coin); ?></span></div>
<div class="small text-muted"><?= h($type !== '' ? $type : '—'); ?></div>
</div>
<div class="col-md-4 d-none d-md-block">
<div class="small text-muted">From: <?= h($sender); ?></div>
<div class="small text-muted">To: <?= h($recv); ?></div>
</div>
<div class="col-md-2 col-12 mt-2 mt-md-0 text-md-end">
<span class="number-sm <?= $badgeClass; ?> py-1 px-2 rounded-3">
<?= h($status); ?>
</span>
<div class="small text-muted mt-1"><?= h($created); ?></div>
</div>
</a>
<?php endforeach; ?>
<?php else: ?>
<div class="alert alert-light border mx-1">No recent transactions.</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
</div>
<script>
(function () {
const POLL_MS = 10000;
function fmtBalance(n) {
const num = Number(n || 0);
return num.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 6 });
}
async function refreshWalletCards() {
try {
const url = window.location.pathname + '?ajax=wallets';
const res = await fetch(url, { cache: 'no-store' });
const data = await res.json();
if (!data || !data.ok || !Array.isArray(data.wallets)) return;
const map = {};
data.wallets.forEach(w => {
const coin = (w.coin || '').toString();
if (!coin) return;
map[coin] = {
platform: Number(w.platform_balance || 0),
users: Number(w.user_balance || 0),
growth: Number(w.growth_percent || 0),
};
});
document.querySelectorAll('.js-wallet-platform').forEach(el => {
const coin = el.getAttribute('data-coin');
if (coin && map[coin]) el.textContent = fmtBalance(map[coin].platform);
});
document.querySelectorAll('.js-wallet-users').forEach(el => {
const coin = el.getAttribute('data-coin');
if (coin && map[coin]) el.textContent = fmtBalance(map[coin].users);
});
document.querySelectorAll('.js-growth').forEach(el => {
const coin = el.getAttribute('data-coin');
if (!coin || !map[coin]) return;
const usersBal = map[coin].users;
const growth = map[coin].growth;
let text = '—';
let cls = 'text-muted';
if (usersBal > 0) {
text = (growth >= 0 ? '+' : '') + growth.toFixed(2) + '%';
cls = (growth >= 0) ? 'text-success' : 'text-danger';
}
el.textContent = text;
el.classList.remove('text-success','text-danger','text-muted');
el.classList.add(cls);
});
} catch (e) {
// silent on transient errors
}
}
setInterval(refreshWalletCards, POLL_MS);
})();
</script>
<?php include '../common/footer.php'; ?>
Выполнить команду
Для локальной разработки. Не используйте в интернете!