2026-03-26 14:30:45 +09:00
|
|
|
<?php
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
helper('admin');
|
|
|
|
|
$siteNavTree = get_site_nav_tree();
|
2026-04-08 00:18:01 +09:00
|
|
|
$currentPath = current_nav_request_path();
|
2026-03-26 14:30:45 +09:00
|
|
|
$mbLevel = (int) session()->get('mb_level');
|
|
|
|
|
$isAdmin = ($mbLevel === \Config\Roles::LEVEL_SUPER_ADMIN || $mbLevel === \Config\Roles::LEVEL_LOCAL_ADMIN);
|
2026-04-08 00:18:01 +09:00
|
|
|
$dashboardPathAliases = ['dashboard', 'dashboard/blend'];
|
2026-03-26 14:30:45 +09:00
|
|
|
$effectiveLgIdx = admin_effective_lg_idx();
|
|
|
|
|
$effectiveLgName = null;
|
|
|
|
|
if ($effectiveLgIdx) {
|
|
|
|
|
$lgRow = model(\App\Models\LocalGovernmentModel::class)->find($effectiveLgIdx);
|
|
|
|
|
$effectiveLgName = $lgRow ? $lgRow->lg_name : null;
|
|
|
|
|
}
|
2026-04-08 00:18:01 +09:00
|
|
|
$userNav = session_user_nav_display();
|
2026-04-14 00:33:24 +09:00
|
|
|
|
2026-04-14 00:41:14 +09:00
|
|
|
$resolveNavNodeMatchLen = static function (object $node) use ($currentPath, $dashboardPathAliases): int {
|
|
|
|
|
$maxLen = -1;
|
|
|
|
|
foreach (menu_link_candidate_paths($node->mm_link ?? null, $currentPath) as $cand) {
|
|
|
|
|
if (menu_single_path_matches_request($cand, $currentPath, $dashboardPathAliases)) {
|
|
|
|
|
$maxLen = max($maxLen, strlen($cand));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return $maxLen;
|
|
|
|
|
};
|
|
|
|
|
|
2026-04-14 00:33:24 +09:00
|
|
|
$activeTopNav = null;
|
|
|
|
|
$activeTopLen = -1;
|
|
|
|
|
$activeTopNum = PHP_INT_MAX;
|
|
|
|
|
foreach ($siteNavTree as $topNode) {
|
2026-04-14 00:41:14 +09:00
|
|
|
$nodeLen = $resolveNavNodeMatchLen($topNode);
|
2026-04-14 00:33:24 +09:00
|
|
|
if ($nodeLen > $activeTopLen || ($nodeLen === $activeTopLen && (int) ($topNode->mm_num ?? 0) < $activeTopNum)) {
|
|
|
|
|
$activeTop = $topNode;
|
|
|
|
|
$activeTopLen = $nodeLen;
|
|
|
|
|
$activeTopNum = (int) ($topNode->mm_num ?? 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-03-26 14:30:45 +09:00
|
|
|
?>
|
|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
<html lang="ko">
|
|
|
|
|
<head>
|
|
|
|
|
<meta charset="utf-8"/>
|
|
|
|
|
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
|
2026-04-08 00:18:01 +09:00
|
|
|
<title><?= esc($title ?? '종량제 시스템') ?></title>
|
2026-03-26 14:30:45 +09:00
|
|
|
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
|
|
|
|
|
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap" rel="stylesheet"/>
|
|
|
|
|
<script>
|
|
|
|
|
tailwind.config = {
|
|
|
|
|
theme: {
|
|
|
|
|
extend: {
|
|
|
|
|
fontFamily: { sans: ['"Malgun Gothic"', '"Noto Sans KR"', 'sans-serif'] },
|
|
|
|
|
colors: {
|
|
|
|
|
'system-header': '#ffffff',
|
|
|
|
|
'title-bar': '#2c3e50',
|
|
|
|
|
'control-panel': '#f8f9fa',
|
|
|
|
|
'btn-search': '#1c4e80',
|
|
|
|
|
'btn-excel-border': '#28a745',
|
|
|
|
|
'btn-excel-text': '#28a745',
|
|
|
|
|
'btn-print-border': '#ced4da',
|
|
|
|
|
'btn-exit': '#d9534f',
|
|
|
|
|
},
|
|
|
|
|
fontSize: { 'xxs': '0.65rem' }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
<style data-purpose="table-layout">
|
|
|
|
|
.data-table { width: 100%; border-collapse: collapse; font-family: 'Malgun Gothic', 'Noto Sans KR', sans-serif; }
|
|
|
|
|
.data-table th, .data-table td { border: 1px solid #ccc; padding: 4px 8px; white-space: nowrap; font-size: 13px; }
|
|
|
|
|
.data-table th { background-color: #e9ecef; text-align: center; vertical-align: middle; font-weight: bold; color: #333; }
|
|
|
|
|
.data-table tbody tr:nth-child(even) td { background-color: #f9f9f9; }
|
|
|
|
|
.data-table tbody tr:hover td { background-color: #e6f7ff !important; }
|
|
|
|
|
.main-content-area { height: calc(100vh - 130px); overflow: auto; }
|
|
|
|
|
body { overflow: hidden; }
|
2026-03-26 16:40:49 +09:00
|
|
|
@media print {
|
|
|
|
|
header, footer, .no-print, nav { display: none !important; }
|
|
|
|
|
.main-content-area { height: auto !important; overflow: visible !important; }
|
|
|
|
|
body { overflow: visible !important; }
|
|
|
|
|
.bg-title-bar { display: none !important; }
|
|
|
|
|
.bg-control-panel { break-inside: avoid; }
|
|
|
|
|
.print-header { display: block !important; }
|
|
|
|
|
}
|
2026-03-26 14:30:45 +09:00
|
|
|
</style>
|
|
|
|
|
</head>
|
|
|
|
|
<body class="bg-gray-100 text-gray-800 flex flex-col h-screen font-sans antialiased select-none">
|
|
|
|
|
<!-- BEGIN: Top Navigation -->
|
2026-04-08 00:18:01 +09:00
|
|
|
<header class="relative bg-white border-b border-gray-300 h-12 flex items-center justify-between px-4 shrink-0 z-[100]">
|
2026-03-26 14:30:45 +09:00
|
|
|
<div class="flex items-center gap-4">
|
2026-04-08 00:18:01 +09:00
|
|
|
<?= view('components/header_brand') ?>
|
2026-03-26 14:30:45 +09:00
|
|
|
</div>
|
|
|
|
|
<nav class="hidden md:flex gap-5 text-sm font-medium text-gray-600">
|
|
|
|
|
<?php if (! empty($siteNavTree)): ?>
|
|
|
|
|
<?php foreach ($siteNavTree as $navItem): ?>
|
2026-03-30 15:07:09 +09:00
|
|
|
<?php
|
2026-04-08 00:18:01 +09:00
|
|
|
$navLink = menu_link_preferred_href_path($navItem->mm_link ?? null, $currentPath);
|
2026-04-14 00:33:24 +09:00
|
|
|
$isActive = ($activeTop !== null && $navItem === $activeTop);
|
2026-03-30 15:07:09 +09:00
|
|
|
?>
|
2026-03-26 14:30:45 +09:00
|
|
|
<div class="relative group">
|
|
|
|
|
<a class="<?= $isActive ? 'text-blue-700 font-bold border-b-2 border-blue-700 pb-3 -mb-3' : 'hover:text-blue-600' ?>"
|
2026-04-08 00:18:01 +09:00
|
|
|
href="<?= $navLink !== '' ? base_url($navLink) : '#' ?>">
|
2026-03-26 14:30:45 +09:00
|
|
|
<?= esc($navItem->mm_name) ?>
|
|
|
|
|
</a>
|
|
|
|
|
<?php if (! empty($navItem->children)): ?>
|
2026-04-08 00:18:01 +09:00
|
|
|
<?php /* -mt-1 + pt-2: 부모 링크와 패널이 살짝 겹쳐 호버가 끊기지 않게 함. z-index: 드롭다운 클릭 우선 */ ?>
|
|
|
|
|
<div class="absolute left-0 top-full z-[200] -mt-1 pt-2 min-w-[12rem] hidden group-hover:block group-focus-within:block">
|
2026-03-30 15:07:09 +09:00
|
|
|
<div class="bg-white border border-gray-200 rounded shadow-lg py-1">
|
2026-04-14 00:33:24 +09:00
|
|
|
<?php
|
|
|
|
|
$activeChild = site_nav_active_child_for_parent($navItem, $currentPath, $dashboardPathAliases);
|
|
|
|
|
?>
|
2026-03-26 14:30:45 +09:00
|
|
|
<?php foreach ($navItem->children as $child): ?>
|
2026-03-30 15:07:09 +09:00
|
|
|
<?php
|
2026-04-08 00:18:01 +09:00
|
|
|
$childLink = menu_link_preferred_href_path($child->mm_link ?? null, $currentPath);
|
2026-04-14 00:33:24 +09:00
|
|
|
$childCurrent = $activeChild !== null && $child === $activeChild;
|
2026-03-30 15:07:09 +09:00
|
|
|
?>
|
|
|
|
|
<?php if ($childLink !== ''): ?>
|
|
|
|
|
<a href="<?= base_url($childLink) ?>"
|
2026-04-08 00:18:01 +09:00
|
|
|
class="block px-3 py-1.5 text-sm hover:bg-blue-50 whitespace-nowrap <?= $childCurrent ? 'text-blue-700 font-semibold bg-blue-50' : 'text-gray-700' ?>">
|
2026-03-26 14:30:45 +09:00
|
|
|
<?= esc($child->mm_name) ?>
|
|
|
|
|
</a>
|
2026-03-30 15:07:09 +09:00
|
|
|
<?php else: ?>
|
|
|
|
|
<span class="block px-3 py-1.5 text-sm text-gray-400 cursor-default whitespace-nowrap" title="관리자 메뉴 관리에서 링크를 설정해 주세요">
|
|
|
|
|
<?= esc($child->mm_name) ?>
|
|
|
|
|
</span>
|
|
|
|
|
<?php endif; ?>
|
2026-03-26 14:30:45 +09:00
|
|
|
<?php endforeach; ?>
|
2026-03-30 15:07:09 +09:00
|
|
|
</div>
|
2026-03-26 14:30:45 +09:00
|
|
|
</div>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
</div>
|
|
|
|
|
<?php endforeach; ?>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
</nav>
|
2026-04-08 00:18:01 +09:00
|
|
|
<?= view('components/header_user_tools', [
|
|
|
|
|
'userNav' => $userNav,
|
|
|
|
|
'effectiveLgName' => $effectiveLgName,
|
|
|
|
|
'showSiteLink' => false,
|
|
|
|
|
'showAdminLink' => $isAdmin,
|
|
|
|
|
]) ?>
|
2026-03-26 14:30:45 +09:00
|
|
|
</header>
|
|
|
|
|
<!-- END: Top Navigation -->
|
|
|
|
|
<div class="bg-title-bar text-white px-4 py-2 text-sm font-medium shrink-0">
|
|
|
|
|
<?= esc($title ?? '') ?>
|
|
|
|
|
</div>
|
|
|
|
|
<?php if (session()->getFlashdata('success')): ?>
|
|
|
|
|
<div class="mx-4 mt-2 p-3 rounded-lg bg-green-50 text-green-700 text-sm" role="alert"><?= esc(session()->getFlashdata('success')) ?></div>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
<?php if (session()->getFlashdata('error')): ?>
|
|
|
|
|
<div class="mx-4 mt-2 p-3 rounded-lg bg-red-50 text-red-700 text-sm" role="alert"><?= esc(session()->getFlashdata('error')) ?></div>
|
|
|
|
|
<?php endif; ?>
|
|
|
|
|
<main class="main-content-area flex-grow bg-white p-4">
|
|
|
|
|
<?= $content ?>
|
|
|
|
|
</main>
|
|
|
|
|
<footer class="bg-gray-200 border-t border-gray-300 px-4 py-1 text-xs text-gray-600 flex items-center justify-between shrink-0">
|
2026-04-08 00:18:01 +09:00
|
|
|
<span>종량제 시스템</span>
|
2026-03-26 14:30:45 +09:00
|
|
|
<span><?= date('Y.m.d (D) g:i:sA') ?></span>
|
|
|
|
|
</footer>
|
|
|
|
|
</body>
|
|
|
|
|
</html>
|