| import React from 'react'; |
|
|
| export default function ScoreDial({ score, subScores }) { |
| |
| const getScoreColorClass = (val) => { |
| if (val >= 80) return 'text-emerald-400'; |
| if (val >= 60) return 'text-amber-400'; |
| return 'text-rose-500'; |
| }; |
|
|
| const getScoreColorHex = (val) => { |
| if (val >= 80) return '#50c878'; |
| if (val >= 60) return '#d4af37'; |
| return '#e53e3e'; |
| }; |
|
|
| const getScoreLabel = (val) => { |
| if (val >= 85) return 'Auspicious (Imperial)'; |
| if (val >= 70) return 'Harmonious (Sheng Qi)'; |
| if (val >= 50) return 'Moderately Balanced'; |
| return 'Inauspicious (Sha Qi)'; |
| }; |
|
|
| |
| const size = 180; |
| const strokeWidth = 12; |
| const center = size / 2; |
| const radius = center - strokeWidth; |
| const circumference = 2 * Math.PI * radius; |
| const offset = circumference - (score / 100) * circumference; |
|
|
| return ( |
| <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '20px' }}> |
| <div style={{ position: 'relative', width: size, height: size }}> |
| {/* Radial SVG Gauge */} |
| <svg width={size} height={size} style={{ transform: 'rotate(-90deg)' }}> |
| {/* Background circle */} |
| <circle |
| cx={center} |
| cy={center} |
| r={radius} |
| fill="transparent" |
| stroke="rgba(255, 255, 255, 0.05)" |
| strokeWidth={strokeWidth} |
| /> |
| {/* Active progress circle */} |
| <circle |
| cx={center} |
| cy={center} |
| r={radius} |
| fill="transparent" |
| stroke={getScoreColorHex(score)} |
| strokeWidth={strokeWidth} |
| strokeDasharray={circumference} |
| strokeDashoffset={offset} |
| strokeLinecap="round" |
| style={{ transition: 'stroke-dashoffset 1s ease-in-out' }} |
| /> |
| </svg> |
| |
| {/* Core details inside the dial */} |
| <div style={{ |
| position: 'absolute', |
| top: 0, |
| left: 0, |
| width: '100%', |
| height: '100%', |
| display: 'flex', |
| flexDirection: 'column', |
| alignItems: 'center', |
| justifyContent: 'center' |
| }}> |
| <span style={{ fontSize: '12px', textTransform: 'uppercase', color: 'var(--text-secondary)', letterSpacing: '0.1em' }}> |
| Feng Shui Score |
| </span> |
| <span style={{ |
| fontSize: '44px', |
| fontFamily: 'var(--font-serif)', |
| fontWeight: 'bold', |
| color: getScoreColorHex(score), |
| lineHeight: 1 |
| }}> |
| {score} |
| </span> |
| <span style={{ fontSize: '11px', color: 'var(--text-muted)', marginTop: '4px' }}> |
| out of 100 |
| </span> |
| </div> |
| </div> |
| |
| <div style={{ |
| textAlign: 'center', |
| padding: '6px 16px', |
| borderRadius: '20px', |
| backgroundColor: 'rgba(255,255,255,0.03)', |
| border: '1px solid rgba(255,255,255,0.05)', |
| fontSize: '14px', |
| fontWeight: '500', |
| color: getScoreColorHex(score) |
| }}> |
| {getScoreLabel(score)} |
| </div> |
| |
| {/* Grid of Sub-Scores */} |
| <div style={{ |
| display: 'grid', |
| gridTemplateColumns: 'repeat(2, 1fr)', |
| gap: '12px', |
| width: '100%', |
| marginTop: '10px' |
| }}> |
| {[ |
| { key: 'terrain', label: '⛰️ Terrain', value: subScores.terrain }, |
| { key: 'vitality', label: '🌱 Vitality', value: subScores.vitality }, |
| { key: 'water', label: '💧 Water', value: subScores.water }, |
| { key: 'sha_qi', label: '⚡ Sha Qi', value: subScores.sha_qi } |
| ].map((sub) => ( |
| <div key={sub.key} style={{ |
| padding: '10px', |
| borderRadius: '8px', |
| background: 'rgba(255,255,255,0.02)', |
| border: '1px solid rgba(255,255,255,0.04)', |
| display: 'flex', |
| flexDirection: 'column', |
| gap: '6px' |
| }}> |
| <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: '12px' }}> |
| <span style={{ color: 'var(--text-secondary)' }}>{sub.label}</span> |
| <span style={{ fontWeight: 'bold', color: getScoreColorHex(sub.value) }}>{Math.round(sub.value)}</span> |
| </div> |
| {/* Progress bar */} |
| <div style={{ height: '4px', background: 'rgba(255,255,255,0.05)', borderRadius: '2px', overflow: 'hidden' }}> |
| <div style={{ |
| height: '100%', |
| width: `${sub.value}%`, |
| background: getScoreColorHex(sub.value), |
| borderRadius: '2px', |
| transition: 'width 1s ease-in-out' |
| }} /> |
| </div> |
| </div> |
| ))} |
| </div> |
| </div> |
| ); |
| } |
|
|