Roadmap 2,3,4
This commit is contained in:
@@ -6,6 +6,8 @@ import DogForm from '../components/DogForm'
|
||||
import { ChampionBadge, ChampionBloodlineBadge } from '../components/ChampionBadge'
|
||||
import ClearanceSummaryCard from '../components/ClearanceSummaryCard'
|
||||
import HealthRecordForm from '../components/HealthRecordForm'
|
||||
import GeneticPanelCard from '../components/GeneticPanelCard'
|
||||
import { ShieldCheck } from 'lucide-react'
|
||||
|
||||
function DogDetail() {
|
||||
const { id } = useParams()
|
||||
@@ -262,6 +264,18 @@ function DogDetail() {
|
||||
<span className="info-value" style={{ fontFamily: 'monospace' }}>{dog.registration_number}</span>
|
||||
</div>
|
||||
)}
|
||||
{dog.chic_number && (
|
||||
<div className="info-row">
|
||||
<span className="info-label"><ShieldCheck size={14} style={{ display: 'inline', marginRight: '0.25rem' }} />CHIC Status</span>
|
||||
<span className="info-value">
|
||||
<span style={{
|
||||
fontSize: '0.75rem', fontWeight: 600, padding: '0.2rem 0.6rem',
|
||||
background: 'rgba(99,102,241,0.15)', color: '#818cf8',
|
||||
borderRadius: '999px', border: '1px solid rgba(99,102,241,0.3)'
|
||||
}}>CHIC #{dog.chic_number}</span>
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{dog.microchip && (
|
||||
<div className="info-row">
|
||||
<span className="info-label"><Hash size={14} style={{ display: 'inline', marginRight: '0.25rem' }} />Microchip</span>
|
||||
@@ -317,6 +331,9 @@ function DogDetail() {
|
||||
{/* OFA Clearance Summary */}
|
||||
<ClearanceSummaryCard dogId={id} onAddRecord={openAddHealth} />
|
||||
|
||||
{/* DNA Genetics Panel */}
|
||||
<GeneticPanelCard dogId={id} />
|
||||
|
||||
{/* Health Records List */}
|
||||
{healthRecords.length > 0 && (
|
||||
<div className="card" style={{ marginBottom: '1.5rem' }}>
|
||||
|
||||
@@ -259,6 +259,19 @@ function DogList() {
|
||||
{dog.registration_number}
|
||||
</div>
|
||||
)}
|
||||
{dog.chic_number && (
|
||||
<div style={{
|
||||
display: 'inline-flex', alignItems: 'center', gap: '0.25rem',
|
||||
padding: '0.25rem 0.5rem',
|
||||
background: 'rgba(99,102,241,0.1)',
|
||||
border: '1px solid rgba(99,102,241,0.3)',
|
||||
borderRadius: 'var(--radius-sm)',
|
||||
fontSize: '0.75rem', fontWeight: 600,
|
||||
color: '#818cf8', marginLeft: '0.5rem'
|
||||
}}>
|
||||
CHIC #{dog.chic_number}
|
||||
</div>
|
||||
)}
|
||||
</Link>
|
||||
|
||||
{/* Actions */}
|
||||
|
||||
@@ -11,6 +11,8 @@ export default function PairingSimulator() {
|
||||
const [dogsLoading, setDogsLoading] = useState(true)
|
||||
const [relationWarning, setRelationWarning] = useState(null)
|
||||
const [relationChecking, setRelationChecking] = useState(false)
|
||||
const [geneticRisk, setGeneticRisk] = useState(null)
|
||||
const [geneticChecking, setGeneticChecking] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
// include_external=1 ensures external sires/dams appear for pairing
|
||||
@@ -27,17 +29,28 @@ export default function PairingSimulator() {
|
||||
const checkRelation = useCallback(async (sid, did) => {
|
||||
if (!sid || !did) {
|
||||
setRelationWarning(null)
|
||||
setGeneticRisk(null)
|
||||
return
|
||||
}
|
||||
setRelationChecking(true)
|
||||
setGeneticChecking(true)
|
||||
try {
|
||||
const res = await fetch(`/api/pedigree/relations/${sid}/${did}`)
|
||||
const data = await res.json()
|
||||
setRelationWarning(data.related ? data.relationship : null)
|
||||
const [relRes, genRes] = await Promise.all([
|
||||
fetch(`/api/pedigree/relations/${sid}/${did}`),
|
||||
fetch(`/api/genetics/pairing-risk?sireId=${sid}&damId=${did}`)
|
||||
])
|
||||
|
||||
const relData = await relRes.json()
|
||||
setRelationWarning(relData.related ? relData.relationship : null)
|
||||
|
||||
const genData = await genRes.json()
|
||||
setGeneticRisk(genData)
|
||||
} catch {
|
||||
setRelationWarning(null)
|
||||
setGeneticRisk(null)
|
||||
} finally {
|
||||
setRelationChecking(false)
|
||||
setGeneticChecking(false)
|
||||
}
|
||||
}, [])
|
||||
|
||||
@@ -142,7 +155,7 @@ export default function PairingSimulator() {
|
||||
|
||||
{relationChecking && (
|
||||
<div style={{ fontSize: '0.85rem', color: 'var(--text-muted)', marginBottom: '0.75rem' }}>
|
||||
Checking relationship...
|
||||
Checking relationship and genetics...
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -158,6 +171,31 @@ export default function PairingSimulator() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{geneticRisk && geneticRisk.risks && geneticRisk.risks.length > 0 && !geneticChecking && (
|
||||
<div style={{
|
||||
padding: '0.6rem 1rem', marginBottom: '0.75rem',
|
||||
background: 'rgba(255,159,10,0.08)', border: '1px solid rgba(255,159,10,0.3)',
|
||||
borderRadius: 'var(--radius)', fontSize: '0.875rem', color: 'var(--warning)',
|
||||
}}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', marginBottom: '0.25rem', fontWeight: 600 }}>
|
||||
<ShieldAlert size={16} /> Genetic Risks Detected
|
||||
</div>
|
||||
<ul style={{ margin: 0, paddingLeft: '1.5rem' }}>
|
||||
{geneticRisk.risks.map(r => (
|
||||
<li key={r.marker}>
|
||||
<strong>{r.marker}</strong>: {r.message}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{geneticRisk && geneticRisk.missing_data && !geneticChecking && (
|
||||
<div style={{ fontSize: '0.8rem', color: 'var(--text-muted)', marginBottom: '0.75rem', fontStyle: 'italic' }}>
|
||||
* Sire or dam has missing genetic tests. Clearances cannot be fully verified.
|
||||
</div>
|
||||
)}
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-primary"
|
||||
|
||||
Reference in New Issue
Block a user