/** * Rewards Section - Referral System * Uses real blockchain data from ReferralContext */ import { useState, useEffect, useCallback } from 'react'; import { Gift, Users, Trophy, Copy, Check, Share2, RefreshCw, Star, TrendingUp, Award, Zap, Coins, Shield, Target, Sparkles, GraduationCap, } from 'lucide-react'; import { cn, formatAddress } from '@/lib/utils'; import { useTelegram } from '@/hooks/useTelegram'; import { useAuth } from '@/contexts/AuthContext'; import { useReferral } from '@/contexts/ReferralContext'; import { useWallet } from '@/contexts/WalletContext'; import { SocialLinks } from '@/components/SocialLinks'; import { getAllScoresWithFallback, getFrontendStakingScore, formatStakedAmount, getScoreColor, getScoreRating, type FrontendTrustScoreResult, type FrontendStakingScoreResult, } from '@/lib/scores'; // Activity tracking constants const ACTIVITY_STORAGE_KEY = 'pezkuwi_last_active'; const ACTIVITY_DURATION_MS = 24 * 60 * 60 * 1000; // 24 hours export function RewardsSection() { const { hapticImpact, hapticNotification, shareUrl, showAlert } = useTelegram(); const { user: authUser } = useAuth(); const { stats, myReferrals, loading, refreshStats } = useReferral(); const { isConnected, address, api, peopleApi } = useWallet(); const [copied, setCopied] = useState(false); const [activeTab, setActiveTab] = useState<'overview' | 'referrals' | 'scores'>('overview'); const [isActive, setIsActive] = useState(false); const [timeRemaining, setTimeRemaining] = useState(null); const [userScores, setUserScores] = useState< (FrontendTrustScoreResult & { isFromFrontend: boolean }) | null >(null); const [stakingDetails, setStakingDetails] = useState(null); const [scoresLoading, setScoresLoading] = useState(false); // Check activity status const checkActivityStatus = useCallback(() => { const lastActive = localStorage.getItem(ACTIVITY_STORAGE_KEY); if (lastActive) { const lastActiveTime = parseInt(lastActive, 10); const now = Date.now(); const elapsed = now - lastActiveTime; if (elapsed < ACTIVITY_DURATION_MS) { setIsActive(true); const remaining = ACTIVITY_DURATION_MS - elapsed; const hours = Math.floor(remaining / (60 * 60 * 1000)); const minutes = Math.floor((remaining % (60 * 60 * 1000)) / (60 * 1000)); setTimeRemaining(`${hours}s ${minutes}d`); } else { setIsActive(false); setTimeRemaining(null); } } else { setIsActive(false); setTimeRemaining(null); } }, []); // Check activity status on mount and every minute useEffect(() => { // Run check after a microtask to avoid synchronous setState in effect const timeoutId = setTimeout(checkActivityStatus, 0); const interval = setInterval(checkActivityStatus, 60000); return () => { clearTimeout(timeoutId); clearInterval(interval); }; }, [checkActivityStatus]); // Fetch user scores when on scores tab const fetchUserScores = useCallback(async () => { if (!address) { setUserScores(null); setStakingDetails(null); return; } setScoresLoading(true); try { const [scores, staking] = await Promise.all([ getAllScoresWithFallback(peopleApi, api, address), api ? getFrontendStakingScore(api, address) : Promise.resolve(null), ]); setUserScores(scores); setStakingDetails(staking); } catch (err) { console.error('Error fetching scores:', err); } finally { setScoresLoading(false); } }, [api, peopleApi, address]); // Fetch scores when tab changes to scores or on initial load useEffect(() => { if (activeTab === 'scores' && address) { fetchUserScores(); } }, [activeTab, address, fetchUserScores]); const handleActivate = () => { hapticNotification('success'); localStorage.setItem(ACTIVITY_STORAGE_KEY, Date.now().toString()); setIsActive(true); setTimeRemaining('24s 0d'); showAlert('Tu niha aktîv î! 24 saet paşê dîsa bikirtîne.'); }; // Telegram referral link (for sharing) - use authenticated user ID const referralLink = authUser?.telegram_id ? `https://t.me/pezkuwichain_bot?start=ref_${authUser.telegram_id}` : 'https://t.me/pezkuwichain_bot'; const handleCopy = async () => { try { await window.navigator.clipboard.writeText(referralLink); setCopied(true); hapticNotification('success'); setTimeout(() => setCopied(false), 2000); } catch { showAlert('Kopî bû'); } }; const handleShare = () => { hapticImpact('medium'); shareUrl( referralLink, 'Pezkuwichain - Dewleta Dîjîtal a Kurd! Bi lînka min ve tev li me bibe:' ); }; const handleRefresh = () => { hapticImpact('medium'); refreshStats(); }; // Calculate points per referral based on position const getPointsForPosition = (position: number): number => { if (position <= 10) return 10; if (position <= 50) return 5; if (position <= 100) return 4; return 0; }; if (!isConnected) { return (

