/** * App UI editor: screen → keys mapping and tablet mocks matching current Android layouts. * Screens with multiple states expose `variants` (chip picker in the editor). */ /** @typedef {{ id: string, label: string, focusKeys?: string[], mock: () => string }} AppUiVariant */ /** @typedef {{ id: string, label: string, hint?: string, keys: string[], mock?: () => string, variants?: AppUiVariant[] }} AppUiScreen */ function f(key, cls = '', tag = 'input') { const safe = String(key).replace(/"/g, ''); if (tag === 'textarea') { return ``; } return ``; } function iconHelp() { return ``; } function iconRefresh() { return ``; } function iconPerson() { return ``; } function iconLock() { return ``; } function iconBack() { return ``; } function iconChevron() { return ``; } function langChip() { return `Deutsch ${iconChevron()}`; } function toastBanner(key, cls = '') { return `
${f(key, 'aq-toast-field')}
`; } /** Client note row as on opening_screen (ClientNoteUi.bindRow). */ function clientNoteRow({ hasNote = false, pending = false } = {}) { const preview = hasNote ? `Beispielnotiz…` : f('client_note_add', 'aq-muted aq-sm'); const actionLabel = hasNote ? 'client_note_edit' : 'client_note_add_action'; const badge = pending ? `${f('client_note_pending', 'aq-xs')}` : ''; return `
${f('client_note_for_client', 'aq-note-label')} ${badge}
${preview}
${f(actionLabel, 'aq-field-on-primary aq-xs')}
`; } /** Settings bottom sheet (HandlerOpeningScreen.showSettingsSheet — handle + logout only, no title). */ function settingsSheet() { return `
${f('logout', 'aq-field-on-primary')}
`; } /** Client note editor bottom sheet (ClientNoteUi.showEditor — bottom_sheet_client_note.xml). */ function clientNoteEditorSheet({ errorKey = null } = {}) { const err = errorKey ? `
${f(errorKey, 'aq-sm')}
` : ''; return `
${f('client_note_title', 'aq-sheet-title')} ${f('client_note_for_client', 'aq-muted aq-sm')}
${f('client_note_hint', 'aq-outlined-input aq-note-input', 'textarea')}
${err}
${f('save', 'aq-field-on-primary')}
${f('cancel', 'aq-sm')}
`; } function homeHeaderChrome({ status = 'online', note = 'empty' } = {}) { const statusChip = status === 'offline' ? `
${f('offline', 'aq-status-text')}
` : `
${f('online', 'aq-status-text')}
`; const noteRow = note === 'none' ? '' : clientNoteRow({ hasNote: note === 'filled' || note === 'pending', pending: note === 'pending', }); return `
${f('hub_welcome_back', 'aq-muted aq-sm')}
demoCounselor
${statusChip} ${iconHelp()} ${iconRefresh()}
${f('language', 'aq-label-xs')}
Deutsch ${iconChevron()}
${f('active_client', 'aq-label-xs')}
${iconPerson()} demoClient ${iconChevron()}
${noteRow}
`; } function homeDock() { const iconReview = ``; const iconUpload = ``; return `
${iconReview}${f('review_scores', 'aq-field-on-primary aq-xs')}
${iconUpload}${f('upload', 'aq-field-on-primary aq-xs')}
`; } function homeNextStep(titleKey, bodyKey, actionKey) { return `
${f('next_step_label', 'aq-eyebrow-field')}
${f(titleKey, 'aq-bold')} ${f(bodyKey, 'aq-muted aq-sm')}
${actionKey ? `
${f(actionKey, 'aq-field-on-primary aq-xs')}
` : ''}
`; } /** In-group Ampelkategorie / Punkteprüfung badge (view_category_review_badge.xml). */ function categoryReviewBadge({ band = 'yellow' } = {}) { const lamp = band === 'green' ? '' : band === 'red' ? '' : ''; return `
${lamp}
${f('next_step_review_title', 'aq-category-review-title')} ${f('next_step_review_body', 'aq-category-review-body', 'textarea')}
`; } /** Process-complete / Ampelkategorie panel (view_process_complete_panel.xml). */ function processCompleteBadge({ mode = 'complete', showUpload = false, } = {}) { const review = mode === 'review'; const titleKey = review ? 'next_step_review_title' : 'process_complete_title'; const bodyKey = review ? 'next_step_review_body' : 'process_complete_hub_body'; const actionKey = review ? 'process_complete_set_category' : ( mode === 'edit' ? 'process_complete_edit_category' : 'process_complete_set_category' ); const tone = review ? 'review' : 'complete'; const icon = review ? `
` : ``; const upload = showUpload ? `
${f('upload', 'aq-xs')}
` : ''; return `
${icon}
${f(titleKey, `aq-bold aq-process-complete-title`)} ${f(bodyKey, 'aq-sm aq-process-complete-body', 'textarea')}
${f(actionKey, 'aq-field-on-primary aq-xs')}
${upload}
`; } /** Save-only questionnaire footer (questionnaire_all_in_one has only btnSave, no previous). */ function qnFooter({ progressPct = 0, showProgress = true } = {}) { const progress = showProgress ? `
${f('questionnaire_progress_answered', 'aq-muted aq-xs aq-progress-label-end')}
` : ''; return ` `; } function helpShell(topicTitleKey, introKey, sections) { const sectionHtml = sections.map((s, i) => `
${i + 1} ${f(s.titleKey, 'aq-bold aq-sm aq-help-section-title')}
${f(s.bodyKey, 'aq-muted aq-xs aq-mt', 'textarea')}
`).join('
'); return `
${f('help_title', 'aq-screen-title')}
${f('language', 'aq-muted aq-sm aq-picker-label')} ${langChip()}
${f('help_topic', 'aq-muted aq-sm aq-picker-label')}
${f(topicTitleKey, 'aq-sm')} ${iconChevron()}
${f('help_this_page', 'aq-xs')} ${f(topicTitleKey, 'aq-bold aq-mt')} ${f(introKey, 'aq-muted aq-sm', 'textarea')}
${sectionHtml}
`; } function syncPhaseMock(statusKey, subtitleKey, progressPct, finished = false) { const stage = finished ? `
` : `
`; // 7 checkpoint phases: preparing(10%), questionnaires(25%), client_info(40%), answers(55%), processing(70%), saving(85%), finished(100%) const phases = [10, 25, 40, 55, 70, 85, 100]; const dots = phases.map(p => `
`).join(''); return `
${f('sync_title', 'aq-muted aq-sync-title')} ${stage} ${f(statusKey, 'aq-sync-status')} ${f(subtitleKey, 'aq-muted aq-sm aq-sync-sub', 'textarea')}
`; } /** * Branded app dialog (dialog_app_message.xml). * @param {'info'|'warning'|'logout'|'danger'} tone */ function dialogMock({ titleKey, messageKey, primaryKey, secondaryKey = null, detailsKeys = null, tone = 'info', }) { const details = detailsKeys?.length ? `
${detailsKeys.map(k => f(k, 'aq-sm aq-dialog-detail-line')).join('')}
` : ''; const secondary = secondaryKey ? `
${f(secondaryKey, 'aq-muted')}
` : ''; const primaryCls = tone === 'logout' || tone === 'danger' ? 'aq-btn-pill aq-btn-danger' : 'aq-btn-pill aq-btn-primary'; return `
${f(titleKey, 'aq-dialog-title')} ${f(messageKey, 'aq-muted aq-sm aq-dialog-msg', 'textarea')} ${details}
${f(primaryKey, 'aq-field-on-primary')}
${secondary}
`; } function scoreCalculatedMock() { return `
${f('score_calculated_eyebrow', 'aq-score-eyebrow')} ${f('score_calculated_title', 'aq-score-title')}
${f('score_calculated_result_label', 'aq-muted aq-xs')}
RHS Index · 27.0
${f('category_yellow', 'aq-xs')}
${f('score_calculated_band_hint', 'aq-muted aq-xs aq-mt')}
${f('score_calculated_next_label', 'aq-muted aq-xs')} ${f('score_calculated_next_title', 'aq-bold aq-mt')} ${f('score_calculated_body', 'aq-muted aq-sm', 'textarea')}
${f('score_calculated_continue', 'aq-field-on-primary')}
`; } /** @type {AppUiScreen[]} */ export const APP_UI_SCREENS = [ { id: 'auth', label: 'Anmeldung', hint: 'activity_auth.xml', keys: [ 'auth_title', 'auth_subtitle_login', 'auth_subtitle_change_password', 'auth_footer_accounts', 'username_hint', 'password_hint', 'login_btn', 'exit_btn', 'new_password_hint', 'confirm_password_hint', 'save_password_btn', 'password_too_short', 'passwords_dont_match', 'please_username_password', 'password_needs_prefix', 'password_rule_min_length', 'password_rule_uppercase', 'password_rule_number', 'password_rule_special', 'login_failed_with_reason', 'language', 'help_title', ], variants: [ { id: 'login', label: 'Login', focusKeys: [ 'auth_title', 'auth_subtitle_login', 'username_hint', 'password_hint', 'login_btn', 'exit_btn', 'auth_footer_accounts', 'language', 'help_title', ], mock: () => `
${iconHelp()}${langChip()}
${f('auth_title', 'aq-auth-title')} ${f('auth_subtitle_login', 'aq-muted aq-auth-sub')}
${iconPerson()} ${f('username_hint', 'aq-outlined-input')}
${iconLock()} ${f('password_hint', 'aq-outlined-input')}
${f('login_btn', 'aq-field-on-primary')}
${f('exit_btn', 'aq-muted')}
`, }, { id: 'login_error', label: 'Login Fehler', focusKeys: [ 'please_username_password', 'login_failed_with_reason', 'username_hint', 'password_hint', 'login_btn', 'exit_btn', ], mock: () => `
${iconHelp()}${langChip()}
${f('auth_title', 'aq-auth-title')} ${f('auth_subtitle_login', 'aq-muted aq-auth-sub')}
${iconPerson()} ${f('username_hint', 'aq-outlined-input')}
${iconLock()} ${f('password_hint', 'aq-outlined-input')}
${f('login_btn', 'aq-field-on-primary')}
${f('exit_btn', 'aq-muted')}
${toastBanner('please_username_password')}
`, }, { id: 'login_failed', label: 'Login fehlgeschlagen', focusKeys: ['login_failed_with_reason', 'username_hint', 'password_hint', 'login_btn'], mock: () => `
${iconHelp()}${langChip()}
${f('auth_title', 'aq-auth-title')} ${f('auth_subtitle_login', 'aq-muted aq-auth-sub')}
${iconPerson()} ${f('username_hint', 'aq-outlined-input')}
${iconLock()} ${f('password_hint', 'aq-outlined-input')}
${f('login_btn', 'aq-field-on-primary')}
${f('exit_btn', 'aq-muted')}
${toastBanner('login_failed_with_reason')}
`, }, { id: 'password', label: 'Passwort ändern', focusKeys: [ 'auth_title', 'auth_subtitle_change_password', 'new_password_hint', 'confirm_password_hint', 'save_password_btn', 'auth_footer_accounts', 'password_needs_prefix', 'password_rule_min_length', 'password_rule_uppercase', 'password_rule_number', 'password_rule_special', ], mock: () => `
${iconHelp()}${langChip()}
${f('auth_title', 'aq-auth-title')} ${f('auth_subtitle_change_password', 'aq-muted aq-auth-sub')}
${iconLock()} ${f('new_password_hint', 'aq-outlined-input')}
${f('password_needs_prefix', 'aq-xs')} ${f('password_rule_min_length', 'aq-xs')} ${f('password_rule_uppercase', 'aq-xs')} ${f('password_rule_number', 'aq-xs')} ${f('password_rule_special', 'aq-xs')}
${iconLock()} ${f('confirm_password_hint', 'aq-outlined-input')}
${f('save_password_btn', 'aq-field-on-primary')}
`, }, { id: 'password_error', label: 'Passwort Fehler', focusKeys: ['password_too_short', 'passwords_dont_match', 'new_password_hint', 'confirm_password_hint'], mock: () => `
${iconHelp()}${langChip()}
${f('auth_title', 'aq-auth-title')} ${f('auth_subtitle_change_password', 'aq-muted aq-auth-sub')}
${iconLock()} ${f('new_password_hint', 'aq-outlined-input')}
${f('password_needs_prefix', 'aq-xs')} ${f('password_rule_min_length', 'aq-xs')} ${f('password_rule_uppercase', 'aq-xs')} ${f('password_rule_number', 'aq-xs')} ${f('password_rule_special', 'aq-xs')}
${iconLock()} ${f('confirm_password_hint', 'aq-outlined-input')}
${f('save_password_btn', 'aq-field-on-primary')}
${toastBanner('password_too_short')}
`, }, ], }, { id: 'home', label: 'Startseite', hint: 'opening_screen.xml + hub dock', keys: [ 'hub_welcome_back', 'language', 'active_client', 'online', 'offline', 'settings', 'logout', 'next_step_label', 'next_step_questionnaire_title', 'next_step_questionnaire_body', 'next_step_review_title', 'next_step_review_body', 'next_step_upload_title', 'next_step_upload_body', 'next_step_completed_title', 'next_step_completed_body', 'next_step_loading_title', 'next_step_loading_body', 'next_step_show_questionnaire', 'questionnaire_title', 'start', 'locked', 'questionnaire_chip_edit', 'questionnaire_chip_edit_pending', 'process_complete_title', 'process_complete_set_category', 'process_complete_edit_category', 'upload', 'review_scores', 'refresh_complete', 'help_title', 'client_note_for_client', 'client_note_add', 'client_note_edit', 'client_note_add_action', 'client_note_pending', 'process_complete_hub_body', 'questionnaire_unlock_2_rhs', 'questionnaire_unlock_3_integration_index', 'questionnaire_unlock_4_consultation_results', 'consultation_unlock_requires_rhs', 'review_required_before_continue', 'download_failed_use_offline', 'no_profile', 'cancel', 'save', 'client_note_title', 'client_note_hint', 'client_note_too_long', 'client_note_saved', 'client_note_saved_pending', ], variants: [ { id: 'questionnaire', label: 'Nächster Fragebogen', focusKeys: [ 'hub_welcome_back', 'language', 'active_client', 'online', 'next_step_label', 'next_step_questionnaire_title', 'next_step_questionnaire_body', 'next_step_show_questionnaire', 'questionnaire_title', 'start', 'locked', 'questionnaire_unlock_2_rhs', 'questionnaire_unlock_3_integration_index', 'consultation_unlock_requires_rhs', 'review_scores', 'upload', 'client_note_for_client', 'client_note_add', 'client_note_add_action', ], mock: () => `
${homeHeaderChrome()} ${homeNextStep('next_step_questionnaire_title', 'next_step_questionnaire_body', 'next_step_show_questionnaire')}
${f('questionnaire_title', 'aq-section-title-field')}
Demografie ${f('start', 'aq-chip-field')}
RHS
${f('questionnaire_unlock_2_rhs', 'aq-qn-lock-hint')}
${f('locked', 'aq-chip-field')}
Integrationsindex
${f('questionnaire_unlock_3_integration_index', 'aq-qn-lock-hint')}
${f('locked', 'aq-chip-field')}
Beratung
${f('consultation_unlock_requires_rhs', 'aq-qn-lock-hint')}
${f('locked', 'aq-chip-field')}
${homeDock()}
`, }, { id: 'review', label: 'Ampelkategorie', focusKeys: [ 'next_step_label', 'next_step_review_title', 'next_step_review_body', 'process_complete_set_category', 'review_scores', 'upload', 'questionnaire_chip_edit', 'questionnaire_title', 'review_required_before_continue', ], mock: () => `
${homeHeaderChrome({ note: 'filled' })} ${homeNextStep('next_step_review_title', 'next_step_review_body', 'process_complete_set_category')}
${f('questionnaire_title', 'aq-section-title-field')}
Demografie ${f('questionnaire_chip_edit', 'aq-chip-field')}
RHS ${f('questionnaire_chip_edit', 'aq-chip-field')}
${categoryReviewBadge({ band: 'yellow' })}
${homeDock()} ${toastBanner('review_required_before_continue')}
`, }, { id: 'upload', label: 'Upload bereit', focusKeys: [ 'next_step_label', 'next_step_upload_title', 'next_step_upload_body', 'upload', 'review_scores', 'questionnaire_chip_edit_pending', 'client_note_pending', 'client_note_edit', ], mock: () => `
${homeHeaderChrome({ note: 'pending' })} ${homeNextStep('next_step_upload_title', 'next_step_upload_body', 'upload')}
${f('questionnaire_title', 'aq-section-title-field')}
Demografie ${f('questionnaire_chip_edit_pending', 'aq-chip-field')}
${homeDock()}
`, }, { id: 'complete', label: 'Abgeschlossen', focusKeys: [ 'process_complete_title', 'process_complete_hub_body', 'process_complete_set_category', 'upload', ], mock: () => `
${homeHeaderChrome()} ${processCompleteBadge({ mode: 'complete', showUpload: true })}
${homeDock()}
`, }, { id: 'complete_edit', label: 'Abgeschlossen · Kategorie', focusKeys: [ 'process_complete_title', 'process_complete_hub_body', 'process_complete_edit_category', ], mock: () => `
${homeHeaderChrome()} ${processCompleteBadge({ mode: 'edit' })}
${homeDock()}
`, }, { id: 'set_category', label: 'Ampelkategorie setzen', focusKeys: [ 'next_step_review_title', 'next_step_review_body', 'process_complete_set_category', ], mock: () => `
${homeHeaderChrome()} ${processCompleteBadge({ mode: 'review' })}
${homeDock()}
`, }, { id: 'completed_banner', label: 'Nächster Schritt · Fertig', focusKeys: [ 'next_step_label', 'next_step_completed_title', 'next_step_completed_body', 'review_scores', 'upload', 'questionnaire_chip_edit', ], mock: () => `
${homeHeaderChrome()} ${homeNextStep('next_step_completed_title', 'next_step_completed_body', null)}
${f('questionnaire_title', 'aq-section-title-field')}
Demografie ${f('questionnaire_chip_edit', 'aq-chip-field')}
${homeDock()}
`, }, { id: 'loading', label: 'Laden', focusKeys: [ 'next_step_loading_title', 'next_step_loading_body', 'next_step_label', ], mock: () => `
${homeHeaderChrome()}
${f('next_step_label', 'aq-eyebrow-field')}
${f('next_step_loading_title', 'aq-bold')} ${f('next_step_loading_body', 'aq-muted aq-sm')}
${homeDock()}
`, }, { id: 'offline', label: 'Offline', focusKeys: [ 'offline', 'hub_welcome_back', 'active_client', 'download_failed_use_offline', ], mock: () => `
${homeHeaderChrome({ status: 'offline' })} ${homeNextStep('next_step_questionnaire_title', 'next_step_questionnaire_body', 'next_step_show_questionnaire')}
${homeDock()} ${toastBanner('download_failed_use_offline')}
`, }, { id: 'settings', label: 'Einstellungen', focusKeys: ['settings', 'logout'], mock: () => `
${homeHeaderChrome()} ${homeNextStep('next_step_questionnaire_title', 'next_step_questionnaire_body', 'next_step_show_questionnaire')}
${homeDock()} ${settingsSheet()}
`, }, { id: 'refresh_done', label: 'Aktualisiert', focusKeys: ['refresh_complete'], mock: () => `
${homeHeaderChrome()} ${homeNextStep('next_step_questionnaire_title', 'next_step_questionnaire_body', 'next_step_show_questionnaire')}
${homeDock()} ${toastBanner('refresh_complete')}
`, }, { id: 'note_editor', label: 'Notiz bearbeiten', focusKeys: [ 'client_note_title', 'client_note_for_client', 'client_note_hint', 'client_note_too_long', 'cancel', 'save', ], mock: () => `
${homeHeaderChrome({ note: 'filled' })} ${homeNextStep('next_step_questionnaire_title', 'next_step_questionnaire_body', 'next_step_show_questionnaire')}
${homeDock()} ${clientNoteEditorSheet({ errorKey: 'client_note_too_long' })}
`, }, { id: 'note_saved', label: 'Notiz gespeichert', focusKeys: [ 'client_note_saved', 'client_note_saved_pending', 'client_note_for_client', 'client_note_edit', 'client_note_pending', ], mock: () => `
${homeHeaderChrome({ note: 'pending' })} ${homeNextStep('next_step_questionnaire_title', 'next_step_questionnaire_body', 'next_step_show_questionnaire')}
${homeDock()} ${toastBanner('client_note_saved_pending')}
`, }, ], }, { id: 'client', label: 'Klient wählen', hint: 'view_client_select_gate.xml', keys: [ 'client_select_gate_title', 'client_select_gate_body', 'client_select_gate_hint', 'client_select_gate_count', 'client_picker_title', 'client_picker_subtitle', 'client_picker_search', 'client_picker_current', 'client_picker_recent', 'client_picker_all', 'client_picker_empty', 'client_picker_status_finished', 'client_picker_status_started', 'client_picker_status_new', 'client_picker_status_finished_pending_upload', 'client_picker_status_pending_upload', 'client_picker_status_next_step_category', 'client_picker_status_next', 'client_picker_category_assigned', 'client_picker_category_calculated', 'client_picker_score', 'client_picker_loading_title', 'client_picker_loading_body', 'active_client', 'language', 'no_clients_assigned', 'client', 'client_note', ], variants: [ { id: 'gate', label: 'Gate', focusKeys: [ 'client_select_gate_title', 'client_select_gate_body', 'client_select_gate_hint', 'client_select_gate_count', 'client_picker_search', 'language', 'client_picker_status_finished', 'client_picker_status_started', 'client_picker_status_new', ], mock: () => `
${iconPerson()}
${f('client_select_gate_title', 'aq-screen-title')}
${f('client_select_gate_body', 'aq-body')} ${f('client_select_gate_hint', 'aq-muted aq-sm')} ${f('client_select_gate_count', 'aq-count')} ${f('language', 'aq-label-xs')}
Deutsch ${iconChevron()}
${iconPerson()}
demoClient ${f('client_picker_status_finished', 'aq-xs')}
${iconPerson()}
demoClient2
${f('client_picker_status_new', 'aq-xs')}
`, }, { id: 'list', label: 'Liste', focusKeys: [ 'client_picker_title', 'client_picker_subtitle', 'client_picker_recent', 'client_picker_all', 'client_picker_current', 'client_picker_score', 'client_picker_category_assigned', 'client_picker_category_calculated', 'client_picker_status_finished_pending_upload', 'client_picker_status_pending_upload', 'client_picker_status_next_step_category', 'client_picker_status_next', 'client', 'client_picker_search', ], mock: () => `
${f('client_picker_title', 'aq-screen-title')} ${f('client_picker_subtitle', 'aq-muted aq-sm')}
${f('client_picker_current', 'aq-label-xs')}
${iconPerson()}
${f('client', 'aq-xs')} demoA
${f('client_picker_status_next', 'aq-xs')}
${f('client_picker_score', 'aq-xs')}: 27.0
${f('client_picker_category_calculated', 'aq-xs')}
${f('client_picker_recent', 'aq-label-xs')}
${f('client_picker_all', 'aq-label-xs')}
${iconPerson()}
demoB ${f('client_picker_status_pending_upload', 'aq-xs')}
${f('client_picker_status_finished_pending_upload', 'aq-xs')}
${f('client_picker_status_next_step_category', 'aq-xs')}
${f('client_picker_category_assigned', 'aq-xs')}
`, }, { id: 'loading', label: 'Laden', focusKeys: ['client_picker_loading_title', 'client_picker_loading_body'], mock: () => `
${f('client_picker_loading_title', 'aq-screen-title')} ${f('client_picker_loading_body', 'aq-muted aq-sm', 'textarea')}
`, }, { id: 'empty', label: 'Leer', focusKeys: ['client_picker_empty', 'no_clients_assigned'], mock: () => `
${f('client_picker_title', 'aq-screen-title')} ${f('client_picker_empty', 'aq-muted aq-sm', 'textarea')} ${f('no_clients_assigned', 'aq-muted aq-sm aq-mt', 'textarea')}
`, }, ], }, { id: 'questionnaire', label: 'Fragebogen', hint: 'questionnaire_all_in_one.xml · pick a question type', keys: [ 'coach_code', 'client_code', 'client_note_for_client', 'client_note_add', 'client_note_edit', 'client_note_add_action', 'client_note_pending', 'client_note_title', 'client_note_hint', 'client_note_too_long', 'cancel', 'save', 'previous', 'choose_answer', 'fill_all_fields', 'select_one_answer', 'select_one_answer_per_row', 'choose_more_elements', 'questionnaire_progress_answered', 'no_questions_available', 'questionnaire_missing_options', 'help_title', 'language', 'please_client_code', 'fill_both_fields', 'client_code_exists', 'no_profile', 'other_option', 'other_country', 'january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december', ], variants: [ { id: 'codes', label: 'Codes', focusKeys: [ 'client_code', 'coach_code', 'please_client_code', 'fill_both_fields', 'client_code_exists', 'no_profile', 'previous', 'save', 'questionnaire_progress_answered', 'client_note_for_client', 'client_note_add', 'client_note_add_action', ], mock: () => `
${iconBack()}
${iconHelp()}${langChip()}
${clientNoteRow()}
${f('client_code', 'aq-sm')}
demoClient
${f('coach_code', 'aq-sm')}
demoCounselor ${iconLock()}
${qnFooter({ progressPct: 5 })} ${toastBanner('fill_both_fields')}
`, }, { id: 'choice', label: 'Auswahl', focusKeys: [ 'choose_answer', 'other_option', 'other_country', 'select_one_answer', 'choose_more_elements', 'previous', 'save', 'questionnaire_progress_answered', ], mock: () => `
${iconBack()}
${iconHelp()}${langChip()}
Beispiel-Fragetext
Option A
${f('other_option', 'aq-sm')}
${f('other_country', 'aq-sm')}
${f('choose_answer', 'aq-sm')}
${qnFooter({ progressPct: 35 })} ${toastBanner('select_one_answer')}
`, }, { id: 'multi', label: 'Mehrfachauswahl', focusKeys: [ 'choose_more_elements', 'other_option', 'previous', 'save', 'questionnaire_progress_answered', ], mock: () => `
${iconBack()}
${iconHelp()}${langChip()}
Beispiel-Mehrfachauswahl
Option A
${f('other_option', 'aq-sm')}
${qnFooter({ progressPct: 40 })} ${toastBanner('choose_more_elements')}
`, }, { id: 'date', label: 'Datum', focusKeys: [ 'choose_answer', 'january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december', 'fill_all_fields', 'previous', 'save', ], mock: () => `
${iconBack()}
${iconHelp()}${langChip()}
Beispiel-Datumsfrage
15
${f('march', 'aq-sm')}
${f('january', 'aq-xs')} ${f('february', 'aq-xs')} ${f('march', 'aq-xs')} ${f('april', 'aq-xs')} ${f('may', 'aq-xs')} ${f('june', 'aq-xs')} ${f('july', 'aq-xs')} ${f('august', 'aq-xs')} ${f('september', 'aq-xs')} ${f('october', 'aq-xs')} ${f('november', 'aq-xs')} ${f('december', 'aq-xs')}
${f('choose_answer', 'aq-xs')}
${qnFooter({ progressPct: 0, showProgress: false })} ${toastBanner('fill_all_fields')}
`, }, { id: 'empty', label: 'Leer / Fehler', focusKeys: [ 'no_questions_available', 'questionnaire_missing_options', 'previous', ], mock: () => `
${iconBack()}
${iconHelp()}${langChip()}
${f('no_questions_available', 'aq-muted aq-sm', 'textarea')}
${qnFooter({ progressPct: 0, showProgress: false })} ${toastBanner('questionnaire_missing_options')}
`, }, { id: 'note', label: 'Notiz', focusKeys: [ 'client_note_title', 'client_note_for_client', 'client_note_hint', 'client_note_too_long', 'cancel', 'save', 'client_note_edit', ], mock: () => `
${iconBack()}
${iconHelp()}${langChip()}
${clientNoteRow({ hasNote: true })}
Beispiel-Fragetext
${clientNoteEditorSheet({ errorKey: 'client_note_too_long' })}
`, }, ], }, { id: 'review', label: 'Ampelkategorie', hint: 'review_scores_screen.xml', keys: [ 'review_scores', 'review_scores_subtitle', 'review_scores_agree', 'review_scores_calculated_category', 'review_scores_coach_category', 'review_scores_empty', 'review_scores_pending_upload', 'review_scores_complete_title', 'review_scores_complete_body', 'review_scores_complete_body_uploaded', 'review_scores_done', 'review_scores_save_failed', 'review_scores_saved', 'review_scores_saved_pending', 'review_scores_set_category', 'review_scores_supervisor_notice', 'review_scores_supervisor_confirm_title', 'review_scores_supervisor_confirm_body', 'review_scores_supervisor_confirm_action', 'review_scores_total', 'category_green', 'category_yellow', 'category_red', 'score_calculated_title', 'score_calculated_body', 'score_calculated_eyebrow', 'score_calculated_result_label', 'score_calculated_next_label', 'score_calculated_next_title', 'score_calculated_band_hint', 'score_calculated_continue', 'points', 'help_title', 'not_done', 'previous', ], variants: [ { id: 'active', label: 'Aktiv', focusKeys: [ 'review_scores', 'review_scores_subtitle', 'review_scores_agree', 'review_scores_calculated_category', 'review_scores_coach_category', 'review_scores_total', 'review_scores_set_category', 'category_green', 'category_yellow', 'category_red', 'not_done', 'points', 'previous', 'review_scores_supervisor_notice', ], mock: () => `
${f('review_scores', 'aq-screen-title')} ${f('review_scores_subtitle', 'aq-muted aq-sm')}
${langChip()}${iconHelp()}
${f('review_scores_supervisor_notice', 'aq-sm')}
RHS Index
${f('review_scores_total', 'aq-xs')}: 27.0 ${f('points', 'aq-xs')}
${f('review_scores_calculated_category', 'aq-xs')} ${f('category_yellow', 'aq-xs')}
${f('review_scores_coach_category', 'aq-xs')} ${f('not_done', 'aq-xs')}
${f('review_scores_agree', 'aq-field-on-primary aq-xs')}
${f('review_scores_set_category', 'aq-label-xs')}
${f('category_green', 'aq-xs')} ${f('category_yellow', 'aq-xs')} ${f('category_red', 'aq-xs')}
${f('previous', 'aq-sm')}
`, }, { id: 'empty', label: 'Leer', focusKeys: ['review_scores_empty', 'review_scores'], mock: () => `
${f('review_scores', 'aq-screen-title')} ${f('review_scores_empty', 'aq-muted aq-sm', 'textarea')}
${langChip()}${iconHelp()}
`, }, { id: 'complete', label: 'Abgeschlossen', focusKeys: [ 'review_scores_complete_title', 'review_scores_complete_body', 'review_scores_complete_body_uploaded', 'review_scores_done', 'review_scores_pending_upload', 'review_scores_saved_pending', 'previous', ], mock: () => `
${f('review_scores', 'aq-screen-title')} ${f('review_scores_subtitle', 'aq-muted aq-sm')}
${langChip()}${iconHelp()}
${f('review_scores_complete_title', 'aq-bold')} ${f('review_scores_complete_body', 'aq-muted aq-sm', 'textarea')}
${f('review_scores_pending_upload', 'aq-sm')}
${f('review_scores_done', 'aq-field-on-primary aq-xs')}
${f('previous', 'aq-sm')}
${toastBanner('review_scores_saved_pending')}
`, }, ], }, { id: 'upload', label: 'Hochladen', hint: 'upload_overview_screen.xml', keys: [ 'upload', 'start_upload', 'upload_pending_subtitle', 'upload_summary', 'upload_nothing_pending', 'upload_prepare_failed', 'upload_failed_title', 'upload_success_title', 'upload_success_message', 'upload_success_questionnaires', 'upload_success_scoring_reviews', 'upload_success_client_notes', 'upload_success_sync_next', 'upload_item_scoring_review', 'upload_scoring_review_summary', 'cancel', 'previous', 'help_title', 'questions_filled', 'done', 'client_code', 'upload_connect_network_first', 'no_questionnaires', 'login_required', 'client_note', ], variants: [ { id: 'pending', label: 'Ausstehend', focusKeys: [ 'upload_pending_subtitle', 'start_upload', 'upload_summary', 'upload', 'cancel', 'previous', 'client_code', 'done', 'questions_filled', 'upload_item_scoring_review', 'upload_scoring_review_summary', 'upload_connect_network_first', 'client_note', ], mock: () => `
${f('upload_pending_subtitle', 'aq-muted aq-sm')} ${f('start_upload', 'aq-screen-title')}
${langChip()}${iconHelp()}
${f('upload_summary', 'aq-sm')}
${f('client_code', 'aq-xs')}: demoClient
Demografie
✓ ${f('done', 'aq-xs')} · 12 ${f('questions_filled', 'aq-xs')}
${f('upload_item_scoring_review', 'aq-sm')}
${f('upload_scoring_review_summary', 'aq-xs')}
${f('client_note', 'aq-sm')}
`, }, { id: 'empty', label: 'Leer', focusKeys: [ 'upload_nothing_pending', 'no_questionnaires', 'start_upload', 'login_required', 'upload_connect_network_first', ], mock: () => `
${f('start_upload', 'aq-screen-title')} ${f('upload_nothing_pending', 'aq-muted aq-sm aq-mt', 'textarea')} ${f('no_questionnaires', 'aq-muted aq-sm aq-mt', 'textarea')}
${toastBanner('login_required')}
`, }, ], }, { id: 'help', label: 'Hilfe', hint: 'activity_help.xml · pick a topic below', keys: [ 'help_title', 'help_topic', 'help_this_page', 'language', 'help_auth_title', 'help_auth_intro', 'help_auth_signin_title', 'help_auth_signin_body', 'help_auth_password_title', 'help_auth_password_body', 'help_opening_title', 'help_opening_intro', 'help_opening_pick_client_title', 'help_opening_pick_client_body', 'help_opening_home_title', 'help_opening_home_body', 'help_opening_client_lang_title', 'help_opening_client_lang_body', 'help_opening_questionnaires_title', 'help_opening_questionnaires_body', 'help_opening_complete_title', 'help_opening_complete_body', 'help_questionnaire_title', 'help_questionnaire_intro', 'help_questionnaire_header_title', 'help_questionnaire_header_body', 'help_questionnaire_answer_title', 'help_questionnaire_answer_body', 'help_questionnaire_save_title', 'help_questionnaire_save_body', 'help_category_title', 'help_category_intro', 'help_category_set_title', 'help_category_set_body', 'help_category_change_title', 'help_category_change_body', 'help_upload_title', 'help_upload_intro', 'help_upload_check_title', 'help_upload_check_body', 'help_upload_fix_title', 'help_upload_fix_body', 'help_upload_send_title', 'help_upload_send_body', ], variants: [ { id: 'auth', label: 'Anmeldung', focusKeys: [ 'help_title', 'help_topic', 'help_this_page', 'language', 'help_auth_title', 'help_auth_intro', 'help_auth_signin_title', 'help_auth_signin_body', 'help_auth_password_title', 'help_auth_password_body', ], mock: () => helpShell('help_auth_title', 'help_auth_intro', [ { titleKey: 'help_auth_signin_title', bodyKey: 'help_auth_signin_body' }, { titleKey: 'help_auth_password_title', bodyKey: 'help_auth_password_body' }, ]), }, { id: 'opening', label: 'Startseite', focusKeys: [ 'help_title', 'help_topic', 'help_this_page', 'language', 'help_opening_title', 'help_opening_intro', 'help_opening_pick_client_title', 'help_opening_pick_client_body', 'help_opening_home_title', 'help_opening_home_body', 'help_opening_client_lang_title', 'help_opening_client_lang_body', 'help_opening_questionnaires_title', 'help_opening_questionnaires_body', 'help_opening_complete_title', 'help_opening_complete_body', ], mock: () => helpShell('help_opening_title', 'help_opening_intro', [ { titleKey: 'help_opening_pick_client_title', bodyKey: 'help_opening_pick_client_body' }, { titleKey: 'help_opening_home_title', bodyKey: 'help_opening_home_body' }, { titleKey: 'help_opening_client_lang_title', bodyKey: 'help_opening_client_lang_body' }, { titleKey: 'help_opening_questionnaires_title', bodyKey: 'help_opening_questionnaires_body' }, { titleKey: 'help_opening_complete_title', bodyKey: 'help_opening_complete_body' }, ]), }, { id: 'questionnaire', label: 'Fragebogen', focusKeys: [ 'help_title', 'help_topic', 'help_this_page', 'language', 'help_questionnaire_title', 'help_questionnaire_intro', 'help_questionnaire_header_title', 'help_questionnaire_header_body', 'help_questionnaire_answer_title', 'help_questionnaire_answer_body', 'help_questionnaire_save_title', 'help_questionnaire_save_body', ], mock: () => helpShell('help_questionnaire_title', 'help_questionnaire_intro', [ { titleKey: 'help_questionnaire_header_title', bodyKey: 'help_questionnaire_header_body' }, { titleKey: 'help_questionnaire_answer_title', bodyKey: 'help_questionnaire_answer_body' }, { titleKey: 'help_questionnaire_save_title', bodyKey: 'help_questionnaire_save_body' }, ]), }, { id: 'category', label: 'Ampelkategorie', focusKeys: [ 'help_title', 'help_topic', 'help_this_page', 'language', 'help_category_title', 'help_category_intro', 'help_category_set_title', 'help_category_set_body', 'help_category_change_title', 'help_category_change_body', ], mock: () => helpShell('help_category_title', 'help_category_intro', [ { titleKey: 'help_category_set_title', bodyKey: 'help_category_set_body' }, { titleKey: 'help_category_change_title', bodyKey: 'help_category_change_body' }, ]), }, { id: 'upload', label: 'Hochladen', focusKeys: [ 'help_title', 'help_topic', 'help_this_page', 'language', 'help_upload_title', 'help_upload_intro', 'help_upload_check_title', 'help_upload_check_body', 'help_upload_fix_title', 'help_upload_fix_body', 'help_upload_send_title', 'help_upload_send_body', ], mock: () => helpShell('help_upload_title', 'help_upload_intro', [ { titleKey: 'help_upload_check_title', bodyKey: 'help_upload_check_body' }, { titleKey: 'help_upload_fix_title', bodyKey: 'help_upload_fix_body' }, { titleKey: 'help_upload_send_title', bodyKey: 'help_upload_send_body' }, ]), }, ], }, { id: 'sync', label: 'Synchronisation', hint: 'view_sync_progress_overlay.xml · pick a phase below', keys: [ 'sync_title', 'sync_status_preparing', 'sync_status_downloading_questionnaires', 'sync_status_downloading_client_info', 'sync_status_downloading_answers', 'sync_status_processing', 'sync_status_securely_saving', 'sync_status_finished', 'sync_subtitle_preparing', 'sync_subtitle_downloading_questionnaires', 'sync_subtitle_downloading_client_info', 'sync_subtitle_downloading_answers', 'sync_subtitle_processing', 'sync_subtitle_securely_saving', 'sync_subtitle_finished', ], variants: [ { id: 'preparing', label: 'Vorbereitung', focusKeys: ['sync_title', 'sync_status_preparing', 'sync_subtitle_preparing'], mock: () => syncPhaseMock('sync_status_preparing', 'sync_subtitle_preparing', 10), }, { id: 'questionnaires', label: 'Fragebögen', focusKeys: [ 'sync_title', 'sync_status_downloading_questionnaires', 'sync_subtitle_downloading_questionnaires', ], mock: () => syncPhaseMock( 'sync_status_downloading_questionnaires', 'sync_subtitle_downloading_questionnaires', 25, ), }, { id: 'client_info', label: 'Klienten', focusKeys: [ 'sync_title', 'sync_status_downloading_client_info', 'sync_subtitle_downloading_client_info', ], mock: () => syncPhaseMock( 'sync_status_downloading_client_info', 'sync_subtitle_downloading_client_info', 40, ), }, { id: 'answers', label: 'Antworten', focusKeys: [ 'sync_title', 'sync_status_downloading_answers', 'sync_subtitle_downloading_answers', ], mock: () => syncPhaseMock( 'sync_status_downloading_answers', 'sync_subtitle_downloading_answers', 55, ), }, { id: 'processing', label: 'Verarbeitung', focusKeys: ['sync_title', 'sync_status_processing', 'sync_subtitle_processing'], mock: () => syncPhaseMock('sync_status_processing', 'sync_subtitle_processing', 70), }, { id: 'saving', label: 'Speichern', focusKeys: [ 'sync_title', 'sync_status_securely_saving', 'sync_subtitle_securely_saving', ], mock: () => syncPhaseMock( 'sync_status_securely_saving', 'sync_subtitle_securely_saving', 85, ), }, { id: 'finished', label: 'Fertig', focusKeys: ['sync_title', 'sync_status_finished', 'sync_subtitle_finished'], mock: () => syncPhaseMock('sync_status_finished', 'sync_subtitle_finished', 100, true), }, ], }, { id: 'dialogs', label: 'Dialoge', hint: 'dialog_app_message.xml + notices · pick a dialog below', keys: [ 'logout', 'logout_confirm_title', 'logout_confirm_message', 'logout_confirm_action', 'logout_offline_title', 'logout_offline_message', 'logout_pending_title', 'logout_pending_message', 'logout_pending_detail_questionnaires', 'logout_pending_detail_scoring', 'logout_pending_detail_notes', 'logout_pending_detail_in_progress', 'upload_pending_title', 'upload_pending_review_message', 'upload', 'later', 'review_scores_supervisor_confirm_title', 'review_scores_supervisor_confirm_body', 'review_scores_supervisor_confirm_action', 'cancel', 'ok', 'upload_success_title', 'upload_success_message', 'upload_success_questionnaires', 'upload_success_scoring_reviews', 'upload_success_client_notes', 'upload_success_sync_next', 'upload_failed_title', 'upload_nothing_pending', 'upload_prepare_failed', 'error', 'error_invalid_data', 'error_not_found', 'score_calculated_eyebrow', 'score_calculated_title', 'score_calculated_body', 'score_calculated_result_label', 'score_calculated_next_label', 'score_calculated_next_title', 'score_calculated_band_hint', 'score_calculated_continue', 'category_yellow', 'questionnaire_exit_title', 'questionnaire_exit_message', 'leave', ], variants: [ { id: 'logout_confirm', label: 'Abmelden bestätigen', focusKeys: [ 'logout_confirm_title', 'logout_confirm_message', 'logout_confirm_action', 'cancel', 'logout', ], mock: () => dialogMock({ titleKey: 'logout_confirm_title', messageKey: 'logout_confirm_message', primaryKey: 'logout_confirm_action', secondaryKey: 'cancel', tone: 'logout', }), }, { id: 'logout_offline', label: 'Abmelden offline', focusKeys: ['logout_offline_title', 'logout_offline_message', 'ok'], mock: () => dialogMock({ titleKey: 'logout_offline_title', messageKey: 'logout_offline_message', primaryKey: 'ok', tone: 'warning', }), }, { id: 'logout_pending', label: 'Abmelden blockiert', focusKeys: [ 'logout_pending_title', 'logout_pending_message', 'logout_pending_detail_questionnaires', 'logout_pending_detail_scoring', 'logout_pending_detail_notes', 'logout_pending_detail_in_progress', 'ok', ], mock: () => dialogMock({ titleKey: 'logout_pending_title', messageKey: 'logout_pending_message', primaryKey: 'ok', detailsKeys: [ 'logout_pending_detail_questionnaires', 'logout_pending_detail_scoring', 'logout_pending_detail_notes', 'logout_pending_detail_in_progress', ], tone: 'warning', }), }, { id: 'upload_pending', label: 'Upload bereit', focusKeys: [ 'upload_pending_title', 'upload_pending_review_message', 'upload', 'later', ], mock: () => dialogMock({ titleKey: 'upload_pending_title', messageKey: 'upload_pending_review_message', primaryKey: 'upload', secondaryKey: 'later', tone: 'info', }), }, { id: 'supervisor', label: 'Supervision', focusKeys: [ 'review_scores_supervisor_confirm_title', 'review_scores_supervisor_confirm_body', 'review_scores_supervisor_confirm_action', 'cancel', ], mock: () => dialogMock({ titleKey: 'review_scores_supervisor_confirm_title', messageKey: 'review_scores_supervisor_confirm_body', primaryKey: 'review_scores_supervisor_confirm_action', secondaryKey: 'cancel', tone: 'warning', }), }, { id: 'upload_success', label: 'Upload OK', focusKeys: [ 'upload_success_title', 'upload_success_message', 'upload_success_questionnaires', 'upload_success_scoring_reviews', 'upload_success_client_notes', 'upload_success_sync_next', 'ok', ], mock: () => dialogMock({ titleKey: 'upload_success_title', messageKey: 'upload_success_message', primaryKey: 'ok', detailsKeys: [ 'upload_success_questionnaires', 'upload_success_scoring_reviews', 'upload_success_client_notes', 'upload_success_sync_next', ], tone: 'info', }), }, { id: 'upload_failed', label: 'Upload Fehler', focusKeys: [ 'upload_failed_title', 'upload_prepare_failed', 'ok', 'cancel', ], mock: () => dialogMock({ titleKey: 'upload_failed_title', messageKey: 'upload_prepare_failed', primaryKey: 'ok', secondaryKey: 'cancel', tone: 'danger', }), }, { id: 'exit_questionnaire', label: 'Fragebogen verlassen', focusKeys: [ 'questionnaire_exit_title', 'questionnaire_exit_message', 'leave', 'cancel', ], mock: () => `
${f('questionnaire_exit_title', 'aq-dialog-title')} ${f('questionnaire_exit_message', 'aq-muted aq-sm aq-dialog-msg', 'textarea')}
${f('leave', 'aq-field-on-primary')}
${f('cancel', 'aq-muted')}
`, }, { id: 'error_invalid', label: 'Fehler (Daten)', focusKeys: ['error', 'error_invalid_data', 'ok'], mock: () => dialogMock({ titleKey: 'error', messageKey: 'error_invalid_data', primaryKey: 'ok', tone: 'danger', }), }, { id: 'error_not_found', label: 'Fehler (Nicht gefunden)', focusKeys: ['error', 'error_not_found', 'ok'], mock: () => dialogMock({ titleKey: 'error', messageKey: 'error_not_found', primaryKey: 'ok', tone: 'danger', }), }, { id: 'score_notice', label: 'Punktzahl berechnet', focusKeys: [ 'score_calculated_eyebrow', 'score_calculated_title', 'score_calculated_body', 'score_calculated_result_label', 'score_calculated_next_label', 'score_calculated_next_title', 'score_calculated_band_hint', 'score_calculated_continue', 'category_yellow', ], mock: () => scoreCalculatedMock(), }, ], }, ]; export function screenById(id) { return APP_UI_SCREENS.find(s => s.id === id) || APP_UI_SCREENS[0]; } /** @returns {AppUiVariant[]} */ export function getVariants(screen) { if (screen.variants?.length) return screen.variants; return [{ id: 'default', label: screen.label, focusKeys: screen.keys, mock: screen.mock || (() => ''), }]; } export function variantById(screen, variantId) { const variants = getVariants(screen); return variants.find(v => v.id === variantId) || variants[0]; } export function allScreenKeys() { const set = new Set(); APP_UI_SCREENS.forEach(s => s.keys.forEach(k => set.add(k))); return set; }