From 32b45a4fb370525aa7fb7f228928d04f8331b2f3 Mon Sep 17 00:00:00 2001 From: jason Date: Sun, 8 Mar 2026 23:31:02 -0500 Subject: [PATCH] Redesign: Horizontal info cards with avatars for Dogs list --- client/src/pages/DogList.jsx | 234 +++++++++++++++++++++++++++++------ 1 file changed, 195 insertions(+), 39 deletions(-) diff --git a/client/src/pages/DogList.jsx b/client/src/pages/DogList.jsx index 9f0c7bf..d1e6aed 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 } from 'lucide-react' +import { Dog, Plus, Search, Calendar, Hash, ArrowRight } from 'lucide-react' import axios from 'axios' import DogForm from '../components/DogForm' @@ -52,68 +52,224 @@ function DogList() { fetchDogs() } + const calculateAge = (birthDate) => { + if (!birthDate) return null + const today = new Date() + const birth = new Date(birthDate) + let years = today.getFullYear() - birth.getFullYear() + let months = today.getMonth() - birth.getMonth() + + if (months < 0) { + years-- + months += 12 + } + + if (years === 0) return `${months}mo` + if (months === 0) return `${years}y` + return `${years}y ${months}mo` + } + if (loading) { return
Loading dogs...
} return ( -
+
-

Dogs

+
+

Dogs

+

+ {filteredDogs.length} {filteredDogs.length === 1 ? 'dog' : 'dogs'} + {search || sexFilter !== 'all' ? ' matching filters' : ' total'} +

+
-
-
+ {/* Search and Filter Bar */} +
+
- + setSearch(e.target.value)} - style={{ paddingLeft: '2.5rem' }} + style={{ paddingLeft: '2.75rem' }} />
- setSexFilter(e.target.value)} style={{ width: '140px' }}> + + + + {(search || sexFilter !== 'all') && ( + + )}
-
- {filteredDogs.map(dog => ( - -
- {dog.photo_urls && dog.photo_urls.length > 0 ? ( - {dog.name} - ) : ( - - )} -
-

{dog.name}

-

- {dog.breed} • {dog.sex === 'male' ? '♂' : '♀'} -

- {dog.registration_number && ( -

{dog.registration_number}

- )} - {dog.birth_date && ( -

Born: {new Date(dog.birth_date).toLocaleDateString()}

- )} - - ))} -
+ {/* Dogs List */} + {filteredDogs.length === 0 ? ( +
+ +

+ {search || sexFilter !== 'all' ? 'No dogs found' : 'No dogs yet'} +

+

+ {search || sexFilter !== 'all' + ? 'Try adjusting your search or filters' + : 'Add your first dog to get started'} +

+ {!search && sexFilter === 'all' && ( + + )} +
+ ) : ( +
+ {filteredDogs.map(dog => ( + { + e.currentTarget.style.borderColor = 'var(--primary)' + e.currentTarget.style.transform = 'translateY(-2px)' + e.currentTarget.style.boxShadow = '0 8px 16px rgba(0, 0, 0, 0.3)' + }} + onMouseLeave={(e) => { + e.currentTarget.style.borderColor = 'var(--border)' + e.currentTarget.style.transform = 'translateY(0)' + e.currentTarget.style.boxShadow = 'var(--shadow-sm)' + }} + > + {/* Avatar Photo */} +
+ {dog.photo_urls && dog.photo_urls.length > 0 ? ( + {dog.name} + ) : ( + + )} +
- {filteredDogs.length === 0 && ( -
-

No dogs found matching your search criteria.

+ {/* Info Section */} +
+

+ {dog.name} + + {dog.sex === 'male' ? '♂' : '♀'} + +

+ +
+ {dog.breed} + {dog.birth_date && ( + <> + + + + {calculateAge(dog.birth_date)} + + + )} + {dog.color && ( + <> + + {dog.color} + + )} +
+ + {dog.registration_number && ( +
+ + {dog.registration_number} +
+ )} +
+ + {/* Arrow Indicator */} +
+ +
+ + ))}
)}