feat(api): add endpoint to fetch guest list

* implement ListGuests method in store
* create handleGuestList function in API
* add GuestListEntry and GuestList interfaces in UI
* create guest list page to display RSVPs
This commit is contained in:
2026-08-12 19:21:14 +02:00
parent 2c28b18098
commit df5d8efeb1
5 changed files with 152 additions and 6 deletions
+33
View File
@@ -33,6 +33,7 @@ func (s *Server) Routes(mux *http.ServeMux) {
mux.HandleFunc("GET /healthz", s.handleHealthz)
mux.HandleFunc("GET /api/config", s.handleConfig)
mux.HandleFunc("POST /api/rsvp", s.handleRSVP)
mux.HandleFunc("GET /api/guests", s.handleGuestList)
mux.HandleFunc("POST /api/photos/upload", s.handlePhotoUpload)
}
@@ -108,6 +109,38 @@ func (s *Server) handleRSVP(w http.ResponseWriter, r *http.Request) {
writeJSON(w, http.StatusCreated, map[string]bool{"ok": true})
}
type guestResponse struct {
Name string `json:"name"`
IsChild bool `json:"isChild"`
}
func (s *Server) handleGuestList(w http.ResponseWriter, r *http.Request) {
guests, err := s.store.ListGuests()
if err != nil {
log.Printf("guests: list failed: %v", err)
writeError(w, http.StatusInternalServerError, "could not load guests")
return
}
out := make([]guestResponse, 0, len(guests))
adults, children := 0, 0
for _, g := range guests {
out = append(out, guestResponse{Name: g.Name, IsChild: g.IsChild})
if g.IsChild {
children++
} else {
adults++
}
}
writeJSON(w, http.StatusOK, map[string]any{
"guests": out,
"total": len(out),
"adults": adults,
"children": children,
})
}
var allowedImageTypes = map[string]bool{
"image/jpeg": true,
"image/png": true,
+24
View File
@@ -78,6 +78,30 @@ type RSVP struct {
Message string
}
// ListGuests returns every RSVP'd guest, ordered by submission then entry order.
func (s *Store) ListGuests() ([]Guest, error) {
rows, err := s.db.Query(
`SELECT g.name, g.is_child
FROM rsvp_guests g
JOIN rsvps r ON r.id = g.rsvp_id
ORDER BY r.created_at ASC, g.id ASC`,
)
if err != nil {
return nil, err
}
defer rows.Close()
var guests []Guest
for rows.Next() {
var g Guest
if err := rows.Scan(&g.Name, &g.IsChild); err != nil {
return nil, err
}
guests = append(guests, g)
}
return guests, rows.Err()
}
func (s *Store) InsertRSVP(r RSVP) error {
tx, err := s.db.Begin()
if err != nil {