PHP WebShell

Текущая директория: /var/www/bitcardoApp/backyard/user/users

Просмотр файла: view.php

<?php
// backyard/user/users/view.php
include '../common/header.php';

if (!isset($conn)) { include_once '../../config/db_config.php'; }
require_once '../../models/users/index.php';

date_default_timezone_set('Africa/Lagos');

$user_id = isset($_GET['user_id']) ? (int)$_GET['user_id'] : 0;
if ($user_id <= 0) {
  echo '<div class="nk-content nk-content-fluid"><div class="container-xl wide-lg"><div class="nk-content-body"><div class="alert alert-warning">Invalid user.</div></div></div></div>';
  include '../common/footer.php'; exit;
}

$u   = users_get_basic($conn, $user_id);
if (!$u) {
  echo '<div class="nk-content nk-content-fluid"><div class="container-xl wide-lg"><div class="nk-content-body"><div class="alert alert-warning">User not found.</div></div></div></div>';
  include '../common/footer.php'; exit;
}

$wl  = users_get_wallets($conn, $user_id);
$tr  = users_get_recent_trades($conn, $user_id, 20);
$tx  = users_get_recent_tx($conn, $user_id, 20);
$ss  = users_get_sessions($conn, $user_id, 20);
$dv  = users_get_devices($conn, $user_id);
$sec = users_get_security($conn, $user_id);

// Total transactions count (for Overview card)
$tx_total = 0;
if ($res = mysqli_query($conn, "SELECT COUNT(*) AS c FROM transactions WHERE user_id = {$user_id}")) {
  $row = mysqli_fetch_assoc($res);
  $tx_total = (int)($row['c'] ?? 0);
  mysqli_free_result($res);
}

$fullname = trim(($u['first_name'] ?? '').' '.($u['last_name'] ?? ''));
$statusClass = badge_class($u['user_status'] ?? '');

