From dc07f2a98df11a555d3827dc96388e49fac63ef2 Mon Sep 17 00:00:00 2001 From: delta-lynx-89e8 Date: Sun, 22 Feb 2026 17:03:23 -0800 Subject: [PATCH] fix: price sorting by period type, pagination, avgRating on dashboard - Sort by monthlyPrice when periodType=MONTHLY instead of always dailyPrice - Fix client-side pagination in MyBookingsPage and LandlordListingsPage - Compute avgRating in /rentals/mine endpoint so dashboard shows ratings - Fix falsy filter for avgRating=0 on landlord dashboard Co-Authored-By: Claude Opus 4.6 --- client/src/pages/MyBookingsPage.tsx | 6 ++---- .../src/pages/landlord/LandlordDashboardPage.tsx | 2 +- .../src/pages/landlord/LandlordListingsPage.tsx | 6 ++---- server/src/routes/rental.ts | 15 +++++++++++---- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/client/src/pages/MyBookingsPage.tsx b/client/src/pages/MyBookingsPage.tsx index 753c12a..d8039e0 100644 --- a/client/src/pages/MyBookingsPage.tsx +++ b/client/src/pages/MyBookingsPage.tsx @@ -17,7 +17,6 @@ const STATUS_TABS: (BookingStatus | 'ALL')[] = ['ALL', 'PENDING', 'CONFIRMED', ' export function MyBookingsPage() { const navigate = useNavigate(); const [bookings, setBookings] = useState([]); - const [total, setTotal] = useState(0); const [page, setPage] = useState(1); const [tab, setTab] = useState('ALL'); const [, setLoading] = useState(true); @@ -37,7 +36,6 @@ export function MyBookingsPage() { try { const res = await api.get(`/bookings?${params}`); setBookings(res); - setTotal(res.length); } catch { setBookings([]); } finally { @@ -170,8 +168,8 @@ export function MyBookingsPage() { render: (b: Booking) => , }, ]} - data={bookings} - total={total} + data={bookings.slice((page - 1) * 20, page * 20)} + total={bookings.length} page={page} pageSize={20} onPageChange={setPage} diff --git a/client/src/pages/landlord/LandlordDashboardPage.tsx b/client/src/pages/landlord/LandlordDashboardPage.tsx index ca1a238..7234278 100644 --- a/client/src/pages/landlord/LandlordDashboardPage.tsx +++ b/client/src/pages/landlord/LandlordDashboardPage.tsx @@ -38,7 +38,7 @@ export function LandlordDashboardPage() { .filter((b) => b.status === 'COMPLETED') .reduce((sum, b) => sum + b.totalAmount, 0); - const ratings = rentalsRes.filter((r) => r.avgRating).map((r) => r.avgRating!); + const ratings = rentalsRes.filter((r) => r.avgRating !== undefined && r.avgRating !== null).map((r) => r.avgRating!); const avgRating = ratings.length > 0 ? ratings.reduce((a, b) => a + b, 0) / ratings.length : 0; setStats({ totalRentals, activeBookings, revenue, avgRating }); diff --git a/client/src/pages/landlord/LandlordListingsPage.tsx b/client/src/pages/landlord/LandlordListingsPage.tsx index 52367e0..36d0e8e 100644 --- a/client/src/pages/landlord/LandlordListingsPage.tsx +++ b/client/src/pages/landlord/LandlordListingsPage.tsx @@ -9,7 +9,6 @@ import type { RentalListing } from '../../types/rental'; export function LandlordListingsPage() { const [listings, setListings] = useState([]); - const [total, setTotal] = useState(0); const [page, setPage] = useState(1); const [search, setSearch] = useState(''); @@ -19,7 +18,6 @@ export function LandlordListingsPage() { if (search) params.set('search', search); const res = await api.get(`/rentals/mine?${params}`); setListings(res); - setTotal(res.length); } catch { // silently fail } @@ -143,8 +141,8 @@ export function LandlordListingsPage() { render: (l: RentalListing) => l._count?.bookings ?? 0, }, ]} - data={listings} - total={total} + data={listings.slice((page - 1) * 20, page * 20)} + total={listings.length} page={page} pageSize={20} onPageChange={setPage} diff --git a/server/src/routes/rental.ts b/server/src/routes/rental.ts index a37220b..e9d2692 100644 --- a/server/src/routes/rental.ts +++ b/server/src/routes/rental.ts @@ -37,10 +37,16 @@ router.get('/mine', authenticate, async (req, res, next) => { const listings = await prisma.rentalListing.findMany({ where, - select: rentalSelect, + select: { ...rentalSelect, reviews: { select: { rating: true } } }, orderBy: { createdAt: 'desc' }, }); - res.json(listings); + const withRatings = listings.map(l => ({ + ...l, + avgRating: l.reviews.length > 0 + ? l.reviews.reduce((sum, r) => sum + r.rating, 0) / l.reviews.length + : undefined, + })); + res.json(withRatings); } catch (error) { next(error); } @@ -111,8 +117,9 @@ router.get('/', optionalAuth, async (req, res, next) => { where.dailyPrice = priceFilter; } - const orderBy = sort === 'price_asc' ? { dailyPrice: 'asc' as const } - : sort === 'price_desc' ? { dailyPrice: 'desc' as const } + const priceField = periodType === 'MONTHLY' ? 'monthlyPrice' : 'dailyPrice'; + const orderBy = sort === 'price_asc' ? { [priceField]: 'asc' as const } + : sort === 'price_desc' ? { [priceField]: 'desc' as const } : sort === 'popular' ? { viewCount: 'desc' as const } : { createdAt: 'desc' as const };