diff --git a/api/import_google_form.php b/api/import_google_form.php index dc3084f..16d95d8 100644 --- a/api/import_google_form.php +++ b/api/import_google_form.php @@ -9,19 +9,22 @@ require_once __DIR__ . '/../config/database.php'; require_once __DIR__ . '/../config/auth.php'; header('Content-Type: application/json; charset=utf-8'); -requireLogin(); +if (php_sapi_name() !== 'cli') { + requireLogin(); +} -$action = $_GET['action'] ?? ''; - -switch ($action) { - case 'importFromUrl': - importFromUrl(); - break; - case 'importFromJson': - importFromJson(); - break; - default: - jsonResponse(['error' => 'Invalid action'], 400); +if (isset($_GET['action'])) { + $action = $_GET['action'] ?? ''; + switch ($action) { + case 'importFromUrl': + importFromUrl(); + break; + case 'importFromJson': + importFromJson(); + break; + default: + jsonResponse(['error' => 'Invalid action'], 400); + } } function importFromUrl() { @@ -111,9 +114,10 @@ function parseGoogleFormData($data) { $sections = []; $currentSection = [ 'section_number' => 1, - 'title' => 'ส่วนที่ 1 ข้อมูลทั่วไป', + 'title' => 'ตอนที่ 1 ข้อมูลทั่วไป', 'description' => '', 'category' => 'general', + 'headings' => [], 'questions' => [] ]; @@ -127,24 +131,64 @@ function parseGoogleFormData($data) { $qTypeNum = $item[3] ?? 0; $qDetails = $item[4][0] ?? []; - if (empty($qTitle) && $qTypeNum != 8) continue; // Skip empty items except section breaks + if (empty($qTitle) && $qTypeNum != 8 && $qTypeNum != 7) continue; // Type 8 = Section Break in Google Forms if ($qTypeNum == 8) { - if (!empty($currentSection['questions'])) { + if (!empty($currentSection['questions']) || !empty($currentSection['headings'])) { $sections[] = $currentSection; } $sectionCount++; $currentSection = [ 'section_number' => $sectionCount, - 'title' => $qTitle ?: ('ส่วนที่ ' . $sectionCount), - 'description' => $qDesc, + 'title' => $qTitle ?: ('ตอนที่ ' . $sectionCount), + 'description' => $qDesc ?: '', 'category' => 'rating', + 'headings' => [], 'questions' => [] ]; continue; } + // Type 7 = Grid / Matrix (ตารางประเมินระดับความพึงพอใจ 5 ระดับ) + if ($qTypeNum == 7) { + $gridTitle = $qTitle ?: 'ด้านที่ประเมิน'; + $gridDesc = $qDesc ?: ''; + $gridQuestions = []; + + if (isset($item[4]) && is_array($item[4])) { + foreach ($item[4] as $sub) { + if (!is_array($sub)) continue; + $rowTitle = ''; + if (isset($sub[3]) && is_array($sub[3]) && !empty($sub[3])) { + $rowTitle = $sub[3][0]; + } elseif (isset($sub[3]) && is_string($sub[3])) { + $rowTitle = $sub[3]; + } + if (empty($rowTitle)) continue; + + $gridQuestions[] = [ + 'question_text' => $rowTitle, + 'question_type' => 'radio', + 'is_required' => 1, + 'description' => '', + 'options' => null, // 5-point Rating scale + 'scale_min' => 1, + 'scale_max' => 5 + ]; + } + } + + if (!empty($gridQuestions)) { + $currentSection['headings'][] = [ + 'title' => $gridTitle, + 'description' => $gridDesc, + 'questions' => $gridQuestions + ]; + } + continue; + } + $qType = 'radio'; $options = []; $scaleMin = 1; @@ -154,7 +198,6 @@ function parseGoogleFormData($data) { // 0: Short Text, 1: Paragraph // 2: Radio (Multiple Choice), 3: Dropdown, 4: Checkbox // 5: Linear Scale (1-5) - // 7: Grid / Matrix switch ($qTypeNum) { case 0: case 1: @@ -209,7 +252,7 @@ function parseGoogleFormData($data) { $currentSection['questions'][] = $questionObj; } - if (!empty($currentSection['questions'])) { + if (!empty($currentSection['questions']) || !empty($currentSection['headings'])) { $sections[] = $currentSection; } @@ -219,6 +262,7 @@ function parseGoogleFormData($data) { 'title' => 'ส่วนที่ 1 ข้อมูลและข้อคำถาม', 'description' => 'นำเข้าจาก Google Forms', 'category' => 'general', + 'headings' => [], 'questions' => [] ]; } @@ -257,27 +301,63 @@ function saveParsedSurveyToDB($parsedSurvey, $projectId = null) { $stmt->execute([ $surveyId, $sec['section_number'] ?? $secNum, - $sec['title'] ?? ('ส่วนที่ ' . $secNum), + $sec['title'] ?? ('ตอนที่ ' . $secNum), $sec['description'] ?? '', $sec['category'] ?? 'rating' ]); $sectionId = $db->lastInsertId(); $orderNum = 1; - foreach ($sec['questions'] as $q) { - $optionsJson = !empty($q['options']) ? json_encode($q['options'], JSON_UNESCAPED_UNICODE) : null; - $stmtQ = $db->prepare("INSERT INTO survey_questions (section_id, question_text, question_type, is_required, order_num, options, scale_min, scale_max, description) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"); - $stmtQ->execute([ - $sectionId, - $q['question_text'], - $q['question_type'] ?? 'radio', - $q['is_required'] ?? 1, - $orderNum++, - $optionsJson, - $q['scale_min'] ?? 1, - $q['scale_max'] ?? 5, - $q['description'] ?? null - ]); + + // 1. Insert Headings & their questions (e.g. Grids) + if (!empty($sec['headings'])) { + foreach ($sec['headings'] as $hIdx => $h) { + $stmtH = $db->prepare("INSERT INTO survey_headings (section_id, title, description, order_num) VALUES (?, ?, ?, ?)"); + $stmtH->execute([ + $sectionId, + $h['title'] ?? '', + $h['description'] ?? '', + $hIdx + 1 + ]); + $headingId = $db->lastInsertId(); + + foreach ($h['questions'] as $q) { + $optionsJson = !empty($q['options']) ? json_encode($q['options'], JSON_UNESCAPED_UNICODE) : null; + $stmtQ = $db->prepare("INSERT INTO survey_questions (section_id, heading_id, question_text, question_type, is_required, order_num, options, scale_min, scale_max, description) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + $stmtQ->execute([ + $sectionId, + $headingId, + $q['question_text'], + $q['question_type'] ?? 'radio', + $q['is_required'] ?? 1, + $orderNum++, + $optionsJson, + $q['scale_min'] ?? 1, + $q['scale_max'] ?? 5, + $q['description'] ?? null + ]); + } + } + } + + // 2. Insert Loose questions + if (!empty($sec['questions'])) { + foreach ($sec['questions'] as $q) { + $optionsJson = !empty($q['options']) ? json_encode($q['options'], JSON_UNESCAPED_UNICODE) : null; + $stmtQ = $db->prepare("INSERT INTO survey_questions (section_id, heading_id, question_text, question_type, is_required, order_num, options, scale_min, scale_max, description) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + $stmtQ->execute([ + $sectionId, + null, + $q['question_text'], + $q['question_type'] ?? 'radio', + $q['is_required'] ?? 1, + $orderNum++, + $optionsJson, + $q['scale_min'] ?? 1, + $q['scale_max'] ?? 5, + $q['description'] ?? null + ]); + } } $secNum++; } diff --git a/js/admin.js b/js/admin.js index d8944f6..a2fdcda 100644 --- a/js/admin.js +++ b/js/admin.js @@ -809,9 +809,9 @@ async function generateLink(id) {