diff --git a/client/src/pages/DogDetail.jsx b/client/src/pages/DogDetail.jsx
index 9688c63..7c1f91c 100644
--- a/client/src/pages/DogDetail.jsx
+++ b/client/src/pages/DogDetail.jsx
@@ -1,15 +1,17 @@
import { useEffect, useState, useRef } from 'react'
-import { useParams, Link } from 'react-router-dom'
-import { Dog, GitBranch, Edit, Upload, Trash2 } from 'lucide-react'
+import { useParams, Link, useNavigate } from 'react-router-dom'
+import { Dog, GitBranch, Edit, Upload, Trash2, ArrowLeft, Calendar, Hash, Award } from 'lucide-react'
import axios from 'axios'
import DogForm from '../components/DogForm'
function DogDetail() {
const { id } = useParams()
+ const navigate = useNavigate()
const [dog, setDog] = useState(null)
const [loading, setLoading] = useState(true)
const [showEditModal, setShowEditModal] = useState(false)
const [uploading, setUploading] = useState(false)
+ const [selectedPhoto, setSelectedPhoto] = useState(0)
const fileInputRef = useRef(null)
useEffect(() => {
@@ -55,12 +57,32 @@ function DogDetail() {
try {
await axios.delete(`/api/dogs/${id}/photos/${photoIndex}`)
fetchDog()
+ if (selectedPhoto >= photoIndex && selectedPhoto > 0) {
+ setSelectedPhoto(selectedPhoto - 1)
+ }
} catch (error) {
console.error('Error deleting photo:', error)
alert('Failed to delete photo')
}
}
+ const calculateAge = (birthDate) => {
+ if (!birthDate) return null
+ const today = new Date()
+ const birth = new Date(birthDate)
+ 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' : ''}`
+ if (months === 0) return `${years} year${years !== 1 ? 's' : ''}`
+ return `${years}y ${months}m`
+ }
+
if (loading) {
return
Loading...
}
@@ -70,64 +92,51 @@ function DogDetail() {
}
return (
-
-
-
{dog.name}
-
-
-
- View Pedigree
+
+ {/* Header */}
+
+
+
+
{dog.name}
+
+ {dog.breed}
+ •
+ {dog.sex === 'male' ? 'Male ♂' : 'Female ♀'}
+ {dog.birth_date && (
+ <>
+ •
+ {calculateAge(dog.birth_date)}
+ >
+ )}
+
+
+
+
+
+ Pedigree
-
-
-
-
Basic Information
-
-
- Breed: {dog.breed}
-
-
- Sex: {dog.sex === 'male' ? 'Male ♂' : 'Female ♀'}
-
- {dog.birth_date && (
-
- Birth Date: {new Date(dog.birth_date).toLocaleDateString()}
-
- )}
- {dog.color && (
-
- Color: {dog.color}
-
- )}
- {dog.registration_number && (
-
- Registration: {dog.registration_number}
-
- )}
- {dog.microchip && (
-
- Microchip: {dog.microchip}
-
- )}
-
-
-
-
-
-
Photos
+
+ {/* Photo Section - Compact */}
+
+
+
Photos
fileInputRef.current?.click()}
disabled={uploading}
+ style={{ padding: '0.375rem 0.75rem', fontSize: '0.75rem' }}
>
-
- {uploading ? 'Uploading...' : 'Upload'}
+
+ {uploading ? 'Uploading...' : 'Add'}
+
{dog.photo_urls && dog.photo_urls.length > 0 ? (
-
- {dog.photo_urls.map((url, index) => (
-
-

-
handleDeletePhoto(index)}
- style={{
- position: 'absolute',
- top: '0.25rem',
- right: '0.25rem',
- background: 'rgba(255,255,255,0.9)'
- }}
- >
-
-
+ <>
+ {/* Main Photo */}
+
+

+
handleDeletePhoto(selectedPhoto)}
+ style={{
+ position: 'absolute',
+ top: '0.5rem',
+ right: '0.5rem',
+ background: 'rgba(15, 23, 42, 0.8)',
+ backdropFilter: 'blur(8px)'
+ }}
+ >
+
+
+
+
+ {/* Thumbnail Strip */}
+ {dog.photo_urls.length > 1 && (
+
+ {dog.photo_urls.map((url, index) => (
+

setSelectedPhoto(index)}
+ style={{
+ width: '60px',
+ height: '60px',
+ objectFit: 'cover',
+ 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'
+ }}
+ />
+ ))}
- ))}
-
+ )}
+ >
) : (
-
-
-
No photos uploaded
+
)}
+
+ {/* Info Section */}
+
+
+
Details
+
+
+
+ Breed
+ {dog.breed}
+
+
+
+ Sex
+ {dog.sex === 'male' ? 'Male ♂' : 'Female ♀'}
+
+
+ {dog.birth_date && (
+
+ Birth Date
+
+ {new Date(dog.birth_date).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })}
+ ({calculateAge(dog.birth_date)})
+
+
+ )}
+
+ {dog.color && (
+
+ Color
+ {dog.color}
+
+ )}
+
+ {dog.registration_number && (
+
+
Registration
+
{dog.registration_number}
+
+ )}
+
+ {dog.microchip && (
+
+ Microchip
+ {dog.microchip}
+
+ )}
+
+
+
+ {/* Parents */}
+
+
Pedigree
+
+
+
Sire
+ {dog.sire ? (
+
+ {dog.sire.name}
+
+ ) : (
+
Unknown
+ )}
+
+
+
Dam
+ {dog.dam ? (
+
+ {dog.dam.name}
+
+ ) : (
+
Unknown
+ )}
+
+
+
+
+ {/* Notes */}
{dog.notes && (
-
-
Notes
-
{dog.notes}
+
)}
-
-
Parents
-
-
-
Sire (Father)
- {dog.sire ? (
-
{dog.sire.name}
- ) : (
-
Unknown
- )}
-
-
-
Dam (Mother)
- {dog.dam ? (
-
{dog.dam.name}
- ) : (
-
Unknown
- )}
-
-
-
-
+ {/* Offspring */}
{dog.offspring && dog.offspring.length > 0 && (
-
-
Offspring ({dog.offspring.length})
-
+
+
Offspring ({dog.offspring.length})
+
{dog.offspring.map(child => (
-
- {child.name} - {child.sex === 'male' ? '♂' : '♀'}
+ {
+ e.currentTarget.style.borderColor = 'var(--primary)'
+ e.currentTarget.style.background = 'var(--bg-tertiary)'
+ }}
+ onMouseLeave={(e) => {
+ e.currentTarget.style.borderColor = 'var(--border)'
+ e.currentTarget.style.background = 'var(--bg-primary)'
+ }}
+ >
+ {child.name}
+ {child.sex === 'male' ? '♂' : '♀'}
))}