diff --git a/client/src/components/PedigreeView.jsx b/client/src/components/PedigreeView.jsx
new file mode 100644
index 0000000..bba0b0b
--- /dev/null
+++ b/client/src/components/PedigreeView.jsx
@@ -0,0 +1,234 @@
+import { useState, useEffect, useCallback } from 'react'
+import { X, ZoomIn, ZoomOut, Maximize2 } from 'lucide-react'
+import Tree from 'react-d3-tree'
+import axios from 'axios'
+import './PedigreeView.css'
+
+function PedigreeView({ dogId, onClose }) {
+ const [treeData, setTreeData] = useState(null)
+ const [loading, setLoading] = useState(true)
+ const [error, setError] = useState('')
+ const [translate, setTranslate] = useState({ x: 0, y: 0 })
+ const [zoom, setZoom] = useState(0.8)
+ const [dimensions, setDimensions] = useState({ width: 0, height: 0 })
+
+ useEffect(() => {
+ fetchPedigree()
+ }, [dogId])
+
+ useEffect(() => {
+ const updateDimensions = () => {
+ const container = document.querySelector('.pedigree-container')
+ if (container) {
+ const width = container.offsetWidth
+ const height = container.offsetHeight
+ setDimensions({ width, height })
+ setTranslate({ x: width / 4, y: height / 2 })
+ }
+ }
+
+ updateDimensions()
+ window.addEventListener('resize', updateDimensions)
+ return () => window.removeEventListener('resize', updateDimensions)
+ }, [])
+
+ const fetchPedigree = async () => {
+ try {
+ setLoading(true)
+ const response = await axios.get(`/api/pedigree/${dogId}?generations=5`)
+ const formatted = formatTreeData(response.data)
+ setTreeData(formatted)
+ } catch (err) {
+ setError(err.response?.data?.error || 'Failed to load pedigree')
+ } finally {
+ setLoading(false)
+ }
+ }
+
+ const formatTreeData = (dog) => {
+ if (!dog) return null
+
+ const children = []
+ if (dog.sire) children.push(formatTreeData(dog.sire))
+ if (dog.dam) children.push(formatTreeData(dog.dam))
+
+ return {
+ name: dog.name,
+ attributes: {
+ sex: dog.sex,
+ birth_date: dog.birth_date,
+ registration: dog.registration_number,
+ breed: dog.breed,
+ color: dog.color,
+ generation: dog.generation
+ },
+ children: children.length > 0 ? children : undefined
+ }
+ }
+
+ const handleNodeClick = useCallback((nodeData) => {
+ console.log('Node clicked:', nodeData)
+ }, [])
+
+ const handleZoomIn = () => {
+ setZoom(prev => Math.min(prev + 0.2, 2))
+ }
+
+ const handleZoomOut = () => {
+ setZoom(prev => Math.max(prev - 0.2, 0.4))
+ }
+
+ const handleReset = () => {
+ setZoom(0.8)
+ setTranslate({ x: dimensions.width / 4, y: dimensions.height / 2 })
+ }
+
+ const renderCustomNode = ({ nodeDatum, toggleNode }) => (
+
+ Tip: Use mouse wheel to zoom, click and drag to pan. + Click on nodes to view details. +
+