import React, { useState, useEffect, useCallback } from 'react'; import { View, Text, TouchableOpacity, StyleSheet, SafeAreaView, ScrollView, StatusBar, Image, Alert, Dimensions, Platform, ActivityIndicator, } from 'react-native'; import { LinearGradient } from 'expo-linear-gradient'; import { useTranslation } from 'react-i18next'; import { useNavigation } from '@react-navigation/native'; import type { NavigationProp } from '@react-navigation/native'; import type { BottomTabParamList } from '../navigation/BottomTabNavigator'; import type { RootStackParamList } from '../navigation/AppNavigator'; import { KurdistanColors } from '../theme/colors'; import { useAuth } from '../contexts/AuthContext'; import { usePezkuwi } from '../contexts/PezkuwiContext'; import { supabase } from '../lib/supabase'; import AvatarPickerModal from '../components/AvatarPickerModal'; import { fetchUserTikis, getPrimaryRole, getTikiDisplayName, getTikiEmoji, getTikiColor } from '@pezkuwi/lib/tiki'; import { getAllScores, type UserScores } from '@pezkuwi/lib/scores'; import { getKycStatus } from '@pezkuwi/lib/kyc'; // Existing Quick Action Images (Reused) import qaEducation from '../../../shared/images/quick-actions/qa_education.png'; import qaExchange from '../../../shared/images/quick-actions/qa_exchange.png'; import qaForum from '../../../shared/images/quick-actions/qa_forum.jpg'; import qaGovernance from '../../../shared/images/quick-actions/qa_governance.jpg'; import qaTrading from '../../../shared/images/quick-actions/qa_trading.jpg'; import qaB2B from '../../../shared/images/quick-actions/qa_b2b.png'; import qaBank from '../../../shared/images/quick-actions/qa_bank.png'; import qaGames from '../../../shared/images/quick-actions/qa_games.png'; import qaKurdMedia from '../../../shared/images/quick-actions/qa_kurdmedia.jpg'; import qaUniversity from '../../../shared/images/quick-actions/qa_university.png'; import avatarPlaceholder from '../../../shared/images/app-image.png'; // Fallback avatar const { width } = Dimensions.get('window'); // Avatar pool matching AvatarPickerModal const AVATAR_POOL = [ { id: 'avatar1', emoji: '๐Ÿ‘จ๐Ÿป' }, { id: 'avatar2', emoji: '๐Ÿ‘จ๐Ÿผ' }, { id: 'avatar3', emoji: '๐Ÿ‘จ๐Ÿฝ' }, { id: 'avatar4', emoji: '๐Ÿ‘จ๐Ÿพ' }, { id: 'avatar5', emoji: '๐Ÿ‘ฉ๐Ÿป' }, { id: 'avatar6', emoji: '๐Ÿ‘ฉ๐Ÿผ' }, { id: 'avatar7', emoji: '๐Ÿ‘ฉ๐Ÿฝ' }, { id: 'avatar8', emoji: '๐Ÿ‘ฉ๐Ÿพ' }, { id: 'avatar9', emoji: '๐Ÿง”๐Ÿป' }, { id: 'avatar10', emoji: '๐Ÿง”๐Ÿผ' }, { id: 'avatar11', emoji: '๐Ÿง”๐Ÿฝ' }, { id: 'avatar12', emoji: '๐Ÿง”๐Ÿพ' }, { id: 'avatar13', emoji: '๐Ÿ‘ณ๐Ÿปโ€โ™‚๏ธ' }, { id: 'avatar14', emoji: '๐Ÿ‘ณ๐Ÿผโ€โ™‚๏ธ' }, { id: 'avatar15', emoji: '๐Ÿ‘ณ๐Ÿฝโ€โ™‚๏ธ' }, { id: 'avatar16', emoji: '๐Ÿง•๐Ÿป' }, { id: 'avatar17', emoji: '๐Ÿง•๐Ÿผ' }, { id: 'avatar18', emoji: '๐Ÿง•๐Ÿฝ' }, { id: 'avatar19', emoji: '๐Ÿ‘ด๐Ÿป' }, { id: 'avatar20', emoji: '๐Ÿ‘ด๐Ÿผ' }, { id: 'avatar21', emoji: '๐Ÿ‘ต๐Ÿป' }, { id: 'avatar22', emoji: '๐Ÿ‘ต๐Ÿผ' }, { id: 'avatar23', emoji: '๐Ÿ‘ฆ๐Ÿป' }, { id: 'avatar24', emoji: '๐Ÿ‘ฆ๐Ÿผ' }, { id: 'avatar25', emoji: '๐Ÿ‘ง๐Ÿป' }, { id: 'avatar26', emoji: '๐Ÿ‘ง๐Ÿผ' }, ]; // Helper function to get emoji from avatar ID const getEmojiFromAvatarId = (avatarId: string): string => { const avatar = AVATAR_POOL.find(a => a.id === avatarId); return avatar ? avatar.emoji : '๐Ÿ‘ค'; // Default to person emoji if not found }; interface DashboardScreenProps {} const DashboardScreen: React.FC = () => { const { t } = useTranslation(); const navigation = useNavigation>(); const { user } = useAuth(); const { api, isApiReady, selectedAccount } = usePezkuwi(); const [profileData, setProfileData] = useState(null); const [loading, setLoading] = useState(true); const [avatarModalVisible, setAvatarModalVisible] = useState(false); // Blockchain state const [tikis, setTikis] = useState([]); const [scores, setScores] = useState({ trustScore: 0, referralScore: 0, stakingScore: 0, tikiScore: 0, totalScore: 0 }); const [kycStatus, setKycStatus] = useState('NotStarted'); const [loadingScores, setLoadingScores] = useState(false); // Fetch profile data from Supabase const fetchProfile = useCallback(async () => { if (!user) { setLoading(false); return; } try { const { data, error } = await supabase .from('profiles') .select('*') .eq('id', user.id) .maybeSingle(); if (error) { if (__DEV__) console.warn('Profile fetch error:', error); return; } setProfileData(data); } catch (error) { if (__DEV__) console.error('Error fetching profile:', error); } finally { setLoading(false); } }, [user]); // Fetch blockchain data (tikis, scores, KYC) const fetchBlockchainData = useCallback(async () => { if (!selectedAccount || !api || !isApiReady) return; setLoadingScores(true); try { // Fetch tikis const userTikis = await fetchUserTikis(api, selectedAccount.address); setTikis(userTikis); // Fetch all scores const allScores = await getAllScores(api, selectedAccount.address); setScores(allScores); // Fetch KYC status const status = await getKycStatus(api, selectedAccount.address); setKycStatus(status); if (__DEV__) console.log('[Dashboard] Blockchain data fetched:', { tikis: userTikis, scores: allScores, kycStatus: status }); } catch (error) { if (__DEV__) console.error('[Dashboard] Error fetching blockchain data:', error); } finally { setLoadingScores(false); } }, [selectedAccount, api, isApiReady]); useEffect(() => { fetchProfile(); }, [fetchProfile]); useEffect(() => { if (selectedAccount && api && isApiReady) { fetchBlockchainData(); } }, [fetchBlockchainData]); // Check if user is a visitor (default when no blockchain wallet or no tikis) const isVisitor = !selectedAccount || tikis.length === 0; const primaryRole = tikis.length > 0 ? getPrimaryRole(tikis) : 'Visitor'; const showComingSoon = (featureName: string) => { Alert.alert( t('settingsScreen.comingSoon'), `${featureName} ${t('settingsScreen.comingSoonMessage')}`, [{ text: 'OK' }] ); }; const handleAvatarClick = () => { setAvatarModalVisible(true); }; const handleAvatarSelected = (avatarUrl: string) => { // Refresh profile data to show new avatar setProfileData((prev: any) => ({ ...prev, avatar_url: avatarUrl, })); }; const renderAppIcon = (title: string, icon: any, onPress: () => void, isEmoji = false, comingSoon = false) => ( {isEmoji ? ( {icon} ) : ( )} {comingSoon && ( ๐Ÿ”’ )} {title} ); return ( {/* HEADER SECTION */} {profileData?.avatar_url ? ( // Check if avatar_url is a URL (starts with http) or an emoji ID profileData.avatar_url.startsWith('http') ? ( ) : ( // It's an emoji ID, render as emoji text {getEmojiFromAvatarId(profileData.avatar_url)} ) ) : ( )} {/* Online Status Indicator */} {/* Tiki Badge next to avatar - shows primary role */} {getTikiEmoji(primaryRole)} {getTikiDisplayName(primaryRole)} RojbaลŸ, {profileData?.full_name || user?.email?.split('@')[0] || 'Heval'} {tikis.map((tiki, index) => ( โœ“ {tiki} ))} showComingSoon('Notifications')}> ๐Ÿ”” navigation.navigate('Settings')}> โš™๏ธ {/* SCORE CARDS SECTION */} {/* Member Since Card */} ๐Ÿ“… Member Since {profileData?.created_at ? new Date(profileData.created_at).toLocaleDateString('en-US', { month: 'short', year: 'numeric' }) : user?.created_at ? new Date(user.created_at).toLocaleDateString('en-US', { month: 'short', year: 'numeric' }) : 'N/A' } {/* Role Card */} {getTikiEmoji(primaryRole)} Role {getTikiDisplayName(primaryRole)} {selectedAccount ? `${tikis.length} ${tikis.length === 1 ? 'role' : 'roles'}` : 'Connect wallet'} {/* Total Score Card */} ๐Ÿ† Total Score {loadingScores ? ( ) : ( <> {scores.totalScore} All score types )} {/* Trust Score Card */} ๐Ÿ›ก๏ธ Trust Score {loadingScores ? ( ) : ( <> {scores.trustScore} pezpallet_trust )} {/* Referral Score Card */} ๐Ÿ‘ฅ Referral Score {loadingScores ? ( ) : ( <> {scores.referralScore} Referrals )} {/* Staking Score Card */} ๐Ÿ“ˆ Staking Score {loadingScores ? ( ) : ( <> {scores.stakingScore} pezpallet_staking )} {/* Tiki Score Card */} โญ Tiki Score {loadingScores ? ( ) : ( <> {scores.tikiScore} {tikis.length} {tikis.length === 1 ? 'role' : 'roles'} )} {/* KYC Status Card */} {kycStatus === 'Approved' ? 'โœ…' : kycStatus === 'Pending' ? 'โณ' : '๐Ÿ“'} KYC Status {kycStatus} {kycStatus === 'NotStarted' && ( navigation.navigate('BeCitizen')} > Apply )} {/* 1. FINANCE SECTION */} FINANCE ๐Ÿ’ฐ navigation.navigate('Apps')}> Hemรป / All {/* Wallet Visitors - Everyone can use */} {renderAppIcon('Wallet Visitors', '๐Ÿ‘๏ธ', () => showComingSoon('Wallet Visitors'), true)} {/* Wallet Welati - Only Citizens can use */} {renderAppIcon('Wallet Welati', '๐Ÿ›๏ธ', () => { if (tikis.includes('Citizen') || tikis.includes('Welati')) { showComingSoon('Wallet Welati'); } else { Alert.alert( 'Citizens Only', 'Wallet Welati is only available to Pezkuwi citizens. Please apply for citizenship first.', [{ text: 'OK' }] ); } }, true, !tikis.includes('Citizen') && !tikis.includes('Welati'))} {renderAppIcon('Bank', qaBank, () => showComingSoon('Bank'), false, true)} {renderAppIcon('Exchange', qaExchange, () => showComingSoon('Swap'), false)} {renderAppIcon('P2P', qaTrading, () => showComingSoon('P2P'), false)} {renderAppIcon('B2B', qaB2B, () => showComingSoon('B2B Trading'), false, true)} {renderAppIcon('Tax', '๐Ÿ“Š', () => showComingSoon('Tax/Zekat'), true, true)} {renderAppIcon('Launchpad', '๐Ÿš€', () => showComingSoon('Launchpad'), true, true)} {/* 2. GOVERNANCE SECTION */} GOVERNANCE ๐Ÿ›๏ธ {renderAppIcon('President', '๐Ÿ‘‘', () => showComingSoon('Presidency'), true, true)} {renderAppIcon('Assembly', qaGovernance, () => showComingSoon('Assembly'), false, true)} {renderAppIcon('Vote', '๐Ÿ—ณ๏ธ', () => showComingSoon('Voting'), true, true)} {renderAppIcon('Validators', '๐Ÿ›ก๏ธ', () => showComingSoon('Validators'), true, true)} {renderAppIcon('Justice', 'โš–๏ธ', () => showComingSoon('Dad / Justice'), true, true)} {renderAppIcon('Proposals', '๐Ÿ“œ', () => showComingSoon('Proposals'), true, true)} {renderAppIcon('Polls', '๐Ÿ“Š', () => showComingSoon('Public Polls'), true, true)} {renderAppIcon('Identity', '๐Ÿ†”', () => navigation.navigate('BeCitizen'), true)} {/* 3. SOCIAL SECTION */} SOCIAL ๐Ÿ’ฌ {renderAppIcon('whatsKURD', '๐Ÿ’ฌ', () => showComingSoon('whatsKURD'), true, true)} {renderAppIcon('Forum', qaForum, () => showComingSoon('Forum'), false)} {renderAppIcon('KurdMedia', qaKurdMedia, () => showComingSoon('KurdMedia'), false, true)} {renderAppIcon('Events', '๐ŸŽญ', () => showComingSoon('ร‡alakรฎ / Events'), true, true)} {renderAppIcon('Help', '๐Ÿค', () => showComingSoon('Harรฎkarรฎ / Help'), true, true)} {renderAppIcon('Music', '๐ŸŽต', () => showComingSoon('Music Stream'), true, true)} {renderAppIcon('VPN', '๐Ÿ›ก๏ธ', () => showComingSoon('Decentralized VPN'), true, true)} {renderAppIcon('Referral', '๐Ÿ‘ฅ', () => navigation.navigate('Referral'), true)} {/* 4. EDUCATION SECTION */} EDUCATION ๐Ÿ“š {renderAppIcon('University', qaUniversity, () => showComingSoon('University'), false, true)} {renderAppIcon('Perwerde', qaEducation, () => showComingSoon('Education'), false)} {renderAppIcon('Library', '๐Ÿ“œ', () => showComingSoon('Pirtรปkxane'), true, true)} {renderAppIcon('Language', '๐Ÿ—ฃ๏ธ', () => showComingSoon('Ziman / Language'), true, true)} {renderAppIcon('Kids', '๐Ÿงธ', () => showComingSoon('Zarok / Kids'), true, true)} {renderAppIcon('Certificates', '๐Ÿ†', () => showComingSoon('Certificates'), true, true)} {renderAppIcon('Research', '๐Ÿ”ฌ', () => showComingSoon('Research'), true, true)} {renderAppIcon('History', '๐Ÿบ', () => showComingSoon('History'), true, true)} {/* Avatar Picker Modal */} setAvatarModalVisible(false)} currentAvatar={profileData?.avatar_url} onAvatarSelected={handleAvatarSelected} /> ); }; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#F2F2F7', }, scrollView: { flex: 1, }, scrollContent: { paddingBottom: 40, }, header: { paddingTop: Platform.OS === 'android' ? 40 : 20, paddingBottom: 25, paddingHorizontal: 20, borderBottomLeftRadius: 24, borderBottomRightRadius: 24, boxShadow: '0px 4px 8px rgba(0, 0, 0, 0.2)', elevation: 8, }, headerTop: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', }, avatarSection: { flexDirection: 'row', alignItems: 'center', }, avatar: { width: 56, height: 56, borderRadius: 28, borderWidth: 2, borderColor: KurdistanColors.spi, backgroundColor: '#ddd', justifyContent: 'center', alignItems: 'center', }, avatarEmoji: { fontSize: 32, }, tikiAvatarBadge: { marginLeft: 8, backgroundColor: 'rgba(255, 255, 255, 0.25)', paddingHorizontal: 10, paddingVertical: 4, borderRadius: 12, borderWidth: 1, borderColor: 'rgba(255, 255, 255, 0.4)', }, tikiAvatarText: { fontSize: 11, color: KurdistanColors.spi, fontWeight: '700', }, statusIndicator: { position: 'absolute', bottom: 2, right: 2, width: 14, height: 14, borderRadius: 7, backgroundColor: '#4CAF50', // Online green borderWidth: 2, borderColor: KurdistanColors.kesk, }, headerInfo: { flex: 1, marginLeft: 16, }, greeting: { fontSize: 20, fontWeight: 'bold', color: KurdistanColors.spi, marginBottom: 4, }, tikiContainer: { flexDirection: 'row', flexWrap: 'wrap', }, tikiBadge: { backgroundColor: 'rgba(255, 255, 255, 0.2)', paddingHorizontal: 8, paddingVertical: 2, borderRadius: 12, marginRight: 6, marginBottom: 4, }, tikiText: { fontSize: 11, color: KurdistanColors.spi, fontWeight: '600', }, headerActions: { flexDirection: 'row', }, iconButton: { width: 40, height: 40, backgroundColor: 'rgba(255, 255, 255, 0.15)', borderRadius: 20, justifyContent: 'center', alignItems: 'center', marginLeft: 8, }, headerIcon: { fontSize: 18, }, sectionContainer: { backgroundColor: KurdistanColors.spi, marginHorizontal: 16, marginTop: 16, borderRadius: 16, padding: 16, boxShadow: '0px 2px 4px rgba(0, 0, 0, 0.05)', elevation: 2, }, sectionHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16, borderLeftWidth: 4, paddingLeft: 10, }, sectionTitle: { fontSize: 16, fontWeight: '800', color: KurdistanColors.reลŸ, letterSpacing: 0.5, }, seeAllText: { fontSize: 12, color: KurdistanColors.kesk, fontWeight: '600', }, appsGrid: { flexDirection: 'row', flexWrap: 'wrap', justifyContent: 'flex-start', }, appIconContainer: { width: '25%', // 4 icons per row alignItems: 'center', marginBottom: 16, }, appIconBox: { width: 56, height: 56, borderRadius: 16, backgroundColor: '#F8F9FA', justifyContent: 'center', alignItems: 'center', marginBottom: 6, boxShadow: '0px 1px 2px rgba(0, 0, 0, 0.05)', elevation: 1, }, appIconDisabled: { opacity: 0.5, backgroundColor: '#F0F0F0', }, imageIcon: { width: 32, height: 32, borderRadius: 8, }, emojiIcon: { fontSize: 28, }, appIconTitle: { fontSize: 11, color: '#333', textAlign: 'center', fontWeight: '500', maxWidth: '90%', }, lockBadge: { position: 'absolute', top: -4, right: -4, backgroundColor: 'transparent', }, lockText: { fontSize: 12, }, // Score Cards Styles scoreCardsContainer: { marginTop: 16, marginBottom: 8, }, scoreCardsContent: { paddingHorizontal: 16, }, scoreCard: { backgroundColor: KurdistanColors.spi, borderRadius: 12, padding: 16, marginRight: 12, minWidth: 140, borderLeftWidth: 4, boxShadow: '0px 2px 4px rgba(0, 0, 0, 0.08)', elevation: 3, }, scoreCardIcon: { fontSize: 28, marginBottom: 8, }, scoreCardLabel: { fontSize: 11, color: '#666', fontWeight: '600', marginBottom: 6, textTransform: 'uppercase', letterSpacing: 0.5, }, scoreCardValue: { fontSize: 24, fontWeight: 'bold', color: KurdistanColors.reลŸ, marginBottom: 4, }, scoreCardSubtext: { fontSize: 10, color: '#999', }, kycButton: { marginTop: 8, backgroundColor: KurdistanColors.kesk, paddingVertical: 6, paddingHorizontal: 12, borderRadius: 8, alignItems: 'center', }, kycButtonText: { color: KurdistanColors.spi, fontSize: 11, fontWeight: '700', }, }); export default DashboardScreen;