refactor(api): standardize venues endpoint
Some checks failed
Deploy Fediversion / deploy (push) Failing after 1s

- Backend: /api/venues returns PaginatedResponse envelope
- Frontend: Updated VenuesPage, AdminVenuesPage, VerticalVenuesPage to consume envelope
This commit is contained in:
fullsizemalt 2025-12-30 20:35:59 -08:00
parent c0e3e2a7e2
commit 3aaf35d43b
4 changed files with 34 additions and 27 deletions

View file

@ -1,9 +1,9 @@
from typing import List
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlmodel import Session, select
from sqlmodel import Session, select, func
from database import get_session
from models import Venue
from schemas import VenueCreate, VenueRead, VenueUpdate
from schemas import VenueCreate, VenueRead, VenueUpdate, PaginatedResponse, PaginationMeta
from auth import get_current_user
router = APIRouter(prefix="/venues", tags=["venues"])
@ -16,10 +16,14 @@ def create_venue(venue: VenueCreate, session: Session = Depends(get_session), cu
session.refresh(db_venue)
return db_venue
@router.get("/", response_model=List[VenueRead])
@router.get("/", response_model=PaginatedResponse[VenueRead])
def read_venues(offset: int = 0, limit: int = Query(default=1000, le=1000), session: Session = Depends(get_session)):
total = session.exec(select(func.count()).select_from(Venue)).one()
venues = session.exec(select(Venue).offset(offset).limit(limit)).all()
return venues
return PaginatedResponse(
data=venues,
meta=PaginationMeta(total=total, limit=limit, offset=offset)
)
@router.get("/{slug}", response_model=VenueRead)
def read_venue(slug: str, session: Session = Depends(get_session)):

View file

@ -18,7 +18,8 @@ async function getVenues(verticalSlug: string) {
next: { revalidate: 60 }
})
if (!res.ok) return []
return res.json()
const data = await res.json()
return data.data || []
} catch {
return []
}

View file

@ -1,6 +1,6 @@
"use client"
import { useEffect, useState } from "react"
import { useEffect, useState, useCallback } from "react"
import { useAuth } from "@/contexts/auth-context"
import { useRouter } from "next/navigation"
import { Card, CardContent } from "@/components/ui/card"
@ -38,6 +38,24 @@ export default function AdminVenuesPage() {
const [editingVenue, setEditingVenue] = useState<Venue | null>(null)
const [saving, setSaving] = useState(false)
const fetchVenues = useCallback(async () => {
if (!token) return
try {
const res = await fetch(`${getApiUrl()}/venues?limit=200`, {
headers: { Authorization: `Bearer ${token}` }
})
if (res.ok) {
const data = await res.json()
setVenues(data.data || [])
}
} catch (e) {
console.error("Failed to fetch venues", e)
} finally {
setLoading(false)
}
}, [token])
useEffect(() => {
if (authLoading) return
if (!user) {
@ -49,25 +67,7 @@ export default function AdminVenuesPage() {
return
}
fetchVenues()
}, [user, router, authLoading])
const fetchVenues = async () => {
if (!token) return
try {
const res = await fetch(`${getApiUrl()}/venues?limit=200`, {
headers: { Authorization: `Bearer ${token}` }
})
if (res.ok) {
const data = await res.json()
setVenues(data.venues || data)
}
} catch (e) {
console.error("Failed to fetch venues", e)
} finally {
setLoading(false)
}
}
}, [user, router, authLoading, fetchVenues])
const updateVenue = async () => {
if (!token || !editingVenue) return

View file

@ -34,11 +34,13 @@ export default function VenuesPage() {
setError(null)
// Fetch venues
const venuesRes = await fetch(`${getApiUrl()}/venues/`)
const venuesData: Venue[] = await venuesRes.json()
const venuesEnvelope = await venuesRes.json()
const venuesData: Venue[] = venuesEnvelope.data || []
// Fetch show counts for each venue (batch approach)
const showsRes = await fetch(`${getApiUrl()}/shows/?limit=1000`)
const showsData = await showsRes.json()
const showsEnvelope = await showsRes.json()
const showsData = showsEnvelope.data || []
// Count shows per venue
const showCounts: Record<number, number> = {}