diff --git a/api/export.php b/api/export.php index 8fb280f..edb39f7 100644 --- a/api/export.php +++ b/api/export.php @@ -54,10 +54,16 @@ if (!$questionnaire) { } // Questions ordered -$qStmt = $pdo->prepare("SELECT questionID, defaultText, type, orderIndex FROM question WHERE questionnaireID = :id ORDER BY orderIndex"); +$qStmt = $pdo->prepare("SELECT questionID, defaultText, type, orderIndex, configJson FROM question WHERE questionnaireID = :id ORDER BY orderIndex"); $qStmt->execute([':id' => $qnID]); $questions = $qStmt->fetchAll(PDO::FETCH_ASSOC); $questionIDs = array_column($questions, 'questionID'); +$questionColumnLabels = []; +foreach ($questions as &$q) { + $cfg = json_decode($q['configJson'] ?? '{}', true) ?: []; + $questionColumnLabels[$q['questionID']] = qdb_question_column_label($cfg, $q['defaultText'], $q['questionID'], $qnID); +} +unset($q); // Build answer-option lookup for resolving display text $optionTextMap = []; @@ -118,7 +124,7 @@ foreach ($clients as $c) { foreach ($questions as $q) { $qid = $q['questionID']; $a = $answerMap[$qid] ?? null; - $row[$q['defaultText']] = qdb_format_client_answer_display($q, $a, $optionTextMap); + $row[$questionColumnLabels[$qid]] = qdb_format_client_answer_display($q, $a, $optionTextMap); } $rows[] = $row; } @@ -143,7 +149,9 @@ if (!empty($rows)) { } } else { $header = ['clientCode', 'coach', 'supervisor', 'status', 'sumPoints', 'startedAt', 'completedAt']; - foreach ($questions as $q) $header[] = $q['defaultText']; + foreach ($questions as $q) { + $header[] = $questionColumnLabels[$q['questionID']] ?? $q['defaultText']; + } fputcsv($out, $header); } fclose($out); diff --git a/common.php b/common.php index 50870d1..675a754 100644 --- a/common.php +++ b/common.php @@ -893,6 +893,12 @@ function qdb_question_local_id(string $questionID, ?string $questionnaireID = nu return $pos !== false ? substr($questionID, $pos + 2) : $questionID; } +/** Column / export header: stable question key, else local id (q1, q2, …). */ +function qdb_question_column_label(array $config, string $defaultText, string $questionID, ?string $questionnaireID = null): string { + $key = qdb_question_key($config, $defaultText); + return $key !== '' ? $key : qdb_question_local_id($questionID, $questionnaireID); +} + function qdb_make_question_id(string $questionnaireID, string $localId): string { return $questionnaireID . '__' . $localId; } diff --git a/handlers/export.php b/handlers/export.php index 1546946..2a8ade5 100644 --- a/handlers/export.php +++ b/handlers/export.php @@ -34,10 +34,17 @@ if (!$questionnaire) { json_error('NOT_FOUND', 'Questionnaire not found', 404); } -$qStmt = $pdo->prepare("SELECT questionID, defaultText, type, orderIndex FROM question WHERE questionnaireID = :id ORDER BY orderIndex"); +$qStmt = $pdo->prepare("SELECT questionID, defaultText, type, orderIndex, configJson FROM question WHERE questionnaireID = :id ORDER BY orderIndex"); $qStmt->execute([':id' => $qnID]); $questions = $qStmt->fetchAll(PDO::FETCH_ASSOC); $questionIDs = array_column($questions, 'questionID'); +$questionColumnLabels = []; +foreach ($questions as &$q) { + $cfg = json_decode($q['configJson'] ?? '{}', true) ?: []; + $label = qdb_question_column_label($cfg, $q['defaultText'], $q['questionID'], $qnID); + $questionColumnLabels[$q['questionID']] = $label; +} +unset($q); $optionTextMap = []; foreach ($questionIDs as $qid) { @@ -119,7 +126,9 @@ if (!empty($rows)) { } } else { $header = ['clientCode', 'coachID', 'status', 'sumPoints', 'startedAt', 'completedAt']; - foreach ($questions as $q) $header[] = $q['defaultText']; + foreach ($questions as $q) { + $header[] = $questionColumnLabels[$q['questionID']] ?? $q['defaultText']; + } fputcsv($out, $header); } fclose($out); diff --git a/handlers/results.php b/handlers/results.php index b05d4f6..c50943f 100644 --- a/handlers/results.php +++ b/handlers/results.php @@ -34,6 +34,8 @@ $questionIDs = array_column($questions, 'questionID'); foreach ($questions as &$q) { $q['isRequired'] = (int)$q['isRequired']; $q['orderIndex'] = (int)$q['orderIndex']; + $cfg = json_decode($q['configJson'] ?? '{}', true) ?: []; + $q['questionKey'] = qdb_question_column_label($cfg, $q['defaultText'], $q['questionID'], $qnID); $ao = $pdo->prepare("SELECT answerOptionID, defaultText, points, orderIndex FROM answer_option WHERE questionID = :qid ORDER BY orderIndex"); $ao->execute([':qid' => $q['questionID']]); diff --git a/website/js/pages/results.js b/website/js/pages/results.js index b09e45d..f537be8 100644 --- a/website/js/pages/results.js +++ b/website/js/pages/results.js @@ -2,7 +2,8 @@ import { apiGet } from '../api.js'; import { showToast } from '../app.js'; import { isDevTestClientCode, - questionLocalKey, + questionDisplayKey, + questionGermanLabel, testDataRowClassForClient, } from '../test-data.js'; @@ -106,7 +107,7 @@ function renderResults() { Export CSV -
+