Files
reflector-dashboard/auth/header.php
T

106 lines
7.0 KiB
PHP

<?php
/*
* Reflector Dashboard — web front-end for SvxReflector
* Copyright (C) 2026 SA7AUX (Björn)
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version. See the LICENSE file for details.
*/
// Shared header — include on all pages
if (!function_exists('cfg')) require __DIR__ . '/lib.php';
if (session_status() !== PHP_SESSION_ACTIVE) start_session();
// Never let browsers cache these pages: without this they guess freshness
// themselves and keep showing days-old UI after every deploy.
header('Cache-Control: no-store');
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title><?= $page_title ?? 'Reflector Dashboard' ?></title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
:root{ color-scheme:dark; --bg:#000; --fg:#00ffff; --fg2:rgba(0,255,255,.75); --line:rgba(0,255,255,.35); }
html, body{ height:100%; background:var(--bg); color:var(--fg); margin:0; }
body{ display:flex; flex-direction:column; min-height:100vh; }
*{ color:var(--fg); }
*::selection{ background: rgba(0,255,255,.2); }
.navbar{ background: var(--bg) !important; position:sticky; top:0; z-index:1030; }
a, .nav-link{ color:var(--fg) !important; text-decoration:none; }
.text-muted, .text-secondary{ color: var(--fg2) !important; }
.btn.btn-outline-secondary{ background: var(--bg) !important; color: var(--fg) !important; border-color: rgba(0,255,255,.7) !important; }
.btn.btn-outline-secondary:hover{ background: rgba(0,255,255,.1) !important; }
.btn.btn-primary{ background: rgba(0,255,255,.15) !important; color: var(--fg) !important; border-color: rgba(0,255,255,.7) !important; }
.btn.btn-primary:hover{ background: rgba(0,255,255,.25) !important; }
.btn.btn-danger{ background: rgba(255,80,80,.2) !important; color: #ff8080 !important; border-color: rgba(255,80,80,.6) !important; }
.btn.btn-warning{ background: rgba(255,200,0,.15) !important; color: #ffc800 !important; border-color: rgba(255,200,0,.5) !important; }
.btn.btn-success{ background: rgba(0,200,100,.15) !important; color: #00c864 !important; border-color: rgba(0,200,100,.5) !important; }
.btn.btn-outline-danger{ background: transparent !important; color: #ff8080 !important; border-color: rgba(255,80,80,.6) !important; }
.form-control, .form-select{ background: var(--bg) !important; color: var(--fg) !important; border-color: rgba(0,255,255,.5) !important; }
.form-control:focus, .form-select:focus{ box-shadow: 0 0 0 .2rem rgba(0,255,255,.25) !important; }
.form-label{ color: var(--fg2) !important; }
.panel{ border:1px solid var(--line); border-radius:10px; padding:16px; margin-bottom:16px; }
.mono{ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; }
.border, .border-bottom{ border-color: var(--line) !important; }
main.content{ flex:1; }
footer{ flex-shrink:0; position:sticky; bottom:0; background:var(--bg); }
table.data-table{ width:100%; min-width:500px; border-collapse:collapse; font-size:.85rem; }
table.data-table th, table.data-table td{ padding:6px 10px; border-bottom:1px solid var(--line); }
table.data-table th{ color: var(--fg2); font-weight:600; text-align:left; }
.profile-tabs{ display:flex; gap:4px; flex-wrap:wrap; border-bottom:1px solid var(--line); padding-bottom:8px; margin-bottom:16px; }
.profile-tab{ display:flex; align-items:center; gap:6px; padding:8px 14px; background:transparent; border:1px solid transparent; border-radius:6px 6px 0 0; color:var(--fg2); cursor:pointer; font-size:.85rem; transition:background .15s, color .15s; white-space:nowrap; }
.profile-tab:hover{ background:rgba(0,255,255,.08); color:var(--fg); }
.profile-tab.active{ background:rgba(0,255,255,.12); border-color:var(--line); border-bottom-color:var(--bg); color:var(--fg); }
.node-card{ border:1px solid var(--line); border-radius:8px; padding:12px; margin-bottom:12px; }
.node-badge{ display:inline-block; background:rgba(0,255,255,.1); border:1px solid var(--line); border-radius:4px; padding:2px 8px; font-size:.75rem; margin:2px; }
.node-grid{ display:grid; grid-template-columns:auto 1fr; gap:2px 12px; font-size:.85rem; }
.node-grid dt{ color:var(--fg2); font-weight:normal; }
.node-grid dd{ margin:0; }
#adminMenuItem{ position: relative; }
#adminSubMenu .dropdown-item{ padding: 6px 16px; white-space: nowrap; }
/* Dark dropdown menus (fixes white Bootstrap default on callsign/admin menu) */
.dropdown-menu{ background:#111 !important; border-color:var(--line) !important; }
.dropdown-item{ color:var(--fg) !important; }
.dropdown-item:hover, .dropdown-item:focus{ background:rgba(0,255,255,.1) !important; color:var(--fg) !important; }
.dropdown-divider{ border-color:var(--line) !important; }
#adminSubMenu{ position:absolute; right:100%; left:auto; top:0; min-width:170px; background:#111; border:1px solid var(--line); border-radius:6px; padding:4px 0; list-style:none; margin:0; z-index:1050; }
@media (max-width:576px){ .profile-tab span{ display:none; } .profile-tab{ padding:8px 10px; } }
@media (max-width: 768px) {
.container, .container-fluid { padding-left: 10px; padding-right: 10px; }
table.data-table { font-size: .75rem; }
table.data-table th, table.data-table td { padding: 4px 6px; }
.node-grid { grid-template-columns: 1fr; gap: 1px 0; }
.node-grid dt { margin-top: 6px; }
.panel { padding: 12px; }
.btn-sm { font-size: .75rem; padding: 3px 8px; }
.mono { font-size: .8rem; word-break: break-all; }
}
@media (max-width: 480px) {
table.data-table th:nth-child(3), table.data-table td:nth-child(3),
table.data-table th:nth-child(5), table.data-table td:nth-child(5),
table.data-table th:nth-child(6), table.data-table td:nth-child(6) { display: none; }
}
<?= $extra_css ?? '' ?>
</style>
</head>
<body>
<nav class="navbar navbar-expand border-bottom">
<div class="container-fluid">
<ul class="navbar-nav me-auto">
<li class="nav-item"><a class="nav-link" href="/#clients">Reflector clients</a></li>
<li class="nav-item"><a class="nav-link" href="/#monitor">Monitor</a></li>
<li class="nav-item"><a class="nav-link" href="/#lastheard">Lastheard</a></li>
<li class="nav-item"><a class="nav-link" href="/#ctcss">CTCSS Table</a></li>
<li class="nav-item"><a class="nav-link" href="/#map">Map</a></li>
<li class="nav-item"><a class="nav-link" href="/help.html">Help</a></li>
</ul>
<button class="btn btn-outline-secondary btn-sm me-2" id="btnRegister" type="button">Register</button>
<button class="btn btn-outline-secondary btn-sm" id="btnSignIn" type="button">Sign in</button>
</div>
</nav>
<main class="content">