- Fork elmeg-demo codebase for multi-band support - Add data importer infrastructure with base class - Create band-specific importers: - phish.py: Phish.net API v5 - grateful_dead.py: Grateful Stats API - setlistfm.py: Dead & Company, Billy Strings (Setlist.fm) - Add spec-kit configuration for Gemini - Update README with supported bands and architecture
87 lines
2.9 KiB
TypeScript
87 lines
2.9 KiB
TypeScript
"use client"
|
|
|
|
import { useEffect, useState } from "react"
|
|
import { AttendanceButton } from "@/components/ui/attendance-button"
|
|
import { Button } from "@/components/ui/button"
|
|
import { Check, Plus } from "lucide-react"
|
|
import { getApiUrl } from "@/lib/api-config"
|
|
|
|
// I'll assume I need to fetch directly if no auth context
|
|
// Actually, let's check if auth-context exists.
|
|
// I saw `contexts` folder in `frontend`.
|
|
|
|
interface ShowAttendanceProps {
|
|
showId: number
|
|
}
|
|
|
|
export function ShowAttendance({ showId }: ShowAttendanceProps) {
|
|
const [attended, setAttended] = useState(false)
|
|
const [loading, setLoading] = useState(true)
|
|
const [token, setToken] = useState<string | null>(null)
|
|
|
|
useEffect(() => {
|
|
// Simple token retrieval from localStorage for now
|
|
const t = localStorage.getItem("token")
|
|
setToken(t)
|
|
|
|
if (token) {
|
|
fetch(`${getApiUrl()}/attendance/me`, {
|
|
headers: { Authorization: `Bearer ${token}` }
|
|
})
|
|
.then(res => {
|
|
if (res.ok) return res.json()
|
|
throw new Error("Failed to fetch attendance")
|
|
})
|
|
.then((data: any[]) => {
|
|
const isAttended = data.some((a: any) => a.show_id === showId)
|
|
setAttended(isAttended)
|
|
})
|
|
.catch(err => console.error(err))
|
|
.finally(() => setLoading(false))
|
|
} else {
|
|
setLoading(false)
|
|
}
|
|
}, [showId])
|
|
|
|
const handleToggle = async (newState: boolean) => {
|
|
if (!token) {
|
|
alert("Please login to mark attendance")
|
|
return
|
|
}
|
|
|
|
try {
|
|
if (newState) {
|
|
if (!attended) {
|
|
// Mark attendance
|
|
const res = await fetch(`${getApiUrl()}/attendance/`, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
Authorization: `Bearer ${token}`
|
|
},
|
|
body: JSON.stringify({ show_id: showId })
|
|
})
|
|
if (!res.ok) throw new Error("Failed to mark attendance")
|
|
} else {
|
|
}
|
|
} else {
|
|
// Unmark
|
|
const res = await fetch(`${getApiUrl()}/attendance/${showId}`, {
|
|
method: "DELETE",
|
|
headers: {
|
|
Authorization: `Bearer ${token}`
|
|
}
|
|
})
|
|
if (!res.ok) throw new Error("Failed to remove attendance")
|
|
}
|
|
setAttended(newState)
|
|
} catch (err) {
|
|
console.error(err)
|
|
alert("Something went wrong")
|
|
}
|
|
}
|
|
|
|
if (loading) return <Button variant="outline" disabled>Loading...</Button>
|
|
|
|
return <AttendanceButton initialAttended={attended} onToggle={handleToggle} />
|
|
}
|