'use client'; import { useEffect, useState, useCallback } from 'react'; import Link from 'next/link'; import { Gift, PlusCircle, Sparkles, CheckCircle2, Clock, Users, ShieldCheck, ArrowRight, RefreshCw, LogIn, } from 'lucide-react'; import { GiveawaySummary } from '@/lib/repository/giveaway-repository'; export default function DashboardPage() { const [giveaways, setGiveaways] = useState([]); const [loading, setLoading] = useState(true); const [isUnauthenticated, setIsUnauthenticated] = useState(false); const fetchGiveaways = useCallback(async () => { setLoading(true); try { const res = await fetch('/api/giveaways'); if (res.status === 401) { setIsUnauthenticated(true); setGiveaways([]); return; } setIsUnauthenticated(false); const data = await res.json(); if (data.giveaways) { setGiveaways(data.giveaways); } } catch (err) { console.error('Failed to load giveaways:', err); } finally { setLoading(false); } }, []); useEffect(() => { let ignore = false; fetch('/api/giveaways') .then(res => { if (res.status === 401) { if (!ignore) { setIsUnauthenticated(true); setGiveaways([]); } return null; } return res.json(); }) .then(data => { if (!ignore && data && data.giveaways) { setIsUnauthenticated(false); setGiveaways(data.giveaways); } }) .catch(err => { console.error('Failed to load giveaways:', err); }) .finally(() => { if (!ignore) { setLoading(false); } }); return () => { ignore = true; }; }, []); const completedCount = giveaways.filter(g => g.status === 'DRAWN' || g.status === 'PUBLISHED').length; const totalEligible = giveaways.reduce((acc, g) => acc + (g.eligibleParticipantsCount || 0), 0); return (
{/* Hero Welcome Banner */}
Честные розыгрыши ВКонтакте

Честный рандомайзер с доказуемым результатом

Выбирайте победителей по лайкам и комментариям. Каждый розыгрыш фиксируется неизменяемым слепком (Snapshot) и криптографическим auditHash (HMAC-SHA256).

Создать новый розыгрыш
{/* Metrics Grid */}
Всего кампаний
{giveaways.length}
Проведено розыгрышей
{completedCount}
Участников в розыгрышах
{totalEligible}
{/* List of Giveaways */}

Список розыгрышей

История созданных и завершенных конкурсов

{loading ? (
Загрузка списка...
) : isUnauthenticated ? (

Требуется авторизация

Войдите через VK ID, чтобы управлять своими конкурсами и просматривать историю розыгрышей.

Войти через VK ID
) : giveaways.length === 0 ? (

Пока нет созданных розыгрышей

Вставьте ссылку на пост ВКонтакте, чтобы загрузить участников и зафиксировать результат

Создать первый розыгрыш
) : (
{giveaways.map((gw) => (
VK

{gw.title || 'Розыгрыш по записи VK'}

{gw.sourceUrl}

Создан: {new Date(gw.createdAt).toLocaleDateString('ru-RU')} Лайков: {gw.postLikesCount} Комментов: {gw.postCommentsCount}
{gw.status === 'DRAWN' || gw.status === 'PUBLISHED' ? ( {gw.status} ) : gw.status === 'SNAPSHOT_LOCKED' ? ( Слепок зафиксирован ) : ( {gw.status} )} Подробнее
))}
)}
{/* Provably Fair Info Box */}

Как гарантируется честность результатов?

Перед жеребьевкой список участников фиксируется в неизменяемый слепок и хешируется по стандарту SHA-256. Победитель определяется алгоритмом HMAC_SHA256_FY_V1 с rejection sampling. Любой зритель может воспроизвести результат и проверить неизменность выборки.

); }