<?php
require_once __DIR__ . '/aclhelper.php';
function menu_tree(): array { global $con; $user = current_user(); $roleId = (int)($user['role_id'] ?? 0); $allowed = []; $stmt = $con->prepare('SELECT DISTINCT menu_id FROM jos_admin_rolemenus WHERE can_view=1 AND status=1 AND role_id=?'); $stmt->bind_param('i', $roleId); $stmt->execute(); $res = $stmt->get_result(); while ($r = $res->fetch_assoc()) $allowed[] = (int)$r['menu_id']; $stmt->close(); if (!$allowed) return []; $ids = implode(',', array_map('intval', $allowed)); $rs = $con->query("SELECT id, menu_name, menu_link, icon, parent_id FROM jos_admin_menus WHERE status=1 AND show_in_menu=1 AND id IN ($ids) ORDER BY parent_id ASC, orderby ASC, menu_name ASC"); $rows=[]; while($row=$rs->fetch_assoc()) $rows[]=$row; $tree=[]; $children=[]; foreach($rows as $r){ if ((int)$r['parent_id']===0) $tree[$r['id']]=$r+['children'=>[]]; else $children[(int)$r['parent_id']][]=$r; } foreach($children as $pid=>$kids){ if(isset($tree[$pid])) $tree[$pid]['children']=$kids; } return array_values($tree); }
function render_menu(array $menus, string $active): void { foreach ($menus as $m) { $hasKids = !empty($m['children']); $open = $hasKids && array_reduce($m['children'], fn($c,$x)=>$c || $x['menu_link']===$active, false); $link = $hasKids ? '#' : '/' . ltrim($m['menu_link'], '/'); echo '<div class="nav-group'.($open?' open':'').'">'; echo '<a class="nav-item'.(!$hasKids && $m['menu_link']===$active?' active':'').'" href="'.h($link).'">'; echo '<i class="'.h($m['icon'] ?: 'fa-regular fa-circle').' nav-icon"></i><span>'.h($m['menu_name']).'</span>'; if ($hasKids) echo '<i class="fa-solid fa-chevron-down nav-caret"></i>'; echo '</a>'; if ($hasKids) { echo '<div class="nav-children">'; foreach($m['children'] as $c){ echo '<a class="nav-child'.($c['menu_link']===$active?' active':'').'" href="/'.h(ltrim($c['menu_link'],'/')).'">'.h($c['menu_name']).'</a>'; } echo '</div>'; } echo '</div>'; } }
function render_shell(string $title, string $content, array $acl = []): void { $user = current_user(); $active = normalize_link(); $menus = menu_tree(); ?><!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title><?= h($title) ?> - Attendance Box</title><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet"><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"><link rel="stylesheet" href="/assets/css/console.css"></head><body class="console-body"><aside class="sidebar"><div class="brand"><div class="brand-mark"><i class="fa-solid fa-cube"></i></div><div><strong>Attendance Box</strong><span>Secure Console</span></div></div><nav class="nav"><?php render_menu($menus, $active); ?></nav></aside><main class="main"><header class="topbar"><div><span class="eyebrow">Workspace</span><h1><?= h($title) ?></h1></div><div class="top-actions"><span class="india"><span>🇮🇳</span> Made in India</span><div class="user-chip"><i class="fa-solid fa-user-shield"></i><span><?= h($user['name'] ?? 'Admin') ?></span></div><a class="icon-btn" href="/logout.php" title="Logout"><i class="fa-solid fa-arrow-right-from-bracket"></i></a></div></header><section class="content"><?= $content ?></section></main><script>document.querySelectorAll('.nav-group > .nav-item[href="#"]').forEach(a=>a.addEventListener('click',e=>{e.preventDefault();a.parentElement.classList.toggle('open')}));</script></body></html><?php }