From a434a0114a14675132fe75a4d9f80ee565cd5773 Mon Sep 17 00:00:00 2001 From: balex Date: Tue, 3 Mar 2026 20:06:35 +0100 Subject: [PATCH] download refactoring --- src/public/css/style.css | 361 +++++++++++++ src/public/index.html | 1032 +------------------------------------- src/public/js/app.js | 372 ++++++++++++++ src/public/js/data.js | 92 ++++ 4 files changed, 833 insertions(+), 1024 deletions(-) create mode 100644 src/public/css/style.css create mode 100644 src/public/js/app.js create mode 100644 src/public/js/data.js diff --git a/src/public/css/style.css b/src/public/css/style.css new file mode 100644 index 0000000..41b33d1 --- /dev/null +++ b/src/public/css/style.css @@ -0,0 +1,361 @@ +*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } + +:root { + --bg: #0f1117; + --surface: #1a1d27; + --surface2: #242736; + --border: #2e3247; + --accent: #6c8eff; + --accent-dim: rgba(108, 142, 255, 0.15); + --danger: #ff5f57; + --success: #30d158; + --text: #e8eaf0; + --text-dim: #8b90a7; + --text-muted: #555a72; + --radius: 14px; + --radius-sm: 8px; +} + +body { + font-family: 'DM Sans', sans-serif; + background: var(--bg); + color: var(--text); + min-height: 100dvh; + display: flex; + flex-direction: column; + align-items: center; +} + +.app { + width: 100%; + max-width: 560px; + padding: 20px 16px 40px; + display: flex; + flex-direction: column; + gap: 16px; +} + +/* ── Header ── */ +.header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 12px 0 4px; +} + +.header h1 { font-size: 18px; font-weight: 600; letter-spacing: -0.3px; } +.header h1 span { color: var(--accent); } + +.level-selector { display: flex; gap: 6px; } + +.level-btn { + padding: 5px 11px; + border-radius: 20px; + border: 1px solid var(--border); + background: transparent; + color: var(--text-dim); + font-family: inherit; + font-size: 12px; + font-weight: 500; + cursor: pointer; + transition: all 0.15s; +} + +.level-btn.active { + background: var(--accent-dim); + border-color: var(--accent); + color: var(--accent); +} + +/* ── Screens ── */ +.screen { display: none; flex-direction: column; gap: 16px; } +.screen.active { display: flex; } + +/* ── Topic grid ── */ +.topic-intro { text-align: center; padding: 8px 0 4px; } +.topic-intro p { color: var(--text-dim); font-size: 14px; line-height: 1.5; } + +.topic-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 10px; +} + +.topic-card { + background: var(--surface); + border: 1px solid var(--border); + border-radius: var(--radius); + padding: 18px 16px; + cursor: pointer; + transition: all 0.15s; + text-align: left; +} + +.topic-card:hover, .topic-card:active { + background: var(--surface2); + border-color: var(--accent); + transform: translateY(-1px); +} + +.topic-icon { font-size: 24px; margin-bottom: 8px; } +.topic-card h3 { font-size: 14px; font-weight: 600; margin-bottom: 2px; } +.topic-card p { font-size: 12px; color: var(--text-muted); } + +/* ── Practice screen ── */ +.progress-bar-wrap { display: flex; align-items: center; gap: 10px; } + +.progress-bar { + flex: 1; + height: 4px; + background: var(--border); + border-radius: 2px; + overflow: hidden; +} + +.progress-fill { + height: 100%; + background: var(--accent); + border-radius: 2px; + transition: width 0.4s ease; +} + +.progress-text { font-size: 12px; color: var(--text-muted); white-space: nowrap; } + +.topic-badge { display: flex; align-items: center; gap: 8px; } + +.topic-badge button { + background: none; + border: none; + color: var(--text-muted); + cursor: pointer; + font-size: 13px; + font-family: inherit; + padding: 2px 0; + transition: color 0.15s; +} + +.topic-badge button:hover { color: var(--text); } +.topic-badge span { font-size: 13px; color: var(--text-dim); } + +.question-card { + background: var(--surface); + border: 1px solid var(--border); + border-radius: var(--radius); + padding: 20px; + display: flex; + flex-direction: column; + gap: 12px; +} + +.question-label { + font-size: 11px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.8px; + color: var(--text-muted); +} + +.question-text { font-size: 17px; font-weight: 500; line-height: 1.5; } + +.speak-btn { + align-self: flex-start; + display: flex; + align-items: center; + gap: 6px; + padding: 7px 14px; + border-radius: 20px; + border: 1px solid var(--border); + background: transparent; + color: var(--text-dim); + font-family: inherit; + font-size: 13px; + cursor: pointer; + transition: all 0.15s; +} + +.speak-btn:hover { border-color: var(--accent); color: var(--accent); } +.speak-btn.speaking { border-color: var(--accent); background: var(--accent-dim); color: var(--accent); } + +/* ── Record area ── */ +.record-area { + display: flex; + flex-direction: column; + align-items: center; + gap: 16px; + padding: 8px 0; +} + +.record-btn { + width: 80px; + height: 80px; + border-radius: 50%; + border: none; + background: var(--surface2); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + font-size: 28px; + transition: all 0.2s; + position: relative; +} + +.record-btn::before { + content: ''; + position: absolute; + inset: -4px; + border-radius: 50%; + border: 2px solid var(--border); + transition: all 0.2s; +} + +.record-btn:hover::before { border-color: var(--accent); inset: -6px; } + +.record-btn.recording { + background: rgba(255, 95, 87, 0.15); + animation: pulse 1.5s ease-in-out infinite; +} + +.record-btn.recording::before { border-color: var(--danger); inset: -6px; } + +@keyframes pulse { + 0%, 100% { box-shadow: 0 0 0 0 rgba(255, 95, 87, 0.4); } + 50% { box-shadow: 0 0 0 14px rgba(255, 95, 87, 0); } +} + +.record-hint { font-size: 13px; color: var(--text-muted); text-align: center; } + +/* ── Transcript ── */ +.transcript-box { + background: var(--surface); + border: 1px solid var(--border); + border-radius: var(--radius); + padding: 16px; + min-height: 80px; + font-size: 15px; + line-height: 1.6; + color: var(--text); + position: relative; +} + +.transcript-box.empty::after { + content: 'Hier erscheint dein gesprochener Text...'; + color: var(--text-muted); + font-size: 14px; +} + +.transcript-box[contenteditable="true"] { outline: none; cursor: text; border-color: var(--accent); } + +/* ── Buttons ── */ +.actions { display: flex; gap: 10px; } + +.btn { + flex: 1; + padding: 13px 16px; + border-radius: var(--radius-sm); + border: 1px solid var(--border); + background: var(--surface); + color: var(--text); + font-family: inherit; + font-size: 14px; + font-weight: 500; + cursor: pointer; + transition: all 0.15s; +} + +.btn:hover { background: var(--surface2); } +.btn:disabled { opacity: 0.4; cursor: not-allowed; } + +.btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; } +.btn-primary:hover { filter: brightness(1.1); } +.btn-primary:disabled { filter: none; } + +/* ── Feedback ── */ +.feedback-box { + background: var(--surface); + border: 1px solid var(--border); + border-radius: var(--radius); + padding: 18px; + display: none; + flex-direction: column; + gap: 12px; +} + +.feedback-box.visible { display: flex; } + +.feedback-label { + font-size: 11px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.8px; + color: var(--accent); +} + +.feedback-content { font-size: 14px; line-height: 1.7; color: var(--text-dim); } +.feedback-content strong { color: var(--text); } +.feedback-content h3 { font-size: 13px; color: var(--text); margin: 10px 0 4px; } +.feedback-content ul { padding-left: 18px; } +.feedback-content li { margin-bottom: 4px; } +.feedback-content code { background: var(--surface2); padding: 1px 6px; border-radius: 4px; font-size: 13px; } + +.loading-dots { display: flex; gap: 5px; align-items: center; } + +.loading-dots span { + width: 6px; height: 6px; + border-radius: 50%; + background: var(--accent); + animation: dot-bounce 1.2s ease-in-out infinite; +} + +.loading-dots span:nth-child(2) { animation-delay: 0.2s; } +.loading-dots span:nth-child(3) { animation-delay: 0.4s; } + +@keyframes dot-bounce { + 0%, 80%, 100% { transform: scale(0.6); opacity: 0.4; } + 40% { transform: scale(1); opacity: 1; } +} + +/* ── History ── */ +.history-section { display: none; flex-direction: column; gap: 10px; } +.history-section.has-items { display: flex; } + +.history-title { + font-size: 13px; + font-weight: 600; + color: var(--text-muted); + text-transform: uppercase; + letter-spacing: 0.6px; +} + +.history-list { display: flex; flex-direction: column; gap: 8px; max-height: 260px; overflow-y: auto; } + +.history-item { + background: var(--surface); + border: 1px solid var(--border); + border-radius: var(--radius-sm); + padding: 12px 14px; + font-size: 13px; + cursor: pointer; + transition: border-color 0.15s; +} + +.history-item:hover { border-color: var(--accent); } +.history-item .hi-q { color: var(--text-dim); margin-bottom: 4px; } +.history-item .hi-a { color: var(--text); } + +/* ── Done screen ── */ +.done-screen { text-align: center; padding: 40px 0; display: flex; flex-direction: column; align-items: center; gap: 16px; } +.done-screen .big-icon { font-size: 56px; } +.done-screen h2 { font-size: 22px; font-weight: 600; } +.done-screen p { color: var(--text-dim); font-size: 15px; line-height: 1.5; } + +.stats-row { display: flex; gap: 16px; justify-content: center; } + +.stat-box { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 14px 20px; text-align: center; } +.stat-box .stat-val { font-size: 24px; font-weight: 600; color: var(--accent); } +.stat-box .stat-label { font-size: 12px; color: var(--text-muted); margin-top: 2px; } + +/* ── Scrollbar ── */ +::-webkit-scrollbar { width: 4px; } +::-webkit-scrollbar-track { background: transparent; } +::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; } diff --git a/src/public/index.html b/src/public/index.html index da0c823..f0a8699 100644 --- a/src/public/index.html +++ b/src/public/index.html @@ -9,507 +9,7 @@ - +
@@ -524,7 +24,7 @@
- +

Wähle ein Thema und übe dein gesprochenes Deutsch

@@ -532,7 +32,7 @@
- +
@@ -549,9 +49,7 @@
Frage
- +
@@ -564,6 +62,7 @@
+
@@ -577,14 +76,13 @@
-
Verlauf dieser Sitzung
- +
🎉
@@ -605,521 +103,7 @@
- - + + diff --git a/src/public/js/app.js b/src/public/js/app.js new file mode 100644 index 0000000..70a10a4 --- /dev/null +++ b/src/public/js/app.js @@ -0,0 +1,372 @@ +// ── Constants ───────────────────────────────────────────────────────────────── +const MAX_RECORD_SECONDS = 30; +const MAX_RECORD_WORDS = 60; +const EXT_MAP = { 'audio/webm': 'webm', 'audio/ogg': 'ogg', 'audio/mp4': 'm4a', 'audio/mpeg': 'mp3' }; + +// ── State ───────────────────────────────────────────────────────────────────── +const state = { + level: 'B1', + currentTopic: null, + currentIndex: 0, + questionQueue: [], + transcript: '', + isRecording: false, + isChecking: false, + sessionHistory: [], +}; + +// ── DOM refs ────────────────────────────────────────────────────────────────── +const screens = { + topics: document.getElementById('screen-topics'), + practice: document.getElementById('screen-practice'), + done: document.getElementById('screen-done'), +}; + +const topicGrid = document.getElementById('topic-grid'); +const topicLabel = document.getElementById('topic-label'); +const progressFill = document.getElementById('progress-fill'); +const progressText = document.getElementById('progress-text'); +const questionText = document.getElementById('question-text'); +const transcriptBox = document.getElementById('transcript-box'); +const feedbackBox = document.getElementById('feedback-box'); +const feedbackContent= document.getElementById('feedback-content'); +const recordBtn = document.getElementById('record-btn'); +const recordHint = document.getElementById('record-hint'); +const speakBtn = document.getElementById('speak-btn'); +const checkBtn = document.getElementById('check-btn'); +const clearBtn = document.getElementById('clear-btn'); +const downloadBtn = document.getElementById('download-btn'); +const skipBtn = document.getElementById('skip-btn'); +const nextActions = document.getElementById('next-actions'); +const nextBtn = document.getElementById('next-btn'); +const backBtn = document.getElementById('back-btn'); +const historySection = document.getElementById('history-section'); +const historyList = document.getElementById('history-list'); + +// ── Navigation ──────────────────────────────────────────────────────────────── +function showScreen(name) { + Object.values(screens).forEach(s => s.classList.remove('active')); + screens[name].classList.add('active'); +} + +// ── Level selector ──────────────────────────────────────────────────────────── +document.querySelectorAll('.level-btn').forEach(btn => { + btn.addEventListener('click', () => { + document.querySelectorAll('.level-btn').forEach(b => b.classList.remove('active')); + btn.classList.add('active'); + state.level = btn.dataset.level; + }); +}); + +// ── Topic grid ──────────────────────────────────────────────────────────────── +function buildTopicGrid() { + TOPICS.forEach(topic => { + const card = document.createElement('div'); + card.className = 'topic-card'; + card.innerHTML = `
${topic.icon}

${topic.name}

${topic.desc}

`; + card.addEventListener('click', () => startTopic(topic)); + topicGrid.appendChild(card); + }); +} + +function startTopic(topic) { + state.currentTopic = topic; + state.sessionHistory = []; + const indices = topic.questions.map((_, i) => i); + for (let i = indices.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [indices[i], indices[j]] = [indices[j], indices[i]]; + } + state.questionQueue = indices; + renderHistoryList(); + showScreen('practice'); + loadQuestion(); +} + +// ── Questions ───────────────────────────────────────────────────────────────── +function loadQuestion() { + const topic = state.currentTopic; + state.currentIndex = state.questionQueue[0]; + const total = topic.questions.length; + const done = total - state.questionQueue.length; + + topicLabel.textContent = `${topic.icon} ${topic.name}`; + progressFill.style.width = `${(done / total) * 100}%`; + progressText.textContent = `${done + 1} / ${total}`; + questionText.textContent = topic.questions[state.currentIndex]; + + resetPracticeUI(); + autoSpeak(); +} + +function resetPracticeUI() { + state.transcript = ''; + transcriptBox.contentEditable = 'false'; + updateTranscriptBox(''); + feedbackBox.classList.remove('visible'); + feedbackContent.innerHTML = ''; + nextActions.style.display = 'none'; + checkBtn.disabled = true; + skipBtn.disabled = false; + downloadBtn.disabled = true; + audioBlob = null; + stopRecording(); +} + +// ── Audio playback ──────────────────────────────────────────────────────────── +let audioPlayer = null; + +function stopAudio() { + if (audioPlayer) { audioPlayer.pause(); audioPlayer = null; } + speakBtn.classList.remove('speaking'); +} + +function autoSpeak() { + stopAudio(); + const { id } = state.currentTopic; + audioPlayer = new Audio(`audio/${id}_${state.currentIndex}.mp3`); + speakBtn.classList.add('speaking'); + audioPlayer.onended = stopAudio; + audioPlayer.onerror = stopAudio; + audioPlayer.play(); +} + +speakBtn.addEventListener('click', () => { + if (audioPlayer && !audioPlayer.paused) { stopAudio(); return; } + autoSpeak(); +}); + +// ── Speech recognition ──────────────────────────────────────────────────────── +const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition; +let recognition = null; + +function initRecognition() { + if (!SpeechRecognition) return null; + const r = new SpeechRecognition(); + r.lang = 'de-DE'; + r.continuous = true; + r.interimResults = false; + r.maxAlternatives = 1; + + let finalText = ''; + + r.onstart = () => { + finalText = state.transcript; + recordBtn.classList.add('recording'); + recordHint.textContent = 'Tippen zum Stoppen'; + state.isRecording = true; + }; + + r.onresult = (e) => { + for (let i = e.resultIndex; i < e.results.length; i++) { + if (e.results[i].isFinal) + finalText += (finalText ? ' ' : '') + e.results[i][0].transcript; + } + if (finalText.trim().split(/\s+/).length >= MAX_RECORD_WORDS) { + stopRecording(); + return; + } + updateTranscriptBox(finalText); + state.transcript = finalText; + checkBtn.disabled = !finalText.trim(); + }; + + r.onend = () => { if (state.isRecording) stopRecording(); }; + r.onerror = (e) => { if (e.error !== 'no-speech') stopRecording(); }; + + return r; +} + +// ── MediaRecorder ───────────────────────────────────────────────────────────── +let recordingTimer = null; +let mediaRecorder = null; +let audioChunks = []; +let audioBlob = null; + +async function startRecording() { + if (!SpeechRecognition) { + alert('Spracherkennung wird in diesem Browser nicht unterstützt. Bitte nutze Chrome oder Edge.'); + return; + } + stopAudio(); + audioBlob = null; + audioChunks = []; + downloadBtn.disabled = true; + + try { + const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); + const mimeType = MediaRecorder.isTypeSupported('audio/webm;codecs=opus') + ? 'audio/webm;codecs=opus' : 'audio/webm'; + mediaRecorder = new MediaRecorder(stream, { mimeType }); + mediaRecorder.ondataavailable = e => { if (e.data.size > 0) audioChunks.push(e.data); }; + mediaRecorder.onstop = () => { + audioBlob = new Blob(audioChunks, { type: mimeType }); + stream.getTracks().forEach(t => t.stop()); + if (audioBlob.size > 0) downloadBtn.disabled = false; + }; + mediaRecorder.start(); + } catch (e) { + console.warn('MediaRecorder unavailable:', e); + } + + transcriptBox.contentEditable = 'false'; + recognition = initRecognition(); + state.isRecording = true; + try { recognition.start(); } catch (_) {} + + clearTimeout(recordingTimer); + recordingTimer = setTimeout(stopRecording, MAX_RECORD_SECONDS * 1000); +} + +function stopRecording() { + clearTimeout(recordingTimer); + state.isRecording = false; + if (recognition) { + try { recognition.stop(); } catch (_) {} + recognition = null; + } + if (mediaRecorder && mediaRecorder.state !== 'inactive') { + mediaRecorder.stop(); + mediaRecorder = null; + } + recordBtn.classList.remove('recording'); + recordHint.textContent = 'Tippen zum Aufnehmen'; + transcriptBox.contentEditable = 'true'; +} + +recordBtn.addEventListener('click', () => state.isRecording ? stopRecording() : startRecording()); + +// ── Transcript box ──────────────────────────────────────────────────────────── +function updateTranscriptBox(text) { + transcriptBox.textContent = text; + transcriptBox.classList.toggle('empty', !text); +} + +transcriptBox.addEventListener('input', () => { + state.transcript = transcriptBox.textContent.trim(); + checkBtn.disabled = !state.transcript; +}); + +// ── Download recording ──────────────────────────────────────────────────────── +downloadBtn.addEventListener('click', () => { + if (!audioBlob) return; + const topic = (state.currentTopic?.name || 'antwort').replace(/[^\w]/g, '_'); + const now = new Date(); + const ext = EXT_MAP[audioBlob.type.split(';')[0]] || 'webm'; + const filename = `${topic}_q${state.currentIndex + 1}_${now.getDate()}-${now.getMonth() + 1}.${ext}`; + const url = URL.createObjectURL(audioBlob); + const a = document.createElement('a'); + a.href = url; a.download = filename; a.click(); + URL.revokeObjectURL(url); +}); + +// ── Clear ───────────────────────────────────────────────────────────────────── +clearBtn.addEventListener('click', () => { + stopRecording(); + state.transcript = ''; + transcriptBox.contentEditable = 'false'; + updateTranscriptBox(''); + checkBtn.disabled = true; + feedbackBox.classList.remove('visible'); + nextActions.style.display = 'none'; +}); + +// ── Check answer ────────────────────────────────────────────────────────────── +checkBtn.addEventListener('click', async () => { + const answer = state.transcript.trim(); + if (!answer || state.isChecking) return; + + stopRecording(); + state.isChecking = true; + checkBtn.disabled = true; + feedbackBox.classList.add('visible'); + feedbackContent.innerHTML = '
'; + + try { + const res = await fetch('api/check', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + question: state.currentTopic.questions[state.currentIndex], + answer, + level: state.level, + }), + }); + const data = await res.json(); + if (!res.ok) throw new Error(data.error || 'Fehler'); + + feedbackContent.innerHTML = simpleMarkdown(data.feedback || ''); + state.sessionHistory.push({ question: state.currentTopic.questions[state.currentIndex], answer, feedback: data.feedback }); + renderHistoryList(); + } catch (err) { + feedbackContent.innerHTML = `Fehler: ${err.message}`; + } finally { + state.isChecking = false; + nextActions.style.display = 'flex'; + skipBtn.disabled = true; + } +}); + +// ── Markdown renderer ───────────────────────────────────────────────────────── +function simpleMarkdown(text) { + return text + .replace(/&/g, '&').replace(//g, '>') + .replace(/\*\*(.+?)\*\*/g, '$1') + .replace(/\*(.+?)\*/g, '$1') + .replace(/`(.+?)`/g, '$1') + .replace(/^#{1,3} (.+)$/gm,'

$1

') + .replace(/^\d+\. (.+)$/gm, '
  • $1
  • ') + .replace(/^[-•] (.+)$/gm, '
  • $1
  • ') + .replace(/(
  • .*<\/li>\n?)+/g, m => `
      ${m}
    `) + .replace(/\n{2,}/g, '

    ') + .replace(/\n/g, '
    ') + .replace(/^(.+)$/, '

    $1

    '); +} + +// ── Skip / Retry / Next / Done ──────────────────────────────────────────────── +skipBtn.addEventListener('click', () => { + stopRecording(); stopAudio(); + state.questionQueue.shift(); + state.questionQueue.length === 0 ? showDone() : loadQuestion(); +}); + +document.getElementById('retry-btn').addEventListener('click', () => { resetPracticeUI(); autoSpeak(); }); + +nextBtn.addEventListener('click', () => { + state.questionQueue.shift(); + state.questionQueue.length === 0 ? showDone() : loadQuestion(); +}); + +function showDone() { + document.getElementById('stat-answered').textContent = state.sessionHistory.length; + document.getElementById('stat-level').textContent = state.level; + progressFill.style.width = '100%'; + showScreen('done'); +} + +backBtn.addEventListener('click', () => { stopRecording(); stopAudio(); showScreen('topics'); }); +document.getElementById('restart-btn').addEventListener('click', () => showScreen('topics')); + +// ── History ─────────────────────────────────────────────────────────────────── +function renderHistoryList() { + historySection.classList.toggle('has-items', state.sessionHistory.length > 0); + historyList.innerHTML = ''; + [...state.sessionHistory].reverse().forEach(item => { + const el = document.createElement('div'); + el.className = 'history-item'; + el.innerHTML = `
    F: ${escapeHtml(item.question)}
    A: ${escapeHtml(item.answer)}
    `; + el.addEventListener('click', () => { + feedbackContent.innerHTML = simpleMarkdown(item.feedback); + feedbackBox.classList.add('visible'); + feedbackBox.scrollIntoView({ behavior: 'smooth', block: 'start' }); + }); + historyList.appendChild(el); + }); +} + +function escapeHtml(s) { + return s.replace(/&/g, '&').replace(//g, '>'); +} + +// ── Init ────────────────────────────────────────────────────────────────────── +buildTopicGrid(); diff --git a/src/public/js/data.js b/src/public/js/data.js new file mode 100644 index 0000000..5c8c325 --- /dev/null +++ b/src/public/js/data.js @@ -0,0 +1,92 @@ +const TOPICS = [ + { + id: 'alltag', icon: '🏠', name: 'Alltag', desc: '10 Fragen', + questions: [ + 'Wie sieht dein typischer Morgen aus?', + 'Was machst du normalerweise in deiner Freizeit?', + 'Wie oft kochst du zu Hause und was bereitest du gerne zu?', + 'Beschreibe deinen Tagesablauf an einem Werktag.', + 'Welche Aufgaben im Haushalt magst du und welche nicht?', + 'Wie verbringst du deinen Feierabend?', + 'Machst du regelmäßig Sport? Was und wie oft?', + 'Wie oft triffst du dich mit Freunden oder Familie?', + 'Was liest du gerne – Bücher, Zeitungen oder Online-Artikel?', + 'Wie entspannst du dich nach einem stressigen Tag?', + ], + }, + { + id: 'arbeit', icon: '💼', name: 'Arbeit & Beruf', desc: '10 Fragen', + questions: [ + 'Was machst du beruflich und was gefällt dir an deiner Arbeit?', + 'Wie sieht dein Arbeitsplatz aus – Büro, Homeoffice oder beides?', + 'Was sind die größten Herausforderungen in deinem Job?', + 'Wie lange arbeitest du täglich und wie ist die Work-Life-Balance?', + 'Hast du nette Kollegen? Wie ist das Arbeitsklima?', + 'Welche Fähigkeiten brauchst du für deinen Beruf?', + 'Was würdest du beruflich ändern, wenn du könntest?', + 'Wie wichtig ist Karriere für dich im Vergleich zu Freizeit?', + 'Hast du schon mal den Job gewechselt? Warum?', + 'Was sind deine beruflichen Ziele für die Zukunft?', + ], + }, + { + id: 'reisen', icon: '✈️', name: 'Reisen', desc: '10 Fragen', + questions: [ + 'Wohin bist du zuletzt gereist und wie war es?', + 'Reist du lieber alleine oder mit anderen? Warum?', + 'Was ist dein Traumreiseziel und warum?', + 'Bevorzugst du Strand, Berge oder Städtereisen?', + 'Wie planst du normalerweise deine Reisen?', + 'Was nimmst du immer mit auf Reisen?', + 'Hast du schon mal einen Kulturschock erlebt?', + 'Welches Essen aus einem anderen Land hat dir besonders gefallen?', + 'Wie wichtig ist es für dich, die Landessprache zu kennen?', + 'Erzähl von einem unvergesslichen Reiseerlebnis.', + ], + }, + { + id: 'schweiz', icon: '🇨🇭', name: 'Schweiz & Bern', desc: '10 Fragen', + questions: [ + 'Was magst du am Leben in der Schweiz besonders?', + 'Wie unterscheidet sich das Schweizerdeutsch vom Hochdeutsch?', + 'Was sind typisch schweizerische Gewohnheiten oder Traditionen?', + 'Welche Sehenswürdigkeiten in Bern kennst du?', + 'Was ist das Besondere am schweizerischen Bildungssystem?', + 'Wie ist das öffentliche Verkehrsnetz in der Schweiz?', + 'Was denkst du über die Mehrsprachigkeit in der Schweiz?', + 'Welche Schweizer Gerichte kennst du und magst du?', + 'Wie erleben Ausländer das Einleben in der Schweiz?', + 'Was sind Vor- und Nachteile der direkten Demokratie?', + ], + }, + { + id: 'gesundheit', icon: '🏥', name: 'Gesundheit', desc: '10 Fragen', + questions: [ + 'Wie wichtig ist dir deine Gesundheit im Alltag?', + 'Treibst du Sport für die Gesundheit oder zum Spaß?', + 'Wie ernährst du dich – bewusst oder eher spontan?', + 'Wie gehst du mit Stress um?', + 'Schläfst du gut? Was machst du für besseren Schlaf?', + 'Gehst du regelmäßig zum Arzt für Vorsorgeuntersuchungen?', + 'Was meinst du – wie viel Einfluss hat man auf die eigene Gesundheit?', + 'Wie beeinflusst das Wetter deine Stimmung und Gesundheit?', + 'Hast du Allergien oder besondere gesundheitliche Themen?', + 'Was ist für dich gesunde Ernährung?', + ], + }, + { + id: 'meinungen', icon: '💬', name: 'Meinungen', desc: '10 Fragen', + questions: [ + 'Was denkst du über soziale Medien – Fluch oder Segen?', + 'Glaubst du, dass Homeoffice die Produktivität steigert?', + 'Was meinst du: Ist lebenslanges Lernen wichtig?', + 'Wie stehst du zu vegetarischer oder veganer Ernährung?', + 'Glaubst du, dass KI unsere Arbeitswelt stark verändern wird?', + 'Was hältst du von öffentlichem Nahverkehr statt Autofahren?', + 'Ist es wichtig, mehrere Sprachen zu sprechen? Warum?', + 'Was denkst du über die vier-Tage-Arbeitswoche?', + 'Sollten mehr Menschen ehrenamtlich arbeiten?', + 'Wie wichtig ist lokales Einkaufen für die Umwelt?', + ], + }, +];