import React, { useState, useEffect, useCallback } from 'react'; import { View, Text, TouchableOpacity, StyleSheet, SafeAreaView, ScrollView, StatusBar, Image, Alert, Dimensions, Platform, ActivityIndicator, ImageSourcePropType, RefreshControl, } from 'react-native'; import { LinearGradient } from 'expo-linear-gradient'; 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 { NotificationCenterModal } from '../../components/NotificationCenterModal'; import { fetchUserTikis, getPrimaryRole, getTikiDisplayName, getTikiEmoji } from '../../../shared/lib/tiki'; import { getAllScores, type UserScores } from '../../../shared/lib/scores'; import { getKycStatus } from '../../../shared/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 import { logger } from '../../utils/logger'; const { width: _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 }; type DashboardScreenProps = Record; interface ProfileData { id?: string; full_name?: string | null; avatar_url?: string | null; created_at?: string; } const DashboardScreen: React.FC = () => { const navigation = useNavigation>(); const { user } = useAuth(); const { api, isApiReady, selectedAccount, accounts, connectWallet } = usePezkuwi(); const [profileData, setProfileData] = useState(null); const [_loading, setLoading] = useState(true); const [avatarModalVisible, setAvatarModalVisible] = useState(false); const [notificationModalVisible, setNotificationModalVisible] = useState(false); const [refreshing, setRefreshing] = 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) { logger.warn('Profile fetch error:', error); return; } setProfileData(data); } catch (error) { logger.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); logger.warn('[Dashboard] Blockchain data fetched:', { tikis: userTikis, scores: allScores, kycStatus: status }); } catch (error) { logger.error('[Dashboard] Error fetching blockchain data:', error); } finally { setLoadingScores(false); } }, [selectedAccount, api, isApiReady]); useEffect(() => { fetchProfile(); }, [fetchProfile]); useEffect(() => { if (selectedAccount && api && isApiReady) { fetchBlockchainData(); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [fetchBlockchainData]); // Check if user is a visitor (default when no blockchain wallet or no tikis) const _isVisitor = !selectedAccount || tikis.length === 0; // Handle wallet connection const handleConnectWallet = async () => { if (accounts.length === 0) { navigation.navigate('WalletSetup'); return; } try { await connectWallet(); Alert.alert('Girêdayî / Connected', 'Cîzdanê te bi serkeftî girêdayî bû!\nYour wallet has been connected successfully!'); } catch (error) { logger.error('Wallet connection error:', error); Alert.alert('Çewtî / Error', 'Cîzdan nehat girêdan.\nFailed to connect wallet.'); } }; const primaryRole = tikis.length > 0 ? getPrimaryRole(tikis) : 'Visitor'; const _showComingSoon = (featureName: string) => { Alert.alert( 'Coming Soon', `${featureName} will be available soon!`, [{ text: 'OK' }] ); }; const _showAwaitingGovernment = () => { Alert.alert( 'Li benda damezrandinê / Awaiting Establishment', 'Duaye helbejartina hukumeta Komara Dijitaliya Kurdistanê yên beta damezrandin.\n\nAwaiting the beta elections and establishment of the Digital Kurdistan Republic government.', [{ text: 'Temam / OK' }] ); }; const _showUnderMaintenance = () => { Alert.alert( 'Di bin çêkirinê de ye / Under Maintenance', 'Ev taybetmendî niha di bin çêkirinê de ye. Ji kerema xwe paşê vegerin.\n\nThis feature is currently under maintenance. Please check back later.', [{ text: 'Temam / OK' }] ); }; const _showAwaitingSerokElection = () => { Alert.alert( 'Li benda hilbijartinên çalak / Awaiting Active Elections', 'Duaye hilbijartinên Serokî yên çalak bibin.\n\nAwaiting active Presidential elections to be initiated.', [{ text: 'Temam / OK' }] ); }; const _showAwaitingMinistryOfEducation = () => { Alert.alert( 'Li benda Wezareta Perwerdê / Awaiting Ministry of Education', 'Duaye damezrandina Wezareta Perwerdê yên aktîv bibin.\n\nAwaiting the establishment of an active Ministry of Education.', [{ text: 'Temam / OK' }] ); }; const handleAvatarClick = () => { setAvatarModalVisible(true); }; const handleAvatarSelected = (avatarUrl: string) => { // Refresh profile data to show new avatar setProfileData((prev: ProfileData | null) => ({ ...prev, avatar_url: avatarUrl, })); }; const renderAppIcon = (title: string, icon: string | ImageSourcePropType, onPress: () => void, isEmoji = false, comingSoon = false) => ( {isEmoji ? ( {icon as string} ) : ( )} {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} ))} setNotificationModalVisible(true)} accessibilityRole="button" accessibilityLabel="Open notifications"> 🔔 navigation.navigate('Settings')} accessibilityRole="button" accessibilityLabel="Open settings"> ⚙️ { setRefreshing(true); Promise.all([fetchProfile(), fetchBlockchainData()]).finally(() => setRefreshing(false)); }} />} > {/* 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('BeCitizenChoice')} accessibilityRole="button" accessibilityLabel="Apply for KYC verification" > Apply )} {/* 1. FINANCE SECTION */} FINANCE 💰 {/* Connect Wallet Button */} {!selectedAccount && ( 👛 Girêde )} navigation.navigate('Apps')} accessibilityRole="button" accessibilityLabel="See all finance apps"> Hemû / All {/* Wallet - Navigate to WalletScreen */} {renderAppIcon('Wallet', '👛', () => navigation.navigate('Wallet'), true)} {renderAppIcon('Bank', qaBank, () => navigation.navigate('Bank'), false, true)} {renderAppIcon('Exchange', qaExchange, () => navigation.navigate('Swap'), false)} {renderAppIcon('P2P', qaTrading, () => navigation.navigate('P2P'), false)} {renderAppIcon('B2B', qaB2B, () => navigation.navigate('B2B'), false, true)} {renderAppIcon('Bac/Zekat', '📊', () => navigation.navigate('TaxZekat'), true)} {renderAppIcon('Launchpad', '🚀', () => navigation.navigate('Launchpad'), true, true)} {/* 2. GOVERNANCE SECTION */} GOVERNANCE 🏛️ {renderAppIcon('President', '👑', () => navigation.navigate('President'), true)} {renderAppIcon('Assembly', qaGovernance, () => navigation.navigate('Assembly'), false, true)} {renderAppIcon('Vote', '🗳️', () => navigation.navigate('Vote'), true)} {renderAppIcon('Validators', '🛡️', () => navigation.navigate('Validators'), true)} {renderAppIcon('Justice', '⚖️', () => navigation.navigate('Justice'), true, true)} {renderAppIcon('Proposals', '📜', () => navigation.navigate('Proposals'), true)} {renderAppIcon('Polls', '📊', () => navigation.navigate('Polls'), true, true)} {renderAppIcon('Identity', '🆔', () => navigation.navigate('Identity'), true)} {/* 3. SOCIAL SECTION */} SOCIAL 💬 {renderAppIcon('whatsKURD', '💬', () => navigation.navigate('WhatsKURD'), true, true)} {renderAppIcon('Forum', qaForum, () => navigation.navigate('Forum'), false)} {renderAppIcon('KurdMedia', qaKurdMedia, () => navigation.navigate('KurdMedia'), false)} {renderAppIcon('Events', '🎭', () => navigation.navigate('Events'), true, true)} {renderAppIcon('Help', '🤝', () => navigation.navigate('Help'), true, true)} {renderAppIcon('Music', '🎵', () => navigation.navigate('Music'), true, true)} {renderAppIcon('VPN', '🛡️', () => navigation.navigate('VPN'), true, true)} {renderAppIcon('Referral', '👥', () => navigation.navigate('Referral'), true)} {/* 4. EDUCATION SECTION */} EDUCATION 📚 {renderAppIcon('University', qaUniversity, () => navigation.navigate('University'), false, true)} {renderAppIcon('Perwerde', qaEducation, () => navigation.navigate('Perwerde'), false)} {renderAppIcon('Certificates', '🏆', () => navigation.navigate('Certificates'), true, true)} {renderAppIcon('Research', '🔬', () => navigation.navigate('Research'), true, true)} {/* Avatar Picker Modal */} setAvatarModalVisible(false)} currentAvatar={profileData?.avatar_url ?? undefined} onAvatarSelected={handleAvatarSelected} /> {/* Notification Center Modal */} setNotificationModalVisible(false)} /> ); }; 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, }, sectionTitleRow: { flexDirection: 'row', alignItems: 'center', gap: 10, }, sectionTitle: { fontSize: 16, fontWeight: '800', color: KurdistanColors.reş, letterSpacing: 0.5, }, connectWalletBadge: { flexDirection: 'row', alignItems: 'center', backgroundColor: KurdistanColors.kesk, paddingHorizontal: 10, paddingVertical: 4, borderRadius: 12, gap: 4, }, connectWalletIcon: { fontSize: 14, }, connectWalletText: { fontSize: 11, fontWeight: '600', color: KurdistanColors.spi, }, 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;