if (!function_exists('h'))  { function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); } }
if (!function_exists('mny')){ function mny($n,$d=2){ return number_format((float)$n,$d); } }
?>
<style>
.gc-card { border:1px solid #e5e7eb; border-radius:.5rem; padding:.75rem; }
.gc-kv { display:flex; justify-content:space-between; gap:.75rem; }
.gc-kv .k { color:#6c757d; font-size:.85rem; }
.gc-kv .v { font-weight:600; }
</style>

<div class="nk-content nk-content-fluid">
  <div class="container-xl wide-lg">
    <div class="nk-content-body">

      <div class="nk-block-head">
        <div class="nk-block-between-md g-3 align-items-center">
          <div class="nk-block-head-content">
            <div class="nk-block-head-sub"><span>User Profile</span></div>
            <h3 class="nk-block-title fw-normal mb-1">
              <?= h($fullname ?: '—'); ?>
              <span class="badge <?= $statusClass; ?> align-middle"><?= h($u['user_status'] ?: '—'); ?></span>
            </h3>
            <div class="nk-block-des">
              <p class="text-soft mb-1">
                <?= h($u['email'] ?: '—'); ?> · <?= h($u['phone'] ?: '—'); ?> · ID: <?= (int)$u['user_id']; ?>
              </p>
            </div>
          </div>
          <div class="nk-block-head-content">
            <ul class="nk-block-tools gx-2">
              <li>
                <button class="btn <?= (strtolower($u['user_status'])==='active'?'btn-danger':'btn-success'); ?>"
                        onclick="openStatusConfirm(<?= (int)$u['user_id']; ?>,'<?= h($u['user_status']); ?>','<?= h($fullname ?: 'this user'); ?>')">
                  <?= (strtolower($u['user_status'])==='active'?'Suspend User':'Activate User'); ?>
                </button>
              </li>
              <li><a href="users.php" class="btn btn-outline-secondary">Back to Users</a></li>
            </ul>
          </div>
        </div>
      </div>

      <!-- Tabs -->
      <ul class="nav nav-tabs mt-2" role="tablist">
        <li class="nav-item"><button class="nav-link active" data-bs-toggle="tab" data-bs-target="#tab-overview" type="button">Overview</button></li>
        <li class="nav-item"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#tab-wallets" type="button">Wallets</button></li>
        <li class="nav-item"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#tab-trades" type="button">Gift Cards</button></li>
        <li class="nav-item"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#tab-trans" type="button">Transactions</button></li>
        <li class="nav-item"><button class="nav-link" data-bs-toggle="tab" data-bs-target="#tab-security" type="button">Security</button></li>
      </ul>

      <div class="tab-content mt-3">
        <!-- Overview -->
        <div class="tab-pane fade show active" id="tab-overview">
          <div class="d-md-none">
            <div class="gc-card mb-2">
              <div class="gc-kv"><div class="k">Total No. of Transactions</div><div class="v"><?= (int)$tx_total; ?></div></div>
              <div class="gc-kv"><div class="k">Created</div><div class="v"><?= h($u['created_at'] ?? '—'); ?></div></div>
              <div class="gc-kv"><div class="k">Updated</div><div class="v"><?= h($u['updated_at'] ?? '—'); ?></div></div>
              <div class="gc-kv"><div class="k">Wallets</div><div class="v"><?= count($wl); ?></div></div>
            </div>
          </div>
          <div class="row g-2 d-none d-md-flex">
            <div class="col-md-3"><div class="card card-bordered"><div class="card-inner p-2"><div class="small text-soft">Total No. of Transactions</div><div class="fw-bold"><?= (int)$tx_total; ?></div></div></div></div>
            <div class="col-md-3"><div class="card card-bordered"><div class="card-inner p-2"><div class="small text-soft">Created</div><div class="fw-bold"><?= h($u['created_at'] ?? '—'); ?></div></div></div></div>
            <div class="col-md-3"><div class="card card-bordered"><div class="card-inner p-2"><div class="small text-soft">Updated</div><div class="fw-bold"><?= h($u['updated_at'] ?? '—'); ?></div></div></div></div>
            <div class="col-md-3"><div class="card card-bordered"><div class="card-inner p-2"><div class="small text-soft">Wallets</div><div class="fw-bold"><?= count($wl); ?></div></div></div></div>
          </div>
        </div>

        <!-- Wallets (with toggle) -->
        <div class="tab-pane fade" id="tab-wallets">
          <?php if (empty($wl)): ?>
            <div class="alert alert-light border mb-0">No wallets.</div>
          <?php else: ?>
            <!-- Desktop table -->
            <div class="table-responsive d-none d-md-block">
              <table class="table table-sm align-middle">
                <thead class="small text-soft">
                  <tr>
                    <th>Label</th>
                    <th>Coin</th>
                    <th>Type</th>
                    <th>Balance</th>
                    <th>Status</th>
                    <th>Updated</th>
                    <th class="text-end">Freeze</th>
                  </tr>
                </thead>
                <tbody>
                  <?php foreach ($wl as $w): ?>
                    <?php
                      $isFrozen = strcasecmp((string)$w['wallet_status'], 'Frozen') === 0;
                      $toggleChecked = $isFrozen ? 'checked' : '';
                      $labelText = $isFrozen ? 'Frozen' : 'Active';
                    ?>
                    <tr>
                      <td><?= h($w['label'] ?: '—'); ?></td>
                      <td><?= h($w['coin'] ?: '—'); ?></td>
                      <td><?= h($w['type'] ?: '—'); ?></td>
                      <td><?= mny($w['balance'] ?? 0, 4); ?></td>
                      <td>
                        <span class="badge <?= $isFrozen ? 'bg-secondary' : 'bg-success'; ?> wallet-status-badge">
                          <?= h($labelText); ?>
                        </span>
                      </td>
                      <td class="small"><?= h($w['updated_at'] ?: '—'); ?></td>
                      <td class="text-end">
                        <div class="form-check form-switch m-0 d-inline-block">
                          <input class="form-check-input wallet-freeze-toggle"
                                 type="checkbox"
                                 role="switch"
                                 <?= $toggleChecked; ?>
                                 data-wallet-id="<?= (int)$w['wallet_id']; ?>"
                                 data-label="<?= h(($w['label'] ?: $w['coin'] ?: 'Wallet')); ?>">
                          <label class="form-check-label small ms-1"><?= $isFrozen ? 'On' : 'Off'; ?></label>
                        </div>
                      </td>
                    </tr>
                  <?php endforeach; ?>
                </tbody>
              </table>
            </div>

            <!-- Mobile cards -->
            <div class="d-md-none">
              <?php foreach ($wl as $w): ?>
                <?php
                  $isFrozen = strcasecmp((string)$w['wallet_status'], 'Frozen') === 0;
                  $toggleChecked = $isFrozen ? 'checked' : '';
                  $labelText = $isFrozen ? 'Frozen' : 'Active';
                ?>
                <div class="gc-card mb-2">
                  <div class="d-flex justify-content-between align-items-center mb-1">
                    <div class="fw-bold"><?= h($w['label'] ?: '—'); ?></div>
                    <span class="badge <?= $isFrozen ? 'bg-secondary' : 'bg-success'; ?> wallet-status-badge">
                      <?= h($labelText); ?>
                    </span>
                  </div>
                  <div class="gc-kv mt-1"><div class="k">Coin</div><div class="v"><?= h($w['coin'] ?: '—'); ?></div></div>
                  <div class="gc-kv"><div class="k">Type</div><div class="v"><?= h($w['type'] ?: '—'); ?></div></div>
                  <div class="gc-kv"><div class="k">Balance</div><div class="v"><?= mny($w['balance'] ?? 0, 4); ?></div></div>
                  <div class="gc-kv"><div class="k">Updated</div><div class="v small"><?= h($w['updated_at'] ?: '—'); ?></div></div>
                  <div class="d-flex justify-content-between align-items-center mt-2">
                    <div class="small text-soft">Freeze</div>
                    <div class="form-check form-switch m-0">
                      <input class="form-check-input wallet-freeze-toggle"
                             type="checkbox"
                             role="switch"
                             <?= $toggleChecked; ?>
                             data-wallet-id="<?= (int)$w['wallet_id']; ?>"
                             data-label="<?= h(($w['label'] ?: $w['coin'] ?: 'Wallet')); ?>">
                    </div>
                  </div>
                </div>
              <?php endforeach; ?>
            </div>
          <?php endif; ?>
        </div>

        <!-- Gift Cards -->
        <div class="tab-pane fade" id="tab-trades">
          <?php if (empty($tr)): ?>
            <div class="alert alert-light border mb-0">No recent gift card trades.</div>
          <?php else: ?>
            <div class="d-md-none">
              <?php foreach ($tr as $r):
                $created = $r['trade_created'] ? date('M j, Y g:i A', strtotime($r['trade_created'])) : '—';
                $val = mny($r['card_value'] ?? 0, 2).' '.h($r['card_curr'] ?? '');
                $payout = mny($r['est_payout_ngn'] ?? 0, 2);
              ?>
              <div class="gc-card mb-2">
                <div class="gc-kv"><div class="k">Batch</div><div class="v"><a href="../orders/process_order.php?batch=<?= urlencode($r['batch_ref']); ?>"><?= h($r['batch_ref']); ?></a></div></div>
                <div class="gc-kv"><div class="k">Card Ref</div><div class="v"><?= $r['card_ref'] ? '<a href="../orders/process_order.php?ref='.urlencode($r['card_ref']).'">'.h($r['card_ref']).'</a>' : '—'; ?></div></div>
                <div class="gc-kv"><div class="k">Brand</div><div class="v"><?= h($r['card_brand'] ?: '—'); ?></div></div>
                <div class="gc-kv"><div class="k">Denom</div><div class="v"><?= h($r['demon'] ?: '—'); ?></div></div>
                <div class="gc-kv"><div class="k">Value</div><div class="v"><?= $val; ?></div></div>
                <div class="gc-kv"><div class="k">Est. Payout (₦)</div><div class="v"><?= $payout; ?></div></div>
                <div class="gc-kv"><div class="k">Status</div><div class="v"><?= h($r['trade_status'] ?: '—'); ?></div></div>
                <div class="gc-kv"><div class="k">Created</div><div class="v small"><?= h($created); ?></div></div>
                <div class="mt-2"><a class="btn btn-sm btn-outline-primary w-100" href="../orders/process_order.php?ref=<?= urlencode($r['card_ref']); ?>">Open</a></div>
              </div>
              <?php endforeach; ?>
            </div>
            <div class="table-responsive d-none d-md-block">
              <table class="table table-sm">
                <thead class="small text-soft">
                  <tr><th>Batch</th><th>Card Ref</th><th>Brand</th><th>Denom</th><th>Value</th><th>Est. Payout (₦)</th><th>Status</th><th>Created</th><th></th></tr>
                </thead>
                <tbody>
                  <?php foreach ($tr as $r):
                    $created = $r['trade_created'] ? date('M j, Y g:i A', strtotime($r['trade_created'])) : '—';
                    $val = mny($r['card_value'] ?? 0, 2).' '.h($r['card_curr'] ?? '');
                    $payout = mny($r['est_payout_ngn'] ?? 0, 2);
                  ?>
                  <tr>
                    <td><a href="../orders/process_order.php?batch=<?= urlencode($r['batch_ref']); ?>"><?= h($r['batch_ref']); ?></a></td>
                    <td><?= $r['card_ref'] ? '<a href="../orders/process_order.php?ref='.urlencode($r['card_ref']).'">'.h($r['card_ref']).'</a>' : '—'; ?></td>
                    <td><?= h($r['card_brand'] ?: '—'); ?></td>
                    <td><?= h($r['demon'] ?: '—'); ?></td>
                    <td><?= $val; ?></td>
                    <td><?= $payout; ?></td>
                    <td><?= h($r['trade_status'] ?: '—'); ?></td>
                    <td class="small"><?= h($created); ?></td>
                    <td class="text-end"><a class="btn btn-xs btn-outline-primary" href="../orders/process_order.php?ref=<?= urlencode($r['card_ref']); ?>">Open</a></td>
                  </tr>
                  <?php endforeach; ?>
                </tbody>
              </table>
            </div>
          <?php endif; ?>
        </div>

        <!-- Transactions -->
        <div class="tab-pane fade" id="tab-trans">
          <?php if (empty($tx)): ?>
            <div class="alert alert-light border mb-0">No recent transactions.</div>
          <?php else: ?>
            <div class="d-md-none">
              <?php foreach ($tx as $t): ?>
                <div class="gc-card mb-2">
                  <div class="gc-kv"><div class="k">#</div><div class="v"><?= (int)$t['trans_id']; ?></div></div>
                  <div class="gc-kv"><div class="k">Coin</div><div class="v"><?= h($t['coin'] ?: '—'); ?></div></div>
                  <div class="gc-kv"><div class="k">Amount</div><div class="v"><?= mny($t['amount'] ?? 0, 8); ?></div></div>
                  <div class="gc-kv"><div class="k">Type</div><div class="v"><?= h($t['type'] ?: '—'); ?></div></div>
                  <div class="gc-kv"><div class="k">Status</div><div class="v"><?= h($t['status'] ?: '—'); ?></div></div>
                  <div class="gc-kv"><div class="k">Reference</div><div class="v small"><?= h($t['reference'] ?: ''); ?></div></div>
                  <div class="gc-kv"><div class="k">Created</div><div class="v small"><?= h($t['created_at'] ?: '—'); ?></div></div>
                </div>
              <?php endforeach; ?>
            </div>
            <div class="table-responsive d-none d-md-block">
              <table class="table table-sm">
                <thead class="small text-soft"><tr><th>#</th><th>Coin</th><th>Amount</th><th>Type</th><th>Status</th><th>Reference</th><th>Created</th></tr></thead>
                <tbody>
                  <?php foreach ($tx as $t): ?>
                    <tr>
                      <td><?= (int)$t['trans_id']; ?></td>
                      <td><?= h($t['coin'] ?: '—'); ?></td>
                      <td><?= mny($t['amount'] ?? 0, 8); ?></td>
                      <td><?= h($t['type'] ?: '—'); ?></td>
                      <td><?= h($t['status'] ?: '—'); ?></td>
                      <td class="small"><?= h($t['reference'] ?: ''); ?></td>
                      <td class="small"><?= h($t['created_at'] ?: '—'); ?></td>
                    </tr>
                  <?php endforeach; ?>
                </tbody>
              </table>
            </div>
          <?php endif; ?>
        </div>

        <!-- Security -->
        <div class="tab-pane fade" id="tab-security">
          <div class="row g-2">
            <div class="col-12 col-md-6">
              <div class="card card-bordered h-100">
                <div class="card-inner p-2">
                  <h6 class="mb-2">Two-Factor (TOTP)</h6>
                  <?php if (!empty($sec['totp'])): ?>
                    <div class="small text-soft">Enabled: <strong><?= (int)$sec['totp']['enabled'] ? 'Yes' : 'No'; ?></strong></div>
                    <div class="small">Verified: <strong><?= h($sec['totp']['verified_at'] ?: '—'); ?></strong></div>
                    <div class="small text-soft">Created: <?= h($sec['totp']['created_at'] ?: '—'); ?></div>
                  <?php else: ?>
                    <div class="small">No TOTP record.</div>
                  <?php endif; ?>
                </div>
              </div>
            </div>
            <div class="col-12 col-md-6">
              <div class="card card-bordered h-100">
                <div class="card-inner p-2">
                  <h6 class="mb-2">Recent OTPs</h6>
                  <?php if (empty($sec['otps'])): ?>
                    <div class="small">No recent OTP activity.</div>
                  <?php else: ?>
                    <div class="table-responsive">
                      <table class="table table-sm">
                        <thead class="small text-soft"><tr><th>Channel</th><th>Created</th><th>Expires</th><th>Used</th><th>Attempts</th></tr></thead>
                        <tbody>
                          <?php foreach ($sec['otps'] as $o): ?>
                            <tr>
                              <td><?= h($o['channel']); ?></td>
                              <td class="small"><?= h($o['created_at']); ?></td>
                              <td class="small"><?= h($o['expires_at']); ?></td>
                              <td class="small"><?= h($o['consumed_at'] ?: '—'); ?></td>
                              <td class="small"><?= (int)$o['attempts']; ?></td>
                            </tr>
                          <?php endforeach; ?>
                        </tbody>
                      </table>
                    </div>
                  <?php endif; ?>
                </div>
              </div>
            </div>

            <div class="col-12">
              <div class="card card-bordered">
                <div class="card-inner p-2">
                  <h6 class="mb-2">Sessions</h6>
                  <?php if (empty($ss)): ?>
                    <div class="small">No sessions.</div>
                  <?php else: ?>
                    <div class="table-responsive">
                      <table class="table table-sm">
                        <thead class="small text-soft"><tr><th>IP</th><th>Agent</th><th>Device</th><th>Created</th><th>Last Seen</th><th>Expires</th><th>Revoked</th></tr></thead>
                        <tbody>
                          <?php foreach ($ss as $s): ?>
                          <tr>
                            <td class="small"><?= h($s['ip_address']); ?></td>
                            <td class="small text-break"><?= h($s['user_agent']); ?></td>
                            <td class="small"><?= h($s['device_label'] ?: '—'); ?></td>
                            <td class="small"><?= h($s['created_at'] ?: '—'); ?></td>
                            <td class="small"><?= h($s['last_seen_at'] ?: '—'); ?></td>
                            <td class="small"><?= h($s['expires_at'] ?: '—'); ?></td>
                            <td class="small"><?= h($s['revoked_at'] ?: '—'); ?></td>
                          </tr>
                          <?php endforeach; ?>
                        </tbody>
                      </table>
                    </div>
                  <?php endif; ?>
                </div>
              </div>
            </div>

            <div class="col-12">
              <div class="card card-bordered">
                <div class="card-inner p-2">
                  <h6 class="mb-2">Devices</h6>
                  <?php if (empty($dv)): ?>
                    <div class="small">No devices.</div>
                  <?php else: ?>
                    <div class="table-responsive">
                      <table class="table table-sm">
                        <thead class="small text-soft"><tr><th>Label</th><th>Device ID</th><th>Trusted</th><th>First Seen</th><th>Last Seen</th><th>IP (first/last)</th></tr></thead>
                        <tbody>
                          <?php foreach ($dv as $d): ?>
                          <tr>
                            <td class="small"><?= h($d['device_label'] ?: '—'); ?></td>
                            <td class="small"><?= h($d['device_id']); ?></td>
                            <td class="small"><?= (int)$d['trusted'] ? 'Yes' : 'No'; ?><?= $d['trusted_until'] ? ' (until '.h($d['trusted_until']).')' : ''; ?></td>
                            <td class="small"><?= h($d['first_seen_at'] ?: '—'); ?></td>
                            <td class="small"><?= h($d['last_seen_at'] ?: '—'); ?></td>
                            <td class="small"><?= h(($d['first_ip'] ?: '—').' / '.($d['last_ip'] ?: '—')); ?></td>
                          </tr>
                          <?php endforeach; ?>
                        </tbody>
                      </table>
                    </div>
                  <?php endif; ?>
                </div>
              </div>
            </div>

          </div>
        </div><!-- /Security -->
      </div><!-- /.tab-content -->
    </div>
  </div>
</div>

<!-- Confirm Activate/Suspend Modal -->
<div class="modal fade" id="confirmUserStatusModal" tabindex="-1">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header"><h6 class="modal-title">Confirm Action</h6>
        <button type="button" class="btn-close" data-bs-dismiss="modal"></button></div>
      <div class="modal-body" id="confirmUserStatusBody">Are you sure?</div>
      <div class="modal-footer">
        <button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
        <button type="button" class="btn btn-danger" id="confirmUserStatusBtn">Yes, Proceed</button>
      </div>
    </div>
  </div>
</div>

<script>
let __pendingUserId = null, __pendingUserStatus = '', __pendingUserName = '';

function openStatusConfirm(uid, currentStatus, fullname){
  __pendingUserId = uid;
  __pendingUserStatus = currentStatus;
  __pendingUserName = fullname || 'this user';
  const action = (String(currentStatus).toLowerCase()==='active') ? 'suspend' : 'activate';
  document.getElementById('confirmUserStatusBody').innerText =
    `Are you sure you want to ${action} ${__pendingUserName}?`;
  new bootstrap.Modal(document.getElementById('confirmUserStatusModal')).show();
}

document.getElementById('confirmUserStatusBtn').addEventListener('click', function(){
  const form = new URLSearchParams();
  form.append('user_id', __pendingUserId);
  form.append('status', __pendingUserStatus);
  fetch('../../models/users/update_user.php', {
    method: 'POST', headers: {'Content-Type':'application/x-www-form-urlencoded'}, body: form.toString()
  }).then(r => r.json()).then(j => { if (j.success){ location.reload(); } else { alert(j.message||'Action failed.'); } })
    .catch(()=>alert('Network error'));
});
</script>

<!-- Wallet Freeze Toggle JS -->
<script>
(function(){
  const busy = new Set();

  async function postToggle(walletId, freeze){
    const form = new URLSearchParams();
    form.append('action', 'toggle_freeze');
    form.append('wallet_id', walletId);
    form.append('freeze', freeze);

    const resp = await fetch('../../models/users/toggle_wallet.php', {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: form.toString()
    });

    const text = await resp.text(); // be tolerant to non-JSON
    let data;
    try { data = JSON.parse(text); }
    catch(e){
      throw new Error('Bad JSON from server: ' + text.substring(0, 200));
    }
    if (!resp.ok || !data || data.success !== true) {
      const msg = (data && data.message) ? data.message : ('HTTP ' + resp.status);
      throw new Error(msg + (data && data._diag ? ' | ' + data._diag : ''));
    }
    return data;
  }

  document.addEventListener('change', async function(e){
    const el = e.target.closest('.wallet-freeze-toggle');
    if (!el) return;

    const walletId = el.getAttribute('data-wallet-id');
    if (!walletId || busy.has(walletId)) return;

    const freeze = el.checked ? '1' : '0'; // checked = Freeze ON

    busy.add(walletId);
    el.disabled = true;

    try {
      await postToggle(walletId, freeze);
      // Reload to keep badges/status consistent
      location.reload();
    } catch (err) {
      // revert UI if failed
      el.checked = !el.checked;
      alert('Request failed: ' + (err && err.message ? err.message : err));
    } finally {
      busy.delete(walletId);
      el.disabled = false;
    }
  });
})();
</script>


<script>
(function () {
  // On load: if there is a hash (#tab-wallets etc), show that tab
  document.addEventListener('DOMContentLoaded', function () {
    var hash = window.location.hash;
    if (hash && document.querySelector('[data-bs-target="' + hash + '"]')) {
      var triggerEl = document.querySelector('[data-bs-target="' + hash + '"]');
      bootstrap.Tab.getOrCreateInstance(triggerEl).show();
    }

    // Keep URL hash in sync when the user switches tabs
    document.querySelectorAll('[data-bs-toggle="tab"]').forEach(function (el) {
      el.addEventListener('shown.bs.tab', function (e) {
        var target = e.target.getAttribute('data-bs-target');
        if (target) history.replaceState(null, '', target);
      });
    });
  });
})();
</script>


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

Выполнить команду


Для локальной разработки. Не используйте в интернете!