'use client' import { useMemo } from 'react' import type { CriteriaScores, Annotation } from '@/app/korrektur/types' import { DEFAULT_CRITERIA, ANNOTATION_COLORS, calculateGrade, getGradeLabel } from '@/app/korrektur/types' interface CriteriaPanelProps { scores: CriteriaScores annotations: Annotation[] onScoreChange: (criterion: string, value: number) => void onLoadEHSuggestions?: (criterion: string) => void isLoading?: boolean className?: string } export function CriteriaPanel({ scores, annotations, onScoreChange, onLoadEHSuggestions, isLoading = false, className = '', }: CriteriaPanelProps) { // Count annotations per criterion const annotationCounts = useMemo(() => { const counts: Record = {} for (const annotation of annotations) { const type = annotation.linked_criterion || annotation.type counts[type] = (counts[type] || 0) + 1 } return counts }, [annotations]) // Calculate total grade const { totalWeightedScore, totalWeight, gradePoints, gradeLabel } = useMemo(() => { let weightedScore = 0 let weight = 0 for (const [criterion, config] of Object.entries(DEFAULT_CRITERIA)) { const score = scores[criterion] if (score !== undefined) { weightedScore += score * config.weight weight += config.weight } } const percentage = weight > 0 ? weightedScore / weight : 0 const grade = calculateGrade(percentage) const label = getGradeLabel(grade) return { totalWeightedScore: weightedScore, totalWeight: weight, gradePoints: grade, gradeLabel: label, } }, [scores]) return (
{/* Criteria List */} {Object.entries(DEFAULT_CRITERIA).map(([criterion, config]) => { const score = scores[criterion] || 0 const annotationCount = annotationCounts[criterion] || 0 const color = ANNOTATION_COLORS[criterion as keyof typeof ANNOTATION_COLORS] || '#6b7280' return ( onScoreChange(criterion, value)} onLoadSuggestions={ onLoadEHSuggestions ? () => onLoadEHSuggestions(criterion) : undefined } /> ) })} {/* Total Score */}
Gesamtnote {gradePoints} Punkte
{Math.round(totalWeightedScore / totalWeight)}% gewichtet ({gradeLabel})
) } // ============================================================================= // CRITERION CARD // ============================================================================= interface CriterionCardProps { id: string name: string weight: number score: number annotationCount: number color: string onScoreChange: (value: number) => void onLoadSuggestions?: () => void } function CriterionCard({ id, name, weight, score, annotationCount, color, onScoreChange, onLoadSuggestions, }: CriterionCardProps) { const gradePoints = calculateGrade(score) const gradeLabel = getGradeLabel(gradePoints) return (
{/* Header */}
{name} ({weight}%)
{gradePoints} P ({gradeLabel})
{/* Slider */}
onScoreChange(Number(e.target.value))} className="w-full h-2 bg-white/10 rounded-full appearance-none cursor-pointer" style={{ background: `linear-gradient(to right, ${color} ${score}%, rgba(255,255,255,0.1) ${score}%)`, }} />
0 25 50 75 100
{/* Footer */}
{annotationCount > 0 && ( {annotationCount} Anmerkung{annotationCount !== 1 ? 'en' : ''} )}
{onLoadSuggestions && (id === 'inhalt' || id === 'struktur') && ( )}
) } // ============================================================================= // COMPACT CRITERIA SUMMARY // ============================================================================= interface CriteriaSummaryProps { scores: CriteriaScores className?: string } export function CriteriaSummary({ scores, className = '' }: CriteriaSummaryProps) { const { gradePoints, gradeLabel } = useMemo(() => { let weightedScore = 0 let weight = 0 for (const [criterion, config] of Object.entries(DEFAULT_CRITERIA)) { const score = scores[criterion] if (score !== undefined) { weightedScore += score * config.weight weight += config.weight } } const percentage = weight > 0 ? weightedScore / weight : 0 const grade = calculateGrade(percentage) const label = getGradeLabel(grade) return { gradePoints: grade, gradeLabel: label } }, [scores]) return (
{Object.entries(DEFAULT_CRITERIA).map(([criterion, config]) => { const score = scores[criterion] || 0 const color = ANNOTATION_COLORS[criterion as keyof typeof ANNOTATION_COLORS] || '#6b7280' return (
{score}
) })}
{gradePoints} ({gradeLabel})
) }