elmeg-demo/frontend/components/social/comment-section.tsx

117 lines
3.9 KiB
TypeScript

"use client"
import { useState, useEffect } from "react"
import { Button } from "@/components/ui/button"
import { Textarea } from "@/components/ui/textarea"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { formatDistanceToNow } from "date-fns"
import { getApiUrl } from "@/lib/api-config"
interface Comment {
id: number
user_id: number
content: string
created_at: string
}
interface CommentSectionProps {
entityType: "show" | "venue" | "song" | "tour" | "performance" | "year"
entityId: number
}
export function CommentSection({ entityType, entityId }: CommentSectionProps) {
const [comments, setComments] = useState<Comment[]>([])
const [newComment, setNewComment] = useState("")
const [loading, setLoading] = useState(false)
useEffect(() => {
fetchComments()
}, [entityType, entityId])
const fetchComments = async () => {
try {
const res = await fetch(`${getApiUrl()}/social/comments?${entityType}_id=${entityId}`)
if (res.ok) {
const data = await res.json()
setComments(data)
}
} catch (err) {
console.error("Failed to fetch comments", err)
}
}
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
if (!newComment.trim()) return
const token = localStorage.getItem("token")
if (!token) {
alert("Please log in to comment.")
return
}
setLoading(true)
try {
const body: any = { content: newComment }
body[`${entityType}_id`] = entityId
const res = await fetch(`${getApiUrl()}/social/comments`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`
},
body: JSON.stringify(body)
})
if (!res.ok) throw new Error("Failed to post comment")
const savedComment = await res.json()
setComments(prev => [savedComment, ...prev])
setNewComment("")
} catch (err) {
console.error(err)
alert("Error posting comment")
} finally {
setLoading(false)
}
}
return (
<div className="space-y-6">
<h3 className="text-xl font-semibold">Comments</h3>
<form onSubmit={handleSubmit} className="space-y-4">
<Textarea
placeholder="Join the discussion..."
value={newComment}
onChange={(e) => setNewComment(e.target.value)}
required
/>
<Button type="submit" disabled={loading || !newComment.trim()}>
{loading ? "Posting..." : "Post Comment"}
</Button>
</form>
<div className="space-y-4">
{comments.length === 0 ? (
<p className="text-muted-foreground">No comments yet.</p>
) : (
comments.map(comment => (
<Card key={comment.id}>
<CardContent className="pt-4">
<div className="flex justify-between items-start mb-2">
<span className="font-semibold text-sm">User #{comment.user_id}</span>
<span className="text-xs text-muted-foreground">
{formatDistanceToNow(new Date(comment.created_at), { addSuffix: true })}
</span>
</div>
<p className="text-sm whitespace-pre-wrap">{comment.content}</p>
</CardContent>
</Card>
))
)}
</div>
</div>
)
}