FengShui / frontend /src /components /AnalysisPanel.jsx
Jaosub
Deploy to HF Space
5434776
Raw
History Blame Contribute Delete
11.4 kB
import React, { useState } from 'react';
import { ChevronDown, ChevronUp, ShieldAlert, Sparkles, HelpCircle, Lightbulb } from 'lucide-react';
export default function AnalysisPanel({ report, metrics }) {
const [openSection, setOpenSection] = useState('creatures');
const getStatusColor = (status) => {
switch (status?.toLowerCase()) {
case 'auspicious':
case 'high vitality':
case 'safe':
return '#50c878'; // Jade Green
case 'balanced':
case 'neutral':
case 'moderate':
return '#d4af37'; // Gold
case 'inauspicious':
case 'stagnant':
case 'hazardous':
default:
return '#e53e3e'; // Rose Red
}
};
const toggleSection = (section) => {
setOpenSection(openSection === section ? null : section);
};
const sections = [
{
id: 'creatures',
title: '⛰️ Four Celestial Creatures',
subtitle: 'Terrain configurations, protection, and viewsheds',
data: report.creatures,
metricsContent: [
{ label: 'Aspect (Facing Direction)', value: `${metrics.aspect_deg}°` },
{ label: 'Slope Gradient', value: `${metrics.slope_deg}°` },
{ label: 'Backing Ridge Height', value: metrics.relative_backing_elevation_m > 0 ? `+${metrics.relative_backing_elevation_m}m` : 'None' },
{ label: 'Front Openness (Bright Hall)', value: `${metrics.front_openness_deg}°` }
]
},
{
id: 'vitality',
title: '🌱 Qi Flow & Microclimate',
subtitle: 'Photosynthetic vitality and thermal balance',
data: report.vitality,
metricsContent: [
{ label: 'Vegetation Index (NDVI)', value: metrics.ndvi },
{ label: 'Thermal Deviation (LST)', value: `${metrics.lst_deviation_c > 0 ? '+' : ''}${metrics.lst_deviation_c}°C` }
]
},
{
id: 'water',
title: '💧 Water Feng Shui',
subtitle: 'Sinuosity, hydrology, and curvature safety',
data: report.water,
metricsContent: [
{ label: 'Water Distance', value: metrics.water_distance_m < 9000 ? `${metrics.water_distance_m}m` : 'None nearby' },
{ label: 'Hydrologic Bend Type', value: metrics.water_curve_type === 'concave_embrace' ? 'Embracing (Concave)' : (metrics.water_curve_type === 'convex_bow' ? 'Bow (Convex)' : 'None/Linear') }
]
},
{
id: 'sha_qi',
title: '⚡ Sha Qi & Urban Hazards',
subtitle: 'Road clashing, corner knives, and electromagnetic fields',
data: report.sha_qi,
metricsContent: [
{ label: 'T-Junction Road Clashes', value: metrics.sha_qi_t_junctions },
{ label: 'Adjacent Corner Knives', value: metrics.sha_qi_building_corners },
{ label: 'EMF Proximity Distance', value: `${metrics.emf_distance_m}m` }
]
}
];
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px', width: '100%' }}>
{sections.map((sec) => {
const isOpen = openSection === sec.id;
const statusColor = getStatusColor(sec.data.status);
return (
<div key={sec.id} className="glass-panel" style={{
overflow: 'hidden',
borderLeft: `4px solid ${statusColor}`
}}>
{/* Header Accordion Bar */}
<div
onClick={() => toggleSection(sec.id)}
style={{
padding: '16px',
cursor: 'pointer',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
userSelect: 'none',
background: isOpen ? 'rgba(255,255,255,0.02)' : 'transparent',
transition: 'background 0.2s ease'
}}
>
<div>
<h3 style={{ fontSize: '16px', display: 'flex', alignItems: 'center', gap: '8px' }}>
{sec.title}
<span style={{
fontSize: '10px',
fontWeight: 'bold',
textTransform: 'uppercase',
color: '#fff',
backgroundColor: statusColor,
padding: '2px 8px',
borderRadius: '10px',
letterSpacing: '0.05em'
}}>
{sec.data.status}
</span>
</h3>
<p style={{ fontSize: '12px', color: 'var(--text-secondary)', marginTop: '2px' }}>
{sec.subtitle}
</p>
</div>
<div>
{isOpen ? <ChevronUp size={18} color="var(--text-secondary)" /> : <ChevronDown size={18} color="var(--text-secondary)" />}
</div>
</div>
{/* Content Body */}
{isOpen && (
<div style={{
padding: '16px',
borderTop: '1px solid var(--border-glass)',
display: 'flex',
flexDirection: 'column',
gap: '16px',
background: 'rgba(0,0,0,0.1)'
}}>
{/* Micro Metrics Grid */}
<div style={{
display: 'grid',
gridTemplateColumns: 'repeat(2, 1fr)',
gap: '10px',
background: 'rgba(255,255,255,0.01)',
padding: '10px',
borderRadius: '6px',
border: '1px solid rgba(255,255,255,0.02)'
}}>
{sec.metricsContent.map((metric, idx) => (
<div key={idx} style={{ display: 'flex', flexDirection: 'column' }}>
<span style={{ fontSize: '10px', color: 'var(--text-muted)', textTransform: 'uppercase' }}>
{metric.label}
</span>
<span style={{ fontSize: '13px', fontWeight: '600', color: 'var(--text-primary)', marginTop: '2px' }}>
{metric.value}
</span>
</div>
))}
</div>
{/* Explanations Accordion Cards */}
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
{/* Feng Shui explanation */}
<div style={{
padding: '12px',
borderRadius: '8px',
background: 'linear-gradient(135deg, rgba(34,139,34,0.04) 0%, rgba(0,0,0,0) 100%)',
border: '1px solid rgba(80,200,120,0.08)'
}}>
<h4 style={{
fontSize: '13px',
color: 'var(--color-jade-light)',
display: 'flex',
alignItems: 'center',
gap: '6px',
marginBottom: '6px'
}}>
<Sparkles size={14} /> Traditional Feng Shui
</h4>
<p style={{ fontSize: '12.5px', lineHeight: '1.5', color: '#e2e8f0', fontStyle: 'italic' }}>
"{sec.data.feng_shui_exp}"
</p>
</div>
{/* Scientific explanation */}
<div style={{
padding: '12px',
borderRadius: '8px',
background: 'linear-gradient(135deg, rgba(212,175,55,0.04) 0%, rgba(0,0,0,0) 100%)',
border: '1px solid rgba(212,175,55,0.1)'
}}>
<h4 style={{
fontSize: '13px',
color: 'var(--color-gold)',
display: 'flex',
alignItems: 'center',
gap: '6px',
marginBottom: '6px'
}}>
<HelpCircle size={14} /> Environmental Science
</h4>
<p style={{ fontSize: '12.5px', lineHeight: '1.5', color: '#cbd5e0' }}>
{sec.data.scientific_exp}
</p>
</div>
</div>
{/* Remedies Section */}
{sec.data.remedies && sec.data.remedies.length > 0 && (
<div style={{ marginTop: '4px' }}>
<h4 style={{
fontSize: '13px',
color: 'var(--text-primary)',
display: 'flex',
alignItems: 'center',
gap: '6px',
marginBottom: '10px',
fontWeight: 'bold',
fontFamily: 'var(--font-sans)',
textTransform: 'uppercase',
letterSpacing: '0.05em'
}}>
<Lightbulb size={14} color="var(--color-gold)" /> Actionable Remedies & Mitigations
</h4>
<div style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}>
{sec.data.remedies.map((rem, idx) => (
<div key={idx} style={{
background: 'rgba(255, 255, 255, 0.02)',
border: '1px solid var(--border-glass)',
borderRadius: '8px',
overflow: 'hidden'
}}>
<div style={{
padding: '8px 12px',
background: 'rgba(255,255,255,0.03)',
fontSize: '12px',
fontWeight: '600',
borderBottom: '1px solid var(--border-glass)',
color: 'var(--color-gold)'
}}>
{rem.title}
</div>
<div style={{
display: 'grid',
gridTemplateColumns: '1fr 1fr',
fontSize: '11.5px',
lineHeight: '1.4'
}}>
<div style={{
padding: '10px',
borderRight: '1px solid var(--border-glass)',
background: 'rgba(34,139,34,0.01)'
}}>
<div style={{ color: 'var(--color-jade-light)', fontWeight: 'bold', marginBottom: '2px' }}>Feng Shui Master</div>
<div style={{ color: '#e2e8f0' }}>{rem.feng_shui}</div>
</div>
<div style={{
padding: '10px',
background: 'rgba(212,175,55,0.01)'
}}>
<div style={{ color: 'var(--color-gold)', fontWeight: 'bold', marginBottom: '2px' }}>GIS Engineer</div>
<div style={{ color: '#cbd5e0' }}>{rem.scientific}</div>
</div>
</div>
</div>
))}
</div>
</div>
)}
</div>
)}
</div>
);
})}
</div>
);
}