This repository has been archived on 2026-02-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
breakpilot-pwa/studio-v2/components/companion/lesson-mode/ReflectionSection.tsx
BreakPilot Dev 754a812d4b feat(companion): Migrate Companion from admin-v2 to studio-v2 as pure lesson tool
Remove Companion module entirely from admin-v2. Rebuild in studio-v2 as a
focused lesson timer (no dashboard mode). Direct flow: start → active → ended.
Fix timer bug where lastTickRef reset prevented countdown. Add companion link
to Sidebar and i18n translations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 23:50:20 +01:00

147 lines
4.4 KiB
TypeScript

'use client'
import { useState, useEffect } from 'react'
import { Star, Save, CheckCircle } from 'lucide-react'
import { LessonReflection } from '@/lib/companion/types'
interface ReflectionSectionProps {
reflection?: LessonReflection
onSave: (rating: number, notes: string, nextSteps: string) => void
}
export function ReflectionSection({ reflection, onSave }: ReflectionSectionProps) {
const [rating, setRating] = useState(reflection?.rating || 0)
const [notes, setNotes] = useState(reflection?.notes || '')
const [nextSteps, setNextSteps] = useState(reflection?.nextSteps || '')
const [hoverRating, setHoverRating] = useState(0)
const [saved, setSaved] = useState(false)
useEffect(() => {
if (reflection) {
setRating(reflection.rating)
setNotes(reflection.notes)
setNextSteps(reflection.nextSteps)
}
}, [reflection])
const handleSave = () => {
if (rating === 0) return
onSave(rating, notes, nextSteps)
setSaved(true)
setTimeout(() => setSaved(false), 2000)
}
const ratingLabels = [
'', // 0
'Verbesserungsbedarf',
'Okay',
'Gut',
'Sehr gut',
'Ausgezeichnet',
]
return (
<div className="bg-white border border-slate-200 rounded-xl p-6 space-y-6">
{/* Star Rating */}
<div>
<label className="block text-sm font-medium text-slate-700 mb-3">
Wie lief die Stunde?
</label>
<div className="flex items-center gap-2">
{[1, 2, 3, 4, 5].map((star) => {
const isFilled = star <= (hoverRating || rating)
return (
<button
key={star}
type="button"
onClick={() => setRating(star)}
onMouseEnter={() => setHoverRating(star)}
onMouseLeave={() => setHoverRating(0)}
className="p-1 transition-transform hover:scale-110"
aria-label={`${star} Stern${star > 1 ? 'e' : ''}`}
>
<Star
className={`w-8 h-8 ${
isFilled
? 'fill-amber-400 text-amber-400'
: 'text-slate-300'
}`}
/>
</button>
)
})}
{(hoverRating || rating) > 0 && (
<span className="ml-3 text-sm text-slate-600">
{ratingLabels[hoverRating || rating]}
</span>
)}
</div>
</div>
{/* Notes */}
<div>
<label className="block text-sm font-medium text-slate-700 mb-2">
Notizen zur Stunde
</label>
<textarea
value={notes}
onChange={(e) => setNotes(e.target.value)}
placeholder="Was lief gut? Was koennte besser laufen? Besondere Vorkommnisse..."
rows={4}
className="w-full px-4 py-3 border border-slate-200 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-blue-500 resize-none"
/>
</div>
{/* Next Steps */}
<div>
<label className="block text-sm font-medium text-slate-700 mb-2">
Naechste Schritte
</label>
<textarea
value={nextSteps}
onChange={(e) => setNextSteps(e.target.value)}
placeholder="Was muss fuer die naechste Stunde vorbereitet werden? Follow-ups..."
rows={3}
className="w-full px-4 py-3 border border-slate-200 rounded-xl focus:ring-2 focus:ring-blue-500 focus:border-blue-500 resize-none"
/>
</div>
{/* Save Button */}
<button
onClick={handleSave}
disabled={rating === 0}
className={`
w-full py-3 px-6 rounded-xl font-semibold
flex items-center justify-center gap-2
transition-all duration-200
${saved
? 'bg-green-600 text-white'
: rating === 0
? 'bg-slate-100 text-slate-400 cursor-not-allowed'
: 'bg-blue-600 text-white hover:bg-blue-700'
}
`}
>
{saved ? (
<>
<CheckCircle className="w-5 h-5" />
Gespeichert!
</>
) : (
<>
<Save className="w-5 h-5" />
Reflexion speichern
</>
)}
</button>
{/* Previous Reflection Info */}
{reflection?.savedAt && (
<p className="text-center text-sm text-slate-400">
Zuletzt gespeichert: {new Date(reflection.savedAt).toLocaleString('de-DE')}
</p>
)}
</div>
)
}