elmeg-demo/frontend/components/social/entity-rating.tsx

79 lines
2.7 KiB
TypeScript

"use client"
import { useState, useEffect } from "react"
import { StarRating } from "@/components/ui/star-rating"
import { getApiUrl } from "@/lib/api-config"
interface EntityRatingProps {
entityType: "show" | "song" | "venue" | "tour"
entityId: number
}
export function EntityRating({ entityType, entityId }: EntityRatingProps) {
const [userRating, setUserRating] = useState(0)
const [averageRating, setAverageRating] = useState(0)
const [loading, setLoading] = useState(false)
useEffect(() => {
// Fetch average rating
fetch(`${getApiUrl()}/social/ratings/average?${entityType}_id=${entityId}`)
.then(res => res.json())
.then(data => setAverageRating(data))
.catch(err => console.error("Failed to fetch avg rating", err))
// Fetch user rating (if logged in)
const token = localStorage.getItem("token")
if (token) {
// We don't have a direct "get my rating" endpoint in the snippet I saw,
// but we can infer it or maybe we need to add one.
// For now, let's assume we can't easily get *my* rating without a specific endpoint
// or filtering the list.
// Actually, the backend `create_rating` checks for existing.
// Let's just implement setting it for now.
}
}, [entityType, entityId])
const handleRate = async (score: number) => {
const token = localStorage.getItem("token")
if (!token) {
alert("Please log in to rate.")
return
}
setLoading(true)
try {
const body: any = { score }
body[`${entityType}_id`] = entityId
const res = await fetch(`${getApiUrl()}/social/ratings`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`
},
body: JSON.stringify(body)
})
if (!res.ok) throw new Error("Failed to submit rating")
const data = await res.json()
setUserRating(data.score)
// Refresh average?
} catch (err) {
console.error(err)
alert("Error submitting rating")
} finally {
setLoading(false)
}
}
return (
<div className="flex items-center gap-2 border-l pl-4">
<div className="flex flex-col">
<span className="text-sm font-medium">Rating:</span>
<span className="text-xs text-muted-foreground">Avg: {averageRating.toFixed(1)}</span>
</div>
<StarRating value={userRating} onChange={handleRate} />
</div>
)
}