From 3d738bb14e2b33d5923524a426d4e9be0fa8db0e Mon Sep 17 00:00:00 2001 From: Tom Hempel Date: Mon, 15 Jun 2026 16:04:44 +0200 Subject: [PATCH] updated terminology from "Coach" to "Counselor" across multiple files for consistency and clarity --- common.php | 2 +- data/app_ui_strings.json | 16 ++++++++-------- handlers/assignments.php | 2 +- handlers/clients.php | 2 +- handlers/session.php | 2 +- handlers/users.php | 6 +++--- lib/analytics.php | 2 +- lib/dev_fixture.php | 4 ++-- website/js/app.js | 9 ++++++++- website/js/pages/assignments.js | 2 +- website/js/pages/clients.js | 14 +++++++------- website/js/pages/coaches.js | 2 +- website/js/pages/dev.js | 2 +- website/js/pages/editor.js | 6 +++--- website/js/pages/insights.js | 4 ++-- website/js/pages/questionnaires.js | 2 +- website/js/pages/results.js | 4 ++-- website/js/pages/users.js | 6 +++--- website/js/password-modal.js | 6 ++---- website/js/questionnaire-preview.js | 4 ++-- 20 files changed, 51 insertions(+), 46 deletions(-) diff --git a/common.php b/common.php index 96e4487..daa69cd 100644 --- a/common.php +++ b/common.php @@ -291,7 +291,7 @@ function qdb_reject_coach_web_login(string $role): void { if ($role === 'coach' && qdb_is_web_client_request()) { json_error( 'FORBIDDEN', - 'Coach accounts can only sign in through the mobile app.', + 'Counselor accounts can only sign in through the mobile app.', 403 ); } diff --git a/data/app_ui_strings.json b/data/app_ui_strings.json index aa95e5e..c83fc17 100644 --- a/data/app_ui_strings.json +++ b/data/app_ui_strings.json @@ -1,6 +1,6 @@ { "version": 2, - "description": "Coach-visible app UI strings only (excludes dev settings \/ database tools).", + "description": "Berater-visible app UI strings only (excludes dev settings / database tools).", "keys": [ "all_clients", "answer", @@ -128,7 +128,7 @@ "august": "August", "auth_footer_accounts": "Konten werden von Ihrer Organisation vergeben.", "auth_subtitle_change_password": "Bitte legen Sie jetzt ein eigenes Passwort fest.", - "auth_subtitle_login": "Melden Sie sich mit Ihrem Coach-Konto an.", + "auth_subtitle_login": "Melden Sie sich mit Ihrem Berater-Konto an.", "auth_title": "BW Schützt - NAT-AS", "cancel": "Abbrechen", "category_green": "Grün", @@ -139,7 +139,7 @@ "client": "Klient", "client_code": "Klientencode", "client_code_exists": "Dieser Client-Code existiert bereits.", - "coach_code": "Code Coach", + "coach_code": "Berater-Code", "confirm_password_hint": "Passwort bestätigen", "date_after": "Das Datum muss nach", "date_before": "Das Datum muss vor", @@ -148,7 +148,7 @@ "done": "Erledigt", "download": "Herunterladen", "download_failed_use_offline": "Download fehlgeschlagen – arbeite offline mit vorhandener Datenbank", - "enter_coach_code": "Bitte geben Sie Ihren Coach Code ein, um fortzufahren!", + "enter_coach_code": "Bitte geben Sie Ihren Berater-Code ein, um fortzufahren!", "error": "Fehler", "error_invalid_data": "Ungültige Daten", "error_not_found": "Nicht gefunden", @@ -157,7 +157,7 @@ "extreme_glass": "Extrem", "february": "Februar", "fill_all_fields": "Bitte alle Felder ausfüllen!", - "fill_both_fields": "Bitte Klienten-Code und Coach-Code prüfen.", + "fill_both_fields": "Bitte Klienten-Code und Berater-Code prüfen.", "hours_short": "h", "january": "Januar", "july": "Juli", @@ -210,7 +210,7 @@ "review_scores": "Punkte prüfen", "review_scores_agree": "Berechnete Kategorie bestätigen", "review_scores_calculated_category": "Berechnete Kategorie", - "review_scores_coach_category": "Coach-Kategorie", + "review_scores_coach_category": "Berater-Kategorie", "review_scores_empty": "Noch keine vollständigen Profilwerte zum Prüfen.", "review_scores_pending_upload": "Ausstehend — wird mit dem Upload gesendet", "review_scores_save_failed": "Kategorie konnte nicht gespeichert werden.", @@ -233,10 +233,10 @@ "upload_item_scoring_review": "Punkteprüfung: {profile}", "upload_nothing_pending": "Es wurde nichts hochgeladen. Es liegen keine abgeschlossenen Fragebögen zum Upload vor. Bitte zuerst einen Fragebogen abschließen.", "upload_prepare_failed": "Es wurde nichts hochgeladen. Die Daten konnten nicht für den Upload vorbereitet werden. Bitte erneut synchronisieren oder den Support kontaktieren.", - "upload_scoring_review_summary": "Coach: {band} · Summe {total}", + "upload_scoring_review_summary": "Berater: {band} · Summe {total}", "upload_summary": "{qn} Fragebögen · {scores} Punkteprüfungen · {clients} Klienten", "upload_success_message": "Hochladen: {count} erledigt.", - "upload_success_questionnaires": "{count} Fragebogen\/Fragebögen", + "upload_success_questionnaires": "{count} Fragebogen/Fragebögen", "upload_success_scoring_reviews": "{count} Punkteprüfung(en)", "username_hint": "Benutzername", "year": "Jahr" diff --git a/handlers/assignments.php b/handlers/assignments.php index cd1275d..3e8696c 100644 --- a/handlers/assignments.php +++ b/handlers/assignments.php @@ -70,7 +70,7 @@ case 'POST': } if (!$chk->fetch()) { qdb_discard($tmpDb, $lockFp); - json_error('NOT_FOUND', 'Coach not found or not authorized', 404); + json_error('NOT_FOUND', 'Counselor not found or not authorized', 404); } [$rbacClause, $rbacParams] = rbac_client_filter($tokenRec); diff --git a/handlers/clients.php b/handlers/clients.php index 2b4950b..594e0d4 100644 --- a/handlers/clients.php +++ b/handlers/clients.php @@ -83,7 +83,7 @@ case 'POST': } if (!$chkCoach->fetch()) { qdb_discard($tmpDb, $lockFp); - json_error('NOT_FOUND', 'Coach not found or not authorized', 404); + json_error('NOT_FOUND', 'Counselor not found or not authorized', 404); } $chk = $pdo->prepare("SELECT clientCode FROM client WHERE clientCode = :cc"); diff --git a/handlers/session.php b/handlers/session.php index 7277f7a..e204d2f 100644 --- a/handlers/session.php +++ b/handlers/session.php @@ -20,7 +20,7 @@ if (!$rec) { $role = (string)($rec['role'] ?? ''); if ($role === 'coach') { - json_error('FORBIDDEN', 'Coach accounts can only sign in through the mobile app.', 403); + json_error('FORBIDDEN', 'Counselor accounts can only sign in through the mobile app.', 403); } $username = ''; diff --git a/handlers/users.php b/handlers/users.php index 18b153f..bc1b69c 100644 --- a/handlers/users.php +++ b/handlers/users.php @@ -207,7 +207,7 @@ case 'PATCH': $chk->execute([':cid' => $target['entityID'], ':svid' => $callerEntityID]); if (!$chk->fetch()) { qdb_discard($tmpDb, $lockFp); - json_error('FORBIDDEN', 'Coach is not under your supervision', 403); + json_error('FORBIDDEN', 'Counselor is not under your supervision', 403); } } else { qdb_discard($tmpDb, $lockFp); @@ -274,7 +274,7 @@ case 'PATCH': $chk->execute([':cid' => $target['entityID'], ':svid' => $callerEntityID]); if (!$chk->fetch()) { qdb_discard($tmpDb, $lockFp); - json_error('FORBIDDEN', 'Coach is not under your supervision', 403); + json_error('FORBIDDEN', 'Counselor is not under your supervision', 403); } } else { qdb_discard($tmpDb, $lockFp); @@ -396,7 +396,7 @@ case 'DELETE': $chk->execute([':cid' => $target['entityID'], ':svid' => $callerEntityID]); if (!$chk->fetch()) { qdb_discard($tmpDb, $lockFp); - json_error('FORBIDDEN', 'Coach is not under your supervision', 403); + json_error('FORBIDDEN', 'Counselor is not under your supervision', 403); } } diff --git a/lib/analytics.php b/lib/analytics.php index bd59592..1e69341 100644 --- a/lib/analytics.php +++ b/lib/analytics.php @@ -346,7 +346,7 @@ function qdb_coach_recent_submissions( $chk->execute([':id' => $coachID]); $coach = $chk->fetch(PDO::FETCH_ASSOC); if (!$coach) { - json_error('NOT_FOUND', 'Coach not found', 404); + json_error('NOT_FOUND', 'Counselor not found', 404); } if ($role === 'supervisor' && ($coach['supervisorID'] ?? '') !== $entityID) { json_error('FORBIDDEN', 'Not authorized for this coach', 403); diff --git a/lib/dev_fixture.php b/lib/dev_fixture.php index 6107c41..7b2ac5b 100644 --- a/lib/dev_fixture.php +++ b/lib/dev_fixture.php @@ -93,13 +93,13 @@ function qdb_import_dev_fixture(PDO $pdo, array $fixture): array $username = qdb_dev_norm_username($row, $prefix); $svUser = trim($row['supervisor'] ?? $row['supervisorUsername'] ?? ''); if ($svUser === '' || !qdb_dev_has_prefix($svUser, $prefix)) { - $errors[] = "Coach $username: missing or invalid supervisor"; + $errors[] = "Counselor $username: missing or invalid supervisor"; continue; } $supervisorID = $supervisorIdByUsername[$svUser] ?? qdb_dev_lookup_entity_id($pdo, $svUser); if ($supervisorID === '') { - $errors[] = "Coach $username: supervisor $svUser not found"; + $errors[] = "Counselor $username: supervisor $svUser not found"; continue; } if (qdb_dev_user_exists($pdo, $username)) { diff --git a/website/js/app.js b/website/js/app.js index 9290399..0b9ac5a 100644 --- a/website/js/app.js +++ b/website/js/app.js @@ -35,6 +35,13 @@ export function canEdit() { return canAccessWebsite(); } +/** User-facing label for the coach role (internal key remains `coach`). */ +export function formatRoleLabel(role) { + if (role === 'coach') return 'Counselor'; + if (!role) return ''; + return role.charAt(0).toUpperCase() + role.slice(1); +} + function clearSession() { invalidateSessionCheck(); localStorage.removeItem('qdb_token'); @@ -109,7 +116,7 @@ function updateNav() { if (isLoggedIn()) { nav.style.display = ''; const role = getRole(); - const roleLabel = role === 'coach' ? 'counselor' : role; + const roleLabel = formatRoleLabel(role); userInfo.textContent = `${getUser()} (${roleLabel})`; // Show/hide role-gated nav items diff --git a/website/js/pages/assignments.js b/website/js/pages/assignments.js index 9abe17b..978c350 100644 --- a/website/js/pages/assignments.js +++ b/website/js/pages/assignments.js @@ -108,7 +108,7 @@ function renderAssignments() { Client Code - Current Counselor + Current counselor diff --git a/website/js/pages/clients.js b/website/js/pages/clients.js index 2eb0173..4e87451 100644 --- a/website/js/pages/clients.js +++ b/website/js/pages/clients.js @@ -105,7 +105,7 @@ function renderClients() { Client Code - Current Counselor + Current counselor ${showProfileColumn ? 'Profile scores' : ''} Actions @@ -305,7 +305,7 @@ function scoringLegendHTML() {
Calculated
-
Automatic category from answers and profile rules (shown before counselor review).
+
Automatic category from answers and profile rules (shown before Counselor review).
Counselor
@@ -371,7 +371,7 @@ function coachBandPickerHTML(p, clientCode) { data-weighted="${esc(String(p.weightedTotal ?? ''))}" data-coach="${esc(current)}"> @@ -423,7 +423,7 @@ function renderClientScoringProfiles(profiles, clientCode = '') {
Scoring profiles

- Weighted totals and calculated vs counselor categories for this client. + Weighted totals and calculated vs Counselor categories for this client.

${profiles.map(p => { const calc = p.calculatedBand || p.band; @@ -595,7 +595,7 @@ function openCoachBandConfirmModal({ clientCode, profileName, calculatedBand, co overlay.setAttribute('aria-modal', 'true'); overlay.innerHTML = `
- +
- + +
`; break; @@ -824,7 +824,7 @@ function renderEditor() { diff --git a/website/js/pages/insights.js b/website/js/pages/insights.js index 7aed228..790699c 100644 --- a/website/js/pages/insights.js +++ b/website/js/pages/insights.js @@ -102,7 +102,7 @@ function renderInsights() {

${sp.clientCount ?? 0} client(s) with complete profile ${sp.averageTotal != null ? ` · avg ${sp.averageTotal}` : ''} - ${sp.pendingReview ? ` · ${sp.pendingReview} pending counselor review` : ''} + ${sp.pendingReview ? ` · ${sp.pendingReview} pending Counselor review` : ''}

Calculated bands

${computedChart} @@ -141,7 +141,7 @@ function renderInsights() { ${scoringProfiles.length ? `

Scoring profiles

-

Calculated vs counselor band distribution among clients with a complete weighted score

+

Calculated vs Counselor band distribution among clients with a complete weighted score

${scoringCharts}
` : ''}
diff --git a/website/js/pages/questionnaires.js b/website/js/pages/questionnaires.js index 251f939..767c536 100644 --- a/website/js/pages/questionnaires.js +++ b/website/js/pages/questionnaires.js @@ -575,7 +575,7 @@ function openScoringProfileModal(profile, questionnaires, allProfiles) {
- +
- + @@ -423,7 +423,7 @@ function exportCSV() { }); }); - const headers = ['clientCode', 'coach', 'supervisor', 'status', 'sumPoints', 'completedAt', + const headers = ['clientCode', 'Counselor', 'supervisor', 'status', 'sumPoints', 'completedAt', ...resultColumns.map(col => col.label)]; const rows = clients.map(c => { diff --git a/website/js/pages/users.js b/website/js/pages/users.js index 449c78a..fd84b65 100644 --- a/website/js/pages/users.js +++ b/website/js/pages/users.js @@ -17,11 +17,11 @@ let filterSearchByRole = { admin: '', supervisor: '', coach: '' }; function roleGroupsForCaller() { return callerRole === 'supervisor' - ? [{ label: 'Counselors', key: 'coach' }] + ? [{ label: 'Counselor', key: 'coach' }] : [ { label: 'Admins', key: 'admin' }, { label: 'Supervisors', key: 'supervisor' }, - { label: 'Counselors', key: 'coach' }, + { label: 'Counselor', key: 'coach' }, ]; } @@ -541,7 +541,7 @@ function downloadUsersCSV() { const headers = ['username', 'role', 'location', 'supervisor', 'mustChangePassword', 'createdAt', 'userID']; const rows = usersList.map(u => [ u.username, - u.role === 'coach' ? 'counselor' : u.role, + u.role === 'coach' ? 'Counselor' : u.role, u.role === 'coach' ? '' : (u.location || ''), u.role === 'coach' ? (u.supervisorUsername || u.supervisorID || '') : '', u.mustChangePassword == 1 ? 'yes' : 'no', diff --git a/website/js/password-modal.js b/website/js/password-modal.js index 8d3bf9f..33d05af 100644 --- a/website/js/password-modal.js +++ b/website/js/password-modal.js @@ -1,5 +1,5 @@ import { apiPatch, apiPost, invalidateSessionCheck } from './api.js'; -import { getRole, getUser, showToast } from './app.js'; +import { getRole, getUser, showToast, formatRoleLabel } from './app.js'; /** @typedef {'admin_reset' | 'self'} PasswordModalMode */ @@ -13,9 +13,7 @@ function esc(s) { } function roleLabel(role) { - if (!role) return ''; - if (role === 'coach') return 'Counselor'; - return role.charAt(0).toUpperCase() + role.slice(1); + return formatRoleLabel(role); } function signInHintForRole(role) { diff --git a/website/js/questionnaire-preview.js b/website/js/questionnaire-preview.js index 3fcddc3..5ea2e06 100644 --- a/website/js/questionnaire-preview.js +++ b/website/js/questionnaire-preview.js @@ -399,7 +399,7 @@ function renderQuestionBody(q, sectionIdx) { case 'client_coach_code_question': inner += ` -

In the app, client and counselor codes are loaded automatically — counselors review them here, not type them in.

+

In the app, client and Counselor codes are loaded automatically — Counselor review them here, not type them in.