Clean: Remove outdated documentation
This commit is contained in:
@@ -1,345 +0,0 @@
|
|||||||
# BREEDR Database Migrations
|
|
||||||
|
|
||||||
## Automatic Migration System
|
|
||||||
|
|
||||||
BREEDR now includes an **automatic migration system** that runs on every startup to ensure your database schema is always correct and up-to-date.
|
|
||||||
|
|
||||||
## How It Works
|
|
||||||
|
|
||||||
### On Every Startup
|
|
||||||
|
|
||||||
1. **Initialize Database** - Creates tables if they don't exist
|
|
||||||
2. **Run Migrations** - Automatically fixes schema issues
|
|
||||||
3. **Validate Schema** - Verifies everything is correct
|
|
||||||
4. **Start Application** - Server begins accepting requests
|
|
||||||
|
|
||||||
You don't need to do anything manually!
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Migrations Included
|
|
||||||
|
|
||||||
### Migration 001: Remove Old Parent Columns
|
|
||||||
|
|
||||||
**Problem**: Old schema had `sire` and `dam` columns in the `dogs` table causing "no such column: sire" errors.
|
|
||||||
|
|
||||||
**Solution**:
|
|
||||||
- Creates `parents` table for relationships
|
|
||||||
- Migrates existing sire/dam data to `parents` table
|
|
||||||
- Recreates `dogs` table without sire/dam columns
|
|
||||||
- Preserves all existing dog data
|
|
||||||
|
|
||||||
**Automatic**: Runs only if old schema detected
|
|
||||||
|
|
||||||
### Migration 002: Add Litter ID Column
|
|
||||||
|
|
||||||
**Problem**: Dogs table missing `litter_id` column for linking puppies to litters.
|
|
||||||
|
|
||||||
**Solution**:
|
|
||||||
- Adds `litter_id` column to `dogs` table
|
|
||||||
- Creates foreign key to `litters` table
|
|
||||||
|
|
||||||
**Automatic**: Runs only if column is missing
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Schema Version Tracking
|
|
||||||
|
|
||||||
The migration system uses a `schema_version` table to track which migrations have been applied:
|
|
||||||
|
|
||||||
```sql
|
|
||||||
CREATE TABLE schema_version (
|
|
||||||
version INTEGER PRIMARY KEY,
|
|
||||||
applied_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
description TEXT
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
Each migration runs only once, even if you restart the server multiple times.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Correct Schema (Current)
|
|
||||||
|
|
||||||
### Dogs Table (No sire/dam columns!)
|
|
||||||
|
|
||||||
```sql
|
|
||||||
CREATE TABLE dogs (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
name TEXT NOT NULL,
|
|
||||||
registration_number TEXT,
|
|
||||||
microchip TEXT,
|
|
||||||
sex TEXT CHECK(sex IN ('male', 'female')),
|
|
||||||
birth_date DATE,
|
|
||||||
breed TEXT,
|
|
||||||
color TEXT,
|
|
||||||
weight REAL,
|
|
||||||
height REAL,
|
|
||||||
notes TEXT,
|
|
||||||
litter_id INTEGER,
|
|
||||||
photo_urls TEXT,
|
|
||||||
is_active INTEGER DEFAULT 1,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
FOREIGN KEY (litter_id) REFERENCES litters(id) ON DELETE SET NULL
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Parents Table (Relationships)
|
|
||||||
|
|
||||||
```sql
|
|
||||||
CREATE TABLE parents (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
dog_id INTEGER NOT NULL,
|
|
||||||
parent_id INTEGER NOT NULL,
|
|
||||||
parent_type TEXT NOT NULL CHECK(parent_type IN ('sire', 'dam')),
|
|
||||||
FOREIGN KEY (dog_id) REFERENCES dogs(id) ON DELETE CASCADE,
|
|
||||||
FOREIGN KEY (parent_id) REFERENCES dogs(id) ON DELETE CASCADE,
|
|
||||||
UNIQUE(dog_id, parent_type)
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## How to Use
|
|
||||||
|
|
||||||
### Normal Startup (Automatic)
|
|
||||||
|
|
||||||
Just start your application normally:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# With Docker
|
|
||||||
docker-compose up -d
|
|
||||||
|
|
||||||
# Without Docker
|
|
||||||
cd server && npm start
|
|
||||||
```
|
|
||||||
|
|
||||||
Migrations run automatically!
|
|
||||||
|
|
||||||
### Check Migration Logs
|
|
||||||
|
|
||||||
Look at the server console output:
|
|
||||||
|
|
||||||
```
|
|
||||||
============================================================
|
|
||||||
BREEDR Database Migration System
|
|
||||||
============================================================
|
|
||||||
Database: /app/data/breedr.db
|
|
||||||
|
|
||||||
Current schema version: 0
|
|
||||||
|
|
||||||
[Migration 001] Checking for old sire/dam columns...
|
|
||||||
[Migration 001] Found old schema with sire/dam columns
|
|
||||||
[Migration 001] Migrating to parents table...
|
|
||||||
[Migration 001] Backed up 15 dogs
|
|
||||||
[Migration 001] Migrated 8 sire relationships
|
|
||||||
[Migration 001] Migrated 8 dam relationships
|
|
||||||
[Migration 001] Dropped old dogs table
|
|
||||||
[Migration 001] Created new dogs table
|
|
||||||
[Migration 001] Restored 15 dogs
|
|
||||||
[Migration 001] ✓ Migration complete!
|
|
||||||
|
|
||||||
[Migration 002] Checking for litter_id column...
|
|
||||||
[Migration 002] litter_id column already exists, skipping
|
|
||||||
|
|
||||||
[Validation] ✓ Dogs table exists
|
|
||||||
[Validation] ✓ Dogs table has no sire/dam columns
|
|
||||||
[Validation] ✓ Parents table exists
|
|
||||||
[Validation] ✓ Litter_id column exists
|
|
||||||
[Validation] ✓ Litters table exists
|
|
||||||
[Validation] ✓ All schema checks passed!
|
|
||||||
|
|
||||||
============================================================
|
|
||||||
Schema version: 0 → 2
|
|
||||||
Migration system complete!
|
|
||||||
============================================================
|
|
||||||
```
|
|
||||||
|
|
||||||
### Manual Migration (If Needed)
|
|
||||||
|
|
||||||
You can also run migrations manually:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
node server/db/migrations.js
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Fresh Install
|
|
||||||
|
|
||||||
For a fresh installation:
|
|
||||||
|
|
||||||
1. **No database file exists** → `init.js` creates correct schema
|
|
||||||
2. **Migrations check schema** → Everything already correct, no migration needed
|
|
||||||
3. **Application starts** → Ready to use!
|
|
||||||
|
|
||||||
**Result**: Fresh installs automatically have the correct schema.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Upgrading from Old Version
|
|
||||||
|
|
||||||
For existing installations with old schema:
|
|
||||||
|
|
||||||
1. **Old database detected** → Migration system kicks in
|
|
||||||
2. **Data is backed up** → Safety first!
|
|
||||||
3. **Schema is updated** → Sire/dam data moved to parents table
|
|
||||||
4. **Data is restored** → All your dogs are preserved
|
|
||||||
5. **Application starts** → Now using correct schema!
|
|
||||||
|
|
||||||
**Result**: Existing data is preserved and schema is fixed automatically.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Docker Integration
|
|
||||||
|
|
||||||
### Dockerfile
|
|
||||||
|
|
||||||
No changes needed! Migrations run automatically when the container starts.
|
|
||||||
|
|
||||||
### docker-compose.yml
|
|
||||||
|
|
||||||
No changes needed! Just restart:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker-compose restart
|
|
||||||
```
|
|
||||||
|
|
||||||
Or rebuild:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker-compose down
|
|
||||||
docker-compose up --build -d
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Migration Failed
|
|
||||||
|
|
||||||
If you see an error:
|
|
||||||
|
|
||||||
```
|
|
||||||
⚠️ Database migration failed!
|
|
||||||
Error: [error message]
|
|
||||||
```
|
|
||||||
|
|
||||||
1. **Check the error message** - It will tell you what went wrong
|
|
||||||
2. **Check database file permissions** - Make sure the file is writable
|
|
||||||
3. **Check disk space** - Ensure you have enough space
|
|
||||||
4. **Try manual migration**:
|
|
||||||
```bash
|
|
||||||
node server/db/migrations.js
|
|
||||||
```
|
|
||||||
|
|
||||||
### Database is Locked
|
|
||||||
|
|
||||||
If migrations fail with "database is locked":
|
|
||||||
|
|
||||||
1. Stop all running instances of BREEDR
|
|
||||||
2. Check for zombie processes: `ps aux | grep node`
|
|
||||||
3. Kill any old processes: `kill <PID>`
|
|
||||||
4. Restart BREEDR
|
|
||||||
|
|
||||||
### Migration Keeps Running
|
|
||||||
|
|
||||||
If the same migration runs every time:
|
|
||||||
|
|
||||||
1. Check `schema_version` table:
|
|
||||||
```sql
|
|
||||||
SELECT * FROM schema_version;
|
|
||||||
```
|
|
||||||
2. If empty, migration isn't being recorded
|
|
||||||
3. Check for database transaction issues
|
|
||||||
4. Manually add version:
|
|
||||||
```sql
|
|
||||||
INSERT INTO schema_version (version, description) VALUES (1, 'Manual fix');
|
|
||||||
```
|
|
||||||
|
|
||||||
### Want to Start Fresh
|
|
||||||
|
|
||||||
To completely reset the database:
|
|
||||||
|
|
||||||
1. **Stop BREEDR**
|
|
||||||
2. **Backup your data** (optional):
|
|
||||||
```bash
|
|
||||||
cp data/breedr.db data/breedr.db.backup
|
|
||||||
```
|
|
||||||
3. **Delete database**:
|
|
||||||
```bash
|
|
||||||
rm data/breedr.db
|
|
||||||
```
|
|
||||||
4. **Restart BREEDR** - Fresh database will be created
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Validation Checks
|
|
||||||
|
|
||||||
The migration system validates your schema:
|
|
||||||
|
|
||||||
- ✓ Dogs table exists
|
|
||||||
- ✓ Dogs table has no sire/dam columns
|
|
||||||
- ✓ Parents table exists
|
|
||||||
- ✓ Litter_id column exists
|
|
||||||
- ✓ Litters table exists
|
|
||||||
|
|
||||||
If any check fails, you'll see a warning.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Adding New Migrations
|
|
||||||
|
|
||||||
If you need to add a new migration:
|
|
||||||
|
|
||||||
1. **Edit `server/db/migrations.js`**
|
|
||||||
2. **Add new migration function**:
|
|
||||||
```javascript
|
|
||||||
migration003_yourNewMigration() {
|
|
||||||
console.log('[Migration 003] Doing something...');
|
|
||||||
// Your migration code here
|
|
||||||
}
|
|
||||||
```
|
|
||||||
3. **Add to runMigrations()**:
|
|
||||||
```javascript
|
|
||||||
if (currentVersion < 3) {
|
|
||||||
this.migration003_yourNewMigration();
|
|
||||||
this.recordMigration(3, 'Description of migration');
|
|
||||||
}
|
|
||||||
```
|
|
||||||
4. **Test thoroughly** before deploying
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Best Practices
|
|
||||||
|
|
||||||
1. **Let migrations run automatically** - Don't skip them
|
|
||||||
2. **Check logs on startup** - Verify migrations succeeded
|
|
||||||
3. **Backup before major updates** - Safety first
|
|
||||||
4. **Test in development** - Before deploying to production
|
|
||||||
5. **Monitor schema_version** - Know what version you're on
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Schema Version History
|
|
||||||
|
|
||||||
| Version | Description | Date |
|
|
||||||
|---------|-------------|------|
|
|
||||||
| 0 | Initial schema (may have sire/dam columns) | - |
|
|
||||||
| 1 | Migrated to parents table | March 2026 |
|
|
||||||
| 2 | Added litter_id column | March 2026 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
✅ **Migrations run automatically on every startup**
|
|
||||||
✅ **No manual intervention needed**
|
|
||||||
✅ **Data is preserved during migrations**
|
|
||||||
✅ **Schema is validated after migrations**
|
|
||||||
✅ **Works with Docker and standalone**
|
|
||||||
✅ **Fresh installs get correct schema**
|
|
||||||
✅ **Old installs are automatically upgraded**
|
|
||||||
|
|
||||||
**The "no such column: sire" error is now fixed automatically!** 🎉
|
|
||||||
466
DEPLOY_NOW.md
466
DEPLOY_NOW.md
@@ -1,466 +0,0 @@
|
|||||||
# 🚀 BREEDR v0.4.0 - Ready to Deploy!
|
|
||||||
|
|
||||||
## ✅ What's Fixed
|
|
||||||
|
|
||||||
### Database Migration System
|
|
||||||
- **Automatic migrations** run on every server startup
|
|
||||||
- Detects and fixes old `sire`/`dam` column schema
|
|
||||||
- Migrates existing data to `parents` table
|
|
||||||
- Adds missing `litter_id` column
|
|
||||||
- Validates schema after migration
|
|
||||||
- **NO MANUAL SQL REQUIRED!**
|
|
||||||
|
|
||||||
### Frontend Form Fix
|
|
||||||
- Updated `DogForm.jsx` to ensure `sire_id` and `dam_id` are sent as `null` instead of empty strings
|
|
||||||
- Improved ID field handling with proper type conversion
|
|
||||||
- Better null value handling throughout the form
|
|
||||||
|
|
||||||
### Features Included
|
|
||||||
- ✅ Interactive pedigree tree with D3 visualization
|
|
||||||
- ✅ Litter management with parent auto-linking
|
|
||||||
- ✅ Dual parent selection mode (litter or manual)
|
|
||||||
- ✅ Enhanced error handling
|
|
||||||
- ✅ Automatic database repairs
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📦 Files Changed in This Branch
|
|
||||||
|
|
||||||
### Backend
|
|
||||||
- `server/db/migrations.js` - **NEW** Automatic migration system
|
|
||||||
- `server/index.js` - Runs migrations on startup
|
|
||||||
- `server/routes/dogs.js` - Already correct (uses `sire_id`/`dam_id`)
|
|
||||||
|
|
||||||
### Frontend
|
|
||||||
- `client/src/components/DogForm.jsx` - **FIXED** Null value handling
|
|
||||||
- `client/src/components/PedigreeTree.jsx` - **NEW** D3 visualization
|
|
||||||
- `client/src/components/PedigreeTree.css` - **NEW** Styling
|
|
||||||
- `client/src/utils/pedigreeHelpers.js` - **NEW** Utility functions
|
|
||||||
- `client/src/pages/PedigreeView.jsx` - **UPDATED** Full page
|
|
||||||
|
|
||||||
### Documentation
|
|
||||||
- `DATABASE_MIGRATIONS.md` - Complete migration guide
|
|
||||||
- `FRONTEND_FIX_REQUIRED.md` - Frontend fix reference
|
|
||||||
- `IMPLEMENTATION_PLAN.md` - Sprint planning
|
|
||||||
- `SPRINT1_PEDIGREE_COMPLETE.md` - Sprint 1 summary
|
|
||||||
- `DEPLOY_NOW.md` - **THIS FILE** Deployment guide
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 How to Deploy
|
|
||||||
|
|
||||||
### Step 1: Pull the Branch
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /path/to/breedr
|
|
||||||
git fetch origin
|
|
||||||
git checkout feature/enhanced-litters-and-pedigree
|
|
||||||
git pull origin feature/enhanced-litters-and-pedigree
|
|
||||||
```
|
|
||||||
|
|
||||||
### Step 2: Deploy with Docker (Recommended)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Stop current containers
|
|
||||||
docker-compose down
|
|
||||||
|
|
||||||
# Rebuild with new code
|
|
||||||
docker-compose build
|
|
||||||
|
|
||||||
# Start containers
|
|
||||||
docker-compose up -d
|
|
||||||
|
|
||||||
# Watch logs to see migration
|
|
||||||
docker-compose logs -f breedr
|
|
||||||
```
|
|
||||||
|
|
||||||
**You should see:**
|
|
||||||
```
|
|
||||||
============================================================
|
|
||||||
BREEDR Database Migration System
|
|
||||||
============================================================
|
|
||||||
[Migration 001] Checking for old sire/dam columns...
|
|
||||||
[Migration 001] Schema is already correct, skipping
|
|
||||||
OR
|
|
||||||
[Migration 001] Migrating to parents table...
|
|
||||||
[Migration 001] ✓ Migration complete!
|
|
||||||
|
|
||||||
[Validation] ✓ All schema checks passed!
|
|
||||||
============================================================
|
|
||||||
|
|
||||||
BREEDR Server Running on port 3000
|
|
||||||
```
|
|
||||||
|
|
||||||
### Step 3: Deploy Without Docker
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Install dependencies
|
|
||||||
cd server && npm install
|
|
||||||
cd ../client && npm install
|
|
||||||
|
|
||||||
# Build frontend
|
|
||||||
npm run build
|
|
||||||
|
|
||||||
# Start server (migrations run automatically)
|
|
||||||
cd ../server
|
|
||||||
npm start
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✔️ Post-Deployment Testing
|
|
||||||
|
|
||||||
### 1. Server Startup
|
|
||||||
- [ ] Server starts without errors
|
|
||||||
- [ ] Migration logs show success
|
|
||||||
- [ ] No database errors in console
|
|
||||||
|
|
||||||
### 2. Add Dog Form
|
|
||||||
- [ ] Open "Add New Dog" modal
|
|
||||||
- [ ] Form displays correctly
|
|
||||||
- [ ] Can select Sire from dropdown
|
|
||||||
- [ ] Can select Dam from dropdown
|
|
||||||
- [ ] Can link to a litter
|
|
||||||
- [ ] Submit creates dog successfully
|
|
||||||
- [ ] **No "sire column" error!** ✅
|
|
||||||
|
|
||||||
### 3. Edit Dog Form
|
|
||||||
- [ ] Open existing dog
|
|
||||||
- [ ] Click "Edit"
|
|
||||||
- [ ] Parents display correctly
|
|
||||||
- [ ] Can change parents
|
|
||||||
- [ ] Save works without errors
|
|
||||||
|
|
||||||
### 4. Pedigree Tree
|
|
||||||
- [ ] Navigate to dog with parents
|
|
||||||
- [ ] Pedigree tree displays
|
|
||||||
- [ ] Can zoom and pan
|
|
||||||
- [ ] Can click nodes to navigate
|
|
||||||
- [ ] COI displays correctly
|
|
||||||
- [ ] Generation selector works
|
|
||||||
|
|
||||||
### 5. Litter Features
|
|
||||||
- [ ] Can create new litter
|
|
||||||
- [ ] Can add puppy linked to litter
|
|
||||||
- [ ] Parents auto-populate from litter
|
|
||||||
- [ ] Litter selection dropdown works
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🔍 Troubleshooting
|
|
||||||
|
|
||||||
### Issue: Migration doesn't run
|
|
||||||
|
|
||||||
**Check:**
|
|
||||||
```bash
|
|
||||||
# View server logs
|
|
||||||
docker-compose logs breedr
|
|
||||||
|
|
||||||
# Or if running locally
|
|
||||||
cat server.log
|
|
||||||
```
|
|
||||||
|
|
||||||
**Manual migration:**
|
|
||||||
```bash
|
|
||||||
# In Docker
|
|
||||||
docker exec breedr node /app/server/db/migrations.js
|
|
||||||
|
|
||||||
# Locally
|
|
||||||
node server/db/migrations.js
|
|
||||||
```
|
|
||||||
|
|
||||||
### Issue: Still getting "sire column" error
|
|
||||||
|
|
||||||
**Possible causes:**
|
|
||||||
1. Old frontend code cached in browser
|
|
||||||
- **Fix:** Hard refresh (Ctrl+Shift+R or Cmd+Shift+R)
|
|
||||||
- **Fix:** Clear browser cache
|
|
||||||
|
|
||||||
2. Container not rebuilt
|
|
||||||
- **Fix:** `docker-compose down && docker-compose up --build -d`
|
|
||||||
|
|
||||||
3. Wrong branch
|
|
||||||
- **Fix:** `git branch` to verify on `feature/enhanced-litters-and-pedigree`
|
|
||||||
|
|
||||||
### Issue: Form shows blank screen
|
|
||||||
|
|
||||||
**Cause:** Frontend build issue
|
|
||||||
|
|
||||||
**Fix:**
|
|
||||||
```bash
|
|
||||||
cd client
|
|
||||||
rm -rf dist node_modules
|
|
||||||
npm install
|
|
||||||
npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
### Issue: Database locked error
|
|
||||||
|
|
||||||
**Cause:** Multiple processes accessing database
|
|
||||||
|
|
||||||
**Fix:**
|
|
||||||
```bash
|
|
||||||
# Stop all instances
|
|
||||||
docker-compose down
|
|
||||||
pkill -f "node.*server"
|
|
||||||
|
|
||||||
# Restart
|
|
||||||
docker-compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 Database Schema (Current)
|
|
||||||
|
|
||||||
### Dogs Table
|
|
||||||
```sql
|
|
||||||
CREATE TABLE dogs (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
name TEXT NOT NULL,
|
|
||||||
registration_number TEXT,
|
|
||||||
microchip TEXT,
|
|
||||||
sex TEXT CHECK(sex IN ('male', 'female')),
|
|
||||||
birth_date DATE,
|
|
||||||
breed TEXT,
|
|
||||||
color TEXT,
|
|
||||||
weight REAL,
|
|
||||||
height REAL,
|
|
||||||
notes TEXT,
|
|
||||||
litter_id INTEGER, -- ✅ Links to litter
|
|
||||||
photo_urls TEXT,
|
|
||||||
is_active INTEGER DEFAULT 1,
|
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
FOREIGN KEY (litter_id) REFERENCES litters(id)
|
|
||||||
);
|
|
||||||
-- ❌ NO sire or dam columns!
|
|
||||||
```
|
|
||||||
|
|
||||||
### Parents Table (Relationships)
|
|
||||||
```sql
|
|
||||||
CREATE TABLE parents (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
dog_id INTEGER NOT NULL,
|
|
||||||
parent_id INTEGER NOT NULL,
|
|
||||||
parent_type TEXT NOT NULL CHECK(parent_type IN ('sire', 'dam')),
|
|
||||||
FOREIGN KEY (dog_id) REFERENCES dogs(id) ON DELETE CASCADE,
|
|
||||||
FOREIGN KEY (parent_id) REFERENCES dogs(id) ON DELETE CASCADE,
|
|
||||||
UNIQUE(dog_id, parent_type)
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📈 What Changed
|
|
||||||
|
|
||||||
### From Old Schema
|
|
||||||
```sql
|
|
||||||
CREATE TABLE dogs (
|
|
||||||
...
|
|
||||||
sire INTEGER, -- ❌ OLD
|
|
||||||
dam INTEGER, -- ❌ OLD
|
|
||||||
...
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
### To New Schema
|
|
||||||
```sql
|
|
||||||
CREATE TABLE dogs (
|
|
||||||
...
|
|
||||||
litter_id INTEGER, -- ✅ NEW
|
|
||||||
...
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE parents ( -- ✅ NEW
|
|
||||||
dog_id INTEGER,
|
|
||||||
parent_id INTEGER,
|
|
||||||
parent_type TEXT -- 'sire' or 'dam'
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
**Why?**
|
|
||||||
- More flexible relationship model
|
|
||||||
- Easier to query ancestry
|
|
||||||
- Better data integrity
|
|
||||||
- Supports future features (multiple parents, etc.)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📄 Migration Details
|
|
||||||
|
|
||||||
### What Gets Migrated
|
|
||||||
|
|
||||||
**Migration 001: Remove sire/dam columns**
|
|
||||||
1. Backup all dogs from old table
|
|
||||||
2. Extract sire relationships
|
|
||||||
3. Extract dam relationships
|
|
||||||
4. Drop old table
|
|
||||||
5. Create new table (without sire/dam)
|
|
||||||
6. Restore all dogs
|
|
||||||
7. Create parent relationships in `parents` table
|
|
||||||
|
|
||||||
**Migration 002: Add litter_id column**
|
|
||||||
1. Check if column exists
|
|
||||||
2. If missing, add column
|
|
||||||
3. Create foreign key constraint
|
|
||||||
|
|
||||||
### Data Preservation
|
|
||||||
|
|
||||||
All existing dog data is preserved:
|
|
||||||
- ✅ Dog names
|
|
||||||
- ✅ Registration numbers
|
|
||||||
- ✅ Breeds, colors, dates
|
|
||||||
- ✅ Photos
|
|
||||||
- ✅ Notes
|
|
||||||
- ✅ **Parent relationships** (moved to `parents` table)
|
|
||||||
|
|
||||||
**Nothing is lost!**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📝 API Contract
|
|
||||||
|
|
||||||
### POST /api/dogs
|
|
||||||
|
|
||||||
**Request:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"name": "Buddy",
|
|
||||||
"breed": "Golden Retriever",
|
|
||||||
"sex": "male",
|
|
||||||
"sire_id": 5, // ✅ ID or null
|
|
||||||
"dam_id": 8, // ✅ ID or null
|
|
||||||
"litter_id": 2, // ✅ ID or null
|
|
||||||
"birth_date": "2024-01-15",
|
|
||||||
"registration_number": "GR12345",
|
|
||||||
"microchip": "123456789",
|
|
||||||
"color": "Golden",
|
|
||||||
"notes": "Good temperament"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Response:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"id": 15,
|
|
||||||
"name": "Buddy",
|
|
||||||
"breed": "Golden Retriever",
|
|
||||||
"sex": "male",
|
|
||||||
"litter_id": 2,
|
|
||||||
"birth_date": "2024-01-15",
|
|
||||||
"registration_number": "GR12345",
|
|
||||||
"microchip": "123456789",
|
|
||||||
"color": "Golden",
|
|
||||||
"notes": "Good temperament",
|
|
||||||
"photo_urls": [],
|
|
||||||
"is_active": 1,
|
|
||||||
"created_at": "2026-03-09T06:15:00.000Z",
|
|
||||||
"updated_at": "2026-03-09T06:15:00.000Z"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note:** `sire` and `dam` objects are added by GET endpoint, not stored in table.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🚀 After Successful Deployment
|
|
||||||
|
|
||||||
### Verify Everything Works
|
|
||||||
|
|
||||||
1. **Server Console**
|
|
||||||
- No errors
|
|
||||||
- Migration completed successfully
|
|
||||||
- Server listening on port 3000
|
|
||||||
|
|
||||||
2. **Browser Console** (F12)
|
|
||||||
- No JavaScript errors
|
|
||||||
- API calls succeed (200 status)
|
|
||||||
- No "sire" or "dam" column errors
|
|
||||||
|
|
||||||
3. **Functionality**
|
|
||||||
- Add dog works
|
|
||||||
- Edit dog works
|
|
||||||
- Parents save correctly
|
|
||||||
- Pedigree tree displays
|
|
||||||
- Litters link properly
|
|
||||||
|
|
||||||
### Next Steps
|
|
||||||
|
|
||||||
1. **Merge to master** (after testing)
|
|
||||||
```bash
|
|
||||||
git checkout master
|
|
||||||
git merge feature/enhanced-litters-and-pedigree
|
|
||||||
git push origin master
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Tag release**
|
|
||||||
```bash
|
|
||||||
git tag -a v0.4.0 -m "Database migration system + pedigree tree"
|
|
||||||
git push origin v0.4.0
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Update ROADMAP.md** with next sprint
|
|
||||||
|
|
||||||
4. **Celebrate!** 🎉 The "sire column" error is gone forever!
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 📊 Version Info
|
|
||||||
|
|
||||||
**Current Version:** v0.4.0
|
|
||||||
**Branch:** `feature/enhanced-litters-and-pedigree`
|
|
||||||
**Date:** March 9, 2026
|
|
||||||
|
|
||||||
### What's New
|
|
||||||
- ✅ Automatic database migration system
|
|
||||||
- ✅ Interactive pedigree tree visualization
|
|
||||||
- ✅ Litter management improvements
|
|
||||||
- ✅ Enhanced error handling
|
|
||||||
- ✅ **Fixed "sire column" error permanently**
|
|
||||||
|
|
||||||
### Breaking Changes
|
|
||||||
- **None** - Migrations handle all schema updates automatically
|
|
||||||
- Existing data is preserved and migrated
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ❓ Need Help?
|
|
||||||
|
|
||||||
### Common Questions
|
|
||||||
|
|
||||||
**Q: Will I lose my data?**
|
|
||||||
A: No! Migrations backup and restore all data.
|
|
||||||
|
|
||||||
**Q: Do I need to run SQL manually?**
|
|
||||||
A: No! Everything is automatic on server startup.
|
|
||||||
|
|
||||||
**Q: What if migration fails?**
|
|
||||||
A: Server won't start. Check logs, fix issue, restart.
|
|
||||||
|
|
||||||
**Q: Can I rollback?**
|
|
||||||
A: Yes, checkout previous branch and restore database backup.
|
|
||||||
|
|
||||||
**Q: Will this fix the sire error?**
|
|
||||||
A: Yes! 100%. The error is eliminated at the root cause.
|
|
||||||
|
|
||||||
### Support
|
|
||||||
|
|
||||||
If you encounter issues:
|
|
||||||
|
|
||||||
1. Check this deployment guide
|
|
||||||
2. Review `DATABASE_MIGRATIONS.md`
|
|
||||||
3. Check server logs
|
|
||||||
4. Review `FRONTEND_FIX_REQUIRED.md` for frontend issues
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🎉 Summary
|
|
||||||
|
|
||||||
✅ **Backend migrations** - Automatic, tested, safe
|
|
||||||
✅ **Frontend fixes** - Proper null handling
|
|
||||||
✅ **Pedigree tree** - Beautiful visualization
|
|
||||||
✅ **Litter management** - Enhanced features
|
|
||||||
✅ **Documentation** - Complete guides
|
|
||||||
✅ **Error fixed** - "sire column" error eliminated
|
|
||||||
|
|
||||||
**Ready to deploy!** Just pull the branch and restart. 🚀
|
|
||||||
@@ -1,368 +0,0 @@
|
|||||||
# 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.
|
|
||||||
@@ -1,408 +0,0 @@
|
|||||||
# Frontend Fix Required: Add Dog Form
|
|
||||||
|
|
||||||
## Problem
|
|
||||||
|
|
||||||
The database and API are correct, but the **Add Dog frontend form** is still trying to use old `sire`/`dam` column names.
|
|
||||||
|
|
||||||
## Error Details
|
|
||||||
|
|
||||||
Server logs show migration completed successfully:
|
|
||||||
```
|
|
||||||
[Validation] ✓ Dogs table has no sire/dam columns
|
|
||||||
[Validation] ✓ Parents table exists
|
|
||||||
```
|
|
||||||
|
|
||||||
But when adding a dog, you still get the "no such column: sire" error.
|
|
||||||
|
|
||||||
## Root Cause
|
|
||||||
|
|
||||||
The frontend `DogForm` or `AddDogModal` component is sending:
|
|
||||||
- `sire` and `dam` (wrong)
|
|
||||||
|
|
||||||
But the API expects:
|
|
||||||
- `sire_id` and `dam_id` (correct)
|
|
||||||
|
|
||||||
## Files to Fix
|
|
||||||
|
|
||||||
Look for these files in `client/src/`:
|
|
||||||
- `components/DogForm.jsx`
|
|
||||||
- `components/AddDogModal.jsx`
|
|
||||||
- `components/EditDogModal.jsx`
|
|
||||||
- `pages/DogManagement.jsx`
|
|
||||||
|
|
||||||
Or any component that has the Add/Edit Dog form.
|
|
||||||
|
|
||||||
## The Fix
|
|
||||||
|
|
||||||
### 1. Check Form State
|
|
||||||
|
|
||||||
Look for state variables like:
|
|
||||||
```javascript
|
|
||||||
const [formData, setFormData] = useState({
|
|
||||||
name: '',
|
|
||||||
breed: '',
|
|
||||||
sex: '',
|
|
||||||
sire: '', // ❌ WRONG - should be sire_id
|
|
||||||
dam: '', // ❌ WRONG - should be dam_id
|
|
||||||
// ...
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
**Change to:**
|
|
||||||
```javascript
|
|
||||||
const [formData, setFormData] = useState({
|
|
||||||
name: '',
|
|
||||||
breed: '',
|
|
||||||
sex: '',
|
|
||||||
sire_id: null, // ✅ CORRECT
|
|
||||||
dam_id: null, // ✅ CORRECT
|
|
||||||
// ...
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Check Form Submission
|
|
||||||
|
|
||||||
Look for the API call:
|
|
||||||
```javascript
|
|
||||||
const response = await fetch('/api/dogs', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify({
|
|
||||||
name: formData.name,
|
|
||||||
breed: formData.breed,
|
|
||||||
sex: formData.sex,
|
|
||||||
sire: formData.sire, // ❌ WRONG
|
|
||||||
dam: formData.dam, // ❌ WRONG
|
|
||||||
// ...
|
|
||||||
})
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
**Change to:**
|
|
||||||
```javascript
|
|
||||||
const response = await fetch('/api/dogs', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify({
|
|
||||||
name: formData.name,
|
|
||||||
breed: formData.breed,
|
|
||||||
sex: formData.sex,
|
|
||||||
sire_id: formData.sire_id, // ✅ CORRECT
|
|
||||||
dam_id: formData.dam_id, // ✅ CORRECT
|
|
||||||
// ...
|
|
||||||
})
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Check Select Dropdowns
|
|
||||||
|
|
||||||
Look for parent selection dropdowns:
|
|
||||||
```jsx
|
|
||||||
<select
|
|
||||||
value={formData.sire} // ❌ WRONG
|
|
||||||
onChange={(e) => setFormData({ ...formData, sire: e.target.value })} // ❌ WRONG
|
|
||||||
>
|
|
||||||
<option value="">Select Sire</option>
|
|
||||||
{males.map(dog => (
|
|
||||||
<option key={dog.id} value={dog.id}>{dog.name}</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
```
|
|
||||||
|
|
||||||
**Change to:**
|
|
||||||
```jsx
|
|
||||||
<select
|
|
||||||
value={formData.sire_id || ''} // ✅ CORRECT
|
|
||||||
onChange={(e) => setFormData({
|
|
||||||
...formData,
|
|
||||||
sire_id: e.target.value ? parseInt(e.target.value) : null // ✅ CORRECT - convert to number or null
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<option value="">Select Sire</option>
|
|
||||||
{males.map(dog => (
|
|
||||||
<option key={dog.id} value={dog.id}>{dog.name}</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Check Edit Mode
|
|
||||||
|
|
||||||
When editing an existing dog:
|
|
||||||
```javascript
|
|
||||||
// ❌ WRONG - trying to access old columns
|
|
||||||
setFormData({
|
|
||||||
...dog,
|
|
||||||
sire: dog.sire?.id || '',
|
|
||||||
dam: dog.dam?.id || '',
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
**Change to:**
|
|
||||||
```javascript
|
|
||||||
// ✅ CORRECT - use correct field names
|
|
||||||
setFormData({
|
|
||||||
...dog,
|
|
||||||
sire_id: dog.sire?.id || null,
|
|
||||||
dam_id: dog.dam?.id || null,
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. Check Litter Mode
|
|
||||||
|
|
||||||
If the form has litter selection mode:
|
|
||||||
```javascript
|
|
||||||
if (useLitter && selectedLitter) {
|
|
||||||
dogData.sire = selectedLitter.sire_id; // ❌ WRONG field name
|
|
||||||
dogData.dam = selectedLitter.dam_id; // ❌ WRONG field name
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Change to:**
|
|
||||||
```javascript
|
|
||||||
if (useLitter && selectedLitter) {
|
|
||||||
dogData.sire_id = selectedLitter.sire_id; // ✅ CORRECT
|
|
||||||
dogData.dam_id = selectedLitter.dam_id; // ✅ CORRECT
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Quick Search & Replace
|
|
||||||
|
|
||||||
In your frontend code, search for:
|
|
||||||
|
|
||||||
1. **State initialization**: `sire: ''` → `sire_id: null`
|
|
||||||
2. **State initialization**: `dam: ''` → `dam_id: null`
|
|
||||||
3. **API payload**: `sire:` → `sire_id:`
|
|
||||||
4. **API payload**: `dam:` → `dam_id:`
|
|
||||||
5. **Form handlers**: `formData.sire` → `formData.sire_id`
|
|
||||||
6. **Form handlers**: `formData.dam` → `formData.dam_id`
|
|
||||||
|
|
||||||
## Testing After Fix
|
|
||||||
|
|
||||||
1. Open Add Dog modal
|
|
||||||
2. Fill in name, breed, sex
|
|
||||||
3. Select a sire from dropdown
|
|
||||||
4. Select a dam from dropdown
|
|
||||||
5. Click Submit
|
|
||||||
6. Should work without "sire column" error!
|
|
||||||
|
|
||||||
## API Contract (For Reference)
|
|
||||||
|
|
||||||
The server `POST /api/dogs` expects:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"name": "string",
|
|
||||||
"breed": "string",
|
|
||||||
"sex": "male" | "female",
|
|
||||||
"sire_id": number | null,
|
|
||||||
"dam_id": number | null,
|
|
||||||
"litter_id": number | null,
|
|
||||||
"registration_number": "string" | null,
|
|
||||||
"birth_date": "YYYY-MM-DD" | null,
|
|
||||||
"color": "string" | null,
|
|
||||||
"microchip": "string" | null,
|
|
||||||
"notes": "string" | null
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Why This Happens
|
|
||||||
|
|
||||||
The database migration fixed the backend, but:
|
|
||||||
- Frontend code wasn't updated to use new field names
|
|
||||||
- Old form components still reference `sire`/`dam`
|
|
||||||
- API expects `sire_id`/`dam_id` (correct)
|
|
||||||
|
|
||||||
## Example Complete Fix
|
|
||||||
|
|
||||||
Here's a complete example of a corrected form:
|
|
||||||
|
|
||||||
```jsx
|
|
||||||
import React, { useState, useEffect } from 'react';
|
|
||||||
|
|
||||||
function DogForm({ dog, onSubmit, onCancel }) {
|
|
||||||
const [formData, setFormData] = useState({
|
|
||||||
name: '',
|
|
||||||
breed: '',
|
|
||||||
sex: 'male',
|
|
||||||
birth_date: '',
|
|
||||||
sire_id: null, // ✅ CORRECT
|
|
||||||
dam_id: null, // ✅ CORRECT
|
|
||||||
litter_id: null,
|
|
||||||
registration_number: '',
|
|
||||||
microchip: '',
|
|
||||||
color: '',
|
|
||||||
notes: ''
|
|
||||||
});
|
|
||||||
|
|
||||||
const [males, setMales] = useState([]);
|
|
||||||
const [females, setFemales] = useState([]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// Load existing dogs for parent selection
|
|
||||||
fetch('/api/dogs')
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(dogs => {
|
|
||||||
setMales(dogs.filter(d => d.sex === 'male'));
|
|
||||||
setFemales(dogs.filter(d => d.sex === 'female'));
|
|
||||||
});
|
|
||||||
|
|
||||||
// If editing, populate form
|
|
||||||
if (dog) {
|
|
||||||
setFormData({
|
|
||||||
...dog,
|
|
||||||
sire_id: dog.sire?.id || null, // ✅ CORRECT
|
|
||||||
dam_id: dog.dam?.id || null, // ✅ CORRECT
|
|
||||||
birth_date: dog.birth_date || '',
|
|
||||||
registration_number: dog.registration_number || '',
|
|
||||||
microchip: dog.microchip || '',
|
|
||||||
color: dog.color || '',
|
|
||||||
notes: dog.notes || ''
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [dog]);
|
|
||||||
|
|
||||||
const handleSubmit = async (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
const payload = {
|
|
||||||
name: formData.name,
|
|
||||||
breed: formData.breed,
|
|
||||||
sex: formData.sex,
|
|
||||||
sire_id: formData.sire_id, // ✅ CORRECT
|
|
||||||
dam_id: formData.dam_id, // ✅ CORRECT
|
|
||||||
litter_id: formData.litter_id,
|
|
||||||
birth_date: formData.birth_date || null,
|
|
||||||
registration_number: formData.registration_number || null,
|
|
||||||
microchip: formData.microchip || null,
|
|
||||||
color: formData.color || null,
|
|
||||||
notes: formData.notes || null
|
|
||||||
};
|
|
||||||
|
|
||||||
const url = dog ? `/api/dogs/${dog.id}` : '/api/dogs';
|
|
||||||
const method = dog ? 'PUT' : 'POST';
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch(url, {
|
|
||||||
method,
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify(payload)
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
const error = await response.json();
|
|
||||||
throw new Error(error.error || 'Failed to save dog');
|
|
||||||
}
|
|
||||||
|
|
||||||
const savedDog = await response.json();
|
|
||||||
onSubmit(savedDog);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error saving dog:', error);
|
|
||||||
alert(error.message);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form onSubmit={handleSubmit}>
|
|
||||||
{/* Basic fields */}
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
placeholder="Name"
|
|
||||||
value={formData.name}
|
|
||||||
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
placeholder="Breed"
|
|
||||||
value={formData.breed}
|
|
||||||
onChange={(e) => setFormData({ ...formData, breed: e.target.value })}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
|
|
||||||
<select
|
|
||||||
value={formData.sex}
|
|
||||||
onChange={(e) => setFormData({ ...formData, sex: e.target.value })}
|
|
||||||
required
|
|
||||||
>
|
|
||||||
<option value="male">Male</option>
|
|
||||||
<option value="female">Female</option>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
{/* Parent selection */}
|
|
||||||
<label>Sire (Father)</label>
|
|
||||||
<select
|
|
||||||
value={formData.sire_id || ''} // ✅ CORRECT
|
|
||||||
onChange={(e) => setFormData({
|
|
||||||
...formData,
|
|
||||||
sire_id: e.target.value ? parseInt(e.target.value) : null // ✅ CORRECT
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<option value="">Select Sire (Optional)</option>
|
|
||||||
{males.map(dog => (
|
|
||||||
<option key={dog.id} value={dog.id}>{dog.name}</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<label>Dam (Mother)</label>
|
|
||||||
<select
|
|
||||||
value={formData.dam_id || ''} // ✅ CORRECT
|
|
||||||
onChange={(e) => setFormData({
|
|
||||||
...formData,
|
|
||||||
dam_id: e.target.value ? parseInt(e.target.value) : null // ✅ CORRECT
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<option value="">Select Dam (Optional)</option>
|
|
||||||
{females.map(dog => (
|
|
||||||
<option key={dog.id} value={dog.name}</option>
|
|
||||||
))}
|
|
||||||
</select>
|
|
||||||
|
|
||||||
{/* Other fields */}
|
|
||||||
<input
|
|
||||||
type="date"
|
|
||||||
value={formData.birth_date}
|
|
||||||
onChange={(e) => setFormData({ ...formData, birth_date: e.target.value })}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
placeholder="Registration Number"
|
|
||||||
value={formData.registration_number}
|
|
||||||
onChange={(e) => setFormData({ ...formData, registration_number: e.target.value })}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
placeholder="Microchip"
|
|
||||||
value={formData.microchip}
|
|
||||||
onChange={(e) => setFormData({ ...formData, microchip: e.target.value })}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
placeholder="Color"
|
|
||||||
value={formData.color}
|
|
||||||
onChange={(e) => setFormData({ ...formData, color: e.target.value })}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<textarea
|
|
||||||
placeholder="Notes"
|
|
||||||
value={formData.notes}
|
|
||||||
onChange={(e) => setFormData({ ...formData, notes: e.target.value })}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<button type="submit">{dog ? 'Update' : 'Create'} Dog</button>
|
|
||||||
<button type="button" onClick={onCancel}>Cancel</button>
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DogForm;
|
|
||||||
```
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
|
|
||||||
✅ **Backend is correct** - Database and API use `sire_id`/`dam_id`
|
|
||||||
❌ **Frontend needs update** - Forms still use `sire`/`dam`
|
|
||||||
|
|
||||||
**Fix**: Replace all instances of `sire`/`dam` with `sire_id`/`dam_id` in frontend forms.
|
|
||||||
@@ -1,350 +0,0 @@
|
|||||||
# Implementation Plan: Enhanced Litters & Pedigree Features
|
|
||||||
|
|
||||||
## Project Overview
|
|
||||||
Complete implementation of litter management features and interactive pedigree visualization with family tree functionality.
|
|
||||||
|
|
||||||
## Phase 1: Interactive Pedigree Tree ✅ (Priority 1)
|
|
||||||
|
|
||||||
### 1.1 Core Pedigree Component
|
|
||||||
- [ ] Install react-d3-tree dependency
|
|
||||||
- [ ] Create PedigreeTree component with D3 visualization
|
|
||||||
- [ ] Implement data transformation from API to tree format
|
|
||||||
- [ ] Add zoom and pan controls
|
|
||||||
- [ ] Implement color coding (blue for males, pink for females)
|
|
||||||
- [ ] Add node click navigation
|
|
||||||
- [ ] Display node information (name, registration, birth year, sex)
|
|
||||||
- [ ] Show 5 generations by default
|
|
||||||
|
|
||||||
### 1.2 Pedigree Page Enhancement
|
|
||||||
- [ ] Replace placeholder with full PedigreeTree component
|
|
||||||
- [ ] Add generation selector (3, 4, 5 generations)
|
|
||||||
- [ ] Add COI display prominently
|
|
||||||
- [ ] Add "View as PDF" export button (future)
|
|
||||||
- [ ] Add "Print" button with print-friendly view
|
|
||||||
- [ ] Add loading states
|
|
||||||
- [ ] Add error handling for missing data
|
|
||||||
- [ ] Add breadcrumb navigation
|
|
||||||
|
|
||||||
### 1.3 Pedigree Features
|
|
||||||
- [ ] Collapsible/expandable nodes
|
|
||||||
- [ ] Tooltip on hover with full details
|
|
||||||
- [ ] Highlight common ancestors
|
|
||||||
- [ ] Show linebreeding indicators
|
|
||||||
- [ ] Add legend for colors and symbols
|
|
||||||
- [ ] Responsive design for mobile
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Phase 2: Enhanced Litter Management (Priority 2)
|
|
||||||
|
|
||||||
### 2.1 Litter Detail Page
|
|
||||||
- [ ] Create LitterDetail.jsx page
|
|
||||||
- [ ] Display litter overview card
|
|
||||||
- [ ] Sire and dam information with photos
|
|
||||||
- [ ] Breeding date
|
|
||||||
- [ ] Expected whelping date (63 days)
|
|
||||||
- [ ] Actual whelping date
|
|
||||||
- [ ] Puppy count (expected vs actual)
|
|
||||||
- [ ] COI calculation for the pairing
|
|
||||||
- [ ] Add timeline view of litter events
|
|
||||||
- [ ] Add notes section
|
|
||||||
|
|
||||||
### 2.2 Puppy Management
|
|
||||||
- [ ] Create PuppyBatchAdd component
|
|
||||||
- [ ] Quick add multiple puppies form
|
|
||||||
- [ ] Auto-increment names (Puppy 1, Puppy 2, etc.)
|
|
||||||
- [ ] Bulk set common fields (breed, birth date)
|
|
||||||
- [ ] Individual customization per puppy
|
|
||||||
- [ ] Puppy list view within litter
|
|
||||||
- [ ] Individual puppy cards with quick actions
|
|
||||||
- [ ] Drag-and-drop photo upload per puppy
|
|
||||||
- [ ] Bulk actions (delete, export)
|
|
||||||
|
|
||||||
### 2.3 Litter Photo Gallery
|
|
||||||
- [ ] Create LitterGallery component
|
|
||||||
- [ ] Upload litter photos (not tied to specific puppy)
|
|
||||||
- [ ] Display in grid/carousel view
|
|
||||||
- [ ] Photo captions and dates
|
|
||||||
- [ ] Delete/reorder photos
|
|
||||||
- [ ] Lightbox view for full-size images
|
|
||||||
|
|
||||||
### 2.4 Whelping Countdown
|
|
||||||
- [ ] Create CountdownWidget component
|
|
||||||
- [ ] Calculate days until expected whelping
|
|
||||||
- [ ] Show progress bar
|
|
||||||
- [ ] Alert when within 7 days
|
|
||||||
- [ ] Update when actual date recorded
|
|
||||||
- [ ] Show "days since birth" after whelping
|
|
||||||
|
|
||||||
### 2.5 Enhanced Litter List
|
|
||||||
- [ ] Add "Create New Litter" button
|
|
||||||
- [ ] Add filters (upcoming, current, past)
|
|
||||||
- [ ] Add search by parent names
|
|
||||||
- [ ] Add sorting (date, puppy count)
|
|
||||||
- [ ] Show countdown for upcoming litters
|
|
||||||
- [ ] Show puppy count badge
|
|
||||||
- [ ] Add quick actions (edit, view, delete)
|
|
||||||
- [ ] Add litter status badges (planned, pregnant, whelped)
|
|
||||||
|
|
||||||
### 2.6 Litter Form Enhancement
|
|
||||||
- [ ] Create comprehensive LitterForm component
|
|
||||||
- [ ] Add expected puppy count field
|
|
||||||
- [ ] Add notes/comments field
|
|
||||||
- [ ] Add breeding method dropdown (natural, AI, etc.)
|
|
||||||
- [ ] Add progesterone level tracking
|
|
||||||
- [ ] Add ultrasound confirmation date
|
|
||||||
- [ ] Validation for logical dates
|
|
||||||
- [ ] Auto-calculate expected whelping
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Phase 3: Litter Statistics & Analytics (Priority 3)
|
|
||||||
|
|
||||||
### 3.1 Litter Statistics Dashboard
|
|
||||||
- [ ] Create LitterStats component
|
|
||||||
- [ ] Display on Dashboard and LitterDetail pages
|
|
||||||
- [ ] Show average litter size
|
|
||||||
- [ ] Show male/female ratio
|
|
||||||
- [ ] Show breeding success rate
|
|
||||||
- [ ] Show most productive pairings
|
|
||||||
- [ ] Show genetic diversity metrics
|
|
||||||
- [ ] Charts using Chart.js or Recharts
|
|
||||||
|
|
||||||
### 3.2 Parent Performance
|
|
||||||
- [ ] Track individual sire/dam statistics
|
|
||||||
- [ ] Show on DogDetail page
|
|
||||||
- [ ] Number of litters produced
|
|
||||||
- [ ] Total offspring count
|
|
||||||
- [ ] Average litter size
|
|
||||||
- [ ] Success rate
|
|
||||||
- [ ] Link to all their litters
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Phase 4: Integration & Polish (Priority 4)
|
|
||||||
|
|
||||||
### 4.1 Dog Profile Integration
|
|
||||||
- [ ] Add "View Pedigree" button on DogDetail page
|
|
||||||
- [ ] Add "Litters" tab on DogDetail page
|
|
||||||
- [ ] Show offspring list
|
|
||||||
- [ ] Show parent information with links
|
|
||||||
- [ ] Show siblings
|
|
||||||
|
|
||||||
### 4.2 Navigation Enhancement
|
|
||||||
- [ ] Add Pedigree to main navigation
|
|
||||||
- [ ] Add Litters to main navigation
|
|
||||||
- [ ] Add breadcrumbs to all pages
|
|
||||||
- [ ] Add back buttons where appropriate
|
|
||||||
|
|
||||||
### 4.3 Performance Optimization
|
|
||||||
- [ ] Lazy load pedigree tree data
|
|
||||||
- [ ] Implement API caching for pedigree
|
|
||||||
- [ ] Optimize image loading for galleries
|
|
||||||
- [ ] Add loading skeletons
|
|
||||||
- [ ] Debounce search inputs
|
|
||||||
|
|
||||||
### 4.4 Error Handling & UX
|
|
||||||
- [ ] Add error boundaries
|
|
||||||
- [ ] Add retry mechanisms
|
|
||||||
- [ ] Add empty states for all lists
|
|
||||||
- [ ] Add confirmation dialogs for destructive actions
|
|
||||||
- [ ] Add success/error toast notifications
|
|
||||||
- [ ] Add form validation with helpful messages
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Technical Implementation Details
|
|
||||||
|
|
||||||
### Dependencies to Install
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"react-d3-tree": "^3.6.2",
|
|
||||||
"react-toastify": "^9.1.3",
|
|
||||||
"date-fns": "^2.30.0"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### API Endpoints Needed
|
|
||||||
|
|
||||||
#### Existing (verify functionality)
|
|
||||||
- GET `/api/litters` - List all litters
|
|
||||||
- POST `/api/litters` - Create litter
|
|
||||||
- GET `/api/litters/:id` - Get litter details
|
|
||||||
- PUT `/api/litters/:id` - Update litter
|
|
||||||
- DELETE `/api/litters/:id` - Delete litter
|
|
||||||
- GET `/api/pedigree/:id` - Get pedigree tree
|
|
||||||
|
|
||||||
#### New Endpoints to Create
|
|
||||||
- POST `/api/litters/:id/puppies/batch` - Batch add puppies
|
|
||||||
- GET `/api/litters/:id/photos` - Get litter photos
|
|
||||||
- POST `/api/litters/:id/photos` - Upload litter photo
|
|
||||||
- DELETE `/api/litters/:id/photos/:photoId` - Delete litter photo
|
|
||||||
- GET `/api/litters/statistics` - Get litter statistics
|
|
||||||
- GET `/api/dogs/:id/offspring` - Get dog's offspring
|
|
||||||
- GET `/api/dogs/:id/litters` - Get dog's litters (as parent)
|
|
||||||
|
|
||||||
### Database Schema Changes
|
|
||||||
|
|
||||||
#### Add to `litters` table:
|
|
||||||
```sql
|
|
||||||
ALTER TABLE litters ADD COLUMN expected_puppy_count INTEGER;
|
|
||||||
ALTER TABLE litters ADD COLUMN actual_puppy_count INTEGER;
|
|
||||||
ALTER TABLE litters ADD COLUMN notes TEXT;
|
|
||||||
ALTER TABLE litters ADD COLUMN breeding_method VARCHAR(50);
|
|
||||||
ALTER TABLE litters ADD COLUMN progesterone_level DECIMAL(5,2);
|
|
||||||
ALTER TABLE litters ADD COLUMN ultrasound_date DATE;
|
|
||||||
ALTER TABLE litters ADD COLUMN status VARCHAR(20) DEFAULT 'planned';
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Create `litter_photos` table:
|
|
||||||
```sql
|
|
||||||
CREATE TABLE IF NOT EXISTS litter_photos (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
litter_id INTEGER NOT NULL,
|
|
||||||
filename VARCHAR(255) NOT NULL,
|
|
||||||
path VARCHAR(255) NOT NULL,
|
|
||||||
caption TEXT,
|
|
||||||
upload_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
display_order INTEGER DEFAULT 0,
|
|
||||||
FOREIGN KEY (litter_id) REFERENCES litters(id) ON DELETE CASCADE
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Component Structure
|
|
||||||
|
|
||||||
```
|
|
||||||
client/src/
|
|
||||||
├── components/
|
|
||||||
│ ├── PedigreeTree.jsx (NEW)
|
|
||||||
│ ├── PuppyBatchAdd.jsx (NEW)
|
|
||||||
│ ├── LitterGallery.jsx (NEW)
|
|
||||||
│ ├── CountdownWidget.jsx (NEW)
|
|
||||||
│ ├── LitterStats.jsx (NEW)
|
|
||||||
│ └── LitterForm.jsx (ENHANCE)
|
|
||||||
├── pages/
|
|
||||||
│ ├── PedigreeView.jsx (REBUILD)
|
|
||||||
│ ├── LitterList.jsx (ENHANCE)
|
|
||||||
│ ├── LitterDetail.jsx (NEW)
|
|
||||||
│ └── DogDetail.jsx (ENHANCE)
|
|
||||||
└── utils/
|
|
||||||
├── pedigreeHelpers.js (NEW)
|
|
||||||
└── dateHelpers.js (NEW)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Testing Checklist
|
|
||||||
|
|
||||||
### Pedigree Tree
|
|
||||||
- [ ] Displays correctly for dogs with complete lineage
|
|
||||||
- [ ] Handles missing parents gracefully
|
|
||||||
- [ ] Zoom and pan work smoothly
|
|
||||||
- [ ] Node clicks navigate to correct dog
|
|
||||||
- [ ] COI displays correctly
|
|
||||||
- [ ] Colors are correct for male/female
|
|
||||||
- [ ] Responsive on mobile
|
|
||||||
- [ ] Print view works
|
|
||||||
|
|
||||||
### Litter Management
|
|
||||||
- [ ] Can create new litter
|
|
||||||
- [ ] Can add puppies individually
|
|
||||||
- [ ] Can batch add puppies
|
|
||||||
- [ ] Puppies auto-link to litter parents
|
|
||||||
- [ ] Can upload photos
|
|
||||||
- [ ] Countdown displays correctly
|
|
||||||
- [ ] Expected vs actual puppy count tracks
|
|
||||||
- [ ] Can edit litter details
|
|
||||||
- [ ] Can delete litter (with confirmation)
|
|
||||||
- [ ] Statistics calculate correctly
|
|
||||||
|
|
||||||
### Integration
|
|
||||||
- [ ] Pedigree accessible from dog profile
|
|
||||||
- [ ] Litters show on parent profiles
|
|
||||||
- [ ] Navigation works smoothly
|
|
||||||
- [ ] No console errors
|
|
||||||
- [ ] Loading states display
|
|
||||||
- [ ] Error states display
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Implementation Order (Suggested)
|
|
||||||
|
|
||||||
### Sprint 1 (4-6 hours): Pedigree Tree
|
|
||||||
1. Install react-d3-tree
|
|
||||||
2. Create PedigreeTree component
|
|
||||||
3. Rebuild PedigreeView page
|
|
||||||
4. Add controls and styling
|
|
||||||
5. Test with existing data
|
|
||||||
|
|
||||||
### Sprint 2 (4-6 hours): Litter Detail & Enhancements
|
|
||||||
1. Create database migration for litter enhancements
|
|
||||||
2. Create LitterDetail page
|
|
||||||
3. Create CountdownWidget
|
|
||||||
4. Enhance LitterList
|
|
||||||
5. Create LitterForm enhancements
|
|
||||||
|
|
||||||
### Sprint 3 (3-4 hours): Puppy Management
|
|
||||||
1. Create PuppyBatchAdd component
|
|
||||||
2. Add batch API endpoint
|
|
||||||
3. Integrate into LitterDetail
|
|
||||||
4. Test puppy workflow
|
|
||||||
|
|
||||||
### Sprint 4 (2-3 hours): Photo Gallery
|
|
||||||
1. Create database migration for litter_photos
|
|
||||||
2. Create LitterGallery component
|
|
||||||
3. Add photo upload API endpoints
|
|
||||||
4. Integrate into LitterDetail
|
|
||||||
|
|
||||||
### Sprint 5 (2-3 hours): Statistics & Integration
|
|
||||||
1. Create LitterStats component
|
|
||||||
2. Add statistics API endpoint
|
|
||||||
3. Add pedigree/litter links to DogDetail
|
|
||||||
4. Update navigation
|
|
||||||
|
|
||||||
### Sprint 6 (2 hours): Polish & Testing
|
|
||||||
1. Add error handling
|
|
||||||
2. Add loading states
|
|
||||||
3. Add confirmation dialogs
|
|
||||||
4. Test all workflows
|
|
||||||
5. Fix bugs
|
|
||||||
6. Update documentation
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Success Criteria
|
|
||||||
|
|
||||||
### Pedigree
|
|
||||||
- ✅ Interactive tree with 5 generations
|
|
||||||
- ✅ Zoom, pan, and navigation work smoothly
|
|
||||||
- ✅ COI displayed prominently
|
|
||||||
- ✅ Print-friendly view available
|
|
||||||
- ✅ Responsive design
|
|
||||||
|
|
||||||
### Litters
|
|
||||||
- ✅ Full litter lifecycle management (planned → pregnant → whelped)
|
|
||||||
- ✅ Batch puppy addition saves time
|
|
||||||
- ✅ Photo galleries enhance visual tracking
|
|
||||||
- ✅ Countdown helps with planning
|
|
||||||
- ✅ Statistics provide insights
|
|
||||||
- ✅ Integration with dogs is seamless
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Documentation Updates Needed
|
|
||||||
|
|
||||||
- [ ] Update README.md with new features
|
|
||||||
- [ ] Update ROADMAP.md with completion status
|
|
||||||
- [ ] Create USER_GUIDE.md section for litters
|
|
||||||
- [ ] Create USER_GUIDE.md section for pedigree
|
|
||||||
- [ ] Document API endpoints in API_DOCS.md
|
|
||||||
- [ ] Add screenshots to documentation
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
- Prioritize pedigree tree first as it's highly visible and impressive
|
|
||||||
- Litter features build on each other, implement in order
|
|
||||||
- Consider adding unit tests for complex calculations (COI, dates)
|
|
||||||
- Keep accessibility in mind (keyboard navigation, screen readers)
|
|
||||||
- Consider adding undo/redo for batch operations
|
|
||||||
@@ -1,305 +0,0 @@
|
|||||||
# Sprint 1 Complete: Interactive Pedigree Tree ✅
|
|
||||||
|
|
||||||
## What Was Built
|
|
||||||
|
|
||||||
A fully interactive, production-ready pedigree tree visualization system for BREEDR.
|
|
||||||
|
|
||||||
### Components Created
|
|
||||||
|
|
||||||
1. **PedigreeTree.jsx** - Core D3 tree visualization component
|
|
||||||
- Interactive zoom and pan controls
|
|
||||||
- Color-coded nodes (blue for males, pink for females)
|
|
||||||
- Click-to-navigate functionality
|
|
||||||
- Responsive design
|
|
||||||
- COI display with risk indicators
|
|
||||||
- Legend for visual reference
|
|
||||||
|
|
||||||
2. **PedigreeTree.css** - Complete styling
|
|
||||||
- Polished UI with controls overlay
|
|
||||||
- Mobile-responsive breakpoints
|
|
||||||
- Print-friendly styles
|
|
||||||
- Smooth animations and transitions
|
|
||||||
|
|
||||||
3. **pedigreeHelpers.js** - Utility functions
|
|
||||||
- `transformPedigreeData()` - Converts API data to D3 tree format
|
|
||||||
- `countAncestors()` - Counts total ancestors
|
|
||||||
- `getGenerationCounts()` - Analyzes generation distribution
|
|
||||||
- `isPedigreeComplete()` - Checks pedigree completeness
|
|
||||||
- `findCommonAncestors()` - Identifies shared ancestors
|
|
||||||
- `formatCOI()` - Formats COI with risk levels
|
|
||||||
- `getPedigreeCompleteness()` - Calculates completeness percentage
|
|
||||||
|
|
||||||
4. **PedigreeView.jsx** - Full page implementation
|
|
||||||
- Stats dashboard showing COI, completeness, generation selector
|
|
||||||
- Loading and error states
|
|
||||||
- Breadcrumb navigation
|
|
||||||
- Help tips for users
|
|
||||||
- Responsive grid layout
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
### ✅ Interactive Controls
|
|
||||||
- Zoom In/Out buttons
|
|
||||||
- Reset view button
|
|
||||||
- Mouse wheel zoom
|
|
||||||
- Click and drag to pan
|
|
||||||
- Touch support for mobile
|
|
||||||
|
|
||||||
### ✅ Visual Enhancements
|
|
||||||
- Color-coded by sex (♂ blue, ♀ pink)
|
|
||||||
- Registration numbers displayed
|
|
||||||
- Birth years shown
|
|
||||||
- Clean, modern design
|
|
||||||
- Smooth animations
|
|
||||||
|
|
||||||
### ✅ Data Display
|
|
||||||
- COI with color-coded risk levels:
|
|
||||||
- **Green** (≤5%): Low inbreeding, excellent diversity
|
|
||||||
- **Yellow** (5-10%): Moderate inbreeding, acceptable with caution
|
|
||||||
- **Red** (>10%): High inbreeding, consider genetic diversity
|
|
||||||
- Pedigree completeness percentage
|
|
||||||
- Generation selector (3, 4, or 5 generations)
|
|
||||||
- Progress bars and visual indicators
|
|
||||||
|
|
||||||
### ✅ Navigation
|
|
||||||
- Click any node to view that dog's profile
|
|
||||||
- Back to Profile button
|
|
||||||
- Breadcrumb navigation
|
|
||||||
- Deep linking support
|
|
||||||
|
|
||||||
### ✅ Responsive Design
|
|
||||||
- Desktop optimized
|
|
||||||
- Tablet friendly
|
|
||||||
- Mobile responsive
|
|
||||||
- Print-friendly layout
|
|
||||||
|
|
||||||
## Installation & Setup
|
|
||||||
|
|
||||||
### 1. Install Dependencies
|
|
||||||
|
|
||||||
The required dependencies should already be in `package.json`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd client
|
|
||||||
npm install
|
|
||||||
```
|
|
||||||
|
|
||||||
Key dependencies:
|
|
||||||
- `react-d3-tree`: ^3.6.2 - D3 tree visualization
|
|
||||||
- `date-fns`: ^2.30.0 - Date formatting utilities
|
|
||||||
- `d3`: ^7.9.0 - D3 core library
|
|
||||||
|
|
||||||
### 2. Deploy the Branch
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git checkout feature/enhanced-litters-and-pedigree
|
|
||||||
git pull origin feature/enhanced-litters-and-pedigree
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Restart the Application
|
|
||||||
|
|
||||||
**With Docker:**
|
|
||||||
```bash
|
|
||||||
docker-compose down
|
|
||||||
docker-compose up --build -d
|
|
||||||
```
|
|
||||||
|
|
||||||
**Without Docker:**
|
|
||||||
```bash
|
|
||||||
# Terminal 1 - Server
|
|
||||||
cd server
|
|
||||||
npm install
|
|
||||||
npm run dev
|
|
||||||
|
|
||||||
# Terminal 2 - Client
|
|
||||||
cd client
|
|
||||||
npm install
|
|
||||||
npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Access the Pedigree
|
|
||||||
|
|
||||||
Navigate to any dog and access the pedigree at:
|
|
||||||
```
|
|
||||||
http://localhost:5173/pedigree/:dogId
|
|
||||||
```
|
|
||||||
|
|
||||||
For example:
|
|
||||||
```
|
|
||||||
http://localhost:5173/pedigree/1
|
|
||||||
```
|
|
||||||
|
|
||||||
## Testing Checklist
|
|
||||||
|
|
||||||
### Basic Functionality
|
|
||||||
- [ ] Pedigree page loads without errors
|
|
||||||
- [ ] Tree displays correctly for dogs with parents
|
|
||||||
- [ ] Nodes show correct information (name, registration, birth year)
|
|
||||||
- [ ] Colors are correct (blue=male, pink=female)
|
|
||||||
|
|
||||||
### Interactive Controls
|
|
||||||
- [ ] Zoom in button works
|
|
||||||
- [ ] Zoom out button works
|
|
||||||
- [ ] Reset button returns to default view
|
|
||||||
- [ ] Mouse wheel zoom works
|
|
||||||
- [ ] Click and drag panning works
|
|
||||||
|
|
||||||
### Navigation
|
|
||||||
- [ ] Clicking a node navigates to that dog's profile
|
|
||||||
- [ ] Back to Profile button works
|
|
||||||
- [ ] Generation selector changes displayed generations
|
|
||||||
|
|
||||||
### Data Display
|
|
||||||
- [ ] COI displays correctly with proper color
|
|
||||||
- [ ] Pedigree completeness calculates accurately
|
|
||||||
- [ ] Stats update when generation selector changes
|
|
||||||
|
|
||||||
### Edge Cases
|
|
||||||
- [ ] Handles dogs with no parents gracefully
|
|
||||||
- [ ] Handles dogs with only one parent
|
|
||||||
- [ ] Handles incomplete pedigrees
|
|
||||||
- [ ] Shows appropriate message when no data available
|
|
||||||
|
|
||||||
### Responsive Design
|
|
||||||
- [ ] Works on desktop (1920x1080)
|
|
||||||
- [ ] Works on tablet (768x1024)
|
|
||||||
- [ ] Works on mobile (375x667)
|
|
||||||
- [ ] Print view displays correctly
|
|
||||||
|
|
||||||
## API Requirements
|
|
||||||
|
|
||||||
The pedigree tree depends on these existing API endpoints:
|
|
||||||
|
|
||||||
### Required Endpoints
|
|
||||||
|
|
||||||
1. **GET `/api/pedigree/:id`** - Get pedigree tree
|
|
||||||
- Must return nested sire/dam objects
|
|
||||||
- Should include: id, name, sex, registration_number, birth_date
|
|
||||||
- Example response:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"name": "Dog Name",
|
|
||||||
"sex": "male",
|
|
||||||
"registration_number": "ABC123",
|
|
||||||
"birth_date": "2020-01-01",
|
|
||||||
"sire": {
|
|
||||||
"id": 2,
|
|
||||||
"name": "Father Name",
|
|
||||||
"sex": "male",
|
|
||||||
"sire": { ... },
|
|
||||||
"dam": { ... }
|
|
||||||
},
|
|
||||||
"dam": {
|
|
||||||
"id": 3,
|
|
||||||
"name": "Mother Name",
|
|
||||||
"sex": "female",
|
|
||||||
"sire": { ... },
|
|
||||||
"dam": { ... }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **GET `/api/pedigree/:id/coi`** - Get COI calculation
|
|
||||||
- Returns coefficient of inbreeding
|
|
||||||
- Example response:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"coi": 3.125,
|
|
||||||
"generations": 5
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Known Limitations
|
|
||||||
|
|
||||||
1. **Performance**: Very large pedigrees (>100 nodes) may experience slowdown
|
|
||||||
2. **COI**: Calculation requires complete pedigree data
|
|
||||||
3. **Mobile**: Tree may be difficult to navigate on very small screens
|
|
||||||
4. **Print**: May require landscape orientation for best results
|
|
||||||
|
|
||||||
## Future Enhancements (Not in Sprint 1)
|
|
||||||
|
|
||||||
- [ ] PDF export functionality
|
|
||||||
- [ ] Highlight common ancestors between two dogs
|
|
||||||
- [ ] Show inbreeding loops visually
|
|
||||||
- [ ] Ancestor search/filter
|
|
||||||
- [ ] Save custom tree views
|
|
||||||
- [ ] Share pedigree links
|
|
||||||
- [ ] Printable certificate template
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Tree Doesn't Display
|
|
||||||
- Check browser console for errors
|
|
||||||
- Verify API endpoint `/api/pedigree/:id` is working
|
|
||||||
- Check that dog has parent data in database
|
|
||||||
- Ensure dependencies are installed (`npm install`)
|
|
||||||
|
|
||||||
### Zoom/Pan Not Working
|
|
||||||
- Check that react-d3-tree is properly installed
|
|
||||||
- Clear browser cache and reload
|
|
||||||
- Try in different browser
|
|
||||||
|
|
||||||
### COI Not Showing
|
|
||||||
- Verify `/api/pedigree/:id/coi` endpoint exists
|
|
||||||
- Check that pedigree has sufficient data (at least 3 generations)
|
|
||||||
- COI may be null for incomplete pedigrees
|
|
||||||
|
|
||||||
### Styling Issues
|
|
||||||
- Ensure `PedigreeTree.css` is imported in component
|
|
||||||
- Check that CSS variables are defined in main stylesheet
|
|
||||||
- Clear browser cache
|
|
||||||
|
|
||||||
## Files Modified/Created
|
|
||||||
|
|
||||||
### New Files
|
|
||||||
```
|
|
||||||
client/src/
|
|
||||||
├── components/
|
|
||||||
│ ├── PedigreeTree.jsx ✅ NEW
|
|
||||||
│ └── PedigreeTree.css ✅ NEW
|
|
||||||
├── utils/
|
|
||||||
│ └── pedigreeHelpers.js ✅ NEW
|
|
||||||
└── pages/
|
|
||||||
└── PedigreeView.jsx ✅ UPDATED
|
|
||||||
```
|
|
||||||
|
|
||||||
### Modified Files
|
|
||||||
- `client/package.json` - Dependencies already present
|
|
||||||
- `client/src/pages/PedigreeView.jsx` - Rebuilt from placeholder
|
|
||||||
|
|
||||||
## Next Steps
|
|
||||||
|
|
||||||
Sprint 1 is **COMPLETE** ✅
|
|
||||||
|
|
||||||
Ready to proceed with Sprint 2:
|
|
||||||
- **Litter Detail Page** with comprehensive information
|
|
||||||
- **Countdown Widget** for whelping dates
|
|
||||||
- **Enhanced Litter List** with filters and sorting
|
|
||||||
- **Database Migration** for additional litter fields
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Support
|
|
||||||
|
|
||||||
If you encounter issues:
|
|
||||||
1. Check browser console for errors
|
|
||||||
2. Review this documentation
|
|
||||||
3. Check API endpoints are responding
|
|
||||||
4. Verify database has parent relationships
|
|
||||||
|
|
||||||
## Success Criteria Met ✅
|
|
||||||
|
|
||||||
- ✅ Interactive tree with D3 visualization
|
|
||||||
- ✅ 5-generation display (configurable to 3, 4, or 5)
|
|
||||||
- ✅ Zoom, pan, and navigation controls
|
|
||||||
- ✅ Color-coded nodes by sex
|
|
||||||
- ✅ COI display with risk indicators
|
|
||||||
- ✅ Pedigree completeness tracking
|
|
||||||
- ✅ Click-to-navigate functionality
|
|
||||||
- ✅ Responsive design
|
|
||||||
- ✅ Loading and error states
|
|
||||||
- ✅ Helper utilities for data transformation
|
|
||||||
- ✅ Print-friendly layout
|
|
||||||
|
|
||||||
**Sprint 1: COMPLETE AND READY FOR TESTING** 🎉
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Quick migration script for microchip field fix
|
|
||||||
# Run this after deploying the updated code
|
|
||||||
|
|
||||||
echo "======================================================"
|
|
||||||
echo "BREEDR: Microchip Field Migration"
|
|
||||||
echo "======================================================"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Check if container is running
|
|
||||||
if ! docker ps | grep -q breedr; then
|
|
||||||
echo "Error: breedr container is not running"
|
|
||||||
echo "Please start the container first: docker start breedr"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Running migration inside container..."
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
docker exec breedr node server/db/migrate_microchip.js
|
|
||||||
|
|
||||||
if [ $? -eq 0 ]; then
|
|
||||||
echo ""
|
|
||||||
echo "======================================================"
|
|
||||||
echo "Migration completed successfully!"
|
|
||||||
echo "======================================================"
|
|
||||||
echo ""
|
|
||||||
echo "Restarting container to apply changes..."
|
|
||||||
docker restart breedr
|
|
||||||
echo ""
|
|
||||||
echo "Done! Microchip field is now optional."
|
|
||||||
else
|
|
||||||
echo ""
|
|
||||||
echo "Migration failed. Check the error above."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
Reference in New Issue
Block a user