fix: add pagination to unbounded GET endpoints

All list endpoints now accept ?page and ?limit (default 50, max 200) and
return { data, total, page, limit } instead of a bare array, preventing
memory and performance failures at scale.

- GET /api/dogs: adds pagination, server-side search (?search) and sex
  filter (?sex), and a stats aggregate (total/males/females) for the
  Dashboard to avoid counting from the array
- GET /api/litters: adds pagination; also fixes N+1 query by fetching
  all puppies for the current page in a single query instead of one per
  litter
- DogList: moves search/sex filtering server-side with 300ms debounce;
  adds Prev/Next pagination controls
- LitterList: uses paginated response; adds Prev/Next pagination controls
- Dashboard: reads counts from stats/total fields instead of array length
- LitterDetail, LitterForm: switch dogs fetch to /api/dogs/all (complete
  list, no pagination, for sire/dam dropdowns)
- DogForm: updates litters fetch to use paginated response shape

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
jason
2026-03-16 16:40:28 -05:00
parent fa7a336588
commit b8633863b0
8 changed files with 197 additions and 68 deletions

View File

@@ -64,8 +64,8 @@ function DogForm({ dog, onClose, onSave, isExternal = false }) {
const fetchLitters = async () => {
try {
const res = await axios.get('/api/litters')
const data = res.data || []
const res = await axios.get('/api/litters', { params: { limit: 200 } })
const data = res.data.data || []
setLitters(data)
setLittersAvailable(data.length > 0)
if (data.length === 0) setUseManualParents(true)

View File

@@ -39,7 +39,7 @@ function LitterForm({ litter, prefill, onClose, onSave }) {
const fetchDogs = async () => {
try {
const res = await axios.get('/api/dogs')
const res = await axios.get('/api/dogs/all')
setDogs(res.data)
} catch (error) {
console.error('Error fetching dogs:', error)