made client data browsable with dropdown and version diffs
This commit is contained in:
143
common.php
143
common.php
@ -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).
|
||||
|
||||
Reference in New Issue
Block a user