Files
survey/js/teacher.js
T
2026-09-12 14:34:09 +07:00

806 lines
38 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* TPU Survey - Teacher Dashboard Logic
*/
let teacherSurveys = [];
async function initTeacher() {
const loggedIn = await Auth.check();
if (!loggedIn || !Auth.isTeacher()) {
if (Auth.isAdmin()) {
window.location.href = 'admin.html';
return;
}
window.location.href = 'index.html';
return;
}
document.getElementById('userName').textContent = Auth.user.full_name;
document.getElementById('userRole').textContent = 'อาจารย์ / เจ้าของโครงการ';
document.getElementById('userAvatar').textContent = Auth.user.full_name.charAt(0);
showTeacherView('mySurveys');
}
function showTeacherView(view) {
document.querySelectorAll('.view-section').forEach(s => s.classList.add('hidden'));
document.getElementById(`view-${view}`)?.classList.remove('hidden');
document.querySelectorAll('.nav-item').forEach(n => n.classList.remove('active'));
document.querySelector(`.nav-item[data-view="${view}"]`)?.classList.add('active');
const titles = { mySurveys: 'แบบสอบถามของฉัน', profile: 'ข้อมูลส่วนตัว' };
document.getElementById('pageTitle').textContent = titles[view] || '';
if (view === 'mySurveys') loadTeacherSurveys();
else if (view === 'profile') loadProfile();
}
async function loadTeacherSurveys() {
try {
const data = await API.get('surveys.php?action=list');
teacherSurveys = data.surveys || [];
renderTeacherSurveys();
} catch (err) {
Toast.error(err.message);
}
}
function renderTeacherSurveys() {
const container = document.getElementById('teacherSurveysList') || document.getElementById('teacherSurveysBody');
if (!container) return;
if (teacherSurveys.length === 0) {
const emptyHtml = `
<div class="card-tapi p-8 text-center bg-white rounded-lg border border-slate-200">
<i class="fas fa-clipboard-list text-4xl text-blue-300 mb-3 block"></i>
<p class="text-gray-600 font-bold">ยังไม่มีแบบสอบถาม กดปุ่ม "สร้างแบบสอบถาม" เพื่อเริ่มต้น</p>
</div>
`;
if (container.tagName === 'TBODY') {
container.innerHTML = `<tr><td colspan="5" class="text-center text-muted" style="padding:40px">ยังไม่มีแบบสอบถาม กดปุ่ม "สร้างแบบสอบถาม" เพื่อเริ่มต้น</td></tr>`;
} else {
container.innerHTML = emptyHtml;
}
return;
}
const statusMap = {
active: { label: 'เปิดใช้งาน', bg: 'bg-emerald-100 text-emerald-800 border-emerald-300' },
draft: { label: 'ฉบับร่าง', bg: 'bg-amber-100 text-amber-800 border-amber-300' },
closed: { label: 'ปิดแล้ว', bg: 'bg-rose-100 text-rose-800 border-rose-300' }
};
container.innerHTML = teacherSurveys.map(s => {
const st = statusMap[s.status] || { label: s.status || 'เปิดใช้งาน', bg: 'bg-emerald-100 text-emerald-800 border-emerald-300' };
return `
<div class="card-tapi p-3.5 rounded-xl bg-white flex flex-col lg:flex-row justify-between items-start lg:items-center gap-3 transition-all hover:shadow-md border border-slate-200">
<div class="flex flex-col sm:flex-row sm:items-center gap-2.5 flex-1 min-w-0">
<span class="px-2 py-0.5 text-[11px] font-extrabold rounded border whitespace-nowrap self-start sm:self-auto ${st.bg}">${st.label}</span>
<div class="space-y-0.5 flex-1 min-w-0">
<h4 class="font-bold text-xs sm:text-sm text-blue-950 truncate" title="${escapeHtml(s.title)}">
${escapeHtml(s.title)}
</h4>
<div class="flex items-center gap-3 text-[11px] text-gray-500 font-semibold flex-wrap">
<span><i class="fas fa-comments text-blue-600 mr-1"></i> ${s.response_count || 0} คำตอบ</span>
<span><i class="fas fa-calendar-alt text-amber-600 mr-1"></i> ${formatDate(s.created_at)}</span>
</div>
</div>
</div>
<div class="flex flex-wrap lg:flex-nowrap gap-1 items-center flex-shrink-0 w-full lg:w-auto overflow-x-auto pb-1 lg:pb-0">
<button onclick="teacherEditSurvey(${s.id})" class="bg-amber-400 hover:bg-amber-500 text-gray-900 border border-slate-800 px-2 py-1 rounded text-xs font-bold flex items-center gap-1 shadow-sm transition-all whitespace-nowrap active:scale-95" title="แก้ไขแบบสอบถาม">
✏️ แก้ไข
</button>
<button onclick="teacherDuplicateSurvey(${s.id})" class="bg-blue-600 hover:bg-blue-700 text-white border border-slate-800 px-2 py-1 rounded text-xs font-bold flex items-center gap-1 shadow-sm transition-all whitespace-nowrap active:scale-95" title="คัดลอกแบบสอบถาม">
📑 คัดลอก
</button>
<button onclick="teacherGenerateLink(${s.id})" class="bg-blue-900 hover:bg-blue-950 text-white border border-slate-800 px-2 py-1 rounded text-xs font-bold flex items-center gap-1 shadow-sm transition-all whitespace-nowrap active:scale-95" title="ลิงก์และ QR Code">
🔗 ลิงก์
</button>
<button onclick="showImportResponsesModal(${s.id}, '${escapeHtml(s.title)}')" class="bg-emerald-600 hover:bg-emerald-700 text-white border border-slate-800 px-2 py-1 rounded text-xs font-bold flex items-center gap-1 shadow-sm transition-all whitespace-nowrap active:scale-95" title="นำเข้าคำตอบจาก CSV">
📥 นำเข้าคำตอบ
</button>
<button onclick="teacherViewStats(${s.id})" class="bg-indigo-600 hover:bg-indigo-700 text-white border border-slate-800 px-2 py-1 rounded text-xs font-bold flex items-center gap-1 shadow-sm transition-all whitespace-nowrap active:scale-95" title="ผลสถิติ">
📊 สถิติ
</button>
<button onclick="teacherDeleteSurvey(${s.id}, '${escapeHtml(s.title)}')" class="bg-rose-600 hover:bg-rose-700 text-white border border-slate-800 px-2 py-1 rounded text-xs font-bold flex items-center gap-1 shadow-sm transition-all whitespace-nowrap active:scale-95" title="ลบแบบสอบถาม">
🗑️ ลบ
</button>
</div>
</div>
`;
}).join('');
}
async function teacherDeleteSurvey(id, title) {
if (!confirm(`คุณต้องการลบแบบสอบถาม "${title}" ใช่หรือไม่?`)) return;
try {
await API.get(`surveys.php?action=delete&id=${id}`);
Toast.success('ลบแบบสอบถามเรียบร้อยแล้ว');
loadTeacherSurveys();
} catch (err) {
Toast.error(err.message);
}
}
function showTeacherCreateModal() {
const html = `
<form id="teacherSurveyForm">
<div class="form-group">
<label class="form-label">ชื่อแบบสอบถาม *</label>
<input type="text" class="form-input" name="title" required placeholder="เช่น แบบประเมินความพึงพอใจโครงการ...">
</div>
<div class="form-group">
<label class="form-label">รายละเอียด</label>
<textarea class="form-input" name="description" placeholder="คำอธิบายเพิ่มเติม"></textarea>
</div>
</form>
`;
const footer = `
<button class="btn btn-secondary" onclick="Modal.hide('tCreateModal');document.getElementById('tCreateModal').remove();">ยกเลิก</button>
<button class="btn btn-primary" onclick="submitTeacherCreate()">สร้างแบบสอบถาม (ใช้ 3 ส่วนมาตรฐาน)</button>
`;
Modal.create('สร้างแบบสอบถามใหม่', html, footer);
document.querySelector('.modal-overlay:last-child').id = 'tCreateModal';
}
async function submitTeacherCreate() {
const form = document.getElementById('teacherSurveyForm');
const fd = new FormData(form);
const data = Object.fromEntries(fd);
if (!data.title) { Toast.warning('กรุณากรอกชื่อ'); return; }
// Pre-fill 3 sections
data.sections = [
{
section_number: 1,
title: 'ส่วนที่ ข้อมูลทั่วไป',
category: 'general',
questions: [
{ question_text: 'เพศ', question_type: 'radio', options: ['ชาย', 'หญิง'], is_required: 1 },
{ question_text: 'ช่วงอายุ', question_type: 'dropdown', options: ['18-25 ปี', '26-35 ปี', '36-45 ปี', '46-55 ปี', '56 ปีขึ้นไป'], is_required: 1 }
]
},
{
section_number: 2,
title: 'ส่วนที่ การประเมินความพึงพอใจ',
category: 'rating',
questions: [
{ question_text: 'ด้านเนื้อหาของการจัดโครงการ', question_type: 'radio', is_required: 1 },
{ question_text: 'ด้านวิทยากร / ผู้บรรยาย', question_type: 'radio', is_required: 1 }
]
},
{
section_number: 3,
title: 'ส่วนที่ ข้อเสนอแนะอื่นๆ',
category: 'suggestions',
questions: [
{ question_text: 'ข้อเสนอแนะเพิ่มเติม', question_type: 'text', is_required: 0 }
]
}
];
try {
const result = await API.post('surveys.php?action=create', data);
Toast.success('สร้างแบบสอบถามสำเร็จ');
Modal.hide('tCreateModal');
document.getElementById('tCreateModal').remove();
loadTeacherSurveys();
setTimeout(() => teacherEditSurvey(result.id), 500);
} catch (err) {
Toast.error(err.message);
}
}
function teacherEditSurvey(id) {
window.open(`edit.html?id=${id}`, '_blank');
}
function buildTeacherQEditor(si, qi, q = {}) {
const qType = q.question_type || 'radio';
const qText = q.question_text || '';
const qOptions = Array.isArray(q.options) ? q.options.join('\n') : '';
const showOptions = ['radio', 'checkbox', 'dropdown'].includes(qType);
const qDescription = q.description || '';
return `
<div class="question-builder">
<div class="qb-header">
<span class="qb-handle">⋮⋮</span>
<span class="text-sm fw-600 q-number-label">คำถาม</span>
<div class="qb-actions">
<button type="button" class="btn btn-ghost btn-sm" onclick="addTeacherQ(${si}, this.closest('.question-builder'))" title="แทรกคำถามใต้ข้อนี้">➕ แทรก</button>
<button type="button" class="btn btn-ghost btn-sm text-danger" onclick="removeTeacherQ(this, ${si})" title="ลบคำถาม">🗑️ ลบ</button>
</div>
</div>
<div class="form-group">
<label class="form-label">คำถาม / ข้อความ</label>
<input type="text" class="form-input q-text-input" value="${escapeHtml(qText)}" placeholder="พิมพ์คำถาม...">
</div>
<div class="form-group">
<label class="form-label">รายละเอียดเพิ่มเติม (คำใบ้/คำอธิบาย - ไม่บังคับ)</label>
<input type="text" class="form-input q-desc-input" value="${escapeHtml(qDescription)}" placeholder="เช่น กรุณาระบุเป็นภาษาไทย">
</div>
<div class="form-group">
<label class="form-label">ประเภทคำถาม</label>
<select class="form-input q-type-select" onchange="toggleTeacherOptions(this)">
<option value="radio" ${qType==='radio'?'selected':''}>📊 ระดับ 1-5</option>
<option value="text" ${qType==='text'?'selected':''}>📝 ข้อความ</option>
<option value="dropdown" ${qType==='dropdown'?'selected':''}>📋 Dropdown</option>
<option value="checkbox" ${qType==='checkbox'?'selected':''}>☑️ Checkbox</option>
</select>
</div>
<div class="form-group q-options-group" style="${showOptions ? '' : 'display:none;'}">
<label class="form-label">ตัวเลือก (1 รายการต่อบรรทัด)</label>
<textarea class="form-input q-options-input" placeholder="ตัวเลือกที่ 1\nตัวเลือกที่ 2" rows="3">${escapeHtml(qOptions)}</textarea>
<small class="text-muted">เว้นว่างสำหรับระดับ 1-5 (Radio)</small>
</div>
</div>
`;
}
function addTeacherSection() {
const container = document.getElementById('additionalTeacherSections');
if (!container) return;
const si = document.querySelectorAll('.card[data-section]').length;
const html = `
<div class="card mb-24" data-section="${si}">
<div class="card-header d-flex justify-between items-center">
<input type="text" class="form-input" style="font-weight:700;font-size:16px;border:none;padding:4px 0;background:transparent;"
value="ส่วนที่ ข้อมูลเพิ่มเติม" data-field="section-title-${si}">
<button type="button" class="btn btn-ghost btn-sm text-danger" onclick="this.closest('.card').remove()">🗑️ ลบส่วนนี้</button>
</div>
<div class="card-body">
<div id="t-questions-${si}"></div>
<button type="button" class="btn btn-secondary btn-sm mt-16" onclick="addTeacherQ(${si})">+ เพิ่มคำถาม</button>
</div>
</div>
`;
container.insertAdjacentHTML('beforeend', html);
// Add one initial question to the new section
addTeacherQ(si);
}
function toggleTeacherOptions(select) {
const group = select.closest('.question-builder').querySelector('.q-options-group');
if (['radio', 'checkbox', 'dropdown'].includes(select.value)) {
group.style.display = 'block';
} else {
group.style.display = 'none';
}
}
function addTeacherQ(si, afterEl = null) {
const container = document.getElementById(`t-questions-${si}`);
if (!container) return;
// Create temporary div to parse HTML
const tempDiv = document.createElement('div');
tempDiv.innerHTML = buildTeacherQEditor(si, 0);
const newQ = tempDiv.firstElementChild;
if (afterEl) {
afterEl.after(newQ);
} else {
container.appendChild(newQ);
}
reindexTeacherQuestions(si);
}
function removeTeacherQ(btn, si) {
if (!confirm('ยืนยันลบคำถามนี้?')) return;
btn.closest('.question-builder').remove();
reindexTeacherQuestions(si);
}
function reindexTeacherQuestions(si) {
const container = document.getElementById(`t-questions-${si}`);
if (!container) return;
container.querySelectorAll('.question-builder').forEach((qEl, idx) => {
const label = qEl.querySelector('.q-number-label');
if (label) label.textContent = `คำถาม`;
});
}
async function submitTeacherEdit() {
const form = document.getElementById('tEditForm');
const id = form.querySelector('[name="id"]').value;
const title = form.querySelector('[name="title"]').value;
const description = form.querySelector('[name="description"]').value;
const sections = [];
form.querySelectorAll('.card[data-section]').forEach((sectionEl, si) => {
const sTitleInput = sectionEl.querySelector('input[data-field^="section-title"]');
const sCategorySelect = sectionEl.querySelector('select[data-field^="section-category"]');
const sTitle = sTitleInput ? sTitleInput.value : `ส่วนที่ ${si+1}`;
const sCategory = sCategorySelect ? sCategorySelect.value : 'rating';
const questions = [];
sectionEl.querySelectorAll('.question-builder').forEach((qEl, qi) => {
const qTextInput = qEl.querySelector('.q-text-input');
const qDescInput = qEl.querySelector('.q-desc-input');
const qTypeSelect = qEl.querySelector('.q-type-select');
const qOptionsArea = qEl.querySelector('.q-options-input');
const qText = qTextInput ? qTextInput.value : '';
const qDescription = qDescInput ? qDescInput.value : '';
const qType = qTypeSelect ? qTypeSelect.value : 'radio';
const qOptionsRaw = qOptionsArea ? qOptionsArea.value : '';
const options = qOptionsRaw.split('\n').map(o => o.trim()).filter(o => o !== '');
if (qText.trim()) {
questions.push({
question_text: qText.trim(),
description: qDescription.trim() || null,
question_type: qType,
order_num: qi,
is_required: 1,
options: options.length > 0 ? options : null
});
}
});
sections.push({ section_number: si + 1, title: sTitle, category: sCategory, questions });
});
try {
await API.post('surveys.php?action=update', { id: parseInt(id), title, description, sections });
Toast.success('บันทึกสำเร็จ');
Modal.hide('tEditModal');
document.getElementById('tEditModal').remove();
loadTeacherSurveys();
} catch (err) {
Toast.error(err.message);
}
}
async function teacherDuplicateSurvey(id) {
if (!confirm('ยืนยันสร้างสำเนาแบบสอบถามนี้?')) return;
try {
await API.post('surveys.php?action=duplicate', { id });
Toast.success('คัดลอกสำเร็จ');
loadTeacherSurveys();
} catch (err) {
Toast.error(err.message);
}
}
async function teacherGenerateLink(id) {
try {
const data = await API.post('surveys.php?action=generateLink', { id });
const basePath = window.location.pathname.includes('/survey') ? '/survey' : '';
const fullUrl = data.full_url || `${window.location.origin}${basePath}/respond.php?link=${data.unique_link}`;
// Find survey title
const survey = teacherSurveys.find(s => s.id == id);
const surveyTitle = survey ? survey.title : 'แบบสอบถาม';
const html = `
<div class="qr-link-container">
<div class="qr-link-section">
<div class="qr-link-label">🔗 ลิงก์แบบสอบถาม</div>
<div class="link-display">
<span class="flex-1" id="surveyLinkText">${fullUrl}</span>
<button class="copy-btn" onclick="copyTeacherLink()">📋 คัดลอก</button>
</div>
</div>
<div class="qr-code-section">
<div class="qr-link-label">📱 QR Code สำหรับตอบแบบสอบถาม</div>
<div class="qr-code-wrapper" id="qrCodeWrapper">
<div id="qrCodeContainer"></div>
</div>
<p class="qr-survey-title" id="qrSurveyTitle">${escapeHtml(surveyTitle)}</p>
<div class="qr-actions">
<button class="btn btn-primary btn-sm" onclick="teacherDownloadQR()">📥 ดาวน์โหลด QR</button>
<button class="btn btn-secondary btn-sm" onclick="teacherPrintQR()">🖨️ พิมพ์ QR</button>
</div>
</div>
<p class="mt-16 text-sm text-muted" style="text-align:center;">⚡ แบบสอบถามถูกเปิดใช้งานอัตโนมัติเมื่อสร้างลิงก์</p>
</div>
`;
Modal.create('🔗 ลิงก์และ QR Code', html, '', 'modal-lg');
// Generate QR Code using QRCodeJS
setTimeout(() => {
const container = document.getElementById('qrCodeContainer');
if (container && typeof QRCode !== 'undefined') {
new QRCode(container, {
text: fullUrl,
width: 280,
height: 280,
colorDark: '#1e3a8a',
colorLight: '#ffffff',
correctLevel: QRCode.CorrectLevel.H
});
}
}, 100);
} catch (err) {
Toast.error(err.message);
}
}
function copyTeacherLink() {
const text = document.getElementById('surveyLinkText')?.textContent;
if (text) {
navigator.clipboard.writeText(text).then(() => Toast.success('คัดลอกแล้ว')).catch(() => {
const ta = document.createElement('textarea'); ta.value = text; document.body.appendChild(ta); ta.select(); document.execCommand('copy'); ta.remove();
Toast.success('คัดลอกแล้ว');
});
}
}
function getTeacherQRImage() {
const container = document.getElementById('qrCodeContainer');
if (!container) return null;
return container.querySelector('canvas') || container.querySelector('img');
}
function teacherDownloadQR() {
const qrEl = getTeacherQRImage();
const title = document.getElementById('qrSurveyTitle')?.textContent || 'survey';
if (!qrEl) return;
let qrDataUrl;
if (qrEl.tagName === 'CANVAS') {
qrDataUrl = qrEl.toDataURL('image/png');
} else {
qrDataUrl = qrEl.src;
}
const exportCanvas = document.createElement('canvas');
const qrSize = 280;
const padding = 40;
const titleHeight = 60;
const footerHeight = 40;
exportCanvas.width = qrSize + padding * 2;
exportCanvas.height = qrSize + padding * 2 + titleHeight + footerHeight;
const ctx = exportCanvas.getContext('2d');
ctx.fillStyle = '#ffffff';
ctx.fillRect(0, 0, exportCanvas.width, exportCanvas.height);
ctx.fillStyle = '#1a1a2e';
ctx.font = 'bold 16px sans-serif';
ctx.textAlign = 'center';
const maxTitleWidth = exportCanvas.width - 40;
let displayTitle = title;
if (ctx.measureText(displayTitle).width > maxTitleWidth) {
while (ctx.measureText(displayTitle + '...').width > maxTitleWidth && displayTitle.length > 0) {
displayTitle = displayTitle.slice(0, -1);
}
displayTitle += '...';
}
ctx.fillText(displayTitle, exportCanvas.width / 2, padding + 20);
const img = new Image();
img.onload = function() {
ctx.drawImage(img, padding, padding + titleHeight, qrSize, qrSize);
ctx.fillStyle = '#6b7280';
ctx.font = '12px sans-serif';
ctx.fillText('สแกนเพื่อตอบแบบสอบถาม — TPU Survey', exportCanvas.width / 2, exportCanvas.height - 16);
const link = document.createElement('a');
const safeName = title.replace(/[^a-zA-Z0-9ก-๙]/g, '_').substring(0, 50);
link.download = `QR_${safeName}.png`;
link.href = exportCanvas.toDataURL('image/png');
link.click();
Toast.success('ดาวน์โหลด QR Code สำเร็จ');
};
img.src = qrDataUrl;
}
function teacherPrintQR() {
const qrEl = getTeacherQRImage();
const title = document.getElementById('qrSurveyTitle')?.textContent || 'แบบสอบถาม';
const linkText = document.getElementById('surveyLinkText')?.textContent || '';
if (!qrEl) return;
let qrDataUrl;
if (qrEl.tagName === 'CANVAS') {
qrDataUrl = qrEl.toDataURL('image/png');
} else {
qrDataUrl = qrEl.src;
}
const printWindow = window.open('', '_blank');
printWindow.document.write(`
<!DOCTYPE html><html><head><title>พิมพ์ QR Code</title>
<style>
body { font-family: 'Sarabun', sans-serif; text-align: center; padding: 40px; }
h2 { color: #1a1a2e; margin-bottom: 8px; }
.subtitle { color: #6b7280; font-size: 14px; margin-bottom: 24px; }
img { border: 2px solid #e5e7eb; border-radius: 12px; padding: 8px; }
.link { color: #6b7280; font-size: 11px; word-break: break-all; margin-top: 16px; }
.footer { margin-top: 32px; color: #9ca3af; font-size: 12px; }
</style></head>
<body>
<h2>${title}</h2>
<p class="subtitle">สแกน QR Code เพื่อตอบแบบสอบถาม</p>
<img src="${qrDataUrl}" width="300" height="300">
<p class="link">${linkText}</p>
<p class="footer">TPU Survey — มหาวิทยาลัยตาปี</p>
<script>window.onload = function() { window.print(); }<\/script>
</body></html>
`);
printWindow.document.close();
}
function teacherViewStats(surveyId) {
window.open(`stats.html?survey_id=${surveyId}`, '_blank');
}
// ============================================================
// Profile Management
// ============================================================
async function loadProfile() {
try {
const data = await API.get('profile.php?action=get');
const u = data.user;
// Fill the form
document.getElementById('profileCode').value = u.personnel_code || u.username || '-';
document.getElementById('profileName').value = u.full_name || '';
document.getElementById('profileEmail').value = u.email || '';
document.getElementById('profileSubject').value = u.subject_area || '';
document.getElementById('profileBranch').value = u.branch_code || '';
document.getElementById('profilePassword').value = '';
document.getElementById('profilePasswordConfirm').value = '';
// Fill the sidebar card
document.getElementById('profileDisplayName').textContent = u.full_name || '-';
document.getElementById('profileDisplayRole').textContent = u.role === 'admin' ? 'ผู้ดูแลระบบ' : 'อาจารย์ / เจ้าของโครงการ';
document.getElementById('profileAvatar').textContent = (u.full_name || 'T').charAt(0).toUpperCase();
document.getElementById('profilePersonnelCode').textContent = u.personnel_code || u.username || '-';
const badge = document.getElementById('profileBadge');
if (badge) {
badge.textContent = u.role === 'admin' ? '👑 ผู้ดูแลระบบ' : '🎓 อาจารย์';
badge.className = `user-card-badge ${u.role}`;
}
} catch (err) {
Toast.error(err.message);
}
}
async function saveProfile() {
const fullName = document.getElementById('profileName').value.trim();
const email = document.getElementById('profileEmail').value.trim();
const subjectArea = document.getElementById('profileSubject').value.trim();
const branchCode = document.getElementById('profileBranch').value.trim();
const password = document.getElementById('profilePassword').value;
const passwordConfirm = document.getElementById('profilePasswordConfirm').value;
if (!fullName) {
Toast.warning('กรุณากรอกชื่อ-นามสกุล');
return;
}
if (password && password.length < 4) {
Toast.warning('รหัสผ่านต้องมีอย่างน้อย 4 ตัวอักษร');
return;
}
if (password && password !== passwordConfirm) {
Toast.warning('รหัสผ่านไม่ตรงกัน');
return;
}
const payload = {
full_name: fullName,
email: email,
subject_area: subjectArea,
branch_code: branchCode
};
if (password) {
payload.password = password;
}
try {
await API.post('profile.php?action=update', payload);
Toast.success('บันทึกข้อมูลส่วนตัวสำเร็จ');
// Update sidebar display
document.getElementById('userName').textContent = fullName;
document.getElementById('userAvatar').textContent = fullName.charAt(0).toUpperCase();
// Reload profile card
loadProfile();
} catch (err) {
Toast.error(err.message);
}
}
// ============================================================
// Google Forms Import Modals & Functions
// ============================================================
function showImportGoogleFormModal() {
const html = `
<div style="margin-bottom:16px;">
<div style="display:flex;gap:12px;margin-bottom:16px;border-bottom:1px solid #e5e7eb;padding-bottom:10px;">
<button id="tabUrlBtn" type="button" class="btn btn-sm btn-primary" onclick="switchImportTab('url')">🌐 วาง URL / Link</button>
<button id="tabJsonBtn" type="button" class="btn btn-sm btn-secondary" onclick="switchImportTab('json')">📄 อัปโหลดไฟล์ JSON</button>
</div>
<!-- Tab 1: URL -->
<div id="importTabUrl">
<div class="form-group">
<label class="form-label">Google Form URL / Link *</label>
<input type="url" class="form-input" id="googleFormUrl" placeholder="https://docs.google.com/forms/d/e/1FAIpQLS.../viewform">
<small class="text-muted mt-8" style="display:block;">วางลิงก์แบบสอบถาม Google Forms ที่เปิดสาธารณะ (Public)</small>
</div>
</div>
<!-- Tab 2: JSON -->
<div id="importTabJson" style="display:none;">
<div class="form-group">
<label class="form-label">เลือกไฟล์ JSON โครงสร้างฟอร์ม *</label>
<input type="file" class="form-input" id="googleFormJsonFile" accept=".json">
</div>
<div class="form-group">
<label class="form-label">หรือวางข้อมูล JSON ตรงนี้</label>
<textarea class="form-input" id="googleFormJsonText" rows="4" placeholder='{"title": "แบบสอบถาม...", "sections": [...]}'></textarea>
</div>
</div>
</div>
`;
const footer = `
<button class="btn btn-secondary" onclick="Modal.hide('importGFormModal');document.getElementById('importGFormModal')?.remove();">ยกเลิก</button>
<button class="btn btn-primary" id="btnSubmitImportGForm" onclick="submitImportGoogleForm()">📥 นำเข้าแบบสอบถาม</button>
`;
const modalId = Modal.create('📥 นำเข้าแบบสอบถามจาก Google Forms', html, footer);
const modalEl = document.getElementById(modalId);
if (modalEl) modalEl.id = 'importGFormModal';
}
function switchImportTab(tab) {
const urlTab = document.getElementById('importTabUrl');
const jsonTab = document.getElementById('importTabJson');
const urlBtn = document.getElementById('tabUrlBtn');
const jsonBtn = document.getElementById('tabJsonBtn');
if (tab === 'url') {
if (urlTab) urlTab.style.display = 'block';
if (jsonTab) jsonTab.style.display = 'none';
if (urlBtn) urlBtn.className = 'btn btn-sm btn-primary';
if (jsonBtn) jsonBtn.className = 'btn btn-sm btn-secondary';
} else {
if (urlTab) urlTab.style.display = 'none';
if (jsonTab) jsonTab.style.display = 'block';
if (urlBtn) urlBtn.className = 'btn btn-sm btn-secondary';
if (jsonBtn) jsonBtn.className = 'btn btn-sm btn-primary';
}
}
async function submitImportGoogleForm() {
const urlTab = document.getElementById('importTabUrl');
const btn = document.getElementById('btnSubmitImportGForm');
if (btn) {
btn.disabled = true;
btn.textContent = '⏳ กำลังนำเข้าข้อมูล...';
}
try {
if (urlTab && urlTab.style.display !== 'none') {
const url = document.getElementById('googleFormUrl')?.value?.trim();
if (!url) {
Toast.warning('กรุณาระบุ Google Form URL');
if (btn) { btn.disabled = false; btn.textContent = '📥 นำเข้าแบบสอบถาม'; }
return;
}
const res = await API.post('import_google_form.php?action=importFromUrl', { url });
Toast.success(res.message || 'นำเข้าแบบสอบถามสำเร็จ!');
Modal.hide('importGFormModal');
document.getElementById('importGFormModal')?.remove();
if (typeof loadSurveys === 'function') loadSurveys();
if (typeof loadTeacherSurveys === 'function') loadTeacherSurveys();
} else {
const fileInput = document.getElementById('googleFormJsonFile');
const jsonText = document.getElementById('googleFormJsonText')?.value?.trim();
let surveyData = null;
if (fileInput && fileInput.files.length > 0) {
const text = await fileInput.files[0].text();
surveyData = JSON.parse(text);
} else if (jsonText) {
surveyData = JSON.parse(jsonText);
}
if (!surveyData) {
Toast.warning('กรุณาเลือกไฟล์ JSON หรือระบุข้อความ JSON');
if (btn) { btn.disabled = false; btn.textContent = '📥 นำเข้าแบบสอบถาม'; }
return;
}
const res = await API.post('import_google_form.php?action=importFromJson', { survey_data: surveyData });
Toast.success(res.message || 'นำเข้าแบบสอบถามสำเร็จ!');
Modal.hide('importGFormModal');
document.getElementById('importGFormModal')?.remove();
if (typeof loadSurveys === 'function') loadSurveys();
if (typeof loadTeacherSurveys === 'function') loadTeacherSurveys();
}
} catch (err) {
Toast.error(err.message || 'เกิดข้อผิดพลาดในการนำเข้าแบบสอบถาม');
} finally {
if (btn) {
btn.disabled = false;
btn.textContent = '📥 นำเข้าแบบสอบถาม';
}
}
}
function showImportResponsesModal(surveyId, surveyTitle) {
const html = `
<form id="importRespForm">
<input type="hidden" name="survey_id" value="${surveyId}">
<div class="form-group">
<label class="form-label">แบบสอบถาม:</label>
<div style="font-weight:600;font-size:15px;color:var(--navy-600);">${escapeHtml(surveyTitle)}</div>
</div>
<div class="form-group">
<label class="form-label">เลือกไฟล์ CSV ข้อมูลคำตอบจาก Google Forms *</label>
<input type="file" class="form-input" name="csv_file" accept=".csv" required>
<small class="text-muted mt-8" style="display:block;">ไฟล์ .csv ที่ Export มาจาก Google Sheets / Google Forms (แถวแรกเป็นชื่อคำถาม)</small>
</div>
</form>
`;
const footer = `
<button class="btn btn-secondary" onclick="Modal.hide('importRespModal');document.getElementById('importRespModal')?.remove();">ยกเลิก</button>
<button class="btn btn-primary" id="btnSubmitImportResp" onclick="submitImportResponses(${surveyId})">📥 นำเข้าคำตอบลงระบบ</button>
`;
const modalId = Modal.create('📥 นำเข้าคำตอบจาก Google Forms (CSV)', html, footer);
const modalEl = document.getElementById(modalId);
if (modalEl) modalEl.id = 'importRespModal';
}
async function submitImportResponses(surveyId) {
const form = document.getElementById('importRespForm');
const fileInput = form?.querySelector('input[name="csv_file"]');
if (!fileInput || fileInput.files.length === 0) {
Toast.warning('กรุณาเลือกไฟล์ CSV คำตอบ');
return;
}
const btn = document.getElementById('btnSubmitImportResp');
if (btn) {
btn.disabled = true;
btn.textContent = '⏳ กำลังนำเข้าคำตอบ...';
}
const fd = new FormData(form);
try {
const res = await API.upload('import_responses.php', fd);
Toast.success(res.message || 'นำเข้าคำตอบสำเร็จ!');
Modal.hide('importRespModal');
document.getElementById('importRespModal')?.remove();
if (typeof loadSurveys === 'function') loadSurveys();
if (typeof loadTeacherSurveys === 'function') loadTeacherSurveys();
} catch (err) {
Toast.error(err.message || 'เกิดข้อผิดพลาดในการนำเข้าคำตอบ');
} finally {
if (btn) {
btn.disabled = false;
btn.textContent = '📥 นำเข้าคำตอบลงระบบ';
}
}
}
// Global Window bindings
window.showImportGoogleFormModal = showImportGoogleFormModal;
window.switchImportTab = switchImportTab;
window.submitImportGoogleForm = submitImportGoogleForm;
window.showImportResponsesModal = showImportResponsesModal;
window.submitImportResponses = submitImportResponses;
document.addEventListener('DOMContentLoaded', initTeacher);