Services: Admin-Lehrer, Backend-Lehrer, Studio v2, Website, Klausur-Service, School-Service, Voice-Service, Geo-Service, BreakPilot Drive, Agent-Core Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
281 lines
8.5 KiB
TypeScript
281 lines
8.5 KiB
TypeScript
'use client'
|
|
|
|
import { useState } from 'react'
|
|
import { ChevronRight, ChevronLeft, Check, GraduationCap, Settings, Timer } from 'lucide-react'
|
|
|
|
interface OnboardingModalProps {
|
|
isOpen: boolean
|
|
onClose: () => void
|
|
onComplete: (data: { state?: string; schoolType?: string }) => void
|
|
}
|
|
|
|
const STATES = [
|
|
'Baden-Wuerttemberg',
|
|
'Bayern',
|
|
'Berlin',
|
|
'Brandenburg',
|
|
'Bremen',
|
|
'Hamburg',
|
|
'Hessen',
|
|
'Mecklenburg-Vorpommern',
|
|
'Niedersachsen',
|
|
'Nordrhein-Westfalen',
|
|
'Rheinland-Pfalz',
|
|
'Saarland',
|
|
'Sachsen',
|
|
'Sachsen-Anhalt',
|
|
'Schleswig-Holstein',
|
|
'Thueringen',
|
|
]
|
|
|
|
const SCHOOL_TYPES = [
|
|
'Grundschule',
|
|
'Hauptschule',
|
|
'Realschule',
|
|
'Gymnasium',
|
|
'Gesamtschule',
|
|
'Berufsschule',
|
|
'Foerderschule',
|
|
'Andere',
|
|
]
|
|
|
|
interface Step {
|
|
id: number
|
|
title: string
|
|
description: string
|
|
icon: typeof GraduationCap
|
|
}
|
|
|
|
const steps: Step[] = [
|
|
{
|
|
id: 1,
|
|
title: 'Willkommen',
|
|
description: 'Der Companion hilft Ihnen bei der Unterrichtsplanung und -durchfuehrung.',
|
|
icon: GraduationCap,
|
|
},
|
|
{
|
|
id: 2,
|
|
title: 'Ihre Schule',
|
|
description: 'Waehlen Sie Ihr Bundesland und Ihre Schulform.',
|
|
icon: Settings,
|
|
},
|
|
{
|
|
id: 3,
|
|
title: 'Bereit!',
|
|
description: 'Sie koennen jetzt mit dem Lesson-Modus starten.',
|
|
icon: Timer,
|
|
},
|
|
]
|
|
|
|
export function OnboardingModal({ isOpen, onClose, onComplete }: OnboardingModalProps) {
|
|
const [currentStep, setCurrentStep] = useState(1)
|
|
const [selectedState, setSelectedState] = useState('')
|
|
const [selectedSchoolType, setSelectedSchoolType] = useState('')
|
|
|
|
if (!isOpen) return null
|
|
|
|
const canProceed = () => {
|
|
if (currentStep === 2) {
|
|
return selectedState !== '' && selectedSchoolType !== ''
|
|
}
|
|
return true
|
|
}
|
|
|
|
const handleNext = () => {
|
|
if (currentStep < 3) {
|
|
setCurrentStep(currentStep + 1)
|
|
} else {
|
|
onComplete({
|
|
state: selectedState,
|
|
schoolType: selectedSchoolType,
|
|
})
|
|
}
|
|
}
|
|
|
|
const handleBack = () => {
|
|
if (currentStep > 1) {
|
|
setCurrentStep(currentStep - 1)
|
|
}
|
|
}
|
|
|
|
const currentStepData = steps[currentStep - 1]
|
|
const Icon = currentStepData.icon
|
|
|
|
return (
|
|
<div className="fixed inset-0 z-50 flex items-center justify-center">
|
|
{/* Backdrop */}
|
|
<div className="absolute inset-0 bg-black/50 backdrop-blur-sm" />
|
|
|
|
{/* Modal */}
|
|
<div className="relative bg-white rounded-2xl shadow-xl w-full max-w-lg mx-4 overflow-hidden">
|
|
{/* Progress Bar */}
|
|
<div className="h-1 bg-slate-100">
|
|
<div
|
|
className="h-full bg-blue-600 transition-all duration-300"
|
|
style={{ width: `${(currentStep / 3) * 100}%` }}
|
|
/>
|
|
</div>
|
|
|
|
{/* Content */}
|
|
<div className="p-8">
|
|
{/* Step Indicator */}
|
|
<div className="flex items-center justify-center gap-2 mb-8">
|
|
{steps.map((step) => (
|
|
<div
|
|
key={step.id}
|
|
className={`
|
|
w-3 h-3 rounded-full transition-all
|
|
${step.id === currentStep
|
|
? 'bg-blue-600 scale-125'
|
|
: step.id < currentStep
|
|
? 'bg-blue-600'
|
|
: 'bg-slate-200'
|
|
}
|
|
`}
|
|
/>
|
|
))}
|
|
</div>
|
|
|
|
{/* Icon */}
|
|
<div className="w-16 h-16 bg-blue-100 rounded-2xl flex items-center justify-center mx-auto mb-6">
|
|
<Icon className="w-8 h-8 text-blue-600" />
|
|
</div>
|
|
|
|
{/* Title & Description */}
|
|
<h2 className="text-2xl font-bold text-slate-900 text-center mb-2">
|
|
{currentStepData.title}
|
|
</h2>
|
|
<p className="text-slate-600 text-center mb-8">
|
|
{currentStepData.description}
|
|
</p>
|
|
|
|
{/* Step Content */}
|
|
{currentStep === 1 && (
|
|
<div className="space-y-4 text-center">
|
|
<div className="grid grid-cols-3 gap-4">
|
|
<div className="p-4 bg-blue-50 rounded-xl">
|
|
<div className="text-2xl mb-1">5</div>
|
|
<div className="text-xs text-slate-600">Phasen</div>
|
|
</div>
|
|
<div className="p-4 bg-green-50 rounded-xl">
|
|
<div className="text-2xl mb-1">45</div>
|
|
<div className="text-xs text-slate-600">Minuten</div>
|
|
</div>
|
|
<div className="p-4 bg-purple-50 rounded-xl">
|
|
<div className="text-2xl mb-1">∞</div>
|
|
<div className="text-xs text-slate-600">Flexibel</div>
|
|
</div>
|
|
</div>
|
|
<p className="text-sm text-slate-500 mt-4">
|
|
Einstieg → Erarbeitung → Sicherung → Transfer → Reflexion
|
|
</p>
|
|
</div>
|
|
)}
|
|
|
|
{currentStep === 2 && (
|
|
<div className="space-y-4">
|
|
{/* State Selection */}
|
|
<div>
|
|
<label className="block text-sm font-medium text-slate-700 mb-2">
|
|
Bundesland
|
|
</label>
|
|
<select
|
|
value={selectedState}
|
|
onChange={(e) => setSelectedState(e.target.value)}
|
|
className="w-full px-4 py-3 border border-slate-200 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-blue-500 bg-white"
|
|
>
|
|
<option value="">Bitte waehlen...</option>
|
|
{STATES.map((state) => (
|
|
<option key={state} value={state}>
|
|
{state}
|
|
</option>
|
|
))}
|
|
</select>
|
|
</div>
|
|
|
|
{/* School Type Selection */}
|
|
<div>
|
|
<label className="block text-sm font-medium text-slate-700 mb-2">
|
|
Schulform
|
|
</label>
|
|
<select
|
|
value={selectedSchoolType}
|
|
onChange={(e) => setSelectedSchoolType(e.target.value)}
|
|
className="w-full px-4 py-3 border border-slate-200 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-blue-500 bg-white"
|
|
>
|
|
<option value="">Bitte waehlen...</option>
|
|
{SCHOOL_TYPES.map((type) => (
|
|
<option key={type} value={type}>
|
|
{type}
|
|
</option>
|
|
))}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{currentStep === 3 && (
|
|
<div className="text-center space-y-4">
|
|
<div className="w-20 h-20 bg-green-100 rounded-full flex items-center justify-center mx-auto">
|
|
<Check className="w-10 h-10 text-green-600" />
|
|
</div>
|
|
<div className="p-4 bg-slate-50 rounded-xl">
|
|
<p className="text-sm text-slate-600">
|
|
<strong>Bundesland:</strong> {selectedState || 'Nicht angegeben'}
|
|
</p>
|
|
<p className="text-sm text-slate-600">
|
|
<strong>Schulform:</strong> {selectedSchoolType || 'Nicht angegeben'}
|
|
</p>
|
|
</div>
|
|
<p className="text-sm text-slate-500">
|
|
Sie koennen diese Einstellungen jederzeit aendern.
|
|
</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Footer */}
|
|
<div className="flex items-center justify-between p-6 border-t border-slate-200 bg-slate-50">
|
|
<button
|
|
onClick={currentStep === 1 ? onClose : handleBack}
|
|
className="flex items-center gap-2 px-4 py-2 text-slate-600 hover:bg-slate-200 rounded-lg transition-colors"
|
|
>
|
|
{currentStep === 1 ? (
|
|
'Ueberspringen'
|
|
) : (
|
|
<>
|
|
<ChevronLeft className="w-4 h-4" />
|
|
Zurueck
|
|
</>
|
|
)}
|
|
</button>
|
|
<button
|
|
onClick={handleNext}
|
|
disabled={!canProceed()}
|
|
className={`
|
|
flex items-center gap-2 px-6 py-2 rounded-lg font-medium
|
|
transition-all duration-200
|
|
${canProceed()
|
|
? 'bg-blue-600 text-white hover:bg-blue-700'
|
|
: 'bg-slate-200 text-slate-500 cursor-not-allowed'
|
|
}
|
|
`}
|
|
>
|
|
{currentStep === 3 ? (
|
|
<>
|
|
<Check className="w-4 h-4" />
|
|
Fertig
|
|
</>
|
|
) : (
|
|
<>
|
|
Weiter
|
|
<ChevronRight className="w-4 h-4" />
|
|
</>
|
|
)}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|