made client data browsable with dropdown and version diffs

This commit is contained in:
2026-06-01 13:29:10 +02:00
parent bee7b74e53
commit 3d56abd124
10 changed files with 971 additions and 83 deletions

View File

@ -1105,6 +1105,149 @@ function qdb_option_german_label(PDO $pdo, string $answerOptionID, string $store
return '';
}
/** German label for a string catalog key (symptoms, glass levels, etc.). */
function qdb_string_german_label(PDO $pdo, string $stringKey, array &$cache = []): string {
$stringKey = trim($stringKey);
if ($stringKey === '') {
return '';
}
if (isset($cache[$stringKey])) {
return $cache[$stringKey];
}
$tr = qdb_fetch_translation_map($pdo, 'string', $stringKey);
$de = trim($tr[QDB_SOURCE_LANGUAGE] ?? '');
$label = $de !== '' ? $de : $stringKey;
$cache[$stringKey] = $label;
return $label;
}
/** German question text for UI display. */
function qdb_question_german_label(PDO $pdo, array $questionRow): string {
$tr = qdb_fetch_translation_map($pdo, 'question', $questionRow['questionID']);
$de = trim($tr[QDB_SOURCE_LANGUAGE] ?? '');
if ($de !== '') {
return $de;
}
$defaultText = trim($questionRow['defaultText'] ?? '');
if ($defaultText !== '' && !qdb_is_stable_key($defaultText)) {
return $defaultText;
}
return qdb_question_local_id($questionRow['questionID']);
}
/**
* Result columns + option map using German labels (client detail, not CSV export).
*
* @return array{questions: array, resultColumns: array, optionTextMap: array, stringLabelCache: array}
*/
function qdb_display_questionnaire_context(PDO $pdo, string $questionnaireID): array {
$qStmt = $pdo->prepare(
'SELECT questionID, defaultText, type, orderIndex, configJson FROM question WHERE questionnaireID = :id ORDER BY orderIndex'
);
$qStmt->execute([':id' => $questionnaireID]);
$questions = $qStmt->fetchAll(PDO::FETCH_ASSOC);
$stringLabelCache = [];
$resultColumns = [];
foreach ($questions as $q) {
$cfg = json_decode($q['configJson'] ?? '{}', true) ?: [];
$type = $q['type'] ?? '';
if ($type === 'glass_scale_question') {
$symptoms = $cfg['symptoms'] ?? [];
if (is_array($symptoms) && $symptoms !== []) {
foreach ($symptoms as $symptomKey) {
$sk = trim((string)$symptomKey);
if ($sk === '') {
continue;
}
$resultColumns[] = [
'header' => qdb_string_german_label($pdo, $sk, $stringLabelCache),
'questionID' => $q['questionID'],
'symptomKey' => $sk,
'kind' => 'glass_symptom',
'question' => $q,
];
}
continue;
}
}
$resultColumns[] = [
'header' => qdb_question_german_label($pdo, $q),
'questionID' => $q['questionID'],
'symptomKey' => null,
'kind' => 'question',
'question' => $q,
];
}
$optionTextMap = [];
foreach ($questions as $q) {
$aoStmt = $pdo->prepare('SELECT answerOptionID, defaultText FROM answer_option WHERE questionID = :qid');
$aoStmt->execute([':qid' => $q['questionID']]);
foreach ($aoStmt->fetchAll(PDO::FETCH_ASSOC) as $ao) {
$optionTextMap[$ao['answerOptionID']] = qdb_option_german_label(
$pdo,
$ao['answerOptionID'],
$ao['defaultText']
);
}
}
return [
'questions' => $questions,
'resultColumns' => $resultColumns,
'optionTextMap' => $optionTextMap,
'stringLabelCache' => $stringLabelCache,
];
}
/** Format one answer cell for UI (German labels). */
function qdb_display_column_cell_value(
PDO $pdo,
array $column,
?array $answerRow,
array $optionTextMap,
array &$stringLabelCache
): string {
if (($column['kind'] ?? '') === 'glass_symptom') {
$raw = qdb_glass_symptom_answer_value(
$answerRow['freeTextValue'] ?? null,
(string)($column['symptomKey'] ?? '')
);
if ($raw === '') {
return '';
}
return qdb_string_german_label($pdo, $raw, $stringLabelCache);
}
if (($column['question']['type'] ?? '') === 'glass_scale_question') {
return qdb_format_glass_answer_json_display($pdo, $answerRow['freeTextValue'] ?? null, $stringLabelCache);
}
return qdb_format_client_answer_display($column['question'], $answerRow, $optionTextMap);
}
/** Glass-scale JSON with German symptom keys and level labels. */
function qdb_format_glass_answer_json_display(PDO $pdo, ?string $raw, array &$stringLabelCache): string
{
if ($raw === null || trim($raw) === '') {
return '';
}
$decoded = json_decode($raw, true);
if (!is_array($decoded)) {
return $raw;
}
$parts = [];
foreach ($decoded as $key => $val) {
$val = trim((string)$val);
if ($val === '') {
continue;
}
$symLabel = qdb_string_german_label($pdo, (string)$key, $stringLabelCache);
$levelLabel = qdb_string_german_label($pdo, $val, $stringLabelCache);
$parts[] = $symLabel . ': ' . $levelLabel;
}
return implode('; ', $parts);
}
/**
* Build translation entry lists for one questionnaire.
* Returns ['stringEntries' => [...], 'contentEntries' => [...]] (questions + options interleaved).