369 lines
9.1 KiB
Markdown
369 lines
9.1 KiB
Markdown
|
|
# Feature Implementation: Litter Management & Interactive Pedigree
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
This feature branch implements two major enhancements to the BREEDR system:
|
||
|
|
|
||
|
|
1. **Complete Litter Management System** - Fixes the puppy addition issue and provides full litter tracking
|
||
|
|
2. **Interactive Pedigree Tree Visualization** - Beautiful, zoomable pedigree trees using react-d3-tree
|
||
|
|
|
||
|
|
## Problem Solved
|
||
|
|
|
||
|
|
### Original Issue
|
||
|
|
When attempting to add a puppy, users encountered the error:
|
||
|
|
```
|
||
|
|
no such column: sire
|
||
|
|
```
|
||
|
|
|
||
|
|
This occurred because:
|
||
|
|
- The `dogs` table uses a `parents` relationship table for lineage
|
||
|
|
- The `litters` table existed but had no linkage mechanism to puppies
|
||
|
|
- The DogForm tried to reference non-existent direct parent columns
|
||
|
|
|
||
|
|
## Implementation
|
||
|
|
|
||
|
|
### 1. Database Migration
|
||
|
|
|
||
|
|
**File:** `server/db/migrate_litter_id.js`
|
||
|
|
|
||
|
|
Adds a `litter_id` column to the `dogs` table to link puppies to their litters:
|
||
|
|
|
||
|
|
```sql
|
||
|
|
ALTER TABLE dogs ADD COLUMN litter_id INTEGER;
|
||
|
|
CREATE INDEX idx_dogs_litter ON dogs(litter_id);
|
||
|
|
```
|
||
|
|
|
||
|
|
To run the migration:
|
||
|
|
```bash
|
||
|
|
node server/db/migrate_litter_id.js
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. Enhanced Litter API
|
||
|
|
|
||
|
|
**File:** `server/routes/litters.js`
|
||
|
|
|
||
|
|
New endpoints:
|
||
|
|
- `POST /api/litters/:id/puppies/:puppyId` - Link puppy to litter
|
||
|
|
- `DELETE /api/litters/:id/puppies/:puppyId` - Remove puppy from litter
|
||
|
|
- Enhanced `GET /api/litters` - Returns litters with puppy counts
|
||
|
|
|
||
|
|
Auto-linking logic:
|
||
|
|
- When a puppy is linked to a litter, sire/dam relationships are automatically created in the `parents` table
|
||
|
|
- Prevents orphaned data when litters are deleted
|
||
|
|
|
||
|
|
### 3. Updated DogForm Component
|
||
|
|
|
||
|
|
**File:** `client/src/components/DogForm.jsx`
|
||
|
|
|
||
|
|
Key Features:
|
||
|
|
- **Dual Parent Selection Mode:**
|
||
|
|
- Option 1: Link to existing litter (auto-populates parents)
|
||
|
|
- Option 2: Manual parent selection (traditional method)
|
||
|
|
- Radio button toggle for selection mode
|
||
|
|
- Litter dropdown shows "Sire x Dam - Date" format
|
||
|
|
- Automatic breed inheritance from litter parents
|
||
|
|
|
||
|
|
### 4. New LitterForm Component
|
||
|
|
|
||
|
|
**File:** `client/src/components/LitterForm.jsx`
|
||
|
|
|
||
|
|
Features:
|
||
|
|
- Create/edit litter records
|
||
|
|
- Select sire and dam from dropdown lists
|
||
|
|
- Track breeding date, whelping date, expected puppy count
|
||
|
|
- Notes field for breeding details
|
||
|
|
- Validation: ensures sire is male, dam is female
|
||
|
|
|
||
|
|
### 5. Interactive Pedigree Visualization
|
||
|
|
|
||
|
|
**Files:**
|
||
|
|
- `client/src/components/PedigreeView.jsx`
|
||
|
|
- `client/src/components/PedigreeView.css`
|
||
|
|
|
||
|
|
**Features:**
|
||
|
|
- **Beautiful Tree Visualization:**
|
||
|
|
- Horizontal tree layout (left to right)
|
||
|
|
- Color-coded nodes: Blue for males, Pink for females
|
||
|
|
- Shows 5 generations by default
|
||
|
|
|
||
|
|
- **Interactive Controls:**
|
||
|
|
- Zoom in/out buttons
|
||
|
|
- Reset view button
|
||
|
|
- Mouse wheel zoom support
|
||
|
|
- Click and drag to pan
|
||
|
|
- Click nodes for details
|
||
|
|
|
||
|
|
- **Node Information:**
|
||
|
|
- Dog name (primary)
|
||
|
|
- Registration number
|
||
|
|
- Birth year
|
||
|
|
- Sex indicator (♂/♀)
|
||
|
|
|
||
|
|
- **Uses COI Calculator Backend:**
|
||
|
|
- Leverages existing `/api/pedigree/:id` endpoint
|
||
|
|
- Recursive ancestor tree building
|
||
|
|
- Supports configurable generation depth
|
||
|
|
|
||
|
|
## Usage
|
||
|
|
|
||
|
|
### Adding a Puppy from a Litter
|
||
|
|
|
||
|
|
1. Create a litter first:
|
||
|
|
- Navigate to Litters section
|
||
|
|
- Click "Add New Litter"
|
||
|
|
- Select sire and dam
|
||
|
|
- Enter breeding date
|
||
|
|
- Save
|
||
|
|
|
||
|
|
2. Add puppies to the litter:
|
||
|
|
- Click "Add New Dog"
|
||
|
|
- Enter puppy details
|
||
|
|
- Select "Link to Litter" radio button
|
||
|
|
- Choose the litter from dropdown
|
||
|
|
- Parents are auto-populated
|
||
|
|
- Save
|
||
|
|
|
||
|
|
### Viewing Pedigree Trees
|
||
|
|
|
||
|
|
1. From any dog detail page:
|
||
|
|
- Click "View Pedigree" button
|
||
|
|
- Interactive tree opens in modal
|
||
|
|
- Use zoom/pan controls to navigate
|
||
|
|
- Click nodes to see details
|
||
|
|
|
||
|
|
### Manual Parent Assignment
|
||
|
|
|
||
|
|
For dogs not part of a formal litter:
|
||
|
|
1. Click "Add New Dog"
|
||
|
|
2. Enter dog details
|
||
|
|
3. Select "Manual Parent Selection"
|
||
|
|
4. Choose sire and dam from dropdowns
|
||
|
|
5. Save
|
||
|
|
|
||
|
|
## Technical Details
|
||
|
|
|
||
|
|
### Data Flow: Litter to Puppy
|
||
|
|
|
||
|
|
```
|
||
|
|
1. User creates litter (sire_id, dam_id, breeding_date)
|
||
|
|
↓
|
||
|
|
2. Litter gets unique ID
|
||
|
|
↓
|
||
|
|
3. User adds puppy with litter_id
|
||
|
|
↓
|
||
|
|
4. Backend auto-creates parent relationships:
|
||
|
|
- INSERT INTO parents (puppy_id, sire_id, 'sire')
|
||
|
|
- INSERT INTO parents (puppy_id, dam_id, 'dam')
|
||
|
|
↓
|
||
|
|
5. Puppy linked to litter and parents
|
||
|
|
```
|
||
|
|
|
||
|
|
### Pedigree Tree Data Structure
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
{
|
||
|
|
name: "Dog Name",
|
||
|
|
attributes: {
|
||
|
|
sex: "male",
|
||
|
|
birth_date: "2020-01-15",
|
||
|
|
registration: "AKC12345",
|
||
|
|
breed: "Golden Retriever",
|
||
|
|
generation: 0
|
||
|
|
},
|
||
|
|
children: [
|
||
|
|
{ /* Sire node */ },
|
||
|
|
{ /* Dam node */ }
|
||
|
|
]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### React-D3-Tree Configuration
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
<Tree
|
||
|
|
orientation="horizontal" // Left to right
|
||
|
|
pathFunc="step" // Orthogonal lines
|
||
|
|
separation={{ siblings: 2 }} // Node spacing
|
||
|
|
nodeSize={{ x: 200, y: 100 }} // Node dimensions
|
||
|
|
collapsible={false} // Always show all
|
||
|
|
zoomable={true} // Enable zoom
|
||
|
|
draggable={true} // Enable pan
|
||
|
|
/>
|
||
|
|
```
|
||
|
|
|
||
|
|
## Database Schema Updates
|
||
|
|
|
||
|
|
### Before
|
||
|
|
```sql
|
||
|
|
CREATE TABLE dogs (
|
||
|
|
id INTEGER PRIMARY KEY,
|
||
|
|
name TEXT NOT NULL,
|
||
|
|
-- ... other fields
|
||
|
|
-- NO litter_id column
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE TABLE parents (
|
||
|
|
dog_id INTEGER,
|
||
|
|
parent_id INTEGER,
|
||
|
|
parent_type TEXT -- 'sire' or 'dam'
|
||
|
|
);
|
||
|
|
```
|
||
|
|
|
||
|
|
### After
|
||
|
|
```sql
|
||
|
|
CREATE TABLE dogs (
|
||
|
|
id INTEGER PRIMARY KEY,
|
||
|
|
name TEXT NOT NULL,
|
||
|
|
-- ... other fields
|
||
|
|
litter_id INTEGER -- NEW: Links to litters table
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX idx_dogs_litter ON dogs(litter_id);
|
||
|
|
```
|
||
|
|
|
||
|
|
## API Changes
|
||
|
|
|
||
|
|
### New Endpoints
|
||
|
|
|
||
|
|
```
|
||
|
|
POST /api/litters/:id/puppies/:puppyId
|
||
|
|
DELETE /api/litters/:id/puppies/:puppyId
|
||
|
|
```
|
||
|
|
|
||
|
|
### Modified Endpoints
|
||
|
|
|
||
|
|
```
|
||
|
|
GET /api/litters
|
||
|
|
Response now includes:
|
||
|
|
- actual_puppy_count: Real count from database
|
||
|
|
- puppies: Array of linked puppies
|
||
|
|
|
||
|
|
POST /api/dogs
|
||
|
|
Accepts new field:
|
||
|
|
- litter_id: Optional litter association
|
||
|
|
```
|
||
|
|
|
||
|
|
## Dependencies
|
||
|
|
|
||
|
|
### New npm packages added:
|
||
|
|
- `react-d3-tree@^3.6.2` - Tree visualization library
|
||
|
|
|
||
|
|
### Existing dependencies leveraged:
|
||
|
|
- `lucide-react` - Icons for UI controls
|
||
|
|
- `axios` - API communication
|
||
|
|
- `react` - Component framework
|
||
|
|
|
||
|
|
## Testing Checklist
|
||
|
|
|
||
|
|
- [ ] Run database migration
|
||
|
|
- [ ] Create a new litter
|
||
|
|
- [ ] Add puppies to litter via DogForm
|
||
|
|
- [ ] Verify parent relationships auto-created
|
||
|
|
- [ ] View pedigree tree for a dog with 3+ generations
|
||
|
|
- [ ] Test zoom/pan controls in pedigree view
|
||
|
|
- [ ] Add dog with manual parent selection
|
||
|
|
- [ ] Edit existing dog and change litter assignment
|
||
|
|
- [ ] Delete litter and verify puppies remain (litter_id set to NULL)
|
||
|
|
|
||
|
|
## Future Enhancements
|
||
|
|
|
||
|
|
1. **Litter Dashboard:**
|
||
|
|
- Visual cards for each litter
|
||
|
|
- Photos of puppies
|
||
|
|
- Whelping countdown
|
||
|
|
|
||
|
|
2. **Enhanced Pedigree Features:**
|
||
|
|
- Print to PDF
|
||
|
|
- Color coding by health clearances
|
||
|
|
- COI display on tree nodes
|
||
|
|
- Descendant tree (reverse pedigree)
|
||
|
|
|
||
|
|
3. **Batch Operations:**
|
||
|
|
- Add multiple puppies at once
|
||
|
|
- Bulk photo upload for litter
|
||
|
|
- Auto-naming scheme (Litter Letter + Name)
|
||
|
|
|
||
|
|
4. **Analytics:**
|
||
|
|
- Average litter size by pairing
|
||
|
|
- Color distribution predictions
|
||
|
|
- Genetic diversity metrics
|
||
|
|
|
||
|
|
## Migration Path
|
||
|
|
|
||
|
|
### From Current System
|
||
|
|
|
||
|
|
1. Pull feature branch
|
||
|
|
2. Run migration: `node server/db/migrate_litter_id.js`
|
||
|
|
3. Install dependencies: `cd client && npm install`
|
||
|
|
4. Restart server
|
||
|
|
5. Existing dogs remain unchanged
|
||
|
|
6. Start creating litters for new puppies
|
||
|
|
|
||
|
|
### Rollback Plan
|
||
|
|
|
||
|
|
If issues arise:
|
||
|
|
1. The `litter_id` column can remain NULL
|
||
|
|
2. System continues to work with manual parent selection
|
||
|
|
3. No data loss occurs
|
||
|
|
4. Simply don't use litter feature until fixed
|
||
|
|
|
||
|
|
## Architecture Decisions
|
||
|
|
|
||
|
|
### Why litter_id Column?
|
||
|
|
|
||
|
|
**Considered alternatives:**
|
||
|
|
1. ✗ Bridge table `litter_puppies` - Adds complexity, same result
|
||
|
|
2. ✗ JSON array in `litters.puppy_ids` - Poor query performance
|
||
|
|
3. ✓ **Foreign key in dogs table** - Simple, performant, standard pattern
|
||
|
|
|
||
|
|
### Why Radio Button Toggle?
|
||
|
|
|
||
|
|
**User Experience:**
|
||
|
|
- Clear visual distinction between modes
|
||
|
|
- Prevents accidental litter/manual mixing
|
||
|
|
- Familiar UI pattern
|
||
|
|
- Easy to understand for non-technical users
|
||
|
|
|
||
|
|
### Why react-d3-tree?
|
||
|
|
|
||
|
|
**Alternatives evaluated:**
|
||
|
|
- D3.js directly - Too much custom code required
|
||
|
|
- vis.js - Not React-friendly
|
||
|
|
- react-family-tree - Less flexible
|
||
|
|
- **react-d3-tree** - ✓ React-native, customizable, maintained
|
||
|
|
|
||
|
|
## Performance Considerations
|
||
|
|
|
||
|
|
1. **Pedigree Loading:**
|
||
|
|
- Recursive queries limited to 5 generations
|
||
|
|
- Indexes on `parents` table ensure fast lookups
|
||
|
|
- Tree data cached in component state
|
||
|
|
|
||
|
|
2. **Litter Queries:**
|
||
|
|
- New index on `dogs.litter_id` enables fast filtering
|
||
|
|
- Puppy counts calculated efficiently via JOIN
|
||
|
|
|
||
|
|
3. **Frontend Rendering:**
|
||
|
|
- React-d3-tree uses virtual DOM for smooth updates
|
||
|
|
- Lazy loading prevents rendering off-screen nodes
|
||
|
|
|
||
|
|
## Security Notes
|
||
|
|
|
||
|
|
- All parent/litter relationships validated server-side
|
||
|
|
- Gender validation prevents invalid pairings
|
||
|
|
- Foreign key relationships ensure referential integrity
|
||
|
|
- SQL injection prevented via parameterized queries
|
||
|
|
|
||
|
|
## Contributing
|
||
|
|
|
||
|
|
When extending these features:
|
||
|
|
|
||
|
|
1. **Backend changes:** Update `server/routes/litters.js`
|
||
|
|
2. **Frontend forms:** Modify `client/src/components/LitterForm.jsx` or `DogForm.jsx`
|
||
|
|
3. **Visualization:** Edit `client/src/components/PedigreeView.jsx`
|
||
|
|
4. **Database:** Create new migration file following naming convention
|
||
|
|
|
||
|
|
## Questions?
|
||
|
|
|
||
|
|
See [ROADMAP.md](./ROADMAP.md) for feature priorities or check [README.md](./README.md) for general project info.
|