429 lines
22 KiB
PHP
429 lines
22 KiB
PHP
<?php
|
|
session_start();
|
|
if (!isset($_SESSION["loggedin"]) || $_SESSION["loggedin"] !== true) {
|
|
header("location: index.php");
|
|
exit;
|
|
}
|
|
|
|
require_once 'includes/db_assessment.php';
|
|
|
|
$cid = $_SESSION['cid'];
|
|
|
|
// ดึงปีปัจจุบันจากตาราง it_years
|
|
$stmt = $pdo_assess->query("SELECT year_text FROM it_years WHERE is_active = 1 LIMIT 1");
|
|
$current_year = $stmt->fetchColumn();
|
|
|
|
if (!$current_year) {
|
|
echo "<!DOCTYPE html><html lang='th'><head><meta charset='UTF-8'><title>ระบบประเมิน</title><link href='https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css' rel='stylesheet'></head><body class='bg-light d-flex align-items-center justify-content-center vh-100'><div class='text-center'><h3>ขณะนี้ยังไม่มีการเปิดรับทำแบบประเมินประจำปี</h3><a href='actions/logout.php' class='btn btn-secondary mt-3'>ออกจากระบบ</a></div></body></html>";
|
|
exit;
|
|
}
|
|
|
|
// ตรวจสอบว่าเคยทำประเมินในปีนี้หรือยัง
|
|
$has_assessed = false;
|
|
$assessed_date = null;
|
|
try {
|
|
$stmt = $pdo_assess->prepare("SELECT created_at FROM it_assessments WHERE hr_cid = :cid AND assess_year = :year LIMIT 1");
|
|
$stmt->execute(['cid' => $cid, 'year' => $current_year]);
|
|
$result = $stmt->fetch();
|
|
if ($result) {
|
|
$has_assessed = true;
|
|
$assessed_date = date('d/m/Y H:i', strtotime($result['created_at']));
|
|
}
|
|
} catch (PDOException $e) {
|
|
}
|
|
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="th">
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>แบบประเมิน - หน่วยงานสุขภาพดิจิทัล</title>
|
|
<!-- Favicon -->
|
|
<link rel="icon" type="image/png" href="assets/images/logo.png">
|
|
<!-- Bootstrap 5 -->
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<!-- Google Fonts -->
|
|
<link href="https://fonts.googleapis.com/css2?family=Sarabun:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
|
<!-- SweetAlert2 -->
|
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
|
<style>
|
|
body {
|
|
font-family: 'Sarabun', sans-serif;
|
|
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
|
color: #333;
|
|
min-height: 100vh;
|
|
}
|
|
|
|
.navbar-custom {
|
|
background: rgba(255, 255, 255, 0.9);
|
|
backdrop-filter: blur(10px);
|
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
.form-container {
|
|
background: #ffffff;
|
|
border-radius: 20px;
|
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08);
|
|
padding: 3rem;
|
|
margin-top: 2rem;
|
|
margin-bottom: 3rem;
|
|
border: 1px solid rgba(255, 255, 255, 0.4);
|
|
}
|
|
|
|
.header-title {
|
|
background: linear-gradient(135deg, #008f91, #005d68);
|
|
color: white;
|
|
padding: 2rem;
|
|
border-radius: 15px;
|
|
text-align: center;
|
|
margin-bottom: 2rem;
|
|
box-shadow: 0 8px 20px rgba(0, 143, 145, 0.2);
|
|
}
|
|
|
|
.section-title {
|
|
color: #007f8b;
|
|
font-weight: 700;
|
|
border-left: 5px solid #007f8b;
|
|
padding-left: 15px;
|
|
margin-top: 2.5rem;
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
.table-custom th {
|
|
background: #12344d;
|
|
color: white;
|
|
text-align: center;
|
|
vertical-align: middle;
|
|
}
|
|
|
|
.table-custom td {
|
|
vertical-align: middle;
|
|
}
|
|
|
|
.table-custom tbody tr:hover {
|
|
background-color: #f0faf9;
|
|
}
|
|
|
|
.radio-custom input[type="radio"] {
|
|
width: 20px;
|
|
height: 20px;
|
|
accent-color: #007f8b;
|
|
}
|
|
|
|
.btn-submit {
|
|
background: linear-gradient(135deg, #008f91, #005d68);
|
|
color: white;
|
|
border: none;
|
|
padding: 12px 30px;
|
|
font-size: 1.1rem;
|
|
border-radius: 50px;
|
|
font-weight: 600;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.btn-submit:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 8px 20px rgba(0, 143, 145, 0.3);
|
|
color: white;
|
|
}
|
|
|
|
.card-done {
|
|
background: white;
|
|
border-radius: 15px;
|
|
padding: 3rem;
|
|
text-align: center;
|
|
margin-top: 5rem;
|
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08);
|
|
}
|
|
|
|
.card-done h3 {
|
|
color: #28a745;
|
|
font-weight: 700;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<nav class="navbar navbar-expand-lg navbar-custom sticky-top">
|
|
<div class="container">
|
|
<a class="navbar-brand fw-bold text-dark d-flex align-items-center" href="#">
|
|
<img src="assets/images/logo.png" alt="Logo" width="40" height="40" class="d-inline-block align-text-top me-2">
|
|
<span>IT Assessment System</span>
|
|
</a>
|
|
<div class="d-flex align-items-center">
|
|
<span class="me-3 fw-bold text-muted">ยินดีต้อนรับ, <?php echo htmlspecialchars($_SESSION['fullname']); ?></span>
|
|
<a href="actions/logout.php" class="btn btn-outline-danger btn-sm rounded-pill px-3">ออกจากระบบ</a>
|
|
<?php if(isset($_SESSION['is_admin']) && $_SESSION['is_admin']): ?>
|
|
<a href="summary.php" class="btn btn-outline-primary btn-sm rounded-pill px-3 ms-2">หน้าสรุปผล (Admin)</a>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<div class="container">
|
|
<?php if ($has_assessed): ?>
|
|
<div class="card-done">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="80" height="80" fill="currentColor" class="bi bi-check-circle-fill text-success mb-3" viewBox="0 0 16 16">
|
|
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z" />
|
|
</svg>
|
|
<h3>ท่านได้ทำแบบประเมินประจำปี <?php echo $current_year; ?> เรียบร้อยแล้ว</h3>
|
|
<p class="text-muted fs-5 mt-3">ทำรายการเมื่อวันที่: <strong><?php echo $assessed_date; ?></strong></p>
|
|
<p class="text-muted">ขอขอบคุณที่ให้ความร่วมมือในการทำแบบประเมินของหน่วยงานสุขภาพดิจิทัล</p>
|
|
</div>
|
|
<?php else: ?>
|
|
<div class="form-container">
|
|
<div class="header-title">
|
|
<h2 class="fw-bold mb-2">แบบประเมินระเบียบปฏิบัติในการรักษาความมั่นคงปลอดภัย<br>ระบบเทคโนโลยีสารสนเทศ</h2>
|
|
<h5 class="mb-0">โรงพยาบาลเกาะสมุย ประจำปี <?php echo $current_year; ?></h5>
|
|
</div>
|
|
|
|
<div class="alert alert-info border-0 bg-info bg-opacity-10 text-dark">
|
|
<strong>คำอธิบาย:</strong> แบบประเมินมี 4 ส่วน กรุณาตอบตามความเป็นจริงเพื่อกลุ่มงานสุขภาพดิจิทัลจะนำผลการประเมินไปวิเคราะห์เพื่อจัดการความมั่นคงปลอดภัยระบบเทคโนโลยีสารสนเทศของโรงพยาบาลเกาะสมุย ให้เกิดประโยชน์สูงสุด
|
|
</div>
|
|
|
|
<form id="assessmentForm" action="actions/save_assessment.php" method="POST">
|
|
|
|
<input type="hidden" name="assess_year" value="<?php echo $current_year; ?>">
|
|
|
|
<h4 class="section-title">ส่วนที่ 1 ข้อมูลผู้รับการประเมิน</h4>
|
|
<div class="row g-3">
|
|
<div class="col-md-4">
|
|
<label class="form-label fw-bold">ชื่อ-สกุล</label>
|
|
<input type="text" class="form-control" name="fullname" value="<?php echo htmlspecialchars($_SESSION['fullname']); ?>" readonly>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<label class="form-label fw-bold">ตำแหน่ง</label>
|
|
<input type="text" class="form-control bg-light" name="position" value="<?php echo htmlspecialchars($_SESSION['position'] ?? ''); ?>" readonly>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<label class="form-label fw-bold">หน่วยงาน</label>
|
|
<input type="text" class="form-control bg-light" name="department" value="<?php echo htmlspecialchars($_SESSION['department'] ?? ''); ?>" readonly>
|
|
</div>
|
|
</div>
|
|
|
|
<h4 class="section-title">ส่วนที่ 2 การใช้งานคอมพิวเตอร์</h4>
|
|
<div class="card border-0 shadow-sm mb-4">
|
|
<div class="card-body">
|
|
<div class="form-check mb-2">
|
|
<input class="form-check-input" type="radio" name="computer_use" id="use_yes" value="1" required>
|
|
<label class="form-check-label fw-bold" for="use_yes">
|
|
1. ใช้คอมพิวเตอร์ในการปฏิบัติงาน
|
|
</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="radio" name="computer_use" id="use_no" value="2">
|
|
<label class="form-check-label fw-bold" for="use_no">
|
|
2. ไม่ได้ใช้คอมพิวเตอร์ในการปฏิบัติงาน
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<h4 class="section-title">ส่วนที่ 3 การประเมินการรับรู้ ความเข้าใจ และการปฏิบัติ</h4>
|
|
<div class="table-responsive rounded shadow-sm border border-1 mb-4">
|
|
<table class="table table-bordered table-custom mb-0">
|
|
<thead>
|
|
<tr>
|
|
<th rowspan="2" class="align-middle" style="width: 50%;">ระเบียบปฏิบัติ</th>
|
|
<th colspan="2">การรับรู้</th>
|
|
<th colspan="2">ความเข้าใจ</th>
|
|
<th colspan="2">การปฏิบัติ</th>
|
|
</tr>
|
|
<tr style="background:#173e55;">
|
|
<th>รู้</th>
|
|
<th>ไม่รู้</th>
|
|
<th>เข้าใจ</th>
|
|
<th>ไม่เข้าใจ</th>
|
|
<th>ได้</th>
|
|
<th>ไม่ได้</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php
|
|
$rules = $pdo_assess->query("SELECT * FROM it_rules WHERE is_active = 1 ORDER BY order_no ASC")->fetchAll();
|
|
$n = 1;
|
|
foreach ($rules as $rule):
|
|
$r_id = $rule['id'];
|
|
?>
|
|
<tr>
|
|
<td><?php echo $n . ". " . htmlspecialchars($rule['content']); ?></td>
|
|
<td class="text-center radio-custom"><input type="radio" name="r_<?php echo $r_id; ?>_k" value="yes" required></td>
|
|
<td class="text-center radio-custom"><input type="radio" name="r_<?php echo $r_id; ?>_k" value="no"></td>
|
|
<td class="text-center radio-custom"><input type="radio" name="r_<?php echo $r_id; ?>_u" value="yes" required></td>
|
|
<td class="text-center radio-custom"><input type="radio" name="r_<?php echo $r_id; ?>_u" value="no"></td>
|
|
<td class="text-center radio-custom"><input type="radio" name="r_<?php echo $r_id; ?>_p" value="yes" required></td>
|
|
<td class="text-center radio-custom"><input type="radio" name="r_<?php echo $r_id; ?>_p" value="no"></td>
|
|
</tr>
|
|
<?php
|
|
$n++;
|
|
endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div id="extended_sections">
|
|
<h4 class="section-title">ส่วนที่ 4 แบบประเมินข้อตกลงการให้บริการ (SLA)</h4>
|
|
<div class="alert alert-warning border-0 text-dark" style="background:#fff8e9;">
|
|
<strong>หมายเหตุ:</strong> ส่วนนี้สำหรับเจ้าหน้าที่ที่ใช้คอมพิวเตอร์ในการปฏิบัติงานเท่านั้น
|
|
</div>
|
|
<div class="table-responsive rounded shadow-sm border border-1 mb-5">
|
|
<table class="table table-bordered table-custom mb-0">
|
|
<thead>
|
|
<tr>
|
|
<th rowspan="2" class="align-middle">บริการ</th>
|
|
<th rowspan="2" class="align-middle">เวลามาตรฐาน<br>(นาที)</th>
|
|
<th colspan="5">ระดับความพึงพอใจ</th>
|
|
<th rowspan="2" class="align-middle">ข้อเสนอแนะ / เวลาที่คาดหวัง</th>
|
|
</tr>
|
|
<tr style="background:#173e55;">
|
|
<th>5<br><small>มากที่สุด</small></th>
|
|
<th>4<br><small>มาก</small></th>
|
|
<th>3<br><small>ปานกลาง</small></th>
|
|
<th>2<br><small>น้อย</small></th>
|
|
<th>1<br><small>น้อยมาก</small></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php
|
|
$slas = $pdo_assess->query("SELECT * FROM it_slas WHERE is_active = 1 ORDER BY order_no ASC")->fetchAll();
|
|
$n = 1;
|
|
foreach ($slas as $sla):
|
|
$s_id = $sla['id'];
|
|
?>
|
|
<tr>
|
|
<td><?php echo $n . ". " . htmlspecialchars($sla['service_name']); ?></td>
|
|
<td class="text-center"><?php echo $sla['standard_time']; ?></td>
|
|
<?php for ($score = 5; $score >= 1; $score--): ?>
|
|
<td class="text-center radio-custom"><input type="radio" name="sla_<?php echo $s_id; ?>_score" value="<?php echo $score; ?>" required></td>
|
|
<?php endfor; ?>
|
|
<td><input type="text" class="form-control form-control-sm" name="sla_<?php echo $s_id; ?>_comment" placeholder="ความคิดเห็น..."></td>
|
|
</tr>
|
|
<?php
|
|
$n++;
|
|
endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="text-center mt-4">
|
|
<button type="submit" class="btn btn-submit px-5" id="btnSubmit">บันทึกแบบประเมิน</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener("DOMContentLoaded", function() {
|
|
const useYes = document.getElementById("use_yes");
|
|
const useNo = document.getElementById("use_no");
|
|
const extendedSections = document.getElementById("extended_sections");
|
|
|
|
function toggleSections() {
|
|
if (useNo && useNo.checked) {
|
|
extendedSections.style.display = "none";
|
|
// ยกเลิก required ชั่วคราว
|
|
const reqInputs = extendedSections.querySelectorAll('input[required]');
|
|
reqInputs.forEach(input => {
|
|
input.dataset.required = 'true';
|
|
input.removeAttribute('required');
|
|
|
|
// Clear validation highlights
|
|
let row = input.closest('tr');
|
|
if (row) row.classList.remove('table-danger');
|
|
input.classList.remove('is-invalid');
|
|
});
|
|
} else {
|
|
extendedSections.style.display = "block";
|
|
const reqInputs = extendedSections.querySelectorAll('input[data-required="true"]');
|
|
reqInputs.forEach(input => {
|
|
input.setAttribute('required', 'required');
|
|
});
|
|
}
|
|
}
|
|
|
|
if (useYes && useNo) {
|
|
useYes.addEventListener("change", toggleSections);
|
|
useNo.addEventListener("change", toggleSections);
|
|
}
|
|
|
|
// Highlight invalid fields when native HTML5 validation fails
|
|
const allInputs = document.querySelectorAll('#assessmentForm input');
|
|
allInputs.forEach(input => {
|
|
input.addEventListener('invalid', function() {
|
|
let row = this.closest('tr');
|
|
if (row) {
|
|
row.classList.add('table-danger');
|
|
} else {
|
|
this.classList.add('is-invalid');
|
|
}
|
|
});
|
|
|
|
input.addEventListener('change', function() {
|
|
let row = this.closest('tr');
|
|
if (row) {
|
|
// Because radios in the same row might have different names (like Rule K, U, P),
|
|
// we shouldn't necessarily remove table-danger if other groups in the same row are still invalid.
|
|
// However, a simple approach is to check if the form is valid.
|
|
// Actually, checking if the specific required radios are filled is tricky.
|
|
// For a better UX, we can just remove table-danger and let them submit again to re-check.
|
|
row.classList.remove('table-danger');
|
|
} else {
|
|
this.classList.remove('is-invalid');
|
|
}
|
|
});
|
|
});
|
|
|
|
const form = document.getElementById("assessmentForm");
|
|
if (form) {
|
|
form.addEventListener("submit", function(e) {
|
|
e.preventDefault();
|
|
// Double check if form is valid (it should be if submit fires, due to HTML5, but just in case)
|
|
if (!form.checkValidity()) {
|
|
return;
|
|
}
|
|
Swal.fire({
|
|
title: 'ยืนยันการส่งแบบประเมิน?',
|
|
text: "โปรดตรวจสอบข้อมูลให้ถูกต้องก่อนกดยืนยัน",
|
|
icon: 'warning',
|
|
showCancelButton: true,
|
|
confirmButtonColor: '#008f91',
|
|
cancelButtonColor: '#d33',
|
|
confirmButtonText: 'ยืนยันส่งข้อมูล',
|
|
cancelButtonText: 'ยกเลิก'
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
form.submit();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
});
|
|
|
|
<?php if (isset($_SESSION['success_msg'])): ?>
|
|
Swal.fire({
|
|
icon: 'success',
|
|
title: 'สำเร็จ!',
|
|
text: '<?php echo $_SESSION['success_msg']; ?>',
|
|
confirmButtonColor: '#008f91'
|
|
});
|
|
<?php unset($_SESSION['success_msg']); ?>
|
|
<?php endif; ?>
|
|
|
|
<?php if (isset($_SESSION['error_msg'])): ?>
|
|
Swal.fire({
|
|
icon: 'error',
|
|
title: 'เกิดข้อผิดพลาด',
|
|
text: '<?php echo $_SESSION['error_msg']; ?>',
|
|
confirmButtonColor: '#d33'
|
|
});
|
|
<?php unset($_SESSION['error_msg']); ?>
|
|
<?php endif; ?>
|
|
</script>
|
|
</body>
|
|
|
|
</html>
|