# 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 ``` **Change to:** ```jsx ``` ### 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 (
{/* Basic fields */} setFormData({ ...formData, name: e.target.value })} required /> setFormData({ ...formData, breed: e.target.value })} required /> {/* Parent selection */} {/* Other fields */} setFormData({ ...formData, birth_date: e.target.value })} /> setFormData({ ...formData, registration_number: e.target.value })} /> setFormData({ ...formData, microchip: e.target.value })} /> setFormData({ ...formData, color: e.target.value })} />