Initial commit: 교육 프로젝트 배포

This commit is contained in:
송대일
2026-07-01 18:32:42 +09:00
commit be6dccd120
1483 changed files with 5082202 additions and 0 deletions
+152
View File
@@ -0,0 +1,152 @@
<?php
$navPath = basename(parse_url($_SERVER['REQUEST_URI'] ?? '', PHP_URL_PATH) ?: '');
parse_str(parse_url($_SERVER['REQUEST_URI'] ?? '', PHP_URL_QUERY) ?: '', $navQuery);
$navCate = $navQuery['cate'] ?? '';
/** depth01: 현재 스크립트가 해당 php와 같으면 부모 li active (서브메뉴 페이지 포함) */
function nav_active_depth01($phpFile) {
global $navPath;
return $navPath === $phpFile ? ' class="active"' : '';
}
/** depth02: 스크립트 + cate 쿼리까지 일치 */
function nav_active_depth02($phpFile, $cate) {
global $navPath, $navCate;
return ($navPath === $phpFile && $navCate === $cate) ? ' class="active"' : '';
}
?>
<div class="nav-group">
<ul class="depth01">
<li<?php echo nav_active_depth01('myclass.php'); echo nav_active_depth01('myclass_list.php');?>>
<a href="/edu/skin/myclass.php"> 마이클래스 </a>
<div class="state-box">
<span class="unit">0<small>%</small></span>
<span class="progress">
<span class="progress-bar" style="width: 0%"></span>
</span>
</div>
</li>
<li<?php echo nav_active_depth01('onboarding.php'); ?>>
<a href="/edu/skin/onboarding.php" data-nav="onboarding"> 온보딩 </a>
<div class="state-box">
<span class="unit" id="onboardingNavPercent" style="left: calc(0% - 3px);">0<small>%</small></span>
<span class="progress">
<span class="progress-bar" id="onboardingNavBar" style="width: 0%"></span>
</span>
</div>
</li>
<li<?php echo nav_active_depth01('learning.php'); ?>>
<a href="/edu/skin/learning.php"> 법정교육 </a>
<div class="state-box">
<span class="unit">0<small>%</small></span>
<span class="progress">
<span class="progress-bar" style="width: 0%"></span>
</span>
</div>
</li>
<li<?php echo nav_active_depth01('leadership.php'); ?>>
<a href="/edu/skin/leadership.php">리더십</a>
<ul class="depth02">
<li<?php echo nav_active_depth02('leadership.php', 'CA200L01'); ?>>
<a href="/edu/skin/leadership.php?cate=CA200L01" >
<span class="ico-box">
<img src="/edu/img/ico/ico_leadership_01.svg" />
</span>
리더십 시작하기
</a>
</li>
<li<?php echo nav_active_depth02('leadership.php', 'CA200L02'); ?>>
<a href="/edu/skin/leadership.php?cate=CA200L02" >
<span class="ico-box">
<img src="/edu/img/ico/ico_leadership_02.svg" />
</span>
셀프 리더십
</a>
</li>
<li<?php echo nav_active_depth02('leadership.php', 'CA200L03'); ?>>
<a href="/edu/skin/leadership.php?cate=CA200L03" >
<span class="ico-box">
<img src="/edu/img/ico/ico_leadership_03.svg" />
</span>
팀 리더십
</a>
</li>
<li<?php echo nav_active_depth02('leadership.php', 'CA200L04'); ?>>
<a href="/edu/skin/leadership.php?cate=CA200L04" >
<span class="ico-box">
<img src="/edu/img/ico/ico_leadership_04.svg" />
</span>
실전조직 리더십
</a>
</li>
<li<?php echo nav_active_depth02('leadership.php', 'CA200L05'); ?>>
<a href="/edu/skin/leadership.php?cate=CA200L05" >
<span class="ico-box">
<img src="/edu/img/ico/ico_leadership_05.svg" />
</span>
리더케이스탐구
</a>
</li>
</ul>
</li>
<li<?php echo nav_active_depth01('insight.php'); ?>>
<a href="/edu/skin/insight.php">인사이트 </a>
<!-- 2depth -->
<ul class="depth02">
<li<?php echo nav_active_depth02('insight.php', 'CA200I01'); ?>>
<a href="/edu/skin/insight.php?cate=CA200I01" >
<span class="ico-box">
<img src="/edu/img/ico/ico_insight_01.svg" />
</span>
경제와 사회
</a>
</li>
<li<?php echo nav_active_depth02('insight.php', 'CA200I02'); ?>>
<a href="/edu/skin/insight.php?cate=CA200I02" >
<span class="ico-box">
<img src="/edu/img/ico/ico_insight_02.svg" />
</span>
기술과 미래
</a>
</li>
<li<?php echo nav_active_depth02('insight.php', 'CA200I03'); ?>>
<a href="/edu/skin/insight.php?cate=CA200I03" >
<span class="ico-box">
<img src="/edu/img/ico/ico_insight_03.svg" />
</span>
스킬 업
</a>
</li>
<li<?php echo nav_active_depth02('insight.php', 'CA200I04'); ?>>
<a href="/edu/skin/insight.php?cate=CA200I04" >
<span class="ico-box">
<img src="/edu/img/ico/ico_insight_04.svg" />
</span>
행복과 건강
</a>
</li>
<li<?php echo nav_active_depth02('insight.php', 'CA200I05'); ?>>
<a href="/edu/skin/insight.php?cate=CA200I05" >
<span class="ico-box">
<img src="/edu/img/ico/ico_insight_05.svg" />
</span>
피플스토리
</a>
</li>
<li<?php echo nav_active_depth02('insight.php', 'CA200I06'); ?>>
<a href="/edu/skin/insight.php?cate=CA200I06" >
<span class="ico-box">
<img src="/edu/img/ico/ico_insight_06.svg" />
</span>
라이프
</a>
</li>
</ul>
</li>
<li<?php echo nav_active_depth01('biztrend.php'); ?>>
<a href="/edu/skin/biztrend.php">비즈트렌드</a>
</li>
</ul>
</div>
+39
View File
@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
if (!function_exists('edu_start_session')) {
function edu_start_session(): void
{
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
}
}
if (!function_exists('edu_current_member_id')) {
function edu_current_member_id(): string
{
edu_start_session();
$memberId = trim((string)($_SESSION['ss_mb_id'] ?? $_SESSION['member_id'] ?? ''));
return $memberId;
}
}
if (!function_exists('edu_is_logged_in')) {
function edu_is_logged_in(): bool
{
return edu_current_member_id() !== '';
}
}
if (!function_exists('edu_require_login')) {
function edu_require_login(): void
{
if (edu_is_logged_in()) {
return;
}
header('Location: http://erp.baroncs.co.kr/mobile/sys/controller/Study_controller.php');
exit;
}
}
+52
View File
@@ -0,0 +1,52 @@
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, viewport-fit=cover"
/>
<meta http-equiv="X-UA-compatible" content="IE=edge,chrome=1" />
<meta name="format-detection" content="telephone=no" />
<!-- <meta http-equiv="pragma" content="no-cache"> -->
<link
rel="shortcut icon"
type="image/svg+xml"
href="/img/favicon.ico"
/>
<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=Noto+Sans+KR:wght@100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="/css/lib/swiper11.min.css" />
<link rel="stylesheet" type="text/css" href="/css/common.css" />
<link rel="stylesheet" type="text/css" href="/css/style.css" />
<script src="https://www.youtube.com/iframe_api"></script>
<script src="/js/lib/swiper11.min.js"></script>
<script src="/js/lib/lottie.min.js"></script>
<script src="/js/lib/gsap.min.js"></script>
<script src="/js/lib/scrolltrigger.min.js"></script>
<!--
공통 모듈 로딩 순서 (반드시 유지)
1. Utils 범용 유틸(딜레이, 디바운스, 날짜포맷 )
2. DOMUtils DOM 조작(선택, 페이드, 이벤트 위임)
3. ErrorHandler 에러 처리 (다른 모듈에서 사용)
4. EventManager 이벤트 중앙 관리 (선택적, 없으면 DOMUtils.delegate 폴백)
5. AnimationUtils 이하 애니메이션, 비디오, 모달
-->
<script src="/js/lib/jquery-3.6.1.min.js"></script>
<script src="/js/common/Utils.js" defer></script>
<script src="/js/common/DOMUtils.js" defer></script>
<script src="/js/common/ErrorHandler.js" defer></script>
<script src="/js/common/EventManager.js" defer></script>
<script src="/js/common/AnimationUtils.js" defer></script>
<script src="/js/common/VideoBase.js" defer></script>
<script src="/js/common/ModalBase.js" defer></script>
<script src="/js/common/ModalUtils.js" defer></script>
<script src="/js/common/VideoModalBase.js" defer></script>
<script src="/js/common/LearningGuideModal.js" defer></script>
<script src="/js/common/ConfigManager.js" defer></script>
<script src="/js/common/GaugeBase.js" defer></script>
<!-- 공통 스크립트 (모든 공통 모듈 로드 실행) -->
<script src="/js/common.js" defer></script>
<title>배움터</title>
+589
View File
@@ -0,0 +1,589 @@
<!-- header -->
<?php
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
$headerSearchQuery = trim((string)($_GET['q'] ?? ''));
$memberId = (string)($_SESSION['member_id'] ?? '');
$isLoggedIn = $memberId !== '';
$memberName = isset($_SESSION['member_name']) ? trim((string)$_SESSION['member_name']) : '';
$authLevel = strtoupper(trim((string)($_SESSION['auth_level'] ?? '')));
$canSeePrivilegedButtons = $isLoggedIn && in_array($authLevel, ['LE10001', 'LE10002'], true);
$adminLandingUrl = ($authLevel === 'LE10002')
? '/admin/skin/legal_edu.php'
: '/admin/skin/index.php';
// ── 알림 데이터 조회 (edu_notifications) ──
$notifications = [];
$hasNewAlert = false;
// ---------------------------------------------------------
// 헤더에서 바로 사용할 기본 변수
// ---------------------------------------------------------
$header_myclass_percent = 0;
$header_onboarding_percent = 0;
$header_legal_percent = 0;
require_once __DIR__ . '/../../bbs/init_data_for_header.php';
if($memberId=="M21420" ){
/*
echo "memberId=".$memberId."<br>";
echo "header_myclass_percent=".$header_myclass_percent."<br>";
echo "header_onboarding_percent=".$header_onboarding_percent."<br>";
echo "header_legal_percent=".$header_legal_percent."<br>";
*/
//exit;
}
if ($isLoggedIn) {
try {
require_once __DIR__ . '/../../bbs/db_conn.php';
$pdoHeader = db_conn();
$corpCode = (string)($_SESSION['sys_comp_code'] ?? '');
$stmtNotif = $pdoHeader->prepare("
SELECT n.seq,
fn_get_code_name(n.type_code) AS type_name,
n.type_code,
n.message,
n.sent_at,
n.end_date
FROM edu_notifications n
WHERE n.member_id = ?
AND n.corp_code = ?
AND n.end_date >= CURDATE()
ORDER BY n.sent_at DESC
");
$stmtNotif->execute([$memberId, $corpCode]);
$notifications = $stmtNotif->fetchAll(PDO::FETCH_ASSOC);
$stmtAuth = $pdoHeader->prepare(
"SELECT auth_level
FROM edu_users
WHERE member_id = ?
ORDER BY (sys_comp_code = ?) DESC, sys_comp_code ASC
LIMIT 1"
);
$stmtAuth->execute([$memberId, $corpCode]);
$authLevelFromDb = $stmtAuth->fetchColumn();
$authLevel = strtoupper(trim((string)($authLevelFromDb ?? '')));
$canSeePrivilegedButtons = $isLoggedIn && in_array($authLevel, ['LE10001', 'LE10002'], true);
$adminLandingUrl = ($authLevel === 'LE10002')
? '/admin/skin/legal_edu.php'
: '/admin/skin/index.php';
// sent_at 이 오늘인 알림이 있으면 on 표시
$today = date('Y-m-d');
foreach ($notifications as $notif) {
if (!empty($notif['sent_at']) && substr($notif['sent_at'], 0, 10) === $today) {
$hasNewAlert = true;
break;
}
}
if($memberId=="M21420" ){/*
echo "memberId=".$memberId."<br>";
echo "header_myclass_percent=".$header_myclass_percent."<br>";
echo "header_onboarding_percent=".$header_onboarding_percent."<br>";
echo "header_legal_percent=".$header_legal_percent."<br>";
*/
}
} catch (Exception $e) {
// DB 오류 시 빈 배열 유지
$notifications = [];
$hasNewAlert = false;
}
}
if (!isset($learningGuideDefaultTab)) {
$guideScript = strtolower(basename($_SERVER['SCRIPT_NAME'] ?? '', '.php'));
$guideUri = strtolower(parse_url($_SERVER['REQUEST_URI'] ?? '', PHP_URL_PATH) ?: '');
$guidePageMap = [
'index' => 'main',
'main' => 'main',
'myclass' => 'myclass',
'myclass_list' => 'myclass',
'onboarding' => 'onboarding',
'learning' => 'legal',
'legal_edu' => 'legal',
'legal' => 'legal',
'leadership' => 'leadership',
'insight' => 'insight',
'biztrend' => 'biztrend',
'mypage' => 'mypage',
'player' => 'player',
];
if (isset($guidePageMap[$guideScript])) {
$learningGuideDefaultTab = $guidePageMap[$guideScript];
} else {
foreach ($guidePageMap as $needle => $key) {
if ($needle !== 'player' && (strpos($guideUri, '/' . $needle) !== false || strpos($guideUri, $needle . '.php') !== false)) {
$learningGuideDefaultTab = $key;
break;
}
}
}
}
$learningGuideDefaultTab = $learningGuideDefaultTab ?? 'player';
?>
<!--
$header_myclass_percent
$header_onboarding_percent
$header_legal_percent
-->
<div class="nav-wrap">
<div class="inner">
<!-- header -->
<header class="header">
<a href="./index.php"><h1>배움터.</h1></a>
<button class="btn-guide" type="button" title="가이드 열기/닫기" data-default-guide-key="<?= htmlspecialchars($learningGuideDefaultTab, ENT_QUOTES, 'UTF-8') ?>">
<div class="btn-guide-inner">
<span class="ico-guide-wrap"><i class="ico-guide"></i></span>
<span class="guide-text"><span class="guide-type">학습</span> 가이드</span>
</div>
</button>
</header>
<!--// header -->
<nav class="nav"><?php include(__DIR__ . "/_nav.php") ?></nav>
<div class="item-area">
<!-- 모바일에서만 보이는 검색 아이콘 버튼 -->
<div class="item-box">
<button class="btn-search" type="button" title="검색 열기"></button>
</div>
<!-- 데스크톱 기본 검색 인풋 -->
<form class="input-group" action="./search_result.php" method="get" autocomplete="off">
<input type="text" name="q" value="<?= htmlspecialchars($headerSearchQuery, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?>" placeholder="검색" autocomplete="off" autocapitalize="off" autocorrect="off" spellcheck="false" />
<button type="submit" class="ico-search" aria-label="검색"></button>
<button class="btn-clear" type="button"></button>
<div class="search-suggestions">
<ul class="search-suggestions-list" data-search-history-list="desktop"></ul>
</div>
</form>
<div class="item-box">
<button class="alerts<?= $hasNewAlert ? ' on' : '' ?>" title="알림"></button>
<div class="alerts-area">
<ul class="alerts-list">
<?php if (empty($notifications)): ?>
<li class="alert-item">
<p class="alert-desc">알림이 없습니다.</p>
</li>
<?php else: ?>
<?php foreach ($notifications as $notif): ?>
<li class="alert-item">
<strong class="alert-title"><?= htmlspecialchars($notif['type_name'] ?? '', ENT_QUOTES, 'UTF-8') ?></strong>
<p class="alert-desc" title="<?= htmlspecialchars($notif['message'] ?? '', ENT_QUOTES, 'UTF-8') ?>"><?= htmlspecialchars($notif['message'] ?? '', ENT_QUOTES, 'UTF-8') ?></p>
</li>
<?php endforeach; ?>
<?php endif; ?>
</ul>
</div>
</div>
<div class="item-box">
<a class="mypage<?php echo nav_active_depth01('mypage.php') ? ' active' : ''; ?>" title="마이페이지" href="/skin/mypage.php"></a>
</div>
<!-- 로그인/로그아웃 버튼 -->
<div class="item-box">
<?php if ($isLoggedIn): ?>
<?php if ($canSeePrivilegedButtons): ?>
<button class="btn-auth btn-logout" type="button" title="로그아웃" id="btnAuthDesktop"></button>
<?php endif; ?>
<?php else: ?>
<a class="btn-auth btn-login" href="/bbs/login.php" title="로그인"></a>
<?php endif; ?>
</div>
<?php if ($canSeePrivilegedButtons): ?>
<div class="item-box">
<a class="btn-admin" title="관리자 페이지" href="<?= htmlspecialchars($adminLandingUrl, ENT_QUOTES, 'UTF-8') ?>" target="_blank"></a>
</div>
<?php endif; ?>
<div class="item-box">
<button class="btn-sitemap" type="button" title="메뉴 열기/닫기" aria-expanded="false" aria-controls="siteMap"></button>
</div>
</div>
<div class="site-map" id="siteMap" aria-hidden="true">
<div class="site-map-backdrop" aria-hidden="true"></div>
<div class="site-map-inner">
<div class="site-map-header">
<a href="./index.php" class="mo-logo">배움터</a>
<div class="item-area">
<div class="item-box">
<a class="mypage" title="마이페이지" href="./mypage.php"></a>
</div>
<!-- 로그인/로그아웃 버튼 (모바일) -->
<div class="item-box">
<?php if ($isLoggedIn): ?>
<?php if ($canSeePrivilegedButtons): ?>
<button class="btn-auth btn-logout" type="button" title="로그아웃" id="btnAuthMobile"></button>
<?php endif; ?>
<?php else: ?>
<a class="btn-auth btn-login" href="/bbs/login.php" title="로그인"></a>
<?php endif; ?>
</div>
<button type="button" class="btn-close" aria-label="사이트맵 닫기"></button>
</div>
</div>
<div class="site-map-body">
<!-- 퀵 메뉴 -->
<div class="site-map-quick">
<a href="./myclass.php" class="quick-item">
<span class="quick-icon">
<img src="/img/img_sitemap_01.svg" alt="" />
</span>
<span class="quick-title">마이클래스</span>
<div class="state-box">
<span class="unit"><?=$header_myclass_percent?><small>%</small></span>
<span class="progress">
<span class="progress-bar" style="width: <?=$header_myclass_percent?>%"></span>
</span>
</div>
</a>
<a href="./onboarding.php" class="quick-item" data-quick="onboarding">
<span class="quick-icon">
<img src="/img/img_sitemap_02.svg" alt="" />
</span>
<span class="quick-title">온보딩</span>
<div class="state-box">
<span class="unit" id="onboardingQuickPercent" style="left: 0%;"><?=$header_onboarding_percent?><small>%</small></span>
<span class="progress">
<span class="progress-bar" id="onboardingQuickBar" style="width: <?=$header_onboarding_percent?>%"></span>
</span>
</div>
</a>
<a href="./learning.php" class="quick-item">
<span class="quick-icon">
<img src="/img/img_sitemap_03.svg" alt="" />
</span>
<span class="quick-title">법정교육</span>
<div class="state-box">
<span class="unit" style="left:100%;"><?=$header_legal_percent?><small>%</small></span>
<span class="progress">
<span class="progress-bar" style="width: <?=$header_legal_percent?>%"></span>
</span>
</div>
</a>
</div>
<!-- 아코디언 메뉴 -->
<ul class="site-map-menu">
<li class="menu-section<?php echo nav_active_depth01('leadership.php') ? ' active' : ''; ?>">
<button type="button" class="menu-section-title">
리더십<i class="ico-chevron"></i>
</button>
<ul class="menu-section-list">
<li<?php echo nav_active_depth02('leadership.php', 'CA200L01'); ?>><a href="./leadership.php?cate=CA200L01">리더십 시작하기</a></li>
<li<?php echo nav_active_depth02('leadership.php', 'CA200L02'); ?>><a href="./leadership.php?cate=CA200L02">셀프 리더십</a></li>
<li<?php echo nav_active_depth02('leadership.php', 'CA200L03'); ?>><a href="./leadership.php?cate=CA200L03">팀 리더십</a></li>
<li<?php echo nav_active_depth02('leadership.php', 'CA200L04'); ?>><a href="./leadership.php?cate=CA200L04">실전조직 리더십</a></li>
<li<?php echo nav_active_depth02('leadership.php', 'CA200L05'); ?>><a href="./leadership.php?cate=CA200L05">리더케이스탐구</a></li>
</ul>
</li>
<li class="menu-section<?php echo nav_active_depth01('insight.php') ? ' active' : ''; ?>">
<button type="button" class="menu-section-title">
인사이트
<i class="ico-chevron"></i>
</button>
<ul class="menu-section-list">
<li<?php echo nav_active_depth02('insight.php', 'CA200I01'); ?>><a href="./insight.php?cate=CA200I01">경제와 사회</a></li>
<li<?php echo nav_active_depth02('insight.php', 'CA200I02'); ?>><a href="./insight.php?cate=CA200I02">기술과 미래</a></li>
<li<?php echo nav_active_depth02('insight.php', 'CA200I03'); ?>><a href="./insight.php?cate=CA200I03">스킬 업</a></li>
<li<?php echo nav_active_depth02('insight.php', 'CA200I04'); ?>><a href="./insight.php?cate=CA200I04">행복과 건강</a></li>
<li<?php echo nav_active_depth02('insight.php', 'CA200I05'); ?>><a href="./insight.php?cate=CA200I05">피플스토리</a></li>
<li<?php echo nav_active_depth02('insight.php', 'CA200I06'); ?>><a href="./insight.php?cate=CA200I06">라이프</a></li>
</ul>
</li>
<li class="menu-section<?php echo nav_active_depth01('biztrend.php') ? ' active' : ''; ?>">
<a href="./biztrend.php" class="menu-section-title">
비즈트렌드
</a>
</li>
</ul>
</div>
</div>
</div>
<!-- 모바일 검색 오버레이 (Figma 디자인: 오른쪽 슬라이드 패널) -->
<div class="mo-search-layer" aria-hidden="true">
<div class="mo-search-backdrop" aria-hidden="true"></div>
<div class="mo-search-inner">
<div class="mo-search-header">
<a href="./index.html" class="mo-search-logo">배움터</a>
<button type="button" class="btn-close-search" aria-label="검색 닫기"></button>
</div>
<div class="mo-search-body">
<div class="mo-search-input">
<form class="input-group" action="./search_result.php" method="get" autocomplete="off">
<input type="text" name="q" value="<?= htmlspecialchars($headerSearchQuery, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') ?>" placeholder="검색어를 입력해주세요" autocomplete="off" autocapitalize="off" autocorrect="off" spellcheck="false" />
<button class="btn-clear" type="button" aria-label="입력 지우기"></button>
<button type="submit" class="ico-search" aria-label="검색"></button>
</form>
</div>
<div class="mo-search-history">
<ul class="search-suggestions-list" data-search-history-list="mobile"></ul>
</div>
</div>
</div>
</div>
</div>
</div>
<?php // 페이지별 기본 탭: header include 전에 $learningGuideDefaultTab = 'legal'; 등으로 설정 (자동 감지보다 우선) ?>
<?php include(__DIR__ . "/../_modal/learning-guide.php") ?>
<!--// header -->
<script>
// 로그아웃 버튼 이벤트 처리 (모든 페이지 공통)
document.addEventListener('DOMContentLoaded', function () {
function handleLogout() {
if (!confirm('로그아웃 하시겠습니까?')) return;
console.log('[Logout] Starting logout process...');
fetch('/bbs/logout.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
})
.then(function(response) {
console.log('[Logout] Response status:', response.status);
if (!response.ok) throw new Error('HTTP error! status: ' + response.status);
return response.json();
})
.then(function(data) {
console.log('[Logout] Response data:', data);
if (data.success) {
// window.location.href = '/skin/index.php';
window.location.href = '/skin/login.php';
} else {
alert(data.message || '로그아웃 실패');
}
})
.catch(function(error) {
console.error('[Logout] Error:', error);
alert('로그아웃 중 오류가 발생했습니다: ' + error.message);
});
}
var btnLogoutDesktop = document.getElementById('btnAuthDesktop');
var btnLogoutMobile = document.getElementById('btnAuthMobile');
if (btnLogoutDesktop) btnLogoutDesktop.addEventListener('click', function(e){ e.preventDefault(); handleLogout(); });
if (btnLogoutMobile) btnLogoutMobile.addEventListener('click', function(e){ e.preventDefault(); handleLogout(); });
console.log('[Header] Auth buttons setup done. desktop:', !!btnLogoutDesktop, 'mobile:', !!btnLogoutMobile);
});
// 검색어 동기화 (search_result.php 전용)
document.addEventListener('DOMContentLoaded', function () {
try {
if (!/\/search_result\.php(?:$|\?)/.test(window.location.pathname + window.location.search)) return;
var params = new URLSearchParams(window.location.search);
var q = (params.get('q') || '').trim();
if (!q) return;
document.querySelectorAll('.input-group input[name="q"]').forEach(function (input) {
input.value = q;
});
var keywordEl = document.querySelector('.search-keyword');
if (keywordEl) keywordEl.textContent = q;
} catch (e) {
console.warn('[header search sync]', e);
}
});
// 최근 검색어 렌더링 (헤더 공통)
document.addEventListener('DOMContentLoaded', function () {
var apiUrl = '/bbs/api/search_logs.php?limit=20';
var saveApiUrl = '/bbs/api/search_logs.php';
var searchResultBaseUrl = '/skin/search_result.php?q=';
var desktopInput = document.querySelector('.item-area > form.input-group input[name="q"]');
var mobileInput = document.querySelector('.mo-search-layer .input-group input[name="q"]');
var desktopList = document.querySelector('[data-search-history-list="desktop"]');
var mobileList = document.querySelector('[data-search-history-list="mobile"]');
var searchForms = document.querySelectorAll('form.input-group[action="./search_result.php"]');
var cacheLogs = null;
var cacheAt = 0;
var isLoading = false;
var lastSavedKeyword = '';
var lastSavedAt = 0;
function clearList(listEl) {
while (listEl && listEl.firstChild) {
listEl.removeChild(listEl.firstChild);
}
}
function appendEmptyRow(listEl) {
if (!listEl) return;
var li = document.createElement('li');
var span = document.createElement('span');
span.textContent = '최근 검색어가 없습니다.';
li.appendChild(span);
listEl.appendChild(li);
}
function appendKeywordRow(listEl, keyword) {
if (!listEl || !keyword) return;
var li = document.createElement('li');
var link = document.createElement('a');
var icon = document.createElement('i');
var text = document.createElement('span');
link.href = searchResultBaseUrl + encodeURIComponent(keyword);
icon.className = 'ico-history';
icon.setAttribute('aria-hidden', 'true');
text.textContent = keyword;
link.appendChild(icon);
link.appendChild(text);
li.appendChild(link);
listEl.appendChild(li);
}
function renderLogs(logs) {
var listTargets = [desktopList, mobileList];
listTargets.forEach(function (listEl) {
clearList(listEl);
if (!Array.isArray(logs) || logs.length === 0) {
appendEmptyRow(listEl);
return;
}
logs.forEach(function (log) {
var keyword = String((log && log.keyword) || '').trim();
if (!keyword) return;
appendKeywordRow(listEl, keyword);
});
if (!listEl.children.length) {
appendEmptyRow(listEl);
}
});
}
function loadRecentLogs(force) {
var now = Date.now();
var isCacheFresh = cacheLogs !== null && (now - cacheAt) < 30000;
if (!force && isCacheFresh) {
renderLogs(cacheLogs);
return;
}
if (isLoading) return;
isLoading = true;
fetch(apiUrl, { credentials: 'same-origin' })
.then(function (response) {
if (!response.ok) throw new Error('HTTP ' + response.status);
return response.json();
})
.then(function (json) {
var logs = (json && json.data && Array.isArray(json.data.logs)) ? json.data.logs : [];
cacheLogs = logs;
cacheAt = Date.now();
renderLogs(logs);
})
.catch(function () {
renderLogs([]);
})
.finally(function () {
isLoading = false;
});
}
function postSearchLog(keyword) {
var payload = new URLSearchParams();
payload.append('keyword', keyword);
try {
if (navigator.sendBeacon) {
return navigator.sendBeacon(saveApiUrl, payload);
}
} catch (e) {
// sendBeacon 실패 시 keepalive fetch로 폴백
}
fetch(saveApiUrl, {
method: 'POST',
credentials: 'same-origin',
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
body: payload.toString(),
keepalive: true
}).catch(function () {
// 저장 실패 시 검색 이동은 막지 않는다.
});
return false;
}
[desktopInput, mobileInput].forEach(function (inputEl) {
if (!inputEl) return;
inputEl.addEventListener('focus', function () {
loadRecentLogs(false);
});
inputEl.addEventListener('click', function () {
loadRecentLogs(false);
});
});
searchForms.forEach(function (formEl) {
formEl.addEventListener('submit', function (e) {
var inputEl = formEl.querySelector('input[name="q"]');
var keyword = String((inputEl && inputEl.value) || '').trim();
if (!keyword) {
e.preventDefault();
if (inputEl) inputEl.focus();
return;
}
if (formEl.dataset.searchLogSubmitting === '1') {
return;
}
var now = Date.now();
var normalized = keyword.toLowerCase();
if (lastSavedKeyword === normalized && (now - lastSavedAt) < 1500) {
return;
}
formEl.dataset.searchLogSubmitting = '1';
lastSavedKeyword = normalized;
lastSavedAt = now;
postSearchLog(keyword);
// 짧은 시간 후 플래그 해제: 연속 검색 시 다음 submit 허용
setTimeout(function () {
delete formEl.dataset.searchLogSubmitting;
}, 1200);
});
});
});
</script>
+153
View File
@@ -0,0 +1,153 @@
<?php
$navPath = basename(parse_url($_SERVER['REQUEST_URI'] ?? '', PHP_URL_PATH) ?: '');
parse_str(parse_url($_SERVER['REQUEST_URI'] ?? '', PHP_URL_QUERY) ?: '', $navQuery);
$navCate = $navQuery['cate'] ?? '';
/** depth01: 현재 스크립트가 해당 php와 같으면 부모 li active (서브메뉴 페이지 포함) */
function nav_active_depth01($phpFile) {
global $navPath;
return $navPath === $phpFile ? ' class="active"' : '';
}
/** depth02: 스크립트 + cate 쿼리까지 일치 */
function nav_active_depth02($phpFile, $cate) {
global $navPath, $navCate;
return ($navPath === $phpFile && $navCate === $cate) ? ' class="active"' : '';
}
?>
<div class="nav-group">
<ul class="depth01">
<li<?php echo nav_active_depth01('myclass.php'); echo nav_active_depth01('myclass_list.php');?>>
<a href="/skin/myclass.php"> 마이클래스 </a>
<div class="state-box">
<span class="unit"><?=$header_myclass_percent?><small>%</small></span>
<span class="progress">
<span class="progress-bar" style="width:<?=$header_myclass_percent?>%"></span>
</span>
</div>
</li>
<li<?php echo nav_active_depth01('onboarding.php'); ?>>
<a href="/skin/onboarding.php" data-nav="onboarding"> 온보딩 </a>
<div class="state-box">
<span class="unit" id="onboardingNavPercent" style="left: calc(0% - 3px);"><?=$header_onboarding_percent?><small>%</small></span>
<span class="progress">
<span class="progress-bar" id="onboardingNavBar" style="width: <?=$header_onboarding_percent?>%"></span>
</span>
</div>
</li>
<li<?php echo nav_active_depth01('learning.php'); ?>>
<a href="/skin/learning.php"> 법정교육 </a>
<div class="state-box">
<span class="unit"><?=$header_legal_percent?><small>%</small></span>
<span class="progress">
<span class="progress-bar" style="width: <?=$header_legal_percent?>%"></span>
</span>
</div>
</li>
<li<?php echo nav_active_depth01('leadership.php'); ?>>
<a href="/skin/leadership.php">리더십</a>
<ul class="depth02">
<li<?php echo nav_active_depth02('leadership.php', 'CA200L01'); ?>>
<a href="/skin/leadership.php?cate=CA200L01" >
<span class="ico-box">
<img src="/img/ico/ico_leadership_01.svg" />
</span>
리더십 시작하기
</a>
</li>
<li<?php echo nav_active_depth02('leadership.php', 'CA200L02'); ?>>
<a href="/skin/leadership.php?cate=CA200L02" >
<span class="ico-box">
<img src="/img/ico/ico_leadership_02.svg" />
</span>
셀프 리더십
</a>
</li>
<li<?php echo nav_active_depth02('leadership.php', 'CA200L03'); ?>>
<a href="/skin/leadership.php?cate=CA200L03" >
<span class="ico-box">
<img src="/img/ico/ico_leadership_03.svg" />
</span>
팀 리더십
</a>
</li>
<li<?php echo nav_active_depth02('leadership.php', 'CA200L04'); ?>>
<a href="/skin/leadership.php?cate=CA200L04" >
<span class="ico-box">
<img src="/img/ico/ico_leadership_04.svg" />
</span>
실전조직 리더십
</a>
</li>
<li<?php echo nav_active_depth02('leadership.php', 'CA200L05'); ?>>
<a href="/skin/leadership.php?cate=CA200L05" >
<span class="ico-box">
<img src="/img/ico/ico_leadership_05.svg" />
</span>
리더케이스탐구
</a>
</li>
</ul>
</li>
<li<?php echo nav_active_depth01('insight.php'); ?>>
<a href="/skin/insight.php">인사이트 </a>
<!-- 2depth -->
<ul class="depth02">
<li<?php echo nav_active_depth02('insight.php', 'CA200I01'); ?>>
<a href="/skin/insight.php?cate=CA200I01" >
<span class="ico-box">
<img src="/img/ico/ico_insight_01.svg" />
</span>
경제와 사회
</a>
</li>
<li<?php echo nav_active_depth02('insight.php', 'CA200I02'); ?>>
<a href="/skin/insight.php?cate=CA200I02" >
<span class="ico-box">
<img src="/img/ico/ico_insight_02.svg" />
</span>
기술과 미래
</a>
</li>
<li<?php echo nav_active_depth02('insight.php', 'CA200I03'); ?>>
<a href="/skin/insight.php?cate=CA200I03" >
<span class="ico-box">
<img src="/img/ico/ico_insight_03.svg" />
</span>
스킬 업
</a>
</li>
<li<?php echo nav_active_depth02('insight.php', 'CA200I04'); ?>>
<a href="/skin/insight.php?cate=CA200I04" >
<span class="ico-box">
<img src="/img/ico/ico_insight_04.svg" />
</span>
행복과 건강
</a>
</li>
<li<?php echo nav_active_depth02('insight.php', 'CA200I05'); ?>>
<a href="/skin/insight.php?cate=CA200I05" >
<span class="ico-box">
<img src="/img/ico/ico_insight_05.svg" />
</span>
피플스토리
</a>
</li>
<li<?php echo nav_active_depth02('insight.php', 'CA200I06'); ?>>
<a href="/skin/insight.php?cate=CA200I06" >
<span class="ico-box">
<img src="/img/ico/ico_insight_06.svg" />
</span>
라이프
</a>
</li>
</ul>
</li>
<li<?php echo nav_active_depth01('biztrend.php'); ?>>
<a href="/skin/biztrend.php">비즈트렌드</a>
</li>
</ul>
</div>
+139
View File
@@ -0,0 +1,139 @@
<div class="nav-group">
<ul class="depth01">
<li>
<a href="/edu/skin/myclass.php"> 마이클래스 </a>
<div class="state-box">
<span class="unit">0<small>%</small></span>
<span class="progress">
<span class="progress-bar" style="width: 0%"></span>
</span>
</div>
</li>
<li>
<a href="/edu/skin/onboarding.php" data-nav="onboarding"> 온보딩 </a>
<div class="state-box">
<span class="unit" id="onboardingNavPercent" style="left: calc(0% - 3px);">0<small>%</small></span>
<span class="progress">
<span class="progress-bar" id="onboardingNavBar" style="width: 0%"></span>
</span>
</div>
</li>
<li>
<a href="/edu/skin/learning.php"> 법정교육 </a>
<div class="state-box">
<span class="unit">0<small>%</small></span>
<span class="progress">
<span class="progress-bar" style="width: 0%"></span>
</span>
</div>
</li>
<li>
<a href="/edu/skin/leadership.php">리더십</a>
<ul class="depth02">
<li>
<a href="/edu/skin/leadership.php?cate=CA200L01" >
<span class="ico-box">
<img src="/edu/img/ico/ico_leadership_01.svg" />
</span>
리더십 입문
</a>
</li>
<li>
<a href="/edu/skin/leadership.php?cate=CA200L02" >
<span class="ico-box">
<img src="/edu/img/ico/ico_leadership_02.svg" />
</span>
셀프 리더십
</a>
</li>
<li>
<a href="/edu/skin/leadership.php?cate=CA200L03" >
<span class="ico-box">
<img src="/edu/img/ico/ico_leadership_03.svg" />
</span>
리더십
</a>
</li>
<li>
<a href="/edu/skin/leadership.php?cate=CA200L04" >
<span class="ico-box">
<img src="/edu/img/ico/ico_leadership_04.svg" />
</span>
실전 리더십
</a>
</li>
<li>
<a href="/edu/skin/leadership.php?cate=CA200L05" >
<span class="ico-box">
<img src="/edu/img/ico/ico_leadership_05.svg" />
</span>
인물탐구
</a>
</li>
</ul>
</li>
<li>
<a href="/edu/skin/insight.php">인사이트 </a>
<!-- 2depth -->
<ul class="depth02">
<li>
<a href="/edu/skin/insight.php?cate=CA200I01" >
<span class="ico-box">
<img src="/edu/img/ico/ico_economy.svg" />
</span>
경제와 사회
</a>
</li>
<li>
<a href="/edu/skin/insight.php?cate=CA200I02" >
<span class="ico-box">
<img src="/edu/img/ico/ico_future.svg" />
</span>
기술과 미래
</a>
</li>
<li>
<a href="/edu/skin/insight.php?cate=CA200I03" >
<span class="ico-box">
<img src="/edu/img/ico/ico_trend.svg" />
</span>
트렌드
</a>
</li>
<li>
<a href="/edu/skin/insight.php?cate=CA200I04" >
<span class="ico-box">
<img src="/edu/img/ico/ico_health.svg" />
</span>
행복과 건강
</a>
</li>
<li>
<a href="/edu/skin/insight.php?cate=CA200I05" >
<span class="ico-box">
<img src="/edu/img/ico/ico_people.svg" />
</span>
피플스토리
</a>
</li>
<li>
<a href="/edu/skin/insight.php?cate=CA200I06" >
<span class="ico-box">
<img src="/edu/img/ico/ico_life.svg" />
</span>
라이프
</a>
</li>
</ul>
</li>
<li>
<a href="/edu/skin/biztrend.php">비즈트렌드</a>
</li>
</ul>
</div>