Add PDF Survey Importer with smart Thai questionnaire parser and preview editor
This commit is contained in:
@@ -0,0 +1,523 @@
|
||||
/**
|
||||
* PDF Survey Importer Module for TPU Survey
|
||||
* Handles PDF upload, smart extraction preview, and saving to database
|
||||
*/
|
||||
|
||||
let currentPdfSurveyData = null;
|
||||
|
||||
// ============================================================
|
||||
// 1. Initial Upload Modal
|
||||
// ============================================================
|
||||
function showImportPdfModal() {
|
||||
const html = `
|
||||
<div class="pdf-importer-wrapper">
|
||||
<div class="pdf-notice-box" style="background:#eff6ff;border:1px solid #bfdbfe;border-radius:10px;padding:14px 16px;margin-bottom:18px;display:flex;gap:12px;align-items:flex-start;">
|
||||
<span style="font-size:24px;line-height:1;">💡</span>
|
||||
<div style="font-size:13px;color:#1e40af;line-height:1.5;">
|
||||
<b>ระบบนำเข้าแบบประเมินจาก PDF อัจฉริยะ:</b><br>
|
||||
รองรับไฟล์ PDF แบบประเมินภาษาไทย (เช่น เอกสาร Word ที่บันทึกเป็น PDF) ระบบจะช่วยแยก <b>ตอนที่ 1 (ข้อมูลทั่วไป)</b>, <b>ตอนที่ 2 (ตารางความพึงพอใจ 5 ระดับ)</b>, และ <b>ตอนที่ 3 (ข้อเสนอแนะ)</b> พร้อมให้ตรวจสอบและแก้ไขก่อนบันทึกจริง
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Drop Zone -->
|
||||
<div id="pdfDropZone" class="pdf-drop-zone" onclick="document.getElementById('pdfFileInput').click()">
|
||||
<div class="pdf-drop-icon">📄</div>
|
||||
<div style="font-weight:600;font-size:15px;color:#1e293b;margin-bottom:4px;" id="pdfDropText">
|
||||
คลิกเพื่อเลือกไฟล์ PDF หรือลากไฟล์มาวางที่นี่
|
||||
</div>
|
||||
<div class="text-muted text-xs">รองรับไฟล์ .pdf ขนาดไม่เกิน 20MB</div>
|
||||
<input type="file" id="pdfFileInput" accept=".pdf" style="display:none;" onchange="handlePdfFileSelected(this)">
|
||||
</div>
|
||||
|
||||
<!-- Selected File Info (Hidden initially) -->
|
||||
<div id="pdfSelectedInfo" style="display:none;margin-top:14px;background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:10px 14px;align-items:center;justify-content:space-between;">
|
||||
<div style="display:flex;align-items:center;gap:10px;">
|
||||
<span style="font-size:20px;color:#dc2626;">📄</span>
|
||||
<div>
|
||||
<div id="pdfFileName" style="font-weight:600;font-size:13px;color:#1e293b;">-</div>
|
||||
<div id="pdfFileSize" class="text-muted text-xs">-</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-sm btn-secondary" onclick="clearSelectedPdf(event)">✕ ลบ</button>
|
||||
</div>
|
||||
|
||||
<div id="pdfProcessingState" style="display:none;margin-top:18px;text-align:center;padding:20px;">
|
||||
<div style="font-size:24px;margin-bottom:8px;" class="fa fa-spinner fa-spin text-blue-600"></div>
|
||||
<div style="font-weight:600;color:#1e293b;font-size:14px;">กำลังอ่านและวิเคราะห์โครงสร้างแบบประเมินจาก PDF...</div>
|
||||
<div class="text-muted text-xs mt-1">กำลังแยกตอนที่, ด้านต่างๆ, สเกลคะแนน และตัวเลือกคำถาม</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const footer = `
|
||||
<button class="btn btn-secondary" onclick="Modal.hide('importPdfModal');document.getElementById('importPdfModal')?.remove();">ยกเลิก</button>
|
||||
<button class="btn btn-primary" id="btnProcessPdf" style="background-color:#dc2626;border-color:#dc2626;" onclick="processPdfUpload()" disabled>🔍 วิเคราะห์และดูตัวอย่าง</button>
|
||||
`;
|
||||
|
||||
const modalId = Modal.create('📄 นำเข้าแบบประเมินจากไฟล์ PDF', html, footer, 'modal-lg');
|
||||
const modalEl = document.getElementById(modalId);
|
||||
if (modalEl) modalEl.id = 'importPdfModal';
|
||||
|
||||
initPdfDropZone();
|
||||
}
|
||||
|
||||
function initPdfDropZone() {
|
||||
const dropZone = document.getElementById('pdfDropZone');
|
||||
if (!dropZone) return;
|
||||
|
||||
['dragenter', 'dragover'].forEach(eventName => {
|
||||
dropZone.addEventListener(eventName, (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
dropZone.classList.add('drag-over');
|
||||
}, false);
|
||||
});
|
||||
|
||||
['dragleave', 'drop'].forEach(eventName => {
|
||||
dropZone.addEventListener(eventName, (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
dropZone.classList.remove('drag-over');
|
||||
}, false);
|
||||
});
|
||||
|
||||
dropZone.addEventListener('drop', (e) => {
|
||||
const dt = e.dataTransfer;
|
||||
const files = dt.files;
|
||||
if (files.length > 0) {
|
||||
const input = document.getElementById('pdfFileInput');
|
||||
if (input) {
|
||||
input.files = files;
|
||||
handlePdfFileSelected(input);
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
function handlePdfFileSelected(input) {
|
||||
if (!input.files || input.files.length === 0) return;
|
||||
const file = input.files[0];
|
||||
|
||||
if (!file.name.toLowerCase().endsWith('.pdf')) {
|
||||
Toast.error('กรุณาเลือกไฟล์เอกสาร .pdf เท่านั้น');
|
||||
input.value = '';
|
||||
return;
|
||||
}
|
||||
|
||||
const infoBox = document.getElementById('pdfSelectedInfo');
|
||||
const nameEl = document.getElementById('pdfFileName');
|
||||
const sizeEl = document.getElementById('pdfFileSize');
|
||||
const btn = document.getElementById('btnProcessPdf');
|
||||
|
||||
if (nameEl) nameEl.textContent = file.name;
|
||||
if (sizeEl) sizeEl.textContent = (file.size / (1024 * 1024)).toFixed(2) + ' MB';
|
||||
if (infoBox) infoBox.style.display = 'flex';
|
||||
if (btn) btn.disabled = false;
|
||||
}
|
||||
|
||||
function clearSelectedPdf(e) {
|
||||
if (e) e.stopPropagation();
|
||||
const input = document.getElementById('pdfFileInput');
|
||||
if (input) input.value = '';
|
||||
const infoBox = document.getElementById('pdfSelectedInfo');
|
||||
if (infoBox) infoBox.style.display = 'none';
|
||||
const btn = document.getElementById('btnProcessPdf');
|
||||
if (btn) btn.disabled = true;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 2. Upload & Parse PDF
|
||||
// ============================================================
|
||||
async function processPdfUpload() {
|
||||
const input = document.getElementById('pdfFileInput');
|
||||
if (!input || !input.files || input.files.length === 0) {
|
||||
Toast.warning('กรุณาเลือกไฟล์ PDF ก่อน');
|
||||
return;
|
||||
}
|
||||
|
||||
const btn = document.getElementById('btnProcessPdf');
|
||||
const processingState = document.getElementById('pdfProcessingState');
|
||||
const dropZone = document.getElementById('pdfDropZone');
|
||||
const selectedInfo = document.getElementById('pdfSelectedInfo');
|
||||
|
||||
if (btn) btn.disabled = true;
|
||||
if (dropZone) dropZone.style.display = 'none';
|
||||
if (selectedInfo) selectedInfo.style.display = 'none';
|
||||
if (processingState) processingState.style.display = 'block';
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('pdf_file', input.files[0]);
|
||||
|
||||
try {
|
||||
const res = await API.upload('import_pdf.php?action=parsePdf', formData);
|
||||
|
||||
if (!res.survey) {
|
||||
throw new Error('ไม่พบโครงสร้างแบบประเมินในไฟล์ PDF');
|
||||
}
|
||||
|
||||
currentPdfSurveyData = res.survey;
|
||||
|
||||
// Close upload modal
|
||||
Modal.hide('importPdfModal');
|
||||
document.getElementById('importPdfModal')?.remove();
|
||||
|
||||
// Show Interactive Preview & Edit Modal
|
||||
showPdfPreviewModal(currentPdfSurveyData);
|
||||
|
||||
} catch (err) {
|
||||
Toast.error(err.message || 'เกิดข้อผิดพลาดในการประมวลผลไฟล์ PDF');
|
||||
if (dropZone) dropZone.style.display = 'block';
|
||||
if (selectedInfo) selectedInfo.style.display = 'flex';
|
||||
if (processingState) processingState.style.display = 'none';
|
||||
if (btn) btn.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 3. Interactive Preview & Editor Modal
|
||||
// ============================================================
|
||||
function showPdfPreviewModal(surveyData) {
|
||||
// Calculate Stats
|
||||
let totalQuestions = 0;
|
||||
let totalHeadings = 0;
|
||||
(surveyData.sections || []).forEach(sec => {
|
||||
totalQuestions += (sec.questions || []).length;
|
||||
(sec.headings || []).forEach(h => {
|
||||
totalHeadings++;
|
||||
totalQuestions += (h.questions || []).length;
|
||||
});
|
||||
});
|
||||
|
||||
let sectionsHtml = '';
|
||||
(surveyData.sections || []).forEach((sec, sIdx) => {
|
||||
let secBadgeClass = 'badge-primary';
|
||||
let secBadgeText = 'ตอนที่ ' + (sIdx + 1);
|
||||
if (sec.category === 'general') {
|
||||
secBadgeText += ' (ข้อมูลทั่วไป)';
|
||||
} else if (sec.category === 'rating') {
|
||||
secBadgeText += ' (เกณฑ์ประเมิน 5 ระดับ)';
|
||||
} else if (sec.category === 'suggestion') {
|
||||
secBadgeText += ' (ข้อเสนอแนะ)';
|
||||
}
|
||||
|
||||
let contentHtml = '';
|
||||
|
||||
// Render Headings & Subquestions
|
||||
if (sec.headings && sec.headings.length > 0) {
|
||||
sec.headings.forEach((h, hIdx) => {
|
||||
let questionsList = '';
|
||||
(h.questions || []).forEach((q, qIdx) => {
|
||||
questionsList += `
|
||||
<div class="pdf-q-row" id="q_row_${sIdx}_${hIdx}_${qIdx}" style="display:flex;gap:10px;align-items:center;margin-bottom:8px;background:#fff;padding:8px 12px;border-radius:6px;border:1px solid #e2e8f0;">
|
||||
<span style="font-weight:600;font-size:12px;color:#64748b;min-width:30px;">${hIdx + 1}.${qIdx + 1}</span>
|
||||
<input type="text" class="form-input pdf-q-text" style="padding:6px 10px;font-size:13px;" value="${escapeHtml(q.question_text)}" data-sec="${sIdx}" data-head="${hIdx}" data-q="${qIdx}">
|
||||
<span class="badge" style="background:#e0f2fe;color:#0369a1;font-size:11px;white-space:nowrap;">คะแนน 1-5</span>
|
||||
<button type="button" class="btn btn-sm btn-secondary" style="color:#dc2626;padding:4px 8px;" onclick="deletePdfQuestionRow('q_row_${sIdx}_${hIdx}_${qIdx}')" title="ลบข้อนี้">🗑️</button>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
|
||||
contentHtml += `
|
||||
<div class="pdf-heading-card" id="head_card_${sIdx}_${hIdx}" style="background:#f8fafc;border:1px solid #cbd5e1;border-radius:8px;padding:12px;margin-bottom:12px;">
|
||||
<div style="display:flex;gap:10px;align-items:center;margin-bottom:10px;">
|
||||
<span style="font-weight:700;font-size:13px;color:#334155;">📌 ด้าน/หมวด:</span>
|
||||
<input type="text" class="form-input pdf-head-title" style="font-weight:600;font-size:13px;padding:6px 10px;" value="${escapeHtml(h.title)}" data-sec="${sIdx}" data-head="${hIdx}">
|
||||
</div>
|
||||
<div class="pdf-questions-container">
|
||||
${questionsList}
|
||||
</div>
|
||||
<button type="button" class="btn btn-sm btn-secondary" style="font-size:11px;margin-top:6px;" onclick="addPdfQuestionToHeading(${sIdx}, ${hIdx})">➕ เพิ่มข้อในด้านนี้</button>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
}
|
||||
|
||||
// Render Direct Questions in this section
|
||||
if (sec.questions && sec.questions.length > 0) {
|
||||
sec.questions.forEach((q, qIdx) => {
|
||||
let optionsBadges = '';
|
||||
if (q.options && q.options.length > 0) {
|
||||
optionsBadges = `
|
||||
<div style="display:flex;flex-wrap:wrap;gap:6px;margin-top:6px;">
|
||||
<span style="font-size:11px;color:#64748b;font-weight:600;">ตัวเลือก:</span>
|
||||
${q.options.map(opt => `<span style="background:#f1f5f9;border:1px solid #cbd5e1;border-radius:4px;padding:2px 6px;font-size:11px;color:#334155;">${escapeHtml(opt)}</span>`).join('')}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
let typeLabel = q.question_type === 'text' ? 'ข้อความ/ข้อเสนอแนะ' : (q.options ? 'หลายตัวเลือก (Choice)' : 'คะแนน 1-5');
|
||||
|
||||
contentHtml += `
|
||||
<div class="pdf-q-row" id="q_direct_row_${sIdx}_${qIdx}" style="margin-bottom:10px;background:#fff;padding:10px 12px;border-radius:8px;border:1px solid #e2e8f0;">
|
||||
<div style="display:flex;gap:10px;align-items:center;">
|
||||
<span style="font-weight:600;font-size:12px;color:#64748b;min-width:24px;">${qIdx + 1}.</span>
|
||||
<input type="text" class="form-input pdf-direct-q-text" style="padding:6px 10px;font-size:13px;" value="${escapeHtml(q.question_text)}" data-sec="${sIdx}" data-q="${qIdx}">
|
||||
<span class="badge" style="background:#f0fdf4;color:#15803d;font-size:11px;white-space:nowrap;">${typeLabel}</span>
|
||||
<button type="button" class="btn btn-sm btn-secondary" style="color:#dc2626;padding:4px 8px;" onclick="deletePdfQuestionRow('q_direct_row_${sIdx}_${qIdx}')" title="ลบข้อนี้">🗑️</button>
|
||||
</div>
|
||||
${optionsBadges}
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
}
|
||||
|
||||
sectionsHtml += `
|
||||
<div class="pdf-section-box" style="border:1px solid #e2e8f0;border-radius:10px;padding:16px;margin-bottom:16px;background:#ffffff;box-shadow:0 1px 3px rgba(0,0,0,0.05);">
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;border-bottom:1px solid #f1f5f9;padding-bottom:10px;">
|
||||
<div style="display:flex;align-items:center;gap:10px;flex:1;">
|
||||
<span class="badge ${secBadgeClass}" style="font-size:12px;padding:4px 10px;">${secBadgeText}</span>
|
||||
<input type="text" class="form-input pdf-sec-title" style="font-weight:600;font-size:14px;flex:1;max-width:500px;" value="${escapeHtml(sec.title)}" data-sec="${sIdx}">
|
||||
</div>
|
||||
</div>
|
||||
<div>${contentHtml}</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
|
||||
const html = `
|
||||
<div class="pdf-preview-container" style="max-height:68vh;overflow-y:auto;padding-right:8px;">
|
||||
<!-- Header Summary Banner -->
|
||||
<div style="background:linear-gradient(135deg, #1e3a8a, #2563eb);color:#fff;border-radius:10px;padding:16px 20px;margin-bottom:20px;display:flex;justify-content:space-between;align-items:center;">
|
||||
<div>
|
||||
<div style="font-size:16px;font-weight:700;margin-bottom:4px;">✨ ตรวจสอบความถูกต้องของแบบประเมิน</div>
|
||||
<div style="font-size:12px;opacity:0.9;">ระบบสกัดข้อมูลจาก PDF เรียบร้อยแล้ว ท่านสามารถแก้ไขข้อความหรือปรับปรุงคำถามได้โดยตรงในหน้านี้</div>
|
||||
</div>
|
||||
<div style="display:flex;gap:10px;">
|
||||
<div style="background:rgba(255,255,255,0.2);padding:6px 14px;border-radius:8px;text-align:center;">
|
||||
<div style="font-size:18px;font-weight:700;">${surveyData.sections?.length || 0}</div>
|
||||
<div style="font-size:10px;opacity:0.9;">ตอน/ส่วน</div>
|
||||
</div>
|
||||
<div style="background:rgba(255,255,255,0.2);padding:6px 14px;border-radius:8px;text-align:center;">
|
||||
<div style="font-size:18px;font-weight:700;">${totalHeadings}</div>
|
||||
<div style="font-size:10px;opacity:0.9;">ด้านประเมิน</div>
|
||||
</div>
|
||||
<div style="background:rgba(255,255,255,0.2);padding:6px 14px;border-radius:8px;text-align:center;">
|
||||
<div style="font-size:18px;font-weight:700;">${totalQuestions}</div>
|
||||
<div style="font-size:10px;opacity:0.9;">ข้อคำถาม</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Survey Meta Inputs -->
|
||||
<div class="card" style="margin-bottom:20px;border:1px solid #e2e8f0;padding:16px;border-radius:10px;background:#f8fafc;">
|
||||
<div class="form-group" style="margin-bottom:12px;">
|
||||
<label class="form-label" style="font-weight:700;color:#0f172a;">📝 ชื่อแบบประเมิน / โครงการ *</label>
|
||||
<input type="text" class="form-input" id="pdfPreviewTitle" value="${escapeHtml(surveyData.title || '')}" style="font-size:15px;font-weight:600;" required>
|
||||
</div>
|
||||
<div class="form-group" style="margin-bottom:0;">
|
||||
<label class="form-label" style="font-weight:600;color:#475569;">คำชี้แจง / รายละเอียด</label>
|
||||
<textarea class="form-input" id="pdfPreviewDesc" rows="2" style="font-size:13px;">${escapeHtml(surveyData.description || '')}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sections List -->
|
||||
<div id="pdfSectionsPreviewContainer">
|
||||
${sectionsHtml}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const footer = `
|
||||
<button class="btn btn-secondary" onclick="showImportPdfModal()">⬅️ เลือกไฟล์ใหม่</button>
|
||||
<button class="btn btn-primary" id="btnConfirmImportPdf" style="background-color:#16a34a;border-color:#16a34a;font-weight:700;" onclick="submitFinalPdfSurvey()">✅ ยืนยันและสร้างแบบประเมินทันที</button>
|
||||
`;
|
||||
|
||||
const modalId = Modal.create('📄 ตรวจสอบและปรับแต่งแบบประเมินจาก PDF', html, footer, 'modal-xl');
|
||||
const modalEl = document.getElementById(modalId);
|
||||
if (modalEl) modalEl.id = 'pdfPreviewModal';
|
||||
}
|
||||
|
||||
function deletePdfQuestionRow(rowId) {
|
||||
const el = document.getElementById(rowId);
|
||||
if (el) {
|
||||
el.style.opacity = '0';
|
||||
setTimeout(() => el.remove(), 200);
|
||||
}
|
||||
}
|
||||
|
||||
function addPdfQuestionToHeading(secIdx, headIdx) {
|
||||
const qText = prompt('พิมพ์ข้อคำถามใหม่:');
|
||||
if (!qText || !qText.trim()) return;
|
||||
|
||||
const headCard = document.getElementById(`head_card_${secIdx}_${headIdx}`);
|
||||
if (!headCard) return;
|
||||
|
||||
const container = headCard.querySelector('.pdf-questions-container');
|
||||
if (!container) return;
|
||||
|
||||
const count = container.querySelectorAll('.pdf-q-row').length + 1;
|
||||
const newId = `q_row_${secIdx}_${headIdx}_new_${Date.now()}`;
|
||||
|
||||
const newRow = document.createElement('div');
|
||||
newRow.id = newId;
|
||||
newRow.className = 'pdf-q-row';
|
||||
newRow.style.cssText = 'display:flex;gap:10px;align-items:center;margin-bottom:8px;background:#fff;padding:8px 12px;border-radius:6px;border:1px solid #e2e8f0;';
|
||||
newRow.innerHTML = `
|
||||
<span style="font-weight:600;font-size:12px;color:#64748b;min-width:30px;">+</span>
|
||||
<input type="text" class="form-input pdf-q-text" style="padding:6px 10px;font-size:13px;" value="${escapeHtml(qText.trim())}" data-sec="${secIdx}" data-head="${headIdx}">
|
||||
<span class="badge" style="background:#e0f2fe;color:#0369a1;font-size:11px;white-space:nowrap;">คะแนน 1-5</span>
|
||||
<button type="button" class="btn btn-sm btn-secondary" style="color:#dc2626;padding:4px 8px;" onclick="deletePdfQuestionRow('${newId}')" title="ลบข้อนี้">🗑️</button>
|
||||
`;
|
||||
|
||||
container.appendChild(newRow);
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 4. Confirm & Save to Database
|
||||
// ============================================================
|
||||
async function submitFinalPdfSurvey() {
|
||||
const titleInput = document.getElementById('pdfPreviewTitle');
|
||||
const descInput = document.getElementById('pdfPreviewDesc');
|
||||
const btn = document.getElementById('btnConfirmImportPdf');
|
||||
|
||||
const title = titleInput?.value?.trim();
|
||||
if (!title) {
|
||||
Toast.warning('กรุณาระบุชื่อแบบประเมิน');
|
||||
titleInput?.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!currentPdfSurveyData) {
|
||||
Toast.error('ไม่พบข้อมูลแบบประเมิน');
|
||||
return;
|
||||
}
|
||||
|
||||
// Serialize edited fields back into currentPdfSurveyData
|
||||
currentPdfSurveyData.title = title;
|
||||
currentPdfSurveyData.description = descInput?.value?.trim() || '';
|
||||
|
||||
// Update section titles
|
||||
document.querySelectorAll('.pdf-sec-title').forEach(el => {
|
||||
const sIdx = parseInt(el.getAttribute('data-sec'));
|
||||
if (currentPdfSurveyData.sections[sIdx]) {
|
||||
currentPdfSurveyData.sections[sIdx].title = el.value.trim();
|
||||
}
|
||||
});
|
||||
|
||||
// Update heading titles & heading questions
|
||||
(currentPdfSurveyData.sections || []).forEach((sec, sIdx) => {
|
||||
if (sec.headings) {
|
||||
sec.headings.forEach((h, hIdx) => {
|
||||
const headTitleEl = document.querySelector(`.pdf-head-title[data-sec="${sIdx}"][data-head="${hIdx}"]`);
|
||||
if (headTitleEl) {
|
||||
h.title = headTitleEl.value.trim();
|
||||
}
|
||||
|
||||
// Re-collect active question rows inside this heading
|
||||
const headCard = document.getElementById(`head_card_${sIdx}_${hIdx}`);
|
||||
if (headCard) {
|
||||
const qInputs = headCard.querySelectorAll('.pdf-q-text');
|
||||
const updatedQuestions = [];
|
||||
qInputs.forEach(qi => {
|
||||
const qVal = qi.value.trim();
|
||||
if (qVal) {
|
||||
updatedQuestions.push({
|
||||
question_text: qVal,
|
||||
question_type: 'radio',
|
||||
is_required: 1,
|
||||
options: null,
|
||||
scale_min: 1,
|
||||
scale_max: 5
|
||||
});
|
||||
}
|
||||
});
|
||||
h.questions = updatedQuestions;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Direct questions in this section
|
||||
if (sec.questions) {
|
||||
const updatedDirect = [];
|
||||
document.querySelectorAll(`.pdf-direct-q-text[data-sec="${sIdx}"]`).forEach(qi => {
|
||||
const qVal = qi.value.trim();
|
||||
const qIdx = parseInt(qi.getAttribute('data-q'));
|
||||
const originalQ = sec.questions[qIdx] || {};
|
||||
if (qVal) {
|
||||
updatedDirect.push({
|
||||
...originalQ,
|
||||
question_text: qVal
|
||||
});
|
||||
}
|
||||
});
|
||||
sec.questions = updatedDirect;
|
||||
}
|
||||
});
|
||||
|
||||
if (btn) {
|
||||
btn.disabled = true;
|
||||
btn.textContent = '⏳ กำลังบันทึกแบบประเมินลงฐานข้อมูล...';
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await API.post('import_pdf.php?action=confirmImport', {
|
||||
survey_data: currentPdfSurveyData
|
||||
});
|
||||
|
||||
Toast.success(res.message || 'สร้างแบบประเมินจาก PDF สำเร็จแล้ว!');
|
||||
|
||||
// Close preview modal
|
||||
Modal.hide('pdfPreviewModal');
|
||||
document.getElementById('pdfPreviewModal')?.remove();
|
||||
|
||||
// Refresh surveys list
|
||||
if (typeof loadSurveys === 'function') loadSurveys();
|
||||
if (typeof loadTeacherSurveys === 'function') loadTeacherSurveys();
|
||||
|
||||
// Show Success Action Prompt
|
||||
showImportSuccessPrompt(res.survey_id, res.unique_link, res.title);
|
||||
|
||||
} catch (err) {
|
||||
Toast.error(err.message || 'เกิดข้อผิดพลาดในการบันทึกแบบประเมิน');
|
||||
} finally {
|
||||
if (btn) {
|
||||
btn.disabled = false;
|
||||
btn.textContent = '✅ ยืนยันและสร้างแบบประเมินทันที';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function showImportSuccessPrompt(surveyId, link, title) {
|
||||
const fullUrl = `${window.location.origin}${getAppBasePath()}/respond.php?link=${link}`;
|
||||
const editUrl = `${getAppBasePath()}/edit.html?id=${surveyId}`;
|
||||
|
||||
const html = `
|
||||
<div style="text-align:center;padding:10px 0;">
|
||||
<div style="font-size:48px;margin-bottom:12px;">🎉</div>
|
||||
<h3 style="font-size:18px;font-weight:700;color:#0f172a;margin-bottom:6px;">นำเข้าแบบประเมินสำเร็จเรียบร้อย!</h3>
|
||||
<p style="font-size:14px;color:#64748b;margin-bottom:20px;"><b>"${escapeHtml(title)}"</b> พร้อมเปิดให้ทำแบบประเมินแล้ว</p>
|
||||
|
||||
<div style="background:#f8fafc;border:1px solid #e2e8f0;border-radius:10px;padding:14px;margin-bottom:20px;text-align:left;">
|
||||
<label class="form-label" style="font-size:12px;font-weight:600;color:#64748b;">🔗 ลิงก์สำหรับผู้ตอบแบบประเมิน:</label>
|
||||
<div style="display:flex;gap:8px;">
|
||||
<input type="text" class="form-input" style="font-size:12px;background:#fff;" value="${fullUrl}" readonly id="newSurveyUrlInput">
|
||||
<button class="btn btn-sm btn-primary" onclick="copyTextToClipboard('${fullUrl}', this)">📋 คัดลอก</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display:flex;gap:12px;justify-content:center;">
|
||||
<a href="${editUrl}" class="btn btn-secondary">✏️ ปรับแต่งฟอร์มใน Editor</a>
|
||||
<a href="${fullUrl}" target="_blank" class="btn btn-primary" style="background:#2563eb;border-color:#2563eb;">👁️ ทดลองเปิดทำแบบประเมิน</a>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const footer = `
|
||||
<button class="btn btn-secondary" onclick="Modal.hide('pdfSuccessModal');document.getElementById('pdfSuccessModal')?.remove();">ปิดหน้าต่าง</button>
|
||||
`;
|
||||
|
||||
const modalId = Modal.create('✨ สำเร็จ', html, footer, 'modal-md');
|
||||
const modalEl = document.getElementById(modalId);
|
||||
if (modalEl) modalEl.id = 'pdfSuccessModal';
|
||||
}
|
||||
|
||||
// Global Window Bindings
|
||||
window.showImportPdfModal = showImportPdfModal;
|
||||
window.handlePdfFileSelected = handlePdfFileSelected;
|
||||
window.clearSelectedPdf = clearSelectedPdf;
|
||||
window.processPdfUpload = processPdfUpload;
|
||||
window.showPdfPreviewModal = showPdfPreviewModal;
|
||||
window.deletePdfQuestionRow = deletePdfQuestionRow;
|
||||
window.addPdfQuestionToHeading = addPdfQuestionToHeading;
|
||||
window.submitFinalPdfSurvey = submitFinalPdfSurvey;
|
||||
window.showImportSuccessPrompt = showImportSuccessPrompt;
|
||||
Reference in New Issue
Block a user