Initial commit

This commit is contained in:
Porawit Dongwang
2026-09-16 23:20:08 +07:00
commit 0041668dbb
32577 changed files with 3687927 additions and 0 deletions
@@ -0,0 +1,154 @@
<?php require_once APP_ROOT . '/app/Views/layouts/header.php'; ?>
<div class="flex flex-col md:flex-row md:items-center md:justify-between mb-6 gap-4">
<div>
<h2 class="text-2xl font-bold text-slate-800 dark:text-white">ประวัติการใช้งานระบบ (Logs)</h2>
<p class="text-slate-500 dark:text-slate-400 text-sm mt-1">ตรวจสอบประวัติการเข้าใช้งานและการทำรายการต่างๆ ของผู้ใช้</p>
</div>
<a href="<?= BASE_URL ?>/users" class="inline-flex items-center justify-center px-4 py-2.5 bg-slate-100 dark:bg-slate-700 hover:bg-slate-200 dark:hover:bg-slate-600 text-slate-700 dark:text-slate-200 text-sm font-medium rounded-xl transition-colors shadow-sm w-full md:w-auto">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-4 h-4 mr-2"><path stroke-linecap="round" stroke-linejoin="round" d="M9 15L3 9m0 0l6-6M3 9h12a6 6 0 010 12h-3" /></svg>
กลับไปจัดการผู้ใช้
</a>
</div>
<!-- Filters -->
<div class="bg-white dark:bg-slate-800 p-4 rounded-xl shadow-sm border border-slate-100 dark:border-slate-700 mb-6">
<form action="<?= BASE_URL ?>/users/logs" method="GET" class="flex flex-col md:flex-row gap-4">
<div class="flex-1">
<label class="block text-xs font-medium text-slate-500 dark:text-slate-400 mb-1">ผู้ใช้งาน</label>
<select name="user_id" class="block w-full rounded-lg border-slate-200 dark:border-slate-600 bg-slate-50 dark:bg-slate-900/50 text-slate-700 dark:text-slate-300 text-sm py-2 px-3 focus:ring-sky-500">
<option value="">ทั้งหมด</option>
<?php foreach($users as $u): ?>
<option value="<?= $u['id'] ?>" <?= ($filters['user_id'] ?? '') == $u['id'] ? 'selected' : '' ?>>
<?= htmlspecialchars($u['first_name'] . ' ' . $u['last_name'] . ' (' . $u['username'] . ')') ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="flex-1">
<label class="block text-xs font-medium text-slate-500 dark:text-slate-400 mb-1">ประเภทรายการ</label>
<select name="action" class="block w-full rounded-lg border-slate-200 dark:border-slate-600 bg-slate-50 dark:bg-slate-900/50 text-slate-700 dark:text-slate-300 text-sm py-2 px-3 focus:ring-sky-500">
<option value="">ทั้งหมด</option>
<option value="LOGIN" <?= ($filters['action'] ?? '') == 'LOGIN' ? 'selected' : '' ?>>Login</option>
<option value="CREATE_USER" <?= ($filters['action'] ?? '') == 'CREATE_USER' ? 'selected' : '' ?>>เพิ่มผู้ใช้งาน</option>
<option value="UPDATE_USER" <?= ($filters['action'] ?? '') == 'UPDATE_USER' ? 'selected' : '' ?>>แก้ไขข้อมูลผู้ใช้</option>
<option value="TOGGLE_STATUS" <?= ($filters['action'] ?? '') == 'TOGGLE_STATUS' ? 'selected' : '' ?>>เปลี่ยนสถานะสิทธิ์</option>
<option value="UPDATE_SETTINGS" <?= ($filters['action'] ?? '') == 'UPDATE_SETTINGS' ? 'selected' : '' ?>>อัปเดตการตั้งค่าระบบ</option>
</select>
</div>
<div class="flex-1">
<label class="block text-xs font-medium text-slate-500 dark:text-slate-400 mb-1">วันที่เริ่มต้น</label>
<input type="date" name="date_start" value="<?= htmlspecialchars($filters['date_start'] ?? '') ?>" class="block w-full rounded-lg border-slate-200 dark:border-slate-600 bg-slate-50 dark:bg-slate-900/50 text-slate-700 dark:text-slate-300 text-sm py-2 px-3 focus:ring-sky-500">
</div>
<div class="flex-1">
<label class="block text-xs font-medium text-slate-500 dark:text-slate-400 mb-1">วันที่สิ้นสุด</label>
<input type="date" name="date_end" value="<?= htmlspecialchars($filters['date_end'] ?? '') ?>" class="block w-full rounded-lg border-slate-200 dark:border-slate-600 bg-slate-50 dark:bg-slate-900/50 text-slate-700 dark:text-slate-300 text-sm py-2 px-3 focus:ring-sky-500">
</div>
<div class="flex items-end">
<button type="submit" class="w-full md:w-auto px-4 py-2 bg-sky-500 hover:bg-sky-600 text-white text-sm font-medium rounded-lg transition-colors shadow-sm">
ค้นหา
</button>
<a href="<?= BASE_URL ?>/users/logs" class="ml-2 px-4 py-2 bg-slate-200 dark:bg-slate-700 hover:bg-slate-300 dark:hover:bg-slate-600 text-slate-700 dark:text-slate-300 text-sm font-medium rounded-lg transition-colors text-center">
ล้างค่า
</a>
</div>
</form>
</div>
<div class="bg-white dark:bg-slate-800 rounded-2xl shadow-sm border border-slate-100 dark:border-slate-700 overflow-hidden">
<div class="flex justify-end p-4 pb-0">
<label class="inline-flex items-center cursor-pointer">
<input type="checkbox" id="togglePrefix" class="w-4 h-4 text-indigo-600 bg-slate-100 border-slate-300 rounded focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:ring-offset-slate-800 focus:ring-2 dark:bg-slate-700 dark:border-slate-600">
<span class="ml-2 text-sm font-medium text-slate-700 dark:text-slate-300">แสดงคำนำหน้าชื่อ</span>
</label>
</div>
<div class="overflow-x-auto p-4 pt-2">
<table class="w-full text-left text-sm text-slate-600 dark:text-slate-300">
<thead class="bg-slate-50 dark:bg-slate-900/50 text-slate-500 dark:text-slate-400 text-xs uppercase font-semibold">
<tr>
<th class="px-6 py-4">วัน-เวลา</th>
<th class="px-6 py-4">ผู้ใช้งาน</th>
<th class="px-6 py-4">รายการ (Action)</th>
<th class="px-6 py-4">รายละเอียด</th>
<th class="px-6 py-4">IP Address</th>
</tr>
</thead>
<tbody class="divide-y divide-slate-100 dark:divide-slate-700">
<?php if (empty($logs)): ?>
<tr>
<td colspan="5" class="px-6 py-8 text-center text-slate-500 dark:text-slate-400">
ไม่พบข้อมูลประวัติการใช้งานตามเงื่อนไขที่ค้นหา
</td>
</tr>
<?php else: ?>
<?php foreach ($logs as $log): ?>
<tr class="hover:bg-slate-50 dark:hover:bg-slate-700/50 transition-colors">
<td class="px-6 py-4 whitespace-nowrap text-xs text-slate-500 dark:text-slate-400">
<?= date('d/m/Y H:i:s', strtotime($log['created_at'])) ?>
</td>
<td class="px-6 py-4" data-sort="<?= htmlspecialchars(preg_replace('/^(นาย|นางสาว|นาง|ว่าที่ร้อยตรี|น\.ส\.|นพ\.|พญ\.|ดร\.)\s*/u', '', trim($log['first_name']))) ?>">
<?php
$rawName = trim($log['first_name']);
$prefix = '';
$bodyName = $rawName;
if (preg_match('/^(นาย|นางสาว|นาง|ว่าที่ร้อยตรี|น\.ส\.|นพ\.|พญ\.|ดร\.)\s*(.*)$/u', $rawName, $matches)) {
$prefix = $matches[1];
$bodyName = $matches[2];
}
?>
<?php if ($log['user_id']): ?>
<div class="font-medium text-slate-800 dark:text-slate-200">
<span class="name-prefix hidden"><?= htmlspecialchars($prefix) ?></span><?= htmlspecialchars($bodyName . ' ' . $log['last_name']) ?>
</div>
<div class="text-xs text-slate-500">@<?= htmlspecialchars($log['username']) ?></div>
<?php else: ?>
<div class="font-medium text-sky-600 dark:text-sky-400">ตู้ Kiosk</div>
<div class="text-xs text-slate-500">Public Access</div>
<?php endif; ?>
</td>
<td class="px-6 py-4">
<?php
$actionColors = [
'LOGIN' => 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400',
'CREATE_USER' => 'bg-sky-100 text-sky-700 dark:bg-sky-900/30 dark:text-sky-400',
'UPDATE_USER' => 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-400',
'TOGGLE_STATUS' => 'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400',
'UPDATE_SETTINGS' => 'bg-indigo-100 text-indigo-700 dark:bg-indigo-900/30 dark:text-indigo-400',
'KIOSK_PRINT_SLIP' => 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400',
'KIOSK_PRINT_TAX' => 'bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-400'
];
$color = $actionColors[$log['action']] ?? 'bg-slate-100 text-slate-700 dark:bg-slate-700 dark:text-slate-300';
?>
<span class="inline-flex items-center px-2.5 py-1 rounded-full text-xs font-semibold <?= $color ?>">
<?= htmlspecialchars($log['action']) ?>
</span>
</td>
<td class="px-6 py-4 text-sm text-slate-600 dark:text-slate-400 max-w-md truncate" title="<?= htmlspecialchars($log['description']) ?>">
<?= htmlspecialchars($log['description']) ?>
</td>
<td class="px-6 py-4 text-xs font-mono text-slate-500">
<?= htmlspecialchars($log['ip_address']) ?>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script>
$(document).ready(function() {
// Checkbox toggle prefix
$('#togglePrefix').on('change', function() {
if ($(this).is(':checked')) {
$('.name-prefix').removeClass('hidden');
} else {
$('.name-prefix').addClass('hidden');
}
});
});
</script>
<?php require_once APP_ROOT . '/app/Views/layouts/footer.php'; ?>