From e44883b5e08c9300877d337c260a7b892564f396 Mon Sep 17 00:00:00 2001 From: jason Date: Mon, 9 Mar 2026 22:58:41 -0500 Subject: [PATCH] feat(dogs): add delete button with confirm modal on DogList --- client/src/pages/DogList.jsx | 187 +++++++++++++++++++++++++++-------- 1 file changed, 147 insertions(+), 40 deletions(-) diff --git a/client/src/pages/DogList.jsx b/client/src/pages/DogList.jsx index 1815348..ba5f79c 100644 --- a/client/src/pages/DogList.jsx +++ b/client/src/pages/DogList.jsx @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react' -import { Link } from 'react-router-dom' -import { Dog, Plus, Search, Calendar, Hash, ArrowRight } from 'lucide-react' +import { Link, useNavigate } from 'react-router-dom' +import { Dog, Plus, Search, Calendar, Hash, ArrowRight, Trash2 } from 'lucide-react' import axios from 'axios' import DogForm from '../components/DogForm' import { ChampionBadge, ChampionBloodlineBadge } from '../components/ChampionBadge' @@ -12,6 +12,8 @@ function DogList() { const [sexFilter, setSexFilter] = useState('all') const [loading, setLoading] = useState(true) const [showAddModal, setShowAddModal] = useState(false) + const [deleteTarget, setDeleteTarget] = useState(null) // { id, name } + const [deleting, setDeleting] = useState(false) useEffect(() => { fetchDogs() }, []) useEffect(() => { filterDogs() }, [dogs, search, sexFilter]) @@ -43,6 +45,21 @@ function DogList() { const handleSave = () => { fetchDogs() } + const handleDelete = async () => { + if (!deleteTarget) return + setDeleting(true) + try { + await axios.delete(`/api/dogs/${deleteTarget.id}`) + setDogs(prev => prev.filter(d => d.id !== deleteTarget.id)) + setDeleteTarget(null) + } catch (err) { + console.error('Delete failed:', err) + alert('Failed to delete dog. Please try again.') + } finally { + setDeleting(false) + } + } + const calculateAge = (birthDate) => { if (!birthDate) return null const today = new Date() @@ -55,7 +72,6 @@ function DogList() { return `${years}y ${months}mo` } - // A dog has champion blood if sire or dam is a champion const hasChampionBlood = (dog) => (dog.sire && dog.sire.is_champion) || (dog.dam && dog.dam.is_champion) @@ -132,18 +148,15 @@ function DogList() { ) : (
{filteredDogs.map(dog => ( - { e.currentTarget.style.borderColor = 'var(--primary)' @@ -157,36 +170,44 @@ function DogList() { }} > {/* Avatar */} -
- {dog.photo_urls && dog.photo_urls.length > 0 ? ( - {dog.name} - ) : ( - - )} -
+ +
+ {dog.photo_urls && dog.photo_urls.length > 0 ? ( + {dog.name} + ) : ( + + )} +
+ - {/* Info */} -
+ {/* Info — clicking navigates to detail */} +

)} -

+ -
- + {/* Actions */} +
+ + + +
- +
))}
)} + {/* Add Dog Modal */} {showAddModal && ( setShowAddModal(false)} onSave={handleSave} /> )} + + {/* Delete Confirmation Modal */} + {deleteTarget && ( +
+
+
+ +
+

Delete Dog?

+

+ {deleteTarget.name} will be + permanently removed along with all parent relationships, health records, + and heat cycles. This cannot be undone. +

+
+ + +
+
+
+ )} ) }