'use client' import { useState } from 'react' import { useTranslations } from 'next-intl' import type { VoteSite } from '@/lib/vote' export function VotePanel({ sites, canVote }: { sites: VoteSite[]; canVote: boolean }) { const t = useTranslations('Vote') const [busyId, setBusyId] = useState(null) const [message, setMessage] = useState<{ ok: boolean; text: string } | null>(null) async function vote(site: VoteSite) { if (busyId !== null) return window.open(site.url, '_blank', 'noopener,noreferrer') setBusyId(site.id) setMessage(null) try { const res = await fetch('/api/vote', { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'same-origin', body: JSON.stringify({ url: site.url }), }) const d: { success?: boolean; error?: string; points?: number; siteName?: string; hours?: number; minutes?: number } = await res.json() if (d.success) { setMessage({ ok: true, text: t('success', { site: d.siteName ?? site.name, points: d.points ?? 0 }) }) } else if (d.error === 'cooldown') { setMessage({ ok: false, text: t('cooldown', { hours: d.hours ?? 0, minutes: d.minutes ?? 0 }) }) } else { setMessage({ ok: false, text: t(d.error === 'siteNotFound' ? 'siteNotFound' : 'genericError') }) } } catch { setMessage({ ok: false, text: t('genericError') }) } finally { setBusyId(null) } } if (sites.length === 0) return

{t('noSites')}

return (
{sites.map((s) => (
{s.image_url && ( // eslint-disable-next-line @next/next/no-img-element {s.name} )}

{s.name}

{s.points} {t('pv')}

{canVote ? ( ) : ( {t('vote')} )}
))}
{message && {message.text}}
{!canVote &&

{t('loginToVote')}

}
) }