story-research-zapwall/components/ArticleReviews.tsx
2025-12-23 02:20:57 +01:00

81 lines
2.5 KiB
TypeScript

import { useEffect, useState } from 'react'
import type { Review } from '@/types/nostr'
import { getReviewsForArticle } from '@/lib/reviews'
import { getReviewTipsForArticle } from '@/lib/reviewAggregation'
interface ArticleReviewsProps {
articleId: string
authorPubkey: string
}
export function ArticleReviews({ articleId, authorPubkey }: ArticleReviewsProps) {
const [reviews, setReviews] = useState<Review[]>([])
const [tips, setTips] = useState<number>(0)
const [loading, setLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
useEffect(() => {
const load = async () => {
setLoading(true)
setError(null)
try {
const [list, tipsTotal] = await Promise.all([
getReviewsForArticle(articleId),
getReviewTipsForArticle({ authorPubkey, articleId }),
])
setReviews(list)
setTips(tipsTotal)
} catch (e) {
setError(e instanceof Error ? e.message : 'Erreur lors du chargement des critiques')
} finally {
setLoading(false)
}
}
void load()
}, [articleId, authorPubkey])
return (
<div className="border rounded-lg p-4 bg-white space-y-3">
<ArticleReviewsHeader tips={tips} />
{loading && <p className="text-sm text-gray-600">Chargement des critiques...</p>}
{error && <p className="text-sm text-red-600">{error}</p>}
{!loading && !error && reviews.length === 0 && <p className="text-sm text-gray-600">Aucune critique.</p>}
{!loading && !error && <ArticleReviewsList reviews={reviews} />}
</div>
)
}
function ArticleReviewsHeader({ tips }: { tips: number }) {
return (
<div className="flex items-center justify-between">
<h3 className="text-lg font-semibold">Critiques</h3>
<span className="text-sm text-gray-600">Remerciements versés : {tips} sats</span>
</div>
)
}
function ArticleReviewsList({ reviews }: { reviews: Review[] }) {
return (
<>
{reviews.map((r) => (
<div key={r.id} className="border-t pt-2 text-sm">
<div className="text-gray-800">{r.content}</div>
<div className="text-xs text-gray-500 flex gap-2">
<span>Auteur critique : {formatPubkey(r.reviewerPubkey)}</span>
<span></span>
<span>{formatDate(r.createdAt)}</span>
</div>
</div>
))}
</>
)
}
function formatPubkey(pubkey: string): string {
return `${pubkey.slice(0, 8)}...${pubkey.slice(-8)}`
}
function formatDate(timestamp: number): string {
return new Date(timestamp * 1000).toLocaleString()
}