| Server IP : 188.114.96.3 / Your IP : 216.73.216.143 Web Server : Apache System : Linux sv058.home.net.pl 6.8.2 husak_dirty_pages_fix #1 SMP PREEMPT_DYNAMIC Tue Apr 2 22:06:51 CEST 2024 x86_64 User : ( 3194769) PHP Version : 8.5.12 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /polana/admin/ |
Upload File : |
<?php
declare(strict_types=1);
/** POLANA V18.14 — catalogue of existing features, no changes to data. */
require_once dirname(__DIR__).'/includes/functions.php';
require_login();
if ((string)(admin_user()['role'] ?? '') !== 'admin') { http_response_code(403); exit('Tylko administrator.'); }
header('Cache-Control: private, no-store');
header('X-Robots-Tag: noindex,nofollow');
function pv1814h(string $s): string { return htmlspecialchars($s, ENT_QUOTES|ENT_SUBSTITUTE, 'UTF-8'); }
$groups = [
'Rezerwacje i komunikacja' => [
['Rezerwacje','/admin/reservations.php'],['Plan sali i raport','/admin/reservations-day.php'],
['Godziny przyjęć','/admin/polana-godziny-rezerwacji.php'],['Ustawienia rezerwacji','/admin/reservation-settings.php'],
['Google Kalendarz','/admin/polana-kalendarz.php'],['Poczta i komunikacja','/admin/polana-komunikacja.php'],
['SMTP i wiadomości','/admin/polana-poczta.php'],['Newsletter','/admin/polana-newsletter.php'],
['Newsletter — Excel','/admin/polana-newsletter-excel.php'],['ntfy','/admin/polana-v186-ntfy.php'],
['Diagnostyka maili','/admin/polana-v1812-naprawa-maili.php']
],
'Menu restauracji i języki' => [
['Centrum menu','/admin/polana-menu-centrum.php'],['Karty menu','/admin/menus.php'],
['Edytor pozycji','/admin/menu.php'],['Kolejność pozycji','/admin/menu-order.php'],
['Eksport menu','/admin/menu-export.php'],['Menu Word','/admin/tklm-menu-word.php'],
['Centrum Menu PL/EN','/admin/tklm-menu.php'],['Tłumaczenie menu','/admin/translate-menu.php'],
['Import PL/EN','/admin/import-en.php'],['Tłumaczenia PL/EN/DE/ES','/admin/polana-v16-tlumaczenia.php'],
['Słownik menu','/admin/polana-v14-slownik.php'],['Podgląd menu','/admin/tklm-menu-preview.php'],
['Menu — sprawdzenie','/admin/polana-v15-menu-review.php'],['QR','/admin/qr.php']
],
'SEO i treści' => [
['Centrum SEO','/admin/polana-seo-centrum.php'],['Google / sitemap','/admin/polana-v164-seo.php'],
['IndexNow','/admin/polana-indexnow.php'],['Analityka / GTM / Clarity','/admin/polana-analityka.php'],
['Wizytówka Google','/admin/google-business.php'],['Opinie','/admin/opinie.php'],
['Centrum treści','/admin/polana-centrum-tresci.php'],['Blog','/admin/blog.php'],
['Galeria','/admin/media.php'],['Tłumaczenia stron','/admin/translate-site.php'],
['Tłumaczenia bloga','/admin/translate-blog.php'],['Social media','/admin/socials.php'],
['SEO / zaślepka','/admin/seo.php']
],
'Operacje i system' => [
['Dzisiaj','/admin/today.php'],['Grafik','/admin/schedule.php'],
['Zmiany','/admin/shifts.php'],['Napiwki','/admin/tips.php'],
['Terminal napiwków','/admin/tips-kiosk.php'],['Raport managera','/admin/manager-report.php'],
['Centrum zarządzania','/admin/polana-zarzadzanie.php'],['Ustawienia','/admin/settings.php'],
['Użytkownicy','/admin/users.php'],['Ręczny backup SQL','/admin/database-backup.php'],
['Automatyczne kopie','/admin/polana-backup-automat.php'],
['Pełne kopie V18.11','/admin/polana-v1811-backup-kontrola.php'],
['Audyt V18.4','/admin/polana-v184-audyt-calosc.php']
],
];
$root=realpath(dirname(__DIR__)) ?: dirname(__DIR__);
$missing=0;
$existing=0;
foreach ($groups as $group) foreach ($group as $entry) {
$candidate=$root.$entry[1];
if (is_file($candidate)) $existing++; else $missing++;
}
$calendar = [];
try {
$stmt=db()->query("SELECT COUNT(*) total,
SUM(CASE WHEN r.status='confirmed' AND (e.reservation_id IS NULL OR e.sync_status <> 'synced') THEN 1 ELSE 0 END) waiting,
SUM(CASE WHEN e.sync_status='error' THEN 1 ELSE 0 END) errors
FROM reservations r LEFT JOIN polana_calendar_events e ON e.reservation_id=r.id
WHERE r.reservation_date >= CURDATE()");
$calendar=$stmt->fetch(PDO::FETCH_ASSOC) ?: [];
} catch (Throwable $ignored) { $calendar=[]; }
$menuStats=[];
try {
$menuStats['karty']=(int)db()->query('SELECT COUNT(*) FROM menus')->fetchColumn();
$menuStats['pozycje']=(int)db()->query('SELECT COUNT(*) FROM menu_items')->fetchColumn();
$menuStats['niedostepne']=(int)db()->query('SELECT COUNT(*) FROM menu_items WHERE active=0 OR available=0')->fetchColumn();
} catch (Throwable $ignored) { $menuStats=[]; }
render_admin_header('POLANA — wszystkie moduły');
?>
<style>
.pv1814{max-width:1320px;margin:0 auto;padding:20px 14px 60px}.pv1814 .intro{color:var(--muted,#555)}
.pv1814 .stats{display:flex;gap:10px;flex-wrap:wrap;margin:15px 0}.pv1814 .statx{border:1px solid #ddd;border-radius:13px;padding:12px 16px;min-width:155px;background:var(--card-bg,#fff)}
.pv1814 .group{border:1px solid #ddd;border-radius:17px;padding:16px;margin:16px 0;background:var(--card-bg,#fff)}
.pv1814 .links{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:9px}
.pv1814 .links a,.pv1814 .unavailable{display:block;border:1px solid #d3dacd;border-radius:11px;padding:11px 12px;text-decoration:none;color:inherit;background:transparent}
.pv1814 .unavailable{opacity:.65;border-style:dashed}.pv1814 .note{font-size:.85em;color:#666}.pv1814 [hidden]{display:none!important}
.pv1814 input{max-width:550px;width:100%;padding:12px;border:1px solid #bbb;border-radius:9px;font-size:16px}
@media(max-width:550px){.pv1814 .links{grid-template-columns:1fr}.pv1814{padding:12px 10px}}
</style>
<div class="pv1814">
<h1>Wszystkie moduły POLANA</h1>
<p class="intro">Jedno miejsce z istniejącymi funkcjami. Brak pliku jest oznaczony, nie jest ukrywany. To nie instalator i niczego nie usuwa.</p>
<div class="stats"><div class="statx"><b><?= $existing ?></b><div>Wykryte wejścia</div></div><div class="statx"><b><?= $missing ?></b><div>Brakujące pliki</div></div>
<?php if ($calendar): ?><div class="statx"><b><?= (int)$calendar['waiting'] ?></b><div>Potwierdzone bez synchronizacji*</div></div><div class="statx"><b><?= (int)$calendar['errors'] ?></b><div>Błędy kalendarza*</div></div><?php endif; ?>
<?php if ($menuStats): ?><div class="statx"><b><?= $menuStats['pozycje'] ?></b><div>Pozycje w bazie menu</div></div><div class="statx"><b><?= $menuStats['niedostepne'] ?></b><div>Ukryte / niedostępne pozycje</div></div><?php endif; ?></div>
<p class="note">* Dla przyszłych rezerwacji. Przegląd nie wykonuje synchronizacji. Status pliku „istnieje” nie dowodzi, że działa poprawnie.</p>
<label for="pv1814-search">Szukaj funkcji:</label><p><input id="pv1814-search" type="search" placeholder="np. kalendarz, języki, QR, e-mail" autocomplete="off"></p>
<?php foreach ($groups as $title=>$entries): ?>
<section class="group" data-group><h2><?=pv1814h($title)?></h2><div class="links">
<?php foreach($entries as [$label,$url]):$present=is_file($root.$url); ?>
<?php if($present):?><a data-entry href="<?=pv1814h($url)?>"><?=pv1814h($label)?></a>
<?php else:?><div data-entry class="unavailable"><?=pv1814h($label)?> <span class="note">— brak pliku</span></div><?php endif;?>
<?php endforeach;?></div></section>
<?php endforeach; ?>
</div>
<script>(()=>{const q=document.getElementById('pv1814-search');if(!q)return;q.addEventListener('input',()=>{const s=q.value.trim().toLocaleLowerCase('pl-PL');for(const sec of document.querySelectorAll('[data-group]')){let n=0;for(const e of sec.querySelectorAll('[data-entry]')){const ok=e.textContent.toLocaleLowerCase('pl-PL').includes(s);e.hidden=!ok;if(ok)n++;}sec.hidden=n===0;}});})();</script>
<?php render_admin_footer(); ?>