Files
breakpilot-lehrer/studio-v2/app/onboarding/page.tsx
Benjamin Admin d87645ffce Fix: Cast language selection to Language type
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-25 20:30:11 +02:00

177 lines
7.2 KiB
TypeScript

'use client'
import React, { useState, useEffect } from 'react'
import { useRouter } from 'next/navigation'
import { useTheme } from '@/lib/ThemeContext'
import { useLanguage } from '@/lib/LanguageContext'
import type { Language } from '@/lib/i18n'
interface LangOption {
code: string
name: string
name_native: string
flag: string
rtl: boolean
}
const STORAGE_KEY = 'bp_native_language'
export default function OnboardingPage() {
const router = useRouter()
const { isDark } = useTheme()
const { setLanguage } = useLanguage()
const [languages, setLanguages] = useState<LangOption[]>([])
const [selected, setSelected] = useState<string | null>(null)
const [role, setRole] = useState<'student' | 'parent'>('student')
const [saving, setSaving] = useState(false)
// Skip if already onboarded
useEffect(() => {
const stored = localStorage.getItem(STORAGE_KEY)
if (stored) router.replace('/learn')
}, [router])
// Load supported languages
useEffect(() => {
fetch('/api/user/languages')
.then(r => r.ok ? r.json() : null)
.then(d => { if (d?.languages) setLanguages(d.languages) })
.catch(() => {
// Fallback if API unavailable
setLanguages([
{ code: 'de', name: 'Deutsch', name_native: 'Deutsch', flag: 'de', rtl: false },
{ code: 'tr', name: 'Tuerkisch', name_native: 'Turkce', flag: 'tr', rtl: false },
{ code: 'ar', name: 'Arabisch', name_native: '\u0627\u0644\u0639\u0631\u0628\u064a\u0629', flag: 'sy', rtl: true },
{ code: 'uk', name: 'Ukrainisch', name_native: '\u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430', flag: 'ua', rtl: false },
{ code: 'ru', name: 'Russisch', name_native: '\u0420\u0443\u0441\u0441\u043a\u0438\u0439', flag: 'ru', rtl: false },
{ code: 'pl', name: 'Polnisch', name_native: 'Polski', flag: 'pl', rtl: false },
])
})
}, [])
const handleContinue = async () => {
if (!selected) return
setSaving(true)
// Save to backend
try {
await fetch('/api/user/language-preference?user_id=default', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ native_language: selected, role }),
})
} catch {}
// Save locally + set UI language
localStorage.setItem(STORAGE_KEY, selected)
setLanguage(selected as Language)
// Navigate
if (role === 'parent') {
router.push('/parent')
} else {
router.push('/learn')
}
}
const greetings: Record<string, string> = {
de: 'Willkommen!',
en: 'Welcome!',
tr: 'Hos geldiniz!',
ar: '\u0645\u0631\u062d\u0628\u0627!',
uk: '\u041b\u0430\u0441\u043a\u0430\u0432\u043e \u043f\u0440\u043e\u0441\u0438\u043c\u043e!',
ru: '\u0414\u043e\u0431\u0440\u043e \u043f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c!',
pl: 'Witamy!',
}
return (
<div className={`min-h-screen flex items-center justify-center ${
isDark ? 'bg-gradient-to-br from-indigo-900 via-purple-900 to-pink-800' : 'bg-gradient-to-br from-blue-50 via-indigo-50 to-purple-50'
}`}>
<div className={`w-full max-w-md mx-4 rounded-3xl p-8 ${
isDark ? 'bg-white/10 backdrop-blur-xl border border-white/20' : 'bg-white shadow-2xl border border-slate-200'
}`}>
{/* Greeting in multiple languages */}
<div className="text-center mb-8">
<div className="text-4xl mb-3">
{selected ? greetings[selected] || greetings.de : (
<span className={`${isDark ? 'text-white/80' : 'text-slate-700'}`}>
{Object.values(greetings).slice(0, 4).join(' / ')}
</span>
)}
</div>
<h1 className={`text-xl font-bold ${isDark ? 'text-white' : 'text-slate-900'}`}>
BreakPilot Sprache
</h1>
</div>
{/* Role Selection */}
<div className="flex gap-2 mb-6">
{(['student', 'parent'] as const).map(r => (
<button
key={r}
onClick={() => setRole(r)}
className={`flex-1 py-3 rounded-xl text-sm font-medium transition-all ${
role === r
? 'bg-gradient-to-r from-blue-500 to-cyan-500 text-white shadow-md'
: isDark ? 'bg-white/5 text-white/50 hover:bg-white/10' : 'bg-slate-100 text-slate-500 hover:bg-slate-200'
}`}
>
{r === 'student' ? 'Schueler / Student' : 'Elternteil / Parent'}
</button>
))}
</div>
{/* Question */}
<p className={`text-center text-sm mb-4 ${isDark ? 'text-white/60' : 'text-slate-500'}`}>
{role === 'student' ? 'Was ist deine Muttersprache?' : 'Welche Sprache sprechen Sie?'}
</p>
{/* Language Grid */}
<div className="grid grid-cols-2 gap-2 mb-6">
{languages.map(lang => (
<button
key={lang.code}
onClick={() => setSelected(lang.code)}
className={`p-3 rounded-xl text-left transition-all ${
selected === lang.code
? (isDark ? 'bg-blue-500/30 border-2 border-blue-400 ring-2 ring-blue-400/30' : 'bg-blue-50 border-2 border-blue-500 ring-2 ring-blue-500/20')
: (isDark ? 'bg-white/5 border-2 border-transparent hover:bg-white/10' : 'bg-slate-50 border-2 border-transparent hover:bg-slate-100')
}`}
>
<div className="flex items-center gap-2">
<span className="text-lg">{lang.flag === 'de' ? '\uD83C\uDDE9\uD83C\uDDEA' : lang.flag === 'tr' ? '\uD83C\uDDF9\uD83C\uDDF7' : lang.flag === 'sy' ? '\uD83C\uDDF8\uD83C\uDDFE' : lang.flag === 'ua' ? '\uD83C\uDDFA\uD83C\uDDE6' : lang.flag === 'ru' ? '\uD83C\uDDF7\uD83C\uDDFA' : lang.flag === 'pl' ? '\uD83C\uDDF5\uD83C\uDDF1' : lang.flag === 'gb' ? '\uD83C\uDDEC\uD83C\uDDE7' : '\uD83C\uDFF3\uFE0F'}</span>
<div>
<div className={`text-sm font-medium ${isDark ? 'text-white' : 'text-slate-900'}`}>{lang.name_native}</div>
<div className={`text-xs ${isDark ? 'text-white/40' : 'text-slate-400'}`}>{lang.name}</div>
</div>
</div>
</button>
))}
</div>
{/* Continue */}
<button
onClick={handleContinue}
disabled={!selected || saving}
className={`w-full py-4 rounded-xl font-semibold text-lg transition-all ${
selected
? 'bg-gradient-to-r from-blue-500 to-cyan-500 text-white hover:shadow-lg hover:shadow-blue-500/25'
: isDark ? 'bg-white/5 text-white/30' : 'bg-slate-100 text-slate-400'
}`}
>
{saving ? 'Wird gespeichert...' : selected ? (
selected === 'de' ? 'Weiter' :
selected === 'tr' ? 'Devam' :
selected === 'ar' ? '\u0627\u0633\u062a\u0645\u0631' :
selected === 'uk' ? '\u041f\u0440\u043e\u0434\u043e\u0432\u0436\u0438\u0442\u0438' :
selected === 'ru' ? '\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c' :
selected === 'pl' ? 'Dalej' :
'Continue'
) : 'Sprache waehlen'}
</button>
</div>
</div>
)
}