From 39013fc7c5539c89993f457ce6c998d249f62640 Mon Sep 17 00:00:00 2001 From: jason Date: Mon, 9 Mar 2026 01:14:48 -0500 Subject: [PATCH 1/3] Add frontend fix guide for Add Dog form --- FRONTEND_FIX_REQUIRED.md | 408 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 408 insertions(+) create mode 100644 FRONTEND_FIX_REQUIRED.md diff --git a/FRONTEND_FIX_REQUIRED.md b/FRONTEND_FIX_REQUIRED.md new file mode 100644 index 0000000..e2122b3 --- /dev/null +++ b/FRONTEND_FIX_REQUIRED.md @@ -0,0 +1,408 @@ +# 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 })} + /> + +