chore: migrate git dependencies to Gitea mirror (git.pezkuwichain.io)

This commit is contained in:
2026-04-21 18:52:54 +03:00
parent 95bf48f240
commit 672682558f
947 changed files with 91913 additions and 12 deletions
+856
View File
@@ -0,0 +1,856 @@
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<string, never>;
interface ProfileData {
id?: string;
full_name?: string | null;
avatar_url?: string | null;
created_at?: string;
}
const DashboardScreen: React.FC<DashboardScreenProps> = () => {
const navigation = useNavigation<NavigationProp<BottomTabParamList & RootStackParamList>>();
const { user } = useAuth();
const { api, isApiReady, selectedAccount, accounts, connectWallet } = usePezkuwi();
const [profileData, setProfileData] = useState<ProfileData | null>(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<string[]>([]);
const [scores, setScores] = useState<UserScores>({
trustScore: 0,
referralScore: 0,
stakingScore: 0,
tikiScore: 0,
totalScore: 0
});
const [kycStatus, setKycStatus] = useState<string>('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) => (
<TouchableOpacity
style={styles.appIconContainer}
onPress={onPress}
activeOpacity={0.7}
accessibilityRole="button"
accessibilityLabel={`${title}${comingSoon ? ', coming soon' : ''}`}
>
<View style={[styles.appIconBox, comingSoon && styles.appIconDisabled]}>
{isEmoji ? (
<Text style={styles.emojiIcon}>{icon as string}</Text>
) : (
<Image source={icon as ImageSourcePropType} style={styles.imageIcon} resizeMode="cover" accessibilityLabel={`${title} icon`} />
)}
{comingSoon && (
<View style={styles.lockBadge}>
<Text style={styles.lockText}>🔒</Text>
</View>
)}
</View>
<Text style={styles.appIconTitle} numberOfLines={1}>{title}</Text>
</TouchableOpacity>
);
return (
<SafeAreaView style={styles.container}>
<StatusBar barStyle="light-content" backgroundColor={KurdistanColors.kesk} />
{/* HEADER SECTION */}
<LinearGradient
colors={[KurdistanColors.kesk, '#008f43']}
style={styles.header}
>
<View style={styles.headerTop}>
<View style={styles.avatarSection}>
<TouchableOpacity onPress={handleAvatarClick} accessibilityRole="button" accessibilityLabel="Change profile avatar">
{profileData?.avatar_url ? (
// Check if avatar_url is a URL (starts with http) or an emoji ID
profileData.avatar_url.startsWith('http') ? (
<Image
source={{ uri: profileData.avatar_url }}
style={styles.avatar}
accessibilityLabel="Profile avatar"
/>
) : (
// It's an emoji ID, render as emoji text
<View style={styles.avatar}>
<Text style={styles.avatarEmoji}>
{getEmojiFromAvatarId(profileData.avatar_url)}
</Text>
</View>
)
) : (
<Image
source={avatarPlaceholder}
style={styles.avatar}
accessibilityLabel="Profile avatar placeholder"
/>
)}
{/* Online Status Indicator */}
<View style={styles.statusIndicator} />
</TouchableOpacity>
{/* Tiki Badge next to avatar - shows primary role */}
<View style={styles.tikiAvatarBadge}>
<Text style={styles.tikiAvatarText}>
{getTikiEmoji(primaryRole)} {getTikiDisplayName(primaryRole)}
</Text>
</View>
</View>
<View style={styles.headerInfo}>
<Text style={styles.greeting}>
Rojbaş, {profileData?.full_name || user?.email?.split('@')[0] || 'Heval'}
</Text>
<View style={styles.tikiContainer}>
{tikis.map((tiki, index) => (
<View key={index} style={styles.tikiBadge}>
<Text style={styles.tikiText}> {tiki}</Text>
</View>
))}
</View>
</View>
<View style={styles.headerActions}>
<TouchableOpacity style={styles.iconButton} onPress={() => setNotificationModalVisible(true)} accessibilityRole="button" accessibilityLabel="Open notifications">
<Text style={styles.headerIcon}>🔔</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.iconButton} onPress={() => navigation.navigate('Settings')} accessibilityRole="button" accessibilityLabel="Open settings">
<Text style={styles.headerIcon}></Text>
</TouchableOpacity>
</View>
</View>
</LinearGradient>
<ScrollView
showsVerticalScrollIndicator={false}
contentContainerStyle={styles.scrollContent}
style={styles.scrollView}
refreshControl={<RefreshControl refreshing={refreshing} onRefresh={() => { setRefreshing(true); Promise.all([fetchProfile(), fetchBlockchainData()]).finally(() => setRefreshing(false)); }} />}
>
{/* SCORE CARDS SECTION */}
<View style={styles.scoreCardsContainer}>
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
contentContainerStyle={styles.scoreCardsContent}
>
{/* Member Since Card */}
<View style={[styles.scoreCard, { borderLeftColor: KurdistanColors.kesk }]}>
<Text style={styles.scoreCardIcon}>📅</Text>
<Text style={styles.scoreCardLabel}>Member Since</Text>
<Text style={styles.scoreCardValue}>
{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'
}
</Text>
</View>
{/* Role Card */}
<View style={[styles.scoreCard, { borderLeftColor: '#FF9800' }]}>
<Text style={styles.scoreCardIcon}>{getTikiEmoji(primaryRole)}</Text>
<Text style={styles.scoreCardLabel}>Role</Text>
<Text style={styles.scoreCardValue}>{getTikiDisplayName(primaryRole)}</Text>
<Text style={styles.scoreCardSubtext}>
{selectedAccount ? `${tikis.length} ${tikis.length === 1 ? 'role' : 'roles'}` : 'Connect wallet'}
</Text>
</View>
{/* Total Score Card */}
<View style={[styles.scoreCard, { borderLeftColor: '#9C27B0' }]}>
<Text style={styles.scoreCardIcon}>🏆</Text>
<Text style={styles.scoreCardLabel}>Total Score</Text>
{loadingScores ? (
<ActivityIndicator size="small" color="#9C27B0" />
) : (
<>
<Text style={[styles.scoreCardValue, { color: '#9C27B0' }]}>
{scores.totalScore}
</Text>
<Text style={styles.scoreCardSubtext}>All score types</Text>
</>
)}
</View>
{/* Trust Score Card */}
<View style={[styles.scoreCard, { borderLeftColor: '#9C27B0' }]}>
<Text style={styles.scoreCardIcon}>🛡</Text>
<Text style={styles.scoreCardLabel}>Trust Score</Text>
{loadingScores ? (
<ActivityIndicator size="small" color="#9C27B0" />
) : (
<>
<Text style={[styles.scoreCardValue, { color: '#9C27B0' }]}>
{scores.trustScore}
</Text>
<Text style={styles.scoreCardSubtext}>pezpallet_trust</Text>
</>
)}
</View>
{/* Referral Score Card */}
<View style={[styles.scoreCard, { borderLeftColor: '#00BCD4' }]}>
<Text style={styles.scoreCardIcon}>👥</Text>
<Text style={styles.scoreCardLabel}>Referral Score</Text>
{loadingScores ? (
<ActivityIndicator size="small" color="#00BCD4" />
) : (
<>
<Text style={[styles.scoreCardValue, { color: '#00BCD4' }]}>
{scores.referralScore}
</Text>
<Text style={styles.scoreCardSubtext}>Referrals</Text>
</>
)}
</View>
{/* Staking Score Card */}
<View style={[styles.scoreCard, { borderLeftColor: '#4CAF50' }]}>
<Text style={styles.scoreCardIcon}>📈</Text>
<Text style={styles.scoreCardLabel}>Staking Score</Text>
{loadingScores ? (
<ActivityIndicator size="small" color="#4CAF50" />
) : (
<>
<Text style={[styles.scoreCardValue, { color: '#4CAF50' }]}>
{scores.stakingScore}
</Text>
<Text style={styles.scoreCardSubtext}>pezpallet_staking</Text>
</>
)}
</View>
{/* Tiki Score Card */}
<View style={[styles.scoreCard, { borderLeftColor: '#E91E63' }]}>
<Text style={styles.scoreCardIcon}></Text>
<Text style={styles.scoreCardLabel}>Tiki Score</Text>
{loadingScores ? (
<ActivityIndicator size="small" color="#E91E63" />
) : (
<>
<Text style={[styles.scoreCardValue, { color: '#E91E63' }]}>
{scores.tikiScore}
</Text>
<Text style={styles.scoreCardSubtext}>
{tikis.length} {tikis.length === 1 ? 'role' : 'roles'}
</Text>
</>
)}
</View>
{/* KYC Status Card */}
<View style={[styles.scoreCard, { borderLeftColor: kycStatus === 'Approved' ? '#4CAF50' : '#FFC107' }]}>
<Text style={styles.scoreCardIcon}>
{kycStatus === 'Approved' ? '✅' : kycStatus === 'Pending' ? '⏳' : '📝'}
</Text>
<Text style={styles.scoreCardLabel}>KYC Status</Text>
<Text style={[styles.scoreCardValue, {
color: kycStatus === 'Approved' ? '#4CAF50' : kycStatus === 'Pending' ? '#FFC107' : '#999',
fontSize: 14
}]}>
{kycStatus}
</Text>
{kycStatus === 'NotStarted' && (
<TouchableOpacity
style={styles.kycButton}
onPress={() => navigation.navigate('BeCitizenChoice')}
accessibilityRole="button"
accessibilityLabel="Apply for KYC verification"
>
<Text style={styles.kycButtonText}>Apply</Text>
</TouchableOpacity>
)}
</View>
</ScrollView>
</View>
{/* 1. FINANCE SECTION */}
<View style={styles.sectionContainer}>
<View style={[styles.sectionHeader, { borderLeftColor: KurdistanColors.kesk }]}>
<View style={styles.sectionTitleRow}>
<Text style={styles.sectionTitle}>FINANCE 💰</Text>
{/* Connect Wallet Button */}
{!selectedAccount && (
<TouchableOpacity
style={styles.connectWalletBadge}
onPress={handleConnectWallet}
accessibilityRole="button"
accessibilityLabel="Connect wallet"
>
<Text style={styles.connectWalletIcon}>👛</Text>
<Text style={styles.connectWalletText}>Girêde</Text>
</TouchableOpacity>
)}
</View>
<TouchableOpacity onPress={() => navigation.navigate('Apps')} accessibilityRole="button" accessibilityLabel="See all finance apps">
<Text style={styles.seeAllText}>Hemû / All</Text>
</TouchableOpacity>
</View>
<View style={styles.appsGrid}>
{/* 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)}
</View>
</View>
{/* 2. GOVERNANCE SECTION */}
<View style={styles.sectionContainer}>
<View style={[styles.sectionHeader, { borderLeftColor: KurdistanColors.sor }]}>
<Text style={styles.sectionTitle}>GOVERNANCE 🏛</Text>
</View>
<View style={styles.appsGrid}>
{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)}
</View>
</View>
{/* 3. SOCIAL SECTION */}
<View style={styles.sectionContainer}>
<View style={[styles.sectionHeader, { borderLeftColor: '#2196F3' }]}>
<Text style={styles.sectionTitle}>SOCIAL 💬</Text>
</View>
<View style={styles.appsGrid}>
{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)}
</View>
</View>
{/* 4. EDUCATION SECTION */}
<View style={styles.sectionContainer}>
<View style={[styles.sectionHeader, { borderLeftColor: KurdistanColors.zer }]}>
<Text style={styles.sectionTitle}>EDUCATION 📚</Text>
</View>
<View style={styles.appsGrid}>
{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)}
</View>
</View>
<View style={{ height: 100 }} />
</ScrollView>
{/* Avatar Picker Modal */}
<AvatarPickerModal
visible={avatarModalVisible}
onClose={() => setAvatarModalVisible(false)}
currentAvatar={profileData?.avatar_url ?? undefined}
onAvatarSelected={handleAvatarSelected}
/>
{/* Notification Center Modal */}
<NotificationCenterModal
visible={notificationModalVisible}
onClose={() => setNotificationModalVisible(false)}
/>
</SafeAreaView>
);
};
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;