205 lines
No EOL
11 KiB
PHP
205 lines
No EOL
11 KiB
PHP
<?php
|
|
/**
|
|
* nav.php
|
|
* 공통 네비게이션 컴포넌트 (최상단 고정형 리본 메뉴)
|
|
*/
|
|
require_once 'config.php';
|
|
$current_page = basename($_SERVER['PHP_SELF']);
|
|
|
|
// 시스템 설정 로드 (config.php에서 테이블 생성을 보장함)
|
|
$settings = [];
|
|
try {
|
|
$settings = $db->query("SELECT key_name, value FROM system_settings")->fetchAll(PDO::FETCH_KEY_PAIR);
|
|
} catch (Exception $e) {
|
|
$settings = ['menu_cards_visible' => '1', 'menu_mfp_visible' => '1'];
|
|
}
|
|
?>
|
|
<nav class="fixed top-0 left-0 right-0 bg-[#0f172a] text-white z-[100] shadow-2xl border-b border-blue-500/20 px-6">
|
|
<div class="max-w-[1600px] mx-auto h-20 flex items-center justify-between">
|
|
<!-- Logo -->
|
|
<div class="flex items-center space-x-3 mr-10">
|
|
<a href="index.php" class="flex items-center">
|
|
<div
|
|
class="w-10 h-10 bg-gradient-to-br from-blue-500 to-indigo-600 rounded-xl flex items-center justify-center shadow-lg mr-3">
|
|
<span class="text-xl font-black italic">F</span>
|
|
</div>
|
|
<div class="hidden sm:block">
|
|
<h1 class="text-xl font-black tracking-tighter">FKI <span class="text-blue-400">ASSET</span></h1>
|
|
<p class="text-[9px] text-slate-400 font-bold uppercase tracking-widest leading-none">V2.0 Architect
|
|
</p>
|
|
</div>
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Horizontal Menu -->
|
|
<div class="flex-1 flex items-center justify-center space-x-1 lg:space-x-4 overflow-x-auto no-scrollbar py-2">
|
|
<?php
|
|
$menu_items = [
|
|
['url' => 'index.php', 'name' => '대시보드', 'icon' => 'M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6'],
|
|
['url' => 'rental.php', 'name' => '노트북 임대', 'icon' => 'M8 7h12m0 0l-4-4m4 4l-4 4m0 6H4m0 0l4 4m-4-4l4-4'],
|
|
['url' => 'general_rental.php', 'name' => '임대', 'icon' => 'M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4'],
|
|
['url' => 'users.php', 'name' => '직원 관리', 'icon' => 'M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z'],
|
|
['url' => 'laptops.php', 'name' => '노트북 자산', 'icon' => 'M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z'],
|
|
];
|
|
|
|
if (($settings['menu_cards_visible'] ?? '1') === '1') {
|
|
$menu_items[] = ['url' => 'cards.php', 'name' => '출입증 현황', 'icon' => 'M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z'];
|
|
}
|
|
|
|
if (($settings['menu_mfp_visible'] ?? '1') === '1') {
|
|
$menu_items[] = ['url' => 'mfp.php', 'name' => '복합기 계정', 'icon' => 'M17 17h2a2 2 0 002-2v-4a2 2 0 00-2-2H5a2 2 0 00-2 2v4a2 2 0 002 2h2m2 4h6a2 2 0 002-2v-4a2 2 0 00-2-2H9a2 2 0 00-2 2v4a2 2 0 002 2zm8-12V5a2 2 0 00-2-2H9a2 2 0 00-2 2v4h10z'];
|
|
}
|
|
|
|
$menu_items[] = ['url' => 'models.php', 'name' => '관리자페이지', 'icon' => 'M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4'];
|
|
$menu_items[] = ['url' => 'admins.php', 'name' => 'ADMIN', 'icon' => 'M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z M15 12a3 3 0 11-6 0 3 3 0 016 0z'];
|
|
|
|
foreach ($menu_items as $item):
|
|
$is_active = ($current_page == $item['url']);
|
|
?>
|
|
<a href="<?php echo $item['url']; ?>" class="flex items-center px-4 py-2.5 rounded-xl text-sm font-bold transition-all duration-300 transform whitespace-nowrap
|
|
<?php echo $is_active
|
|
? 'bg-blue-600 text-white shadow-[0_0_20px_rgba(37,99,235,0.4)] scale-105'
|
|
: 'text-slate-400 hover:text-white hover:bg-slate-800'; ?>">
|
|
<svg class="w-5 h-5 mr-2 hidden md:block" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
|
d="<?php echo $item['icon']; ?>" />
|
|
</svg>
|
|
<?php echo $item['name']; ?>
|
|
</a>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
|
|
<!-- User Info & Logout -->
|
|
<div class="hidden lg:flex items-center ml-10 space-x-4 border-l border-slate-700 pl-10" x-data="{
|
|
logout() {
|
|
window.showConfirm('로그아웃 하시겠습니까?', () => {
|
|
fetch('api.php?action=logout').then(() => location.href = 'login.php');
|
|
});
|
|
}
|
|
}">
|
|
<div class="text-right">
|
|
<p class="text-xs font-black text-white"><?php echo $_SESSION['admin_name'] ?? 'ADMIN'; ?></p>
|
|
<button @click="logout()"
|
|
class="text-[10px] text-blue-400 font-bold uppercase tracking-tight hover:text-white transition-colors flex items-center gap-1">
|
|
Sign Out
|
|
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
|
d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
<div
|
|
class="w-10 h-10 bg-slate-800 rounded-full flex items-center justify-center border border-slate-700 shadow-inner">
|
|
<span
|
|
class="text-xs font-black text-slate-300"><?php echo strtoupper(substr($_SESSION['admin_login_id'] ?? 'AD', 0, 2)); ?></span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Mobile Menu Placeholder -->
|
|
<div class="lg:hidden ml-4">
|
|
<div class="w-8 h-8 flex items-center justify-center">
|
|
<span class="w-1.5 h-1.5 bg-emerald-500 rounded-full animate-ping"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- Global Styles for Scrollbar -->
|
|
<style>
|
|
.no-scrollbar::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
|
|
.no-scrollbar {
|
|
-ms-overflow-style: none;
|
|
scrollbar-width: none;
|
|
}
|
|
|
|
body {
|
|
padding-top: 80px;
|
|
}
|
|
</style>
|
|
|
|
<!-- Global Notification System (Antigravity Standard) -->
|
|
<div x-data="{
|
|
show: false,
|
|
type: 'alert',
|
|
title: '',
|
|
message: '',
|
|
onConfirm: null,
|
|
|
|
init() {
|
|
window.showAlert = (msg, title = '알림', type = 'alert') => {
|
|
this.type = type;
|
|
this.title = title;
|
|
this.message = msg;
|
|
this.onConfirm = null;
|
|
this.show = true;
|
|
};
|
|
window.showConfirm = (msg, callback, title = '확인 요청') => {
|
|
this.type = 'confirm';
|
|
this.title = title;
|
|
this.message = msg;
|
|
this.onConfirm = callback;
|
|
this.show = true;
|
|
};
|
|
},
|
|
confirmAction() {
|
|
if (this.onConfirm) this.onConfirm();
|
|
this.show = false;
|
|
}
|
|
}" x-show="show" x-cloak class="fixed inset-0 z-[1000] flex items-center justify-center p-4">
|
|
<div class="fixed inset-0 bg-slate-900/60 backdrop-blur-sm" @click="show = false"></div>
|
|
<div
|
|
class="bg-white rounded-[2.5rem] p-8 max-w-sm w-full relative z-[1001] shadow-[0_32px_64px_-12px_rgba(0,0,0,0.2)] border border-white/20 transform transition-all animate-in zoom-in-95 duration-200">
|
|
<div class="mb-6 text-center">
|
|
<div class="w-20 h-20 rounded-3xl mb-6 flex items-center justify-center mx-auto transition-transform hover:scale-110 duration-300"
|
|
:class="{
|
|
'bg-amber-50 text-amber-500': type === 'confirm',
|
|
'bg-rose-50 text-rose-500': type === 'error',
|
|
'bg-emerald-50 text-emerald-500': type === 'success',
|
|
'bg-blue-50 text-blue-500': type === 'alert'
|
|
}">
|
|
<template x-if="type === 'confirm'">
|
|
<svg class="w-10 h-10" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
|
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
|
</svg>
|
|
</template>
|
|
<template x-if="type === 'error'">
|
|
<svg class="w-10 h-10" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
|
d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
</svg>
|
|
</template>
|
|
<template x-if="type === 'success'">
|
|
<svg class="w-10 h-10" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
|
|
</svg>
|
|
</template>
|
|
<template x-if="type === 'alert'">
|
|
<svg class="w-10 h-10" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
|
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
</svg>
|
|
</template>
|
|
</div>
|
|
<h4 class="text-2xl font-black text-slate-900 mb-3 tracking-tight" x-text="title"></h4>
|
|
<p class="text-sm font-bold text-slate-500 leading-relaxed whitespace-pre-line px-2" x-text="message"></p>
|
|
</div>
|
|
<div class="flex gap-3 mt-8">
|
|
<template x-if="type === 'confirm'">
|
|
<button @click="show = false"
|
|
class="flex-1 py-4 bg-slate-100 rounded-2xl font-black text-sm text-slate-600 hover:bg-slate-200 transition-all active:scale-95">취소</button>
|
|
</template>
|
|
<button @click="confirmAction"
|
|
class="flex-1 py-4 rounded-2xl font-black text-sm text-white shadow-2xl transition-all active:scale-95"
|
|
:class="{
|
|
'bg-amber-500 shadow-amber-200 hover:bg-amber-600': type === 'confirm',
|
|
'bg-rose-500 shadow-rose-200 hover:bg-rose-600': type === 'error',
|
|
'bg-emerald-500 shadow-emerald-200 hover:bg-emerald-600': type === 'success',
|
|
'bg-blue-600 shadow-blue-200 hover:bg-blue-700': type === 'alert'
|
|
}" x-text="type === 'confirm' ? '확인 및 실행' : '확인'"></button>
|
|
</div>
|
|
</div>
|
|
</div>
|