Initial commit - TPU Survey System with Google Forms & Certificate Generator
This commit is contained in:
+214
@@ -0,0 +1,214 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="th">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>ตรวจสอบเกียรติบัตร - TPU Survey</title>
|
||||
<meta name="description" content="หน้าบริการสาธารณะสำหรับตรวจสอบความถูกต้องของเกียรติบัตรจากคณะนวัตกรรมดิจิทัลเทคโนโลยี มหาวิทยาลัยตาปี">
|
||||
<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+Thai:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script>
|
||||
tailwind.config = {
|
||||
theme: {
|
||||
extend: {
|
||||
fontFamily: {
|
||||
'thai': ['"Noto Sans Thai"', 'sans-serif']
|
||||
},
|
||||
colors: {
|
||||
'primary': { 50:'#eff6ff',100:'#dbeafe',200:'#bfdbfe',300:'#93c5fd',400:'#60a5fa',500:'#3b82f6',600:'#2563eb',700:'#1d4ed8',800:'#1e40af',900:'#1e3a8a' },
|
||||
'accent': { 50:'#fffbeb',100:'#fef3c7',200:'#fde68a',300:'#fcd34d',400:'#fbbf24',500:'#f59e0b',600:'#d97706',700:'#b45309',800:'#92400e',900:'#78350f' }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<link rel="stylesheet" href="css/style.css?v=6">
|
||||
<style>
|
||||
body {
|
||||
background: linear-gradient(135deg, #1e3a8a 0%, #1e40af 50%, #1d4ed8 100%);
|
||||
font-family: 'Noto Sans Thai', sans-serif;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
}
|
||||
.verify-card {
|
||||
width: 100%;
|
||||
max-width: 640px;
|
||||
background: #ffffff;
|
||||
border-radius: 24px;
|
||||
padding: 40px;
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.25);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
animation: slideUp 0.6s ease-out;
|
||||
}
|
||||
@keyframes slideUp {
|
||||
from { opacity: 0; transform: translateY(20px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
.result-box {
|
||||
display: none;
|
||||
margin-top: 24px;
|
||||
border-radius: 16px;
|
||||
padding: 24px;
|
||||
animation: fadeIn 0.4s ease;
|
||||
}
|
||||
@keyframes fadeIn {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="font-thai">
|
||||
<div class="verify-card">
|
||||
<div class="h-1.5 bg-gradient-to-r from-yellow-300 via-yellow-400 to-yellow-500 absolute top-0 left-0 right-0"></div>
|
||||
<div class="text-center mb-32">
|
||||
<img src="pic/logo.png" alt="TPU Logo" class="mx-auto h-24 w-auto mb-4 drop-shadow-md">
|
||||
<h1 class="text-2xl font-bold mb-1" style="font-size: 1.6rem; color: #1e3a8a;">ระบบตรวจสอบความถูกต้องเกียรติบัตร</h1>
|
||||
<p class="text-sm text-blue-900 font-bold">คณะนวัตกรรมดิจิทัลเทคโนโลยี</p>
|
||||
<p class="text-xs text-gray-500 font-medium">มหาวิทยาลัยตาปี (Tapi University)</p>
|
||||
</div>
|
||||
|
||||
<form id="verifyForm" onsubmit="handleVerify(event)">
|
||||
<div class="form-group mb-20">
|
||||
<label class="form-label" style="font-weight: 700; color: #1e3a8a; font-size: 1rem; margin-bottom: 8px;">รหัสตรวจสอบเกียรติบัตร (Certificate Code)</label>
|
||||
<div class="flex gap-12">
|
||||
<input type="text" id="certCodeInput" class="form-input flex-1" placeholder="ตัวอย่าง: TPU-2569-0016" required
|
||||
style="border-color: #cbd5e1; border-width: 2px; font-weight: 600; text-transform: uppercase;">
|
||||
<button type="submit" id="verifyBtn" class="btn btn-primary" style="min-width: 140px; border-radius: 8px;">
|
||||
🔍 ตรวจสอบ
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Loading state -->
|
||||
<div id="loadingState" class="hidden text-center py-20">
|
||||
<div class="inline-block animate-spin rounded-full h-32 w-32 border-b-2 border-navy-700" style="width: 40px; height: 40px; border-width: 3px; border-color: transparent; border-bottom-color: #2563eb;"></div>
|
||||
<p class="mt-12 text-sm text-navy-800 font-bold">กำลังค้นหาข้อมูลในระบบ...</p>
|
||||
</div>
|
||||
|
||||
<!-- Result Box: Success -->
|
||||
<div id="resultSuccess" class="result-box bg-emerald-50 border-l-4 border-emerald-500" style="display: none; background-color: #f0fdf4; border-left: 5px solid #10b981;">
|
||||
<div class="flex items-center gap-16 mb-16">
|
||||
<div class="w-40 h-40 rounded-full flex items-center justify-center text-white font-bold" style="width: 36px; height: 36px; background-color: #10b981; font-size: 1.2rem;">✓</div>
|
||||
<div>
|
||||
<h3 class="text-emerald-800 font-extrabold text-lg" style="color: #065f46; font-size: 1.15rem;">เกียรติบัตรของแท้ (Verified Certificate)</h3>
|
||||
<p class="text-xs text-emerald-600 font-medium" style="color: #047857;">รหัสอ้างอิงตรงกับข้อมูลในฐานข้อมูลระบบ</p>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="border-emerald-200 my-12" style="border-color: #a7f3d0;">
|
||||
<div class="space-y-12 text-sm text-gray-800">
|
||||
<div class="flex justify-between py-4 border-b border-dashed border-emerald-100" style="border-color: #d1fae5;">
|
||||
<span class="text-gray-500 font-bold">ชื่อผู้เข้าร่วมโครงการ:</span>
|
||||
<span class="font-extrabold text-navy-900" id="resRecipientName" style="color: #1e3a8a; font-size: 1.05rem;">-</span>
|
||||
</div>
|
||||
<div class="flex justify-between py-4 border-b border-dashed border-emerald-100" style="border-color: #d1fae5;">
|
||||
<span class="text-gray-500 font-bold">ชื่อหลักสูตร / โครงการ:</span>
|
||||
<span class="font-extrabold text-right" id="resCourseTitle" style="color: #1e293b; max-width: 70%;">-</span>
|
||||
</div>
|
||||
<div class="flex justify-between py-4 border-b border-dashed border-emerald-100" style="border-color: #d1fae5;">
|
||||
<span class="text-gray-500 font-bold">วันที่ตอบสำเร็จ:</span>
|
||||
<span class="font-bold text-gray-800" id="resIssueDate">-</span>
|
||||
</div>
|
||||
<div class="flex justify-between py-4">
|
||||
<span class="text-gray-500 font-bold">รหัสยืนยัน:</span>
|
||||
<span class="font-bold text-gray-500 font-mono" id="resCode">-</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Result Box: Error -->
|
||||
<div id="resultError" class="result-box bg-rose-50 border-l-4 border-rose-500" style="display: none; background-color: #fff1f2; border-left: 5px solid #f43f5e;">
|
||||
<div class="flex items-center gap-16">
|
||||
<div class="w-40 h-40 rounded-full flex items-center justify-center text-white font-bold" style="width: 36px; height: 36px; background-color: #f43f5e; font-size: 1.2rem;">✕</div>
|
||||
<div>
|
||||
<h3 class="text-rose-800 font-bold text-lg" style="color: #9f1239; font-size: 1.15rem;">ไม่พบข้อมูลเกียรติบัตร</h3>
|
||||
<p class="text-xs text-rose-600 font-medium" id="errorMessage" style="color: #be123c;">ไม่พบรหัสเกียรติบัตรนี้ในระบบ หรือพิมพ์ผิด</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Check for code in URL query string (e.g. verify.html?code=TPU-2569-0016)
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const code = urlParams.get('code');
|
||||
if (code) {
|
||||
document.getElementById('certCodeInput').value = code;
|
||||
handleVerification(code);
|
||||
}
|
||||
});
|
||||
|
||||
function handleVerify(e) {
|
||||
e.preventDefault();
|
||||
const code = document.getElementById('certCodeInput').value.trim();
|
||||
handleVerification(code);
|
||||
}
|
||||
|
||||
async function handleVerification(code) {
|
||||
const btn = document.getElementById('verifyBtn');
|
||||
const loader = document.getElementById('loadingState');
|
||||
const successBox = document.getElementById('resultSuccess');
|
||||
const errorBox = document.getElementById('resultError');
|
||||
|
||||
// Reset states
|
||||
successBox.style.display = 'none';
|
||||
errorBox.style.display = 'none';
|
||||
loader.classList.remove('hidden');
|
||||
btn.disabled = true;
|
||||
|
||||
try {
|
||||
const response = await fetch('api/verify.php?code=' + encodeURIComponent(code));
|
||||
const data = await response.json();
|
||||
|
||||
loader.classList.add('hidden');
|
||||
|
||||
if (data.success) {
|
||||
document.getElementById('resRecipientName').textContent = data.recipient_name;
|
||||
document.getElementById('resCourseTitle').textContent = data.course_title;
|
||||
document.getElementById('resIssueDate').textContent = formatDate(data.issue_date);
|
||||
document.getElementById('resCode').textContent = data.code;
|
||||
successBox.style.display = 'block';
|
||||
} else {
|
||||
document.getElementById('errorMessage').textContent = data.error || 'เกิดข้อผิดพลาดในการตรวจสอบ';
|
||||
errorBox.style.display = 'block';
|
||||
}
|
||||
} catch (err) {
|
||||
loader.classList.add('hidden');
|
||||
document.getElementById('errorMessage').textContent = 'เกิดข้อผิดพลาดในการเชื่อมต่อเซิร์ฟเวอร์';
|
||||
errorBox.style.display = 'block';
|
||||
} finally {
|
||||
btn.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
function formatDate(dateStr) {
|
||||
if (!dateStr) return '-';
|
||||
try {
|
||||
// dateStr formats: 2026-05-29 11:35:09
|
||||
const parts = dateStr.split(' ')[0].split('-');
|
||||
const y = parseInt(parts[0]) + 543; // แปลงเป็น พ.ศ.
|
||||
const m = parseInt(parts[1]);
|
||||
const d = parseInt(parts[2]);
|
||||
|
||||
const thaiMonths = [
|
||||
'มกราคม', 'กุมภาพันธ์', 'มีนาคม', 'เมษายน', 'พฤษภาคม', 'มิถุนายน',
|
||||
'กรกฎาคม', 'สิงหาคม', 'กันยายน', 'ตุลาคม', 'พฤศจิกายน', 'ธันวาคม'
|
||||
];
|
||||
|
||||
return d + ' ' + thaiMonths[m - 1] + ' ' + y;
|
||||
} catch (e) {
|
||||
return dateStr;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user