250 lines
12 KiB
PHP
250 lines
12 KiB
PHP
<?php
|
|
require_once __DIR__ . '/../../bbs/auth.php';
|
|
edu_require_login();
|
|
|
|
include_once 'header.php';
|
|
require_once __DIR__ . '/../../bbs/db_conn.php';
|
|
|
|
$search_year = $_GET['year'] ?? date('Y');
|
|
$search_sys_comp = $_GET['sys_comp'] ?? '';
|
|
// 만약 사용자가 처음 페이지에 들어왔거나(GET값이 없음), '전체'를 누른 게 아니라면 초기값 설정
|
|
|
|
if (empty($search_sys_comp) && !isset($_GET['sys_comp'])) {
|
|
$search_sys_comp = $sys_comp_code;
|
|
}
|
|
$search_comp = $_GET['comp'] ?? '';
|
|
$search_dept = $_GET['dept'] ?? '';
|
|
$search_text = $_GET['search_text'] ?? '';
|
|
$search_quarter = $_GET['quarter'] ?? '';
|
|
|
|
$corp_list = [];
|
|
$rows = [];
|
|
|
|
try {
|
|
$pdo = db_conn();
|
|
|
|
// 법인 리스트 가져오기
|
|
try {
|
|
$stmt_corp = $pdo->query("CALL proc_get_code2_list('CO100')");
|
|
$corp_list = $stmt_corp->fetchAll(PDO::FETCH_ASSOC);
|
|
while ($stmt_corp->nextRowset()) {}
|
|
unset($stmt_corp);
|
|
} catch (Exception $eProc) {
|
|
$corp_list = [];
|
|
}
|
|
|
|
// 권한에 따른 법인 목록 제어
|
|
// LE10001: 전체권한 → 전체 법인 표시
|
|
// LE10002: 법인권한 → 본인 법인($sys_comp_code)만 표시, 검색값도 강제 고정
|
|
// 그 외: 법인 목록 비움
|
|
// 기준법인 초기값은 로그인한 사용자의 법인으로 설정
|
|
|
|
|
|
if ($auth_level === 'LE10002') {
|
|
$corp_list = array_values(array_filter($corp_list, fn($c) => $c['code'] === $sys_comp_code));
|
|
$search_sys_comp = $sys_comp_code;
|
|
$search_comp = $sys_comp_code;
|
|
} elseif ($auth_level !== 'LE10001') {
|
|
$corp_list = [];
|
|
}
|
|
|
|
// 프로시저 호출로 데이터 가져오기
|
|
$stmt = $pdo->prepare("CALL proc_get_learner_status(?, ?, ?, ?, ?, ?)");
|
|
$stmt->execute([$search_year, $search_sys_comp, $search_comp, $search_dept, $search_text, $search_quarter]);
|
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
while ($stmt->nextRowset()) {}
|
|
unset($stmt);
|
|
|
|
} catch (Exception $e) {
|
|
$db_error = $e->getMessage();
|
|
}
|
|
?>
|
|
<main class="max-w-[1600px] mx-auto p-6">
|
|
|
|
<header class="mb-6">
|
|
<h2 class="text-2xl font-bold text-gray-800 italic">학습자관리</h2>
|
|
</header>
|
|
|
|
<section class="bg-white p-6 rounded-xl border border-gray-200 shadow-sm mb-6">
|
|
<form id="searchForm" method="GET" action="member_list.php"
|
|
class="grid grid-cols-1 md:grid-cols-6 gap-4">
|
|
<div>
|
|
<label class="block text-xs font-bold text-gray-500 mb-2">기준년도</label>
|
|
<input type="text" id="year" name="year" value="<?= htmlspecialchars($search_year) ?>" placeholder="YYYY"
|
|
class="w-full border-gray-200 rounded-lg text-sm p-2.5 bg-gray-50"
|
|
onkeydown="if(event.key==='Enter') this.form.submit();">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-bold text-gray-500 mb-2">기준법인</label>
|
|
<?php if ($auth_level === 'LE10002'): ?>
|
|
<?php $fixed_corp_name = !empty($corp_list) ? htmlspecialchars($corp_list[0]['name']) : htmlspecialchars($sys_comp_code); ?>
|
|
<input type="hidden" name="sys_comp" value="<?= htmlspecialchars($sys_comp_code) ?>">
|
|
<input type="text" value="<?= $fixed_corp_name ?>" readonly
|
|
class="w-full border-gray-200 rounded-lg text-sm p-2.5 bg-gray-100 text-gray-600 cursor-not-allowed">
|
|
<?php else: ?>
|
|
<select id="sys_comp" name="sys_comp" onchange="this.form.submit()"
|
|
class="w-full border-gray-200 rounded-lg text-sm p-2.5 bg-gray-50">
|
|
<option value="">전체</option>
|
|
<?php foreach ($corp_list as $corp): ?>
|
|
<option value="<?= htmlspecialchars($corp['code']) ?>" <?= $search_sys_comp === $corp['code'] ? 'selected' : '' ?>>
|
|
<?= htmlspecialchars($corp['name']) ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
<?php endif; ?>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-bold text-gray-500 mb-2">소속회사</label>
|
|
<?php if ($auth_level === 'LE10002'): ?>
|
|
<input type="hidden" name="comp" value="<?= htmlspecialchars($sys_comp_code) ?>">
|
|
<input type="text" value="<?= $fixed_corp_name ?>" readonly
|
|
class="w-full border-gray-200 rounded-lg text-sm p-2.5 bg-gray-100 text-gray-600 cursor-not-allowed">
|
|
<?php else: ?>
|
|
<select id="comp" name="comp" onchange="this.form.submit()"
|
|
class="w-full border-gray-200 rounded-lg text-sm p-2.5 bg-gray-50">
|
|
<option value="">전체</option>
|
|
<?php foreach ($corp_list as $corp): ?>
|
|
<option value="<?= htmlspecialchars($corp['code']) ?>" <?= $search_comp === $corp['code'] ? 'selected' : '' ?>>
|
|
<?= htmlspecialchars($corp['name']) ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
<?php endif; ?>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-bold text-gray-500 mb-2">부서명</label>
|
|
<input type="text" id="dept" name="dept" value="<?= htmlspecialchars($search_dept) ?>"
|
|
class="w-full border-gray-200 rounded-lg text-sm p-2.5 bg-gray-50"
|
|
onkeydown="if(event.key==='Enter') this.form.submit();">
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-bold text-gray-500 mb-2">분기</label>
|
|
<select id="quarter" name="quarter" onchange="this.form.submit()"
|
|
class="w-full border-gray-200 rounded-lg text-sm p-2.5 bg-gray-50">
|
|
<option value="">전체</option>
|
|
<option value="CA200Q01" <?= $search_quarter === 'CA200Q01' ? 'selected' : '' ?>>1분기</option>
|
|
<option value="CA200Q02" <?= $search_quarter === 'CA200Q02' ? 'selected' : '' ?>>2분기</option>
|
|
<option value="CA200Q03" <?= $search_quarter === 'CA200Q03' ? 'selected' : '' ?>>3분기</option>
|
|
<option value="CA200Q04" <?= $search_quarter === 'CA200Q04' ? 'selected' : '' ?>>4분기</option>
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label class="block text-xs font-bold text-gray-500 mb-2">성명/사번</label>
|
|
<div class="relative">
|
|
<input type="text" id="search_text" name="search_text" value="<?= htmlspecialchars($search_text) ?>" placeholder="성명 또는 사번"
|
|
class="w-full border-gray-200 rounded-lg text-sm p-2.5 pl-8 bg-gray-50"
|
|
onkeydown="if(event.key==='Enter') this.form.submit();">
|
|
<i class="fa-solid fa-magnifying-glass absolute left-3 top-3 text-gray-400 text-xs"></i>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</section>
|
|
|
|
<section class="bg-white rounded-xl border border-gray-200 shadow-sm overflow-hidden mb-12">
|
|
<div class="overflow-x-auto">
|
|
<?php if (isset($db_error)): ?>
|
|
<div class="p-4 bg-red-50 border border-red-200 rounded-md">
|
|
<p class="text-red-600 text-sm">데이터베이스 오류: <?= htmlspecialchars($db_error) ?></p>
|
|
</div>
|
|
<?php endif; ?>
|
|
<table class="w-full text-sm text-left">
|
|
<thead class="bg-gray-50 border-b border-gray-200 text-gray-500 font-bold">
|
|
<tr>
|
|
<th class="p-4">NO</th>
|
|
<th class="p-4">사번</th>
|
|
<th class="p-4">성명</th>
|
|
<th class="p-4">소속법인</th>
|
|
<th class="p-4">근무법인</th>
|
|
<th class="p-4">부서</th>
|
|
<th class="p-4 w-40">마이클래스</th>
|
|
<th class="p-4 w-40">법정의무교육</th>
|
|
<th class="p-4">학습시간</th>
|
|
<th class="p-4">최근 접속일</th>
|
|
<th class="p-4 text-center">학습 레벨</th>
|
|
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-gray-100">
|
|
<?php if (count($rows) === 0): ?>
|
|
<tr>
|
|
<td colspan="11" class="p-8 text-center text-gray-400">데이터가 없습니다.</td>
|
|
</tr>
|
|
<?php else: ?>
|
|
<?php foreach ($rows as $row): ?>
|
|
<tr class="hover:bg-blue-50/30 transition">
|
|
<td class="p-4 text-gray-500 font-medium"><?= htmlspecialchars($row['no'] ?? '') ?></td>
|
|
<td class="p-4 text-gray-500 font-medium"><?= htmlspecialchars($row['member_id'] ?? '') ?></td>
|
|
<td class="p-4 font-bold text-gray-800"><?= htmlspecialchars($row['name'] ?? '') ?></td>
|
|
<td class="p-4"><?= htmlspecialchars($row['belong_name'] ?? '') ?></td>
|
|
<td class="p-4"><?= htmlspecialchars($row['working_name'] ?? '') ?></td>
|
|
<td class="p-4"><?= htmlspecialchars($row['dept_name'] ?? '') ?></td>
|
|
<td class="p-4">
|
|
<div class="flex items-center space-x-2">
|
|
<div class="progress-bar flex-1 h-2 bg-gray-100 rounded-full overflow-hidden">
|
|
<div class="progress-fill bg-blue-500 h-full" style="width: <?= (int)($row['progress_rate1'] ?? 0) ?>%;"></div>
|
|
</div>
|
|
<span class="text-[10px] font-bold text-blue-600"><?= (int)($row['progress_rate1'] ?? 0) ?>%</span>
|
|
</div>
|
|
</td>
|
|
<td class="p-4">
|
|
<div class="flex items-center space-x-2">
|
|
<div class="progress-bar flex-1 h-2 bg-gray-100 rounded-full overflow-hidden">
|
|
<div class="progress-fill bg-teal-500 h-full" style="width: <?= (int)($row['progress_rate2'] ?? 0) ?>%;"></div>
|
|
</div>
|
|
<span class="text-[10px] font-bold text-teal-600"><?= (int)($row['progress_rate2'] ?? 0) ?>%</span>
|
|
</div>
|
|
</td>
|
|
<td class="p-4 font-bold"><?= htmlspecialchars($row['all_tm'] ?? '') ?></td>
|
|
<td class="p-4 text-gray-400"><?= htmlspecialchars($row['last_login_time'] ?? '-') ?></td>
|
|
<td class="p-4 text-center">
|
|
<?php
|
|
$all_tm_text = $row['all_tm'] ?? '';
|
|
preg_match('/(\d+)시간/', $all_tm_text, $matches);
|
|
$total_hours = isset($matches[1]) ? (int)$matches[1] : 0;
|
|
|
|
$level = $total_hours >= 40 ? 'Master' : ($total_hours >= 20 ? 'Elite' : ($total_hours >= 8 ? 'Learner' : 'Rookie'));
|
|
$level_color = $level == 'Master' ? 'purple' : ($level == 'Elite' ? 'blue' : ($level == 'Learner' ? 'green' : 'gray'));
|
|
$levelClass = "bg-{$level_color}-100 text-{$level_color}-600";
|
|
|
|
$levelIcon = '';
|
|
switch ($level) {
|
|
case 'Master': $levelIcon = 'fa-crown'; break;
|
|
case 'Elite': $levelIcon = 'fa-star'; break;
|
|
case 'Learner': $levelIcon = 'fa-graduation-cap'; break;
|
|
case 'Rookie':
|
|
default: $levelIcon = 'fa-seedling'; break;
|
|
}
|
|
?>
|
|
<span class="px-2 py-1 <?= $levelClass ?> rounded-md text-[10px] font-bold uppercase">
|
|
<i class="fa-solid <?= $levelIcon ?> mr-1"></i><?= $level ?>
|
|
</span>
|
|
</td>
|
|
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
|
|
</section>
|
|
|
|
<section class="mt-6 flex flex-wrap gap-4 justify-center py-4 bg-white rounded-xl border border-dashed border-gray-300">
|
|
<div class="flex items-center text-xs font-medium text-gray-500">
|
|
<span class="w-3 h-3 rounded-full bg-gray-200 mr-2"></span> Rookie: 0-8시간
|
|
</div>
|
|
<div class="flex items-center text-xs font-medium text-gray-500">
|
|
<span class="w-3 h-3 rounded-full bg-green-200 mr-2"></span> Learner: 8-20시간
|
|
</div>
|
|
<div class="flex items-center text-xs font-medium text-gray-500">
|
|
<span class="w-3 h-3 rounded-full bg-blue-200 mr-2"></span> Elite: 20-40시간
|
|
</div>
|
|
<div class="flex items-center text-xs font-medium text-gray-500">
|
|
<span class="w-3 h-3 rounded-full bg-purple-200 mr-2"></span> Master: 40시간 이상
|
|
</div>
|
|
</section>
|
|
</main>
|
|
</body>
|
|
</html>
|