diff --git a/client/src/pages/DogDetail.jsx b/client/src/pages/DogDetail.jsx index 60057d5..838c0b4 100644 --- a/client/src/pages/DogDetail.jsx +++ b/client/src/pages/DogDetail.jsx @@ -4,6 +4,8 @@ import { Dog, GitBranch, Edit, Upload, Trash2, ArrowLeft, Calendar, Hash, Award import axios from 'axios' import DogForm from '../components/DogForm' import { ChampionBadge, ChampionBloodlineBadge } from '../components/ChampionBadge' +import ClearanceSummaryCard from '../components/ClearanceSummaryCard' +import HealthRecordForm from '../components/HealthRecordForm' function DogDetail() { const { id } = useParams() @@ -15,7 +17,13 @@ function DogDetail() { const [selectedPhoto, setSelectedPhoto] = useState(0) const fileInputRef = useRef(null) + // Health records state + const [healthRecords, setHealthRecords] = useState([]) + const [showHealthForm, setShowHealthForm] = useState(false) + const [editingRecord, setEditingRecord] = useState(null) + useEffect(() => { fetchDog() }, [id]) + useEffect(() => { fetchHealth() }, [id]) const fetchDog = async () => { try { @@ -28,6 +36,12 @@ function DogDetail() { } } + const fetchHealth = () => { + axios.get(`/api/health/dog/${id}`) + .then(r => setHealthRecords(r.data)) + .catch(() => {}) + } + const handlePhotoUpload = async (e) => { const file = e.target.files[0] if (!file) return @@ -66,7 +80,7 @@ function DogDetail() { if (!birthDate) return null const today = new Date() const birth = new Date(birthDate) - let years = today.getFullYear() - birth.getFullYear() + let years = today.getFullYear() - birth.getFullYear() let months = today.getMonth() - birth.getMonth() if (months < 0) { years--; months += 12 } if (years === 0) return `${months} month${months !== 1 ? 's' : ''}` @@ -77,10 +91,15 @@ function DogDetail() { const hasChampionBlood = (d) => (d.sire && d.sire.is_champion) || (d.dam && d.dam.is_champion) - if (loading) return
Loading...
- if (!dog) return
Dog not found
+ const openAddHealth = () => { setEditingRecord(null); setShowHealthForm(true) } + const openEditHealth = (rec) => { setEditingRecord(rec); setShowHealthForm(true) } + const closeHealthForm = () => { setShowHealthForm(false); setEditingRecord(null) } + const handleHealthSaved = () => { closeHealthForm(); fetchHealth() } - const isChampion = !!dog.is_champion + if (loading) return
Loading...
+ if (!dog) return
Dog not found
+ + const isChampion = !!dog.is_champion const hasBloodline = !isChampion && hasChampionBlood(dog) return ( @@ -93,13 +112,13 @@ function DogDetail() {

{dog.name}

- {isChampion && } + {isChampion && } {hasBloodline && }
{dog.breed} · - {dog.sex === 'male' ? 'Male ♂' : 'Female ♀'} + {dog.sex === 'male' ? 'Male' : 'Female'} {dog.birth_date && ( <> · @@ -180,8 +199,7 @@ function DogDetail() { onClick={() => setSelectedPhoto(index)} style={{ width: '60px', height: '60px', objectFit: 'cover', - borderRadius: 'var(--radius-sm)', - cursor: 'pointer', + borderRadius: 'var(--radius-sm)', cursor: 'pointer', border: selectedPhoto === index ? '2px solid var(--primary)' : '1px solid var(--border)', opacity: selectedPhoto === index ? 1 : 0.6, transition: 'all 0.2s' @@ -210,7 +228,7 @@ function DogDetail() {
Sex - {dog.sex === 'male' ? 'Male ♂' : 'Female ♀'} + {dog.sex === 'male' ? 'Male' : 'Female'}
Champion @@ -219,7 +237,7 @@ function DogDetail() { ? : hasBloodline ? - : + : }
@@ -296,6 +314,49 @@ function DogDetail() {
)} + {/* OFA Clearance Summary */} + + + {/* Health Records List */} + {healthRecords.length > 0 && ( +
+
+

+ Health Records ({healthRecords.length}) +

+ +
+
+ {healthRecords.map(rec => ( +
+
+ + {rec.test_name || (rec.test_type ? rec.test_type.replace(/_/g, ' ') : rec.record_type)} + + {rec.ofa_result && ( + + {rec.ofa_result}{rec.ofa_number ? ` · ${rec.ofa_number}` : ''} + + )} +
+ + {rec.test_date ? new Date(rec.test_date).toLocaleDateString() : ''} + + +
+ ))} +
+
+ )} + {/* Offspring */} {dog.offspring && dog.offspring.length > 0 && (
@@ -317,19 +378,19 @@ function DogDetail() { alignItems: 'center', gap: '0.5rem' }} - onMouseEnter={(e) => { + onMouseEnter={e => { e.currentTarget.style.borderColor = 'var(--primary)' - e.currentTarget.style.background = 'var(--bg-tertiary)' + e.currentTarget.style.background = 'var(--bg-tertiary)' }} - onMouseLeave={(e) => { + onMouseLeave={e => { e.currentTarget.style.borderColor = 'var(--border)' - e.currentTarget.style.background = 'var(--bg-primary)' + e.currentTarget.style.background = 'var(--bg-primary)' }} > {child.name}
{child.is_champion && } - {child.sex === 'male' ? '♂' : '♀'} + {child.sex === 'male' ? '' : ''}
))} @@ -337,6 +398,7 @@ function DogDetail() {
)} + {/* Edit Dog Modal */} {showEditModal && ( { fetchDog(); setShowEditModal(false) }} /> )} + + {/* Health Record Form Modal */} + {showHealthForm && ( + + )} ) }