Spaces:
Sleeping
Sleeping
| import React from 'react'; | |
| const PRIORITY_CONFIG = { | |
| 5: { color: '#ef4444', label: 'CRITICAL' }, | |
| 4: { color: '#f59e0b', label: 'HIGH' }, | |
| 3: { color: '#eab308', label: 'MEDIUM' }, | |
| 2: { color: '#22c55e', label: 'LOW' }, | |
| 1: { color: '#94a3b8', label: 'MINIMAL' }, | |
| }; | |
| function ScoreGauge({ score }) { | |
| const pct = Math.max(0, Math.min(1, score)); | |
| const color = pct >= 0.75 ? '#22c55e' : pct >= 0.5 ? '#f59e0b' : pct >= 0.25 ? '#f97316' : '#ef4444'; | |
| const size = 100; | |
| const stroke = 8; | |
| const r = (size - stroke * 2) / 2; | |
| const circ = 2 * Math.PI * r; | |
| const dash = circ * pct; | |
| return ( | |
| <div className="score-gauge"> | |
| <svg width={size} height={size} style={{ transform: 'rotate(-90deg)' }}> | |
| <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke="rgba(255,255,255,0.07)" strokeWidth={stroke} /> | |
| <circle | |
| cx={size / 2} cy={size / 2} r={r} | |
| fill="none" | |
| stroke={color} | |
| strokeWidth={stroke} | |
| strokeDasharray={`${dash} ${circ}`} | |
| strokeLinecap="round" | |
| style={{ transition: 'stroke-dasharray 0.8s ease' }} | |
| /> | |
| </svg> | |
| <div className="score-gauge-text"> | |
| <span className="score-value" style={{ color }}>{(score * 100).toFixed(0)}</span> | |
| <span className="score-pct-label">/ 100</span> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| export default function ScorePanel({ goals, score, done, totalReward, currentStep, maxSteps }) { | |
| const completedGoals = goals.filter(g => g.completed); | |
| const completionPct = goals.length > 0 ? (completedGoals.length / goals.length) * 100 : 0; | |
| return ( | |
| <div className="panel score-panel"> | |
| <div className="panel-header"> | |
| <span className="panel-title">🎯 Goals & Score</span> | |
| </div> | |
| {/* Score gauge */} | |
| <div className="score-section"> | |
| <ScoreGauge score={score} /> | |
| <div className="score-meta"> | |
| <div className="score-label-main">{done ? 'FINAL SCORE' : 'LIVE SCORE'}</div> | |
| <div className="score-completion"> | |
| {completedGoals.length}/{goals.length} goals done | |
| </div> | |
| <div className="completion-bar-wrapper"> | |
| <div className="completion-bar"> | |
| <div | |
| className="completion-bar-fill" | |
| style={{ | |
| width: `${completionPct}%`, | |
| background: completionPct >= 75 ? '#22c55e' : completionPct >= 50 ? '#f59e0b' : '#ef4444' | |
| }} | |
| /> | |
| </div> | |
| <span className="completion-pct">{completionPct.toFixed(0)}%</span> | |
| </div> | |
| </div> | |
| </div> | |
| {/* Goal checklist */} | |
| <div className="goals-list"> | |
| <div className="goals-header">OBJECTIVES</div> | |
| {goals.map(goal => { | |
| const cfg = PRIORITY_CONFIG[goal.priority] || PRIORITY_CONFIG[1]; | |
| return ( | |
| <div key={goal.id} className={`goal-item ${goal.completed ? 'goal-done' : ''}`}> | |
| <div | |
| className="goal-checkbox" | |
| style={{ | |
| borderColor: goal.completed ? cfg.color : 'rgba(148,163,184,0.3)', | |
| background: goal.completed ? cfg.color : 'transparent', | |
| }} | |
| > | |
| {goal.completed && <span className="goal-check">✓</span>} | |
| </div> | |
| <div className="goal-text"> | |
| <span className="goal-desc" style={{ color: goal.completed ? '#64748b' : '#e2e8f0' }}> | |
| {goal.description} | |
| </span> | |
| <span className="goal-priority-tag" style={{ color: cfg.color }}> | |
| P{goal.priority} • {cfg.label} | |
| </span> | |
| </div> | |
| </div> | |
| ); | |
| })} | |
| </div> | |
| {done && ( | |
| <div className="final-score-banner" style={{ | |
| background: score >= 0.7 ? 'rgba(34,197,94,0.1)' : score >= 0.4 ? 'rgba(245,158,11,0.1)' : 'rgba(239,68,68,0.1)', | |
| borderColor: score >= 0.7 ? '#22c55e' : score >= 0.4 ? '#f59e0b' : '#ef4444', | |
| }}> | |
| <div className="final-score-title"> | |
| {score >= 0.8 ? '🏆 Excellent' : score >= 0.6 ? '✅ Good' : score >= 0.4 ? '⚠️ Adequate' : '❌ Poor'} | |
| </div> | |
| <div className="final-score-num" style={{ color: score >= 0.7 ? '#22c55e' : score >= 0.4 ? '#f59e0b' : '#ef4444' }}> | |
| {score.toFixed(4)} | |
| </div> | |
| </div> | |
| )} | |
| </div> | |
| ); | |
| } | |