feat(pedigree): update PedigreeView stats bar + tip box to use theme vars
This commit is contained in:
@@ -22,19 +22,15 @@ function PedigreeView() {
|
||||
const fetchPedigreeData = async () => {
|
||||
setLoading(true)
|
||||
setError('')
|
||||
|
||||
|
||||
try {
|
||||
// Fetch pedigree tree data
|
||||
const pedigreeRes = await axios.get(`/api/pedigree/${id}`)
|
||||
const dogData = pedigreeRes.data
|
||||
|
||||
setDog(dogData)
|
||||
|
||||
// Transform data for react-d3-tree
|
||||
|
||||
const treeData = transformPedigreeData(dogData, generations)
|
||||
setPedigreeData(treeData)
|
||||
|
||||
// Fetch COI calculation
|
||||
|
||||
try {
|
||||
const coiRes = await axios.get(`/api/pedigree/${id}/coi`)
|
||||
setCoiData(coiRes.data)
|
||||
@@ -42,7 +38,7 @@ function PedigreeView() {
|
||||
console.warn('COI calculation unavailable:', coiError)
|
||||
setCoiData(null)
|
||||
}
|
||||
|
||||
|
||||
setLoading(false)
|
||||
} catch (err) {
|
||||
console.error('Error fetching pedigree:', err)
|
||||
@@ -72,8 +68,8 @@ function PedigreeView() {
|
||||
<AlertCircle size={64} style={{ color: 'var(--danger)', margin: '0 auto 1rem' }} />
|
||||
<h2>Error Loading Pedigree</h2>
|
||||
<p style={{ color: 'var(--text-secondary)', marginTop: '0.5rem' }}>{error}</p>
|
||||
<button
|
||||
className="btn btn-primary"
|
||||
<button
|
||||
className="btn btn-primary"
|
||||
onClick={() => navigate('/dogs')}
|
||||
style={{ marginTop: '1.5rem' }}
|
||||
>
|
||||
@@ -84,11 +80,14 @@ function PedigreeView() {
|
||||
)
|
||||
}
|
||||
|
||||
// Completeness bar colour — uses theme tokens
|
||||
const barColor = completeness === 100 ? 'var(--success)' : 'var(--primary)'
|
||||
|
||||
return (
|
||||
<div className="container">
|
||||
{/* Header */}
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '1rem', marginBottom: '1.5rem' }}>
|
||||
<button
|
||||
<button
|
||||
className="btn btn-secondary"
|
||||
onClick={() => navigate(`/dogs/${id}`)}
|
||||
style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}
|
||||
@@ -96,10 +95,10 @@ function PedigreeView() {
|
||||
<ArrowLeft size={20} />
|
||||
Back to Profile
|
||||
</button>
|
||||
|
||||
|
||||
<div style={{ flex: 1 }}>
|
||||
<h1 style={{ margin: 0, display: 'flex', alignItems: 'center', gap: '0.75rem' }}>
|
||||
<GitBranch size={32} />
|
||||
<GitBranch size={32} style={{ color: 'var(--primary)' }} />
|
||||
{dog?.name}'s Pedigree
|
||||
</h1>
|
||||
{dog?.registration_number && (
|
||||
@@ -113,17 +112,19 @@ function PedigreeView() {
|
||||
{/* Stats Bar */}
|
||||
<div className="card" style={{ marginBottom: '1rem', padding: '1rem' }}>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: '1.5rem' }}>
|
||||
|
||||
{/* COI */}
|
||||
<div>
|
||||
<div style={{ fontSize: '0.875rem', color: 'var(--text-secondary)', marginBottom: '0.25rem' }}>
|
||||
<div style={{ fontSize: '0.875rem', color: 'var(--text-muted)', marginBottom: '0.25rem', textTransform: 'uppercase', letterSpacing: '0.05em', fontWeight: 500 }}>
|
||||
Coefficient of Inbreeding
|
||||
</div>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
|
||||
<span style={{ fontSize: '1.5rem', fontWeight: '700', color: coiInfo.color }}>
|
||||
{coiInfo.value}
|
||||
</span>
|
||||
<span style={{
|
||||
fontSize: '0.75rem',
|
||||
padding: '0.25rem 0.5rem',
|
||||
<span style={{
|
||||
fontSize: '0.75rem',
|
||||
padding: '0.25rem 0.5rem',
|
||||
borderRadius: '4px',
|
||||
background: coiInfo.color + '20',
|
||||
color: coiInfo.color,
|
||||
@@ -133,41 +134,46 @@ function PedigreeView() {
|
||||
{coiInfo.level}
|
||||
</span>
|
||||
</div>
|
||||
<div style={{ fontSize: '0.75rem', color: 'var(--text-secondary)', marginTop: '0.25rem' }}>
|
||||
<div style={{ fontSize: '0.75rem', color: 'var(--text-muted)', marginTop: '0.25rem' }}>
|
||||
{coiInfo.description}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Completeness */}
|
||||
<div>
|
||||
<div style={{ fontSize: '0.875rem', color: 'var(--text-secondary)', marginBottom: '0.25rem' }}>
|
||||
<div style={{ fontSize: '0.875rem', color: 'var(--text-muted)', marginBottom: '0.25rem', textTransform: 'uppercase', letterSpacing: '0.05em', fontWeight: 500 }}>
|
||||
Pedigree Completeness
|
||||
</div>
|
||||
<div style={{ fontSize: '1.5rem', fontWeight: '700' }}>
|
||||
<div style={{ fontSize: '1.5rem', fontWeight: '700', color: 'var(--text-primary)' }}>
|
||||
{completeness}%
|
||||
</div>
|
||||
<div style={{ marginTop: '0.5rem' }}>
|
||||
<div style={{
|
||||
height: '8px',
|
||||
background: '#e5e7eb',
|
||||
borderRadius: '4px',
|
||||
overflow: 'hidden'
|
||||
<div style={{
|
||||
height: '6px',
|
||||
background: 'var(--bg-tertiary)',
|
||||
borderRadius: '3px',
|
||||
overflow: 'hidden',
|
||||
border: '1px solid var(--border)'
|
||||
}}>
|
||||
<div style={{
|
||||
height: '100%',
|
||||
<div style={{
|
||||
height: '100%',
|
||||
width: `${completeness}%`,
|
||||
background: completeness === 100 ? '#10b981' : '#3b82f6',
|
||||
transition: 'width 0.3s ease'
|
||||
background: barColor,
|
||||
borderRadius: '3px',
|
||||
transition: 'width 0.4s ease',
|
||||
boxShadow: `0 0 6px ${barColor}`
|
||||
}} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Generations */}
|
||||
<div>
|
||||
<div style={{ fontSize: '0.875rem', color: 'var(--text-secondary)', marginBottom: '0.25rem' }}>
|
||||
<div style={{ fontSize: '0.875rem', color: 'var(--text-muted)', marginBottom: '0.25rem', textTransform: 'uppercase', letterSpacing: '0.05em', fontWeight: 500 }}>
|
||||
Generations Displayed
|
||||
</div>
|
||||
<select
|
||||
className="input"
|
||||
<select
|
||||
className="input"
|
||||
value={generations}
|
||||
onChange={(e) => setGenerations(Number(e.target.value))}
|
||||
style={{ marginTop: '0.25rem' }}
|
||||
@@ -183,14 +189,14 @@ function PedigreeView() {
|
||||
{/* Pedigree Tree */}
|
||||
<div className="card" style={{ padding: 0 }}>
|
||||
{pedigreeData ? (
|
||||
<PedigreeTree
|
||||
<PedigreeTree
|
||||
dogId={id}
|
||||
pedigreeData={pedigreeData}
|
||||
coi={coiData?.coi}
|
||||
/>
|
||||
) : (
|
||||
<div style={{ textAlign: 'center', padding: '4rem' }}>
|
||||
<GitBranch size={64} style={{ color: 'var(--text-secondary)', margin: '0 auto 1rem' }} />
|
||||
<GitBranch size={64} style={{ color: 'var(--text-muted)', margin: '0 auto 1rem' }} />
|
||||
<h3>No Pedigree Data Available</h3>
|
||||
<p style={{ color: 'var(--text-secondary)' }}>
|
||||
Add parent information to this dog to build the pedigree tree.
|
||||
@@ -199,15 +205,23 @@ function PedigreeView() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Help Text */}
|
||||
<div className="card" style={{ marginTop: '1rem', background: '#eff6ff', border: '1px solid #bfdbfe' }}>
|
||||
<div style={{ fontSize: '0.875rem', color: '#1e40af' }}>
|
||||
<strong>💡 Tip:</strong> Click on any ancestor node to navigate to their profile.
|
||||
Use the zoom controls to explore the tree, or drag to pan around.
|
||||
{/* Tip */}
|
||||
<div className="card" style={{
|
||||
marginTop: '1rem',
|
||||
background: 'var(--bg-elevated)',
|
||||
border: '1px solid var(--border-light)'
|
||||
}}>
|
||||
<div style={{ fontSize: '0.875rem', color: 'var(--text-secondary)', display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
|
||||
<span style={{ color: 'var(--primary)' }}>💡</span>
|
||||
<span>
|
||||
<strong style={{ color: 'var(--text-primary)' }}>Tip:</strong>{' '}
|
||||
Click any ancestor node to navigate to their profile.
|
||||
Use the zoom controls or scroll to explore the tree, and drag to pan.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default PedigreeView
|
||||
export default PedigreeView
|
||||
|
||||
Reference in New Issue
Block a user