download refactoring

This commit is contained in:
2026-03-03 20:06:35 +01:00
parent 29ffaaf211
commit a434a0114a
4 changed files with 833 additions and 1024 deletions

361
src/public/css/style.css Normal file
View File

@@ -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; }

File diff suppressed because it is too large Load Diff

372
src/public/js/app.js Normal file
View File

@@ -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 = `<div class="topic-icon">${topic.icon}</div><h3>${topic.name}</h3><p>${topic.desc}</p>`;
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 = '<div class="loading-dots"><span></span><span></span><span></span></div>';
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 = `<span style="color:var(--danger)">Fehler: ${err.message}</span>`;
} finally {
state.isChecking = false;
nextActions.style.display = 'flex';
skipBtn.disabled = true;
}
});
// ── Markdown renderer ─────────────────────────────────────────────────────────
function simpleMarkdown(text) {
return text
.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
.replace(/\*(.+?)\*/g, '<em>$1</em>')
.replace(/`(.+?)`/g, '<code>$1</code>')
.replace(/^#{1,3} (.+)$/gm,'<h3>$1</h3>')
.replace(/^\d+\. (.+)$/gm, '<li>$1</li>')
.replace(/^[-•] (.+)$/gm, '<li>$1</li>')
.replace(/(<li>.*<\/li>\n?)+/g, m => `<ul>${m}</ul>`)
.replace(/\n{2,}/g, '</p><p>')
.replace(/\n/g, '<br>')
.replace(/^(.+)$/, '<p>$1</p>');
}
// ── 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 = `<div class="hi-q">F: ${escapeHtml(item.question)}</div><div class="hi-a">A: ${escapeHtml(item.answer)}</div>`;
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, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}
// ── Init ──────────────────────────────────────────────────────────────────────
buildTopicGrid();

92
src/public/js/data.js Normal file
View File

@@ -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?',
],
},
];