Xelat - Referral System

Ji bo dîtina referral û xelatên xwe, berî her tiştî cîzdanê xwe girêde.

); } return (
{/* Header */}

Xelat

{/* Tabs */}
{[ { id: 'overview' as const, label: 'Geşbîn' }, { id: 'referrals' as const, label: 'Referral' }, { id: 'scores' as const, label: 'Xal' }, ].map(({ id, label }) => ( ))}
{/* Overview Tab */} {activeTab === 'overview' && (
{loading ? (
{[1, 2, 3, 4].map((i) => (
))}
) : ( <> {/* Score Card */}

Pûana Referral

{stats?.referralScore ?? 0}

Max pûan: 500
{/* Refer More Card */}

زیاتر ڕیفەر بکە، زیاتر قازانج بکە!

هەر کەسێک بهێنیت، HEZ و PEZ وەک خەڵات وەردەگریت. زیاتر ڕیفەر = زیاتر خەڵات!

{/* Stats Grid */}
Referral

{stats?.referralCount ?? 0}

KYC pejirandî

Referrer
{stats?.whoInvitedMe ? (

{formatAddress(stats.whoInvitedMe, 6)}

) : (

Tune

)}

Min vexwand

{/* Pending Referral Notification */} {stats?.pendingReferral && (
Referral li bendê
KYC temam bike ji bo pejirandina referral ji{' '} {formatAddress(stats.pendingReferral, 6)}
)} {/* Invite Card */}

Hevalên xwe vexwîne

Lînka te

{referralLink}
{/* Score System */}

Sîstema pûanan

1-10 referral ×10 pûan
11-50 referral 100 + ×5
51-100 referral 300 + ×4
101+ referral 500 (Max)
{/* I am Active Button */}

Rewşa Aktîvbûnê

{isActive && timeRemaining && (

Dem: {timeRemaining} maye

)}
{isActive ? 'Aktîv' : 'Ne Aktîv'}

Her 24 saet carekê bikirtîne da ku aktîv bimînî û xelatên zêdetir qezenc bikî!

{/* Social Links */} )}
)} {/* Referrals Tab */} {activeTab === 'referrals' && (
{/* Refer More Card */}

زیاتر ڕیفەر بکە، زیاتر قازانج بکە!

هەر کەسێک بهێنیت، HEZ و PEZ وەک خەڵات وەردەگریت. زیاتر ڕیفەر = زیاتر خەڵات!

{/* I am Active Button */}

Rewşa Aktîvbûnê

{isActive && timeRemaining && (

Dem: {timeRemaining} maye

)}
{isActive ? 'Aktîv' : 'Ne Aktîv'}
{loading ? (
{[1, 2, 3, 4, 5].map((i) => (
))}
) : myReferrals.length > 0 ? (
{myReferrals.length} referral (KYC pejirandî)
{myReferrals.map((referralAddress, index) => (
{index + 1}
{formatAddress(referralAddress, 8)}

KYC Pejirandî

+{getPointsForPosition(index + 1)} pûan
))}
) : (

Hêj referralên te tune ne

Lînka xwe parve bike!

)}
)} {/* Scores Tab */} {activeTab === 'scores' && (
{scoresLoading ? (
{[1, 2, 3, 4].map((i) => (
))}
) : ( <> {/* Trust Score - Main Card */}

Pûana Pêbaweriyê (Trust)

{userScores?.trustScore ?? 0}

Rêze: {getScoreRating(userScores?.trustScore || 0)} {userScores?.isCitizen && ( Welatî )}
{/* Score Components Grid */}
{/* Staking Score */}
Staking

{userScores?.stakingScore ?? 0}

{stakingDetails && stakingDetails.stakedAmount > 0n && (

{formatStakedAmount(stakingDetails.stakedAmount)} HEZ

)}
{/* Referral Score */}
Referral

{userScores?.referralScore ?? 0}

{stats?.referralCount ?? 0} kes

{/* Tiki Score */}
Tiki

{userScores?.tikiScore ?? 0}

Rola NFT

{/* Perwerde Score */}
Perwerde

{userScores?.perwerdeScore ?? 0}

Xwendin

{/* Staking Details Card */} {stakingDetails && stakingDetails.stakedAmount > 0n && (

Staking Hûrgelan

HEZ Staked {formatStakedAmount(stakingDetails.stakedAmount)} HEZ
Demjimêr {stakingDetails.monthsStaked} meh
Pir Zêdeker {stakingDetails.timeMultiplier}x
Nominasyon {stakingDetails.nominationsCount}
)} {/* Score Formula Info */}

Formûla Pûanê

Trust = (Staking × Weighted Sum) / 100

Weighted Sum = Staking×100 + Referral×300 + Perwerde×300 + Tiki×300

Staking 0 be, Trust pûan jî 0 dibe. Berî her tiştî stake bike!

{/* Refresh Button */} )}
)}
); }