diff --git a/frontend/App.tsx b/frontend/App.tsx
new file mode 100644
index 00000000..e4701509
--- /dev/null
+++ b/frontend/App.tsx
@@ -0,0 +1,12 @@
+import React from 'react';
+import { StatusBar } from 'expo-status-bar';
+import RootNavigator from './src/navigation/RootNavigator';
+
+export default function App() {
+ return (
+ <>
+
+
+ >
+ );
+}
diff --git a/frontend/app.json b/frontend/app.json
index 0fa96f1e..8ef17a67 100644
--- a/frontend/app.json
+++ b/frontend/app.json
@@ -1,42 +1,30 @@
{
"expo": {
- "name": "frontend",
- "slug": "frontend",
+ "name": "pezkuwi-mobile-app",
+ "slug": "pezkuwi-mobile-app",
"version": "1.0.0",
"orientation": "portrait",
- "icon": "./assets/images/icon.png",
- "scheme": "frontend",
- "userInterfaceStyle": "automatic",
+ "icon": "./assets/icon.png",
+ "userInterfaceStyle": "light",
"newArchEnabled": true,
+ "splash": {
+ "image": "./assets/splash-icon.png",
+ "resizeMode": "contain",
+ "backgroundColor": "#ffffff"
+ },
"ios": {
"supportsTablet": true
},
"android": {
"adaptiveIcon": {
- "foregroundImage": "./assets/images/adaptive-icon.png",
- "backgroundColor": "#000"
+ "foregroundImage": "./assets/adaptive-icon.png",
+ "backgroundColor": "#ffffff"
},
- "edgeToEdgeEnabled": true
+ "edgeToEdgeEnabled": true,
+ "predictiveBackGestureEnabled": false
},
"web": {
- "bundler": "metro",
- "output": "static",
- "favicon": "./assets/images/favicon.png"
- },
- "plugins": [
- "expo-router",
- [
- "expo-splash-screen",
- {
- "image": "./assets/images/splash-icon.png",
- "imageWidth": 200,
- "resizeMode": "contain",
- "backgroundColor": "#000"
- }
- ]
- ],
- "experiments": {
- "typedRoutes": true
+ "favicon": "./assets/favicon.png"
}
}
}
diff --git a/frontend/app/index.tsx b/frontend/app/index.tsx
deleted file mode 100644
index 60b6cda3..00000000
--- a/frontend/app/index.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import { Text, View, StyleSheet, Image } from "react-native";
-
-const EXPO_PUBLIC_BACKEND_URL = process.env.EXPO_PUBLIC_BACKEND_URL;
-
-export default function Index() {
- console.log(EXPO_PUBLIC_BACKEND_URL, "EXPO_PUBLIC_BACKEND_URL");
-
- return (
-
-
-
- );
-}
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- backgroundColor: "#0c0c0c",
- alignItems: "center",
- justifyContent: "center",
- },
- image: {
- width: "100%",
- height: "100%",
- resizeMode: "contain",
- },
-});
diff --git a/frontend/assets/adaptive-icon.png b/frontend/assets/adaptive-icon.png
new file mode 100644
index 00000000..03d6f6b6
Binary files /dev/null and b/frontend/assets/adaptive-icon.png differ
diff --git a/frontend/assets/favicon.png b/frontend/assets/favicon.png
new file mode 100644
index 00000000..e75f697b
Binary files /dev/null and b/frontend/assets/favicon.png differ
diff --git a/frontend/assets/icon.png b/frontend/assets/icon.png
new file mode 100644
index 00000000..a0b1526f
Binary files /dev/null and b/frontend/assets/icon.png differ
diff --git a/frontend/assets/splash-icon.png b/frontend/assets/splash-icon.png
new file mode 100644
index 00000000..03d6f6b6
Binary files /dev/null and b/frontend/assets/splash-icon.png differ
diff --git a/frontend/assets/tokens/hez.png b/frontend/assets/tokens/hez.png
new file mode 100644
index 00000000..c36e353a
Binary files /dev/null and b/frontend/assets/tokens/hez.png differ
diff --git a/frontend/assets/tokens/pez.png b/frontend/assets/tokens/pez.png
new file mode 100644
index 00000000..15e2b9b6
Binary files /dev/null and b/frontend/assets/tokens/pez.png differ
diff --git a/frontend/index.ts b/frontend/index.ts
new file mode 100644
index 00000000..1d6e981e
--- /dev/null
+++ b/frontend/index.ts
@@ -0,0 +1,8 @@
+import { registerRootComponent } from 'expo';
+
+import App from './App';
+
+// registerRootComponent calls AppRegistry.registerComponent('main', () => App);
+// It also ensures that whether you load the app in Expo Go or in a native build,
+// the environment is set up appropriately
+registerRootComponent(App);
diff --git a/frontend/src/components/ReceiveModal.tsx b/frontend/src/components/ReceiveModal.tsx
new file mode 100644
index 00000000..5ae96243
--- /dev/null
+++ b/frontend/src/components/ReceiveModal.tsx
@@ -0,0 +1,225 @@
+import React, { useState } from 'react';
+import {
+ View,
+ Text,
+ StyleSheet,
+ Modal,
+ TouchableOpacity,
+ Image,
+ Alert,
+ Share,
+} from 'react-native';
+import { Ionicons } from '@expo/vector-icons';
+import QRCode from 'react-native-qrcode-svg';
+import * as Clipboard from 'expo-clipboard';
+import Colors from '../constants/colors';
+import { Typography, Spacing, BorderRadius, Shadow } from '../constants/theme';
+
+interface ReceiveModalProps {
+ visible: boolean;
+ onClose: () => void;
+ token: {
+ symbol: string;
+ name: string;
+ icon: any;
+ color: string;
+ };
+}
+
+export default function ReceiveModal({ visible, onClose, token }: ReceiveModalProps) {
+ // Mock wallet address - in production, this would come from user's wallet
+ const walletAddress = 'pezkuwi1a2b3c4d5e6f7g8h9i0j';
+ const network = 'Optimism';
+
+ const handleCopyAddress = async () => {
+ await Clipboard.setStringAsync(walletAddress);
+ Alert.alert('Copied!', 'Wallet address copied to clipboard');
+ };
+
+ const handleShareAddress = async () => {
+ try {
+ await Share.share({
+ message: `My ${token.symbol} wallet address:\n${walletAddress}\n\nNetwork: ${network}`,
+ title: `${token.symbol} Wallet Address`,
+ });
+ } catch (error) {
+ console.error('Error sharing:', error);
+ }
+ };
+
+ return (
+
+
+
+ {/* Close Button */}
+
+
+
+
+ {/* Token Icon */}
+
+
+ {/* Title */}
+ Receive {token.symbol}
+
+ {/* QR Code Card */}
+
+
+
+
+ {/* Wallet Address */}
+
+ {walletAddress}
+
+
+ Tap to copy
+
+ {/* Network Badge */}
+
+
+ {network} Network
+
+
+ {/* Share Button */}
+
+
+ Share Address
+
+
+ {/* Warning Box */}
+
+
+
+ Only send {token.symbol} to this address on {network} network
+
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ overlay: {
+ flex: 1,
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
+ justifyContent: 'center',
+ alignItems: 'center',
+ padding: Spacing.lg,
+ },
+ modalContainer: {
+ width: '100%',
+ maxWidth: 400,
+ backgroundColor: '#FFFFFF',
+ borderRadius: BorderRadius.xl,
+ padding: Spacing.xl,
+ ...Shadow.medium,
+ },
+ closeButton: {
+ position: 'absolute',
+ top: Spacing.md,
+ right: Spacing.md,
+ zIndex: 1,
+ },
+ tokenIcon: {
+ width: 60,
+ height: 60,
+ alignSelf: 'center',
+ marginTop: Spacing.md,
+ },
+ title: {
+ fontSize: Typography.sizes.xxl,
+ fontWeight: Typography.weights.bold,
+ color: Colors.textDark,
+ textAlign: 'center',
+ marginTop: Spacing.sm,
+ marginBottom: Spacing.lg,
+ },
+ qrCard: {
+ backgroundColor: '#FFFFFF',
+ borderRadius: BorderRadius.lg,
+ padding: Spacing.lg,
+ alignItems: 'center',
+ justifyContent: 'center',
+ ...Shadow.small,
+ alignSelf: 'center',
+ },
+ addressContainer: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'center',
+ backgroundColor: Colors.background,
+ borderRadius: BorderRadius.md,
+ paddingHorizontal: Spacing.md,
+ paddingVertical: Spacing.sm,
+ marginTop: Spacing.lg,
+ },
+ addressText: {
+ fontSize: Typography.sizes.sm,
+ fontFamily: 'monospace',
+ color: Colors.textDark,
+ marginRight: Spacing.sm,
+ },
+ tapToCopy: {
+ fontSize: Typography.sizes.xs,
+ color: Colors.textLight,
+ textAlign: 'center',
+ marginTop: Spacing.xs,
+ },
+ networkBadge: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'center',
+ backgroundColor: '#E3F2FD',
+ borderRadius: BorderRadius.md,
+ paddingHorizontal: Spacing.md,
+ paddingVertical: Spacing.sm,
+ marginTop: Spacing.lg,
+ alignSelf: 'center',
+ },
+ networkText: {
+ fontSize: Typography.sizes.md,
+ fontWeight: Typography.weights.semibold,
+ color: '#007AFF',
+ marginLeft: Spacing.xs,
+ },
+ shareButton: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'center',
+ backgroundColor: Colors.background,
+ borderRadius: BorderRadius.md,
+ paddingVertical: Spacing.md,
+ marginTop: Spacing.lg,
+ },
+ shareButtonText: {
+ fontSize: Typography.sizes.md,
+ fontWeight: Typography.weights.semibold,
+ color: Colors.textDark,
+ marginLeft: Spacing.sm,
+ },
+ warningBox: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ backgroundColor: '#FEF3C7',
+ borderRadius: BorderRadius.md,
+ padding: Spacing.md,
+ marginTop: Spacing.lg,
+ },
+ warningText: {
+ flex: 1,
+ fontSize: Typography.sizes.sm,
+ color: '#92400E',
+ marginLeft: Spacing.sm,
+ },
+});
+
diff --git a/frontend/src/components/SendModal.tsx b/frontend/src/components/SendModal.tsx
new file mode 100644
index 00000000..62cdfd9d
--- /dev/null
+++ b/frontend/src/components/SendModal.tsx
@@ -0,0 +1,300 @@
+import React, { useState } from 'react';
+import {
+ View,
+ Text,
+ StyleSheet,
+ Modal,
+ TouchableOpacity,
+ TextInput,
+ Image,
+ Alert,
+} from 'react-native';
+import { Ionicons } from '@expo/vector-icons';
+import Colors from '../constants/colors';
+import { Typography, Spacing, BorderRadius, Shadow } from '../constants/theme';
+
+interface SendModalProps {
+ visible: boolean;
+ onClose: () => void;
+ token: {
+ symbol: string;
+ name: string;
+ balance: string;
+ icon: any;
+ color: string;
+ };
+}
+
+export default function SendModal({ visible, onClose, token }: SendModalProps) {
+ const [recipientAddress, setRecipientAddress] = useState('');
+ const [amount, setAmount] = useState('');
+ const [network, setNetwork] = useState('Optimism');
+
+ const handleMaxAmount = () => {
+ setAmount(token.balance);
+ };
+
+ const handleSend = () => {
+ if (!recipientAddress) {
+ Alert.alert('Error', 'Please enter recipient address');
+ return;
+ }
+ if (!amount || parseFloat(amount) <= 0) {
+ Alert.alert('Error', 'Please enter valid amount');
+ return;
+ }
+ if (parseFloat(amount) > parseFloat(token.balance)) {
+ Alert.alert('Error', 'Insufficient balance');
+ return;
+ }
+
+ Alert.alert(
+ 'Confirm Transaction',
+ `Send ${amount} ${token.symbol} to ${recipientAddress.substring(0, 10)}...?`,
+ [
+ { text: 'Cancel', style: 'cancel' },
+ {
+ text: 'Confirm',
+ onPress: () => {
+ // TODO: Integrate with blockchain service
+ Alert.alert('Success', 'Transaction submitted!');
+ onClose();
+ setRecipientAddress('');
+ setAmount('');
+ },
+ },
+ ]
+ );
+ };
+
+ const handleQRScan = () => {
+ // TODO: Open QR scanner
+ Alert.alert('QR Scanner', 'QR scanner will be implemented');
+ };
+
+ const handlePaste = async () => {
+ // TODO: Paste from clipboard
+ Alert.alert('Paste', 'Clipboard paste will be implemented');
+ };
+
+ const usdValue = (parseFloat(amount) || 0) * 1.5; // Mock exchange rate
+
+ return (
+
+
+
+ {/* Close Button */}
+
+
+
+
+ {/* Token Icon */}
+
+
+ {/* Title */}
+ Send {token.symbol}
+
+ {/* Available Balance */}
+
+ Available Balance: {token.balance} {token.symbol}
+
+
+ {/* Recipient Address */}
+ Recipient Address
+
+
+
+
+
+
+
+
+
+
+ {/* Amount */}
+ Amount
+
+
+
+ MAX
+
+
+ USD Value: ${usdValue.toFixed(2)}
+
+ {/* Network */}
+
+ Network:
+
+ {network}
+
+
+
+
+ {/* Transaction Fee */}
+
+ Fee: 0.001 HEZ (~$0.01)
+
+
+ {/* Send Button */}
+
+ Send {token.symbol}
+
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ overlay: {
+ flex: 1,
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
+ justifyContent: 'center',
+ alignItems: 'center',
+ padding: Spacing.lg,
+ },
+ modalContainer: {
+ width: '100%',
+ maxWidth: 400,
+ backgroundColor: '#FFFFFF',
+ borderRadius: BorderRadius.xl,
+ padding: Spacing.xl,
+ ...Shadow.medium,
+ },
+ closeButton: {
+ position: 'absolute',
+ top: Spacing.md,
+ left: Spacing.md,
+ zIndex: 1,
+ },
+ tokenIcon: {
+ width: 60,
+ height: 60,
+ alignSelf: 'center',
+ marginTop: Spacing.md,
+ },
+ title: {
+ fontSize: Typography.sizes.xxl,
+ fontWeight: Typography.weights.bold,
+ color: Colors.textDark,
+ textAlign: 'center',
+ marginTop: Spacing.sm,
+ },
+ balance: {
+ fontSize: Typography.sizes.md,
+ color: Colors.textLight,
+ textAlign: 'center',
+ marginTop: Spacing.xs,
+ marginBottom: Spacing.lg,
+ },
+ label: {
+ fontSize: Typography.sizes.md,
+ fontWeight: Typography.weights.semibold,
+ color: Colors.textDark,
+ marginBottom: Spacing.xs,
+ marginTop: Spacing.md,
+ },
+ inputContainer: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ backgroundColor: Colors.background,
+ borderRadius: BorderRadius.md,
+ paddingHorizontal: Spacing.md,
+ paddingVertical: Spacing.sm,
+ },
+ input: {
+ flex: 1,
+ fontSize: Typography.sizes.md,
+ color: Colors.textDark,
+ paddingVertical: Spacing.xs,
+ },
+ iconButton: {
+ marginLeft: Spacing.sm,
+ },
+ maxButton: {
+ backgroundColor: Colors.primary,
+ paddingHorizontal: Spacing.md,
+ paddingVertical: Spacing.xs,
+ borderRadius: BorderRadius.sm,
+ },
+ maxButtonText: {
+ fontSize: Typography.sizes.sm,
+ fontWeight: Typography.weights.bold,
+ color: '#FFFFFF',
+ },
+ usdValue: {
+ fontSize: Typography.sizes.sm,
+ color: Colors.textLight,
+ marginTop: Spacing.xs,
+ },
+ networkRow: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ marginTop: Spacing.lg,
+ },
+ networkLabel: {
+ fontSize: Typography.sizes.md,
+ fontWeight: Typography.weights.semibold,
+ color: Colors.textDark,
+ },
+ networkSelector: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ backgroundColor: Colors.background,
+ paddingHorizontal: Spacing.md,
+ paddingVertical: Spacing.sm,
+ borderRadius: BorderRadius.sm,
+ },
+ networkText: {
+ fontSize: Typography.sizes.md,
+ color: Colors.textDark,
+ marginRight: Spacing.xs,
+ },
+ feeRow: {
+ marginTop: Spacing.md,
+ },
+ feeText: {
+ fontSize: Typography.sizes.sm,
+ color: Colors.textLight,
+ },
+ sendButton: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'center',
+ paddingVertical: Spacing.md,
+ borderRadius: BorderRadius.lg,
+ marginTop: Spacing.xl,
+ ...Shadow.small,
+ },
+ sendButtonText: {
+ fontSize: Typography.sizes.lg,
+ fontWeight: Typography.weights.bold,
+ color: '#FFFFFF',
+ marginRight: Spacing.sm,
+ },
+});
+
diff --git a/frontend/src/constants/blockchain.ts b/frontend/src/constants/blockchain.ts
new file mode 100644
index 00000000..56b37cb9
--- /dev/null
+++ b/frontend/src/constants/blockchain.ts
@@ -0,0 +1,92 @@
+/**
+ * PezkuwiChain Blockchain Configuration
+ */
+
+import { ChainConfig } from '../types';
+
+export const CHAIN_CONFIGS: Record<'testnet' | 'mainnet', ChainConfig> = {
+ testnet: {
+ name: 'PezkuwiChain Testnet',
+ rpcUrl: 'wss://testnet-rpc.pezkuwichain.io',
+ chainId: 'pezkuwi-testnet',
+ genesisHash: '0x0000000000000000000000000000000000000000000000000000000000000000', // Will be updated
+ decimals: {
+ hez: 12,
+ pez: 12,
+ },
+ },
+ mainnet: {
+ name: 'PezkuwiChain Mainnet',
+ rpcUrl: 'wss://mainnet-rpc.pezkuwichain.io',
+ chainId: 'pezkuwi-mainnet',
+ genesisHash: '0x0000000000000000000000000000000000000000000000000000000000000000', // Will be updated
+ decimals: {
+ hez: 12,
+ pez: 12,
+ },
+ },
+};
+
+// Default to testnet for development
+export const DEFAULT_CHAIN: 'testnet' | 'mainnet' = 'testnet';
+
+export const CURRENT_CHAIN_CONFIG = CHAIN_CONFIGS[DEFAULT_CHAIN];
+
+// Pallet names
+export const PALLETS = {
+ BALANCES: 'balances',
+ ASSETS: 'assets',
+ STAKING: 'staking',
+ WELATI: 'welati',
+ TRUST: 'trust',
+ PEZ_REWARDS: 'pezRewards',
+ PEZ_TREASURY: 'pezTreasury',
+ IDENTITY_KYC: 'identityKyc',
+ PERWERDE: 'perwerde',
+ REFERRAL: 'referral',
+ VALIDATOR_POOL: 'validatorPool',
+ STAKING_SCORE: 'stakingScore',
+};
+
+// Asset IDs
+export const ASSET_IDS = {
+ PEZ: 1, // PEZ token asset ID
+};
+
+// Constants from blockchain
+export const BLOCKCHAIN_CONSTANTS = {
+ // PEZ Token
+ PEZ_TOTAL_SUPPLY: '5000000000000000000000', // 5 billion with 12 decimals
+ PEZ_HALVING_PERIOD: 48, // months
+ PEZ_EPOCH_BLOCKS: 432000, // ~30 days
+ PEZ_CLAIM_PERIOD: 100800, // ~1 week
+
+ // Parliamentary NFT
+ PARLIAMENTARY_NFT_COUNT: 201,
+ PARLIAMENTARY_NFT_COLLECTION_ID: 100,
+ PARLIAMENTARY_NFT_INCENTIVE_PERCENT: 10, // 10% of rewards pool
+
+ // Trust Score
+ TRUST_SCORE_MIN: 0,
+ TRUST_SCORE_MAX: 1000,
+
+ // Staking
+ MIN_STAKE_AMOUNT: '1000000000000', // 1 HEZ with 12 decimals
+ UNBONDING_PERIOD: 28, // days
+
+ // Governance
+ PROPOSAL_DEPOSIT: '100000000000000', // 100 PEZ with 12 decimals
+ VOTING_PERIOD: 7, // days
+};
+
+// Block time (approximate)
+export const BLOCK_TIME = 6; // seconds
+
+// Transaction fees (approximate)
+export const TX_FEES = {
+ TRANSFER: '0.01', // HEZ
+ STAKE: '0.02',
+ VOTE: '0.01',
+ PROPOSAL: '0.05',
+};
+
diff --git a/frontend/src/constants/colors.ts b/frontend/src/constants/colors.ts
new file mode 100644
index 00000000..5a87bc95
--- /dev/null
+++ b/frontend/src/constants/colors.ts
@@ -0,0 +1,57 @@
+/**
+ * PezkuwiChain Mobile App - Color Palette
+ * Elegant, soft Kurdish-inspired colors
+ */
+
+export const Colors = {
+ // Primary Kurdish Colors (Soft)
+ coral: '#F08080', // Soft red - Send, Home
+ mint: '#98D8C8', // Soft green - Governance, Vote
+ gold: '#E8C896', // Soft gold - Trust score, Parliamentary
+ peach: '#F5B895', // Soft orange - Update, Create buttons
+ teal: '#7DD3C0', // Soft teal - Identity, Receive
+ lavender: '#C8B6D6', // Soft purple - Education, Stake
+ navy: '#5D7A8C', // Soft navy - Business
+
+ // Supporting Colors
+ blue: '#89CFF0', // Soft blue - Wallet, Receive
+ cyan: '#7DD3C0', // Soft cyan - Exchange
+ emerald: '#7FD8BE', // Soft emerald - Trust
+ violet: '#B19CD9', // Soft violet - Rewards
+ pink: '#FFB6C1', // Soft pink - Certificates
+
+ // Backgrounds
+ background: '#FAFAFA', // Off-white main background
+ card: '#FFFFFF', // White cards
+ header: '#F5F5F5', // Light gray header
+
+ // Text Colors
+ textDark: '#2C3E50', // Primary text
+ textGray: '#7F8C8D', // Secondary text
+ textLight: '#BDC3C7', // Tertiary text
+
+ // Functional Colors
+ success: '#2ECC71', // Green for success
+ warning: '#F39C12', // Orange for warnings
+ error: '#E74C3C', // Red for errors
+ info: '#3498DB', // Blue for info
+
+ // Gradients (start and end colors)
+ gradients: {
+ header: ['#F08080', '#F5B895'], // Coral to peach
+ hezCard: ['#F08080', '#F5B895'], // Red to orange
+ pezCard: ['#98D8C8', '#7DD3C0'], // Green to teal
+ governance: ['#98D8C8', '#7DD3C0'], // Mint gradient
+ education: ['#C8B6D6', '#B19CD9'], // Lavender gradient
+ business: ['#5D7A8C', '#7F8C8D'], // Navy gradient
+ exchange: ['#7DD3C0', '#89CFF0'], // Cyan gradient
+ referral: ['#F5B895', '#E8C896'], // Peach to gold
+ identity: ['#7DD3C0', '#98D8C8'], // Teal to mint
+ },
+
+ // Shadow
+ shadow: 'rgba(0, 0, 0, 0.08)',
+};
+
+export default Colors;
+
diff --git a/frontend/src/constants/theme.ts b/frontend/src/constants/theme.ts
new file mode 100644
index 00000000..3101e58b
--- /dev/null
+++ b/frontend/src/constants/theme.ts
@@ -0,0 +1,87 @@
+/**
+ * PezkuwiChain Mobile App - Theme Constants
+ */
+
+export const Typography = {
+ // Font Sizes
+ sizes: {
+ tiny: 10,
+ small: 12,
+ body: 14,
+ medium: 16,
+ large: 18,
+ title: 20,
+ heading: 24,
+ display: 32,
+ hero: 40,
+ },
+
+ // Font Weights
+ weights: {
+ regular: '400' as const,
+ medium: '500' as const,
+ semibold: '600' as const,
+ bold: '700' as const,
+ },
+
+ // Line Heights
+ lineHeights: {
+ tight: 1.2,
+ normal: 1.5,
+ relaxed: 1.8,
+ },
+};
+
+export const Spacing = {
+ xs: 4,
+ sm: 8,
+ md: 12,
+ lg: 16,
+ xl: 20,
+ xxl: 24,
+ xxxl: 32,
+};
+
+export const BorderRadius = {
+ small: 8,
+ medium: 12,
+ large: 16,
+ xlarge: 20,
+ xxlarge: 24,
+ round: 9999,
+};
+
+export const Shadow = {
+ soft: {
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 2 },
+ shadowOpacity: 0.08,
+ shadowRadius: 8,
+ elevation: 3,
+ },
+ medium: {
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 4 },
+ shadowOpacity: 0.12,
+ shadowRadius: 12,
+ elevation: 5,
+ },
+};
+
+export const IconSizes = {
+ tiny: 16,
+ small: 20,
+ medium: 24,
+ large: 32,
+ xlarge: 40,
+ xxlarge: 60,
+};
+
+export default {
+ Typography,
+ Spacing,
+ BorderRadius,
+ Shadow,
+ IconSizes,
+};
+
diff --git a/frontend/src/navigation/BottomTabNavigator.tsx b/frontend/src/navigation/BottomTabNavigator.tsx
new file mode 100644
index 00000000..67b65e87
--- /dev/null
+++ b/frontend/src/navigation/BottomTabNavigator.tsx
@@ -0,0 +1,63 @@
+import React from 'react';
+import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
+import { Ionicons } from '@expo/vector-icons';
+import Colors from '../constants/colors';
+
+// Screens
+import HomeScreen from '../screens/Home/HomeScreen';
+import WalletScreen from '../screens/Wallet/WalletScreen';
+import GovernanceScreen from '../screens/Governance/GovernanceScreen';
+import ReferralScreen from '../screens/Referral/ReferralScreen';
+import ProfileScreen from '../screens/Profile/ProfileScreen';
+
+const Tab = createBottomTabNavigator();
+
+export default function BottomTabNavigator() {
+ return (
+ ({
+ tabBarIcon: ({ focused, color, size }) => {
+ let iconName: keyof typeof Ionicons.glyphMap;
+
+ if (route.name === 'Home') {
+ iconName = focused ? 'home' : 'home-outline';
+ } else if (route.name === 'Wallet') {
+ iconName = focused ? 'wallet' : 'wallet-outline';
+ } else if (route.name === 'Governance') {
+ iconName = focused ? 'business' : 'business-outline';
+ } else if (route.name === 'Referral') {
+ iconName = focused ? 'gift' : 'gift-outline';
+ } else if (route.name === 'Profile') {
+ iconName = focused ? 'person' : 'person-outline';
+ } else {
+ iconName = 'help-outline';
+ }
+
+ return ;
+ },
+ tabBarActiveTintColor: Colors.coral,
+ tabBarInactiveTintColor: Colors.textGray,
+ tabBarStyle: {
+ backgroundColor: '#FFFFFF',
+ borderTopWidth: 1,
+ borderTopColor: '#F0F0F0',
+ paddingBottom: 8,
+ paddingTop: 8,
+ height: 60,
+ },
+ tabBarLabelStyle: {
+ fontSize: 12,
+ fontWeight: '500',
+ },
+ headerShown: false,
+ })}
+ >
+
+
+
+
+
+
+ );
+}
+
diff --git a/frontend/src/navigation/RootNavigator.tsx b/frontend/src/navigation/RootNavigator.tsx
new file mode 100644
index 00000000..714f5204
--- /dev/null
+++ b/frontend/src/navigation/RootNavigator.tsx
@@ -0,0 +1,54 @@
+import React from 'react';
+import { NavigationContainer } from '@react-navigation/native';
+import { createNativeStackNavigator } from '@react-navigation/native-stack';
+
+// Auth Screens
+import LanguageSelectionScreen from '../screens/Auth/LanguageSelectionScreen';
+import SignUpScreen from '../screens/Auth/SignUpScreen';
+
+// Main App
+import BottomTabNavigator from './BottomTabNavigator';
+
+// Identity & KYC Screens
+import IdentityKYCFormScreen from '../screens/Identity/IdentityKYCFormScreen';
+import CitizenCardScreen from '../screens/Identity/CitizenCardScreen';
+
+// Additional Screens
+import EducationScreen from '../screens/Education/EducationScreen';
+import BusinessScreen from '../screens/Business/BusinessScreen';
+import ExchangeScreen from '../screens/Exchange/ExchangeScreen';
+import ReferralScreen from '../screens/Referral/ReferralScreen';
+
+const Stack = createNativeStackNavigator();
+
+export default function RootNavigator() {
+ return (
+
+
+ {/* Auth Flow */}
+
+
+
+ {/* Main App */}
+
+
+ {/* Identity & KYC */}
+
+
+
+ {/* Additional Screens */}
+
+
+
+
+
+
+ );
+}
+
+// Add Ministries screen to imports and stack
diff --git a/frontend/src/screens/Auth/LanguageSelectionScreen.tsx b/frontend/src/screens/Auth/LanguageSelectionScreen.tsx
new file mode 100644
index 00000000..8f5d2774
--- /dev/null
+++ b/frontend/src/screens/Auth/LanguageSelectionScreen.tsx
@@ -0,0 +1,199 @@
+import React, { useState } from 'react';
+import {
+ View,
+ Text,
+ StyleSheet,
+ TouchableOpacity,
+ SafeAreaView,
+ StatusBar,
+} from 'react-native';
+import { LinearGradient } from 'expo-linear-gradient';
+import Colors from '../../constants/colors';
+import { Typography, Spacing, BorderRadius } from '../../constants/theme';
+
+interface Language {
+ code: string;
+ name: string;
+ nativeName: string;
+}
+
+const LANGUAGES: Language[] = [
+ { code: 'en', name: 'English', nativeName: 'English' },
+ { code: 'ku', name: 'Kurdish (Kurmanji)', nativeName: 'Kurdî (Kurmancî)' },
+ { code: 'ckb', name: 'Kurdish (Sorani)', nativeName: 'کوردی (سۆرانی)' },
+ { code: 'tr', name: 'Turkish', nativeName: 'Türkçe' },
+ { code: 'ar', name: 'Arabic', nativeName: 'العربية' },
+ { code: 'fa', name: 'Persian', nativeName: 'فارسی' },
+];
+
+export default function LanguageSelectionScreen({ navigation }: any) {
+ const [selectedLanguage, setSelectedLanguage] = useState('en');
+
+ const handleContinue = () => {
+ // Save language preference
+ // TODO: Implement i18n language switching
+ navigation.navigate('SignUp');
+ };
+
+ return (
+
+
+
+
+ {/* Header */}
+
+ Welcome to
+ PezkuwiChain
+ Your Digital Citizenship Platform
+
+ Building the future of Kurdish digital infrastructure
+
+
+
+ {/* Language Selection */}
+
+ Select Your Language
+
+
+ {LANGUAGES.map((language) => (
+ setSelectedLanguage(language.code)}
+ activeOpacity={0.7}
+ >
+
+ {language.nativeName}
+
+
+ ))}
+
+
+
+ {/* Continue Button */}
+
+ Get Started →
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: Colors.coral,
+ },
+ gradient: {
+ flex: 1,
+ },
+ content: {
+ flex: 1,
+ paddingHorizontal: Spacing.xl,
+ paddingVertical: Spacing.xxxl,
+ justifyContent: 'space-between',
+ },
+ header: {
+ alignItems: 'center',
+ marginTop: Spacing.xxxl,
+ },
+ title: {
+ fontSize: Typography.sizes.heading,
+ fontWeight: Typography.weights.semibold,
+ color: '#FFFFFF',
+ marginBottom: Spacing.sm,
+ },
+ brandName: {
+ fontSize: Typography.sizes.display,
+ fontWeight: Typography.weights.bold,
+ color: '#FFFFFF',
+ marginBottom: Spacing.md,
+ },
+ subtitle: {
+ fontSize: Typography.sizes.medium,
+ fontWeight: Typography.weights.medium,
+ color: '#FFFFFF',
+ marginBottom: Spacing.sm,
+ },
+ description: {
+ fontSize: Typography.sizes.body,
+ color: 'rgba(255, 255, 255, 0.9)',
+ textAlign: 'center',
+ },
+ languageSection: {
+ flex: 1,
+ justifyContent: 'center',
+ },
+ sectionTitle: {
+ fontSize: Typography.sizes.large,
+ fontWeight: Typography.weights.semibold,
+ color: '#FFFFFF',
+ textAlign: 'center',
+ marginBottom: Spacing.xl,
+ },
+ languageGrid: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ justifyContent: 'space-between',
+ gap: Spacing.md,
+ },
+ languageButton: {
+ width: '48%',
+ backgroundColor: 'rgba(255, 255, 255, 0.2)',
+ borderRadius: BorderRadius.large,
+ paddingVertical: Spacing.lg,
+ paddingHorizontal: Spacing.md,
+ borderWidth: 2,
+ borderColor: 'transparent',
+ },
+ languageButtonSelected: {
+ backgroundColor: 'rgba(255, 255, 255, 0.95)',
+ borderColor: '#FFFFFF',
+ },
+ languageText: {
+ fontSize: Typography.sizes.medium,
+ fontWeight: Typography.weights.medium,
+ color: '#FFFFFF',
+ textAlign: 'center',
+ },
+ languageTextSelected: {
+ color: Colors.coral,
+ fontWeight: Typography.weights.semibold,
+ },
+ continueButton: {
+ backgroundColor: 'rgba(212, 160, 23, 0.9)',
+ borderRadius: BorderRadius.xxlarge,
+ paddingVertical: Spacing.lg,
+ paddingHorizontal: Spacing.xxxl,
+ alignItems: 'center',
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 4 },
+ shadowOpacity: 0.2,
+ shadowRadius: 8,
+ elevation: 5,
+ },
+ continueButtonText: {
+ fontSize: Typography.sizes.large,
+ fontWeight: Typography.weights.semibold,
+ color: '#FFFFFF',
+ },
+});
+
diff --git a/frontend/src/screens/Auth/SignUpScreen.tsx b/frontend/src/screens/Auth/SignUpScreen.tsx
new file mode 100644
index 00000000..fff9ba06
--- /dev/null
+++ b/frontend/src/screens/Auth/SignUpScreen.tsx
@@ -0,0 +1,326 @@
+import React, { useState } from 'react';
+import {
+ View,
+ Text,
+ StyleSheet,
+ TextInput,
+ TouchableOpacity,
+ SafeAreaView,
+ KeyboardAvoidingView,
+ Platform,
+ ScrollView,
+} from 'react-native';
+import { Ionicons } from '@expo/vector-icons';
+import Colors from '../../constants/colors';
+import { Typography, Spacing, BorderRadius, Shadow } from '../../constants/theme';
+
+export default function SignUpScreen({ navigation }: any) {
+ const [isSignUp, setIsSignUp] = useState(true);
+ const [formData, setFormData] = useState({
+ fullName: '',
+ email: '',
+ password: '',
+ confirmPassword: '',
+ referralCode: '',
+ });
+ const [showPassword, setShowPassword] = useState(false);
+ const [showConfirmPassword, setShowConfirmPassword] = useState(false);
+
+ const handleSubmit = () => {
+ // TODO: Implement authentication logic
+ navigation.navigate('MainTabs');
+ };
+
+ const toggleMode = () => {
+ setIsSignUp(!isSignUp);
+ };
+
+ return (
+
+
+
+ {/* Header */}
+
+ PezkuwiChain
+ Access your governance account
+
+
+ {/* Toggle Buttons */}
+
+ setIsSignUp(false)}
+ >
+
+ Sign In
+
+
+ setIsSignUp(true)}
+ >
+
+ Sign Up
+
+
+
+
+ {/* Form */}
+
+ {isSignUp && (
+
+ Full Name
+
+
+ setFormData({ ...formData, fullName: text })}
+ />
+
+
+ )}
+
+
+ Email
+
+
+ setFormData({ ...formData, email: text })}
+ />
+
+
+
+
+ Password
+
+
+ setFormData({ ...formData, password: text })}
+ />
+ setShowPassword(!showPassword)}>
+
+
+
+
+
+ {isSignUp && (
+ <>
+
+ Confirm Password
+
+
+
+ setFormData({ ...formData, confirmPassword: text })
+ }
+ />
+ setShowConfirmPassword(!showConfirmPassword)}
+ >
+
+
+
+
+
+
+ Referral Code (Optional)
+
+
+
+ setFormData({ ...formData, referralCode: text })
+ }
+ />
+
+
+ >
+ )}
+
+ {!isSignUp && (
+
+ Forgot Password?
+
+ )}
+
+ {/* Submit Button */}
+
+
+ {isSignUp ? 'Create Account' : 'Sign In'}
+
+
+
+ {/* Footer */}
+
+
+ {isSignUp ? 'Already have an account?' : "Don't have an account?"}
+
+
+
+ {isSignUp ? 'Sign In' : 'Sign Up'}
+
+
+
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: Colors.navy,
+ },
+ keyboardView: {
+ flex: 1,
+ },
+ scrollContent: {
+ flexGrow: 1,
+ paddingHorizontal: Spacing.xl,
+ paddingVertical: Spacing.xxxl,
+ },
+ header: {
+ alignItems: 'center',
+ marginBottom: Spacing.xxxl,
+ },
+ logo: {
+ fontSize: Typography.sizes.display,
+ fontWeight: Typography.weights.bold,
+ color: Colors.mint,
+ marginBottom: Spacing.sm,
+ },
+ subtitle: {
+ fontSize: Typography.sizes.medium,
+ color: Colors.textLight,
+ },
+ toggleContainer: {
+ flexDirection: 'row',
+ backgroundColor: 'rgba(255, 255, 255, 0.1)',
+ borderRadius: BorderRadius.large,
+ padding: Spacing.xs,
+ marginBottom: Spacing.xl,
+ },
+ toggleButton: {
+ flex: 1,
+ paddingVertical: Spacing.md,
+ alignItems: 'center',
+ borderRadius: BorderRadius.medium,
+ },
+ toggleButtonActive: {
+ backgroundColor: Colors.mint,
+ },
+ toggleText: {
+ fontSize: Typography.sizes.medium,
+ fontWeight: Typography.weights.medium,
+ color: Colors.textLight,
+ },
+ toggleTextActive: {
+ color: Colors.navy,
+ fontWeight: Typography.weights.semibold,
+ },
+ form: {
+ flex: 1,
+ },
+ inputContainer: {
+ marginBottom: Spacing.lg,
+ },
+ label: {
+ fontSize: Typography.sizes.body,
+ fontWeight: Typography.weights.medium,
+ color: '#FFFFFF',
+ marginBottom: Spacing.sm,
+ },
+ inputWrapper: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ backgroundColor: 'rgba(255, 255, 255, 0.1)',
+ borderRadius: BorderRadius.medium,
+ paddingHorizontal: Spacing.md,
+ paddingVertical: Spacing.sm,
+ borderWidth: 1,
+ borderColor: 'rgba(255, 255, 255, 0.2)',
+ },
+ input: {
+ flex: 1,
+ fontSize: Typography.sizes.medium,
+ color: '#FFFFFF',
+ marginLeft: Spacing.sm,
+ },
+ forgotPassword: {
+ alignSelf: 'flex-end',
+ marginBottom: Spacing.lg,
+ },
+ forgotPasswordText: {
+ fontSize: Typography.sizes.small,
+ color: Colors.mint,
+ },
+ submitButton: {
+ backgroundColor: Colors.peach,
+ borderRadius: BorderRadius.xxlarge,
+ paddingVertical: Spacing.lg,
+ alignItems: 'center',
+ marginTop: Spacing.lg,
+ ...Shadow.soft,
+ },
+ submitButtonText: {
+ fontSize: Typography.sizes.large,
+ fontWeight: Typography.weights.semibold,
+ color: '#FFFFFF',
+ },
+ footer: {
+ flexDirection: 'row',
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginTop: Spacing.xl,
+ gap: Spacing.xs,
+ },
+ footerText: {
+ fontSize: Typography.sizes.body,
+ color: Colors.textLight,
+ },
+ footerLink: {
+ fontSize: Typography.sizes.body,
+ fontWeight: Typography.weights.semibold,
+ color: Colors.mint,
+ },
+});
+
diff --git a/frontend/src/screens/Business/BusinessScreen.tsx b/frontend/src/screens/Business/BusinessScreen.tsx
new file mode 100644
index 00000000..ce34fb4e
--- /dev/null
+++ b/frontend/src/screens/Business/BusinessScreen.tsx
@@ -0,0 +1,794 @@
+import React, { useState } from 'react';
+import {
+ View,
+ Text,
+ StyleSheet,
+ SafeAreaView,
+ ScrollView,
+ TouchableOpacity,
+ TextInput,
+ Modal,
+ Alert,
+} from 'react-native';
+import { Ionicons } from '@expo/vector-icons';
+import { LinearGradient } from 'expo-linear-gradient';
+import QRCode from 'react-native-qrcode-svg';
+import * as Clipboard from 'expo-clipboard';
+import Colors from '../../constants/colors';
+
+interface BusinessStats {
+ totalSales: number;
+ todaySales: number;
+ pendingPayments: number;
+ totalCustomers: number;
+}
+
+interface Transaction {
+ id: string;
+ customer: string;
+ amount: number;
+ token: 'HEZ' | 'PEZ';
+ date: string;
+ status: 'completed' | 'pending' | 'failed';
+ invoiceId: string;
+}
+
+export default function BusinessScreen({ navigation }: any) {
+ const [merchantAddress] = useState('5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY');
+ const [showPaymentModal, setShowPaymentModal] = useState(false);
+ const [paymentAmount, setPaymentAmount] = useState('');
+ const [selectedToken, setSelectedToken] = useState<'HEZ' | 'PEZ'>('PEZ');
+ const [paymentNote, setPaymentNote] = useState('');
+
+ const [stats] = useState({
+ totalSales: 125450,
+ todaySales: 3250,
+ pendingPayments: 850,
+ totalCustomers: 342,
+ });
+
+ const [transactions] = useState([
+ {
+ id: '1',
+ customer: 'Ahmed Karwan',
+ amount: 500,
+ token: 'PEZ',
+ date: '2024-01-23 14:30',
+ status: 'completed',
+ invoiceId: 'INV-2024-001',
+ },
+ {
+ id: '2',
+ customer: 'Layla Sherzad',
+ amount: 1250,
+ token: 'HEZ',
+ date: '2024-01-23 12:15',
+ status: 'completed',
+ invoiceId: 'INV-2024-002',
+ },
+ {
+ id: '3',
+ customer: 'Saman Aziz',
+ amount: 750,
+ token: 'PEZ',
+ date: '2024-01-23 10:45',
+ status: 'pending',
+ invoiceId: 'INV-2024-003',
+ },
+ {
+ id: '4',
+ customer: 'Hana Dilshad',
+ amount: 350,
+ token: 'PEZ',
+ date: '2024-01-22 16:20',
+ status: 'completed',
+ invoiceId: 'INV-2024-004',
+ },
+ ]);
+
+ const generatePaymentQR = () => {
+ if (!paymentAmount || parseFloat(paymentAmount) <= 0) {
+ Alert.alert('Invalid Amount', 'Please enter a valid payment amount');
+ return;
+ }
+ setShowPaymentModal(true);
+ };
+
+ const copyMerchantAddress = async () => {
+ await Clipboard.setStringAsync(merchantAddress);
+ Alert.alert('✓ Copied!', 'Merchant address copied to clipboard');
+ };
+
+ const getStatusColor = (status: string) => {
+ switch (status) {
+ case 'completed':
+ return Colors.success;
+ case 'pending':
+ return Colors.warning;
+ case 'failed':
+ return Colors.error;
+ default:
+ return Colors.textGray;
+ }
+ };
+
+ const paymentData = JSON.stringify({
+ merchant: merchantAddress,
+ amount: paymentAmount,
+ token: selectedToken,
+ note: paymentNote,
+ timestamp: Date.now(),
+ });
+
+ return (
+
+
+ {/* Header */}
+
+
+
+ Business Hub
+ Merchant Payment Center
+
+ Alert.alert('Settings', 'Business settings coming soon')}
+ >
+
+
+
+
+
+ {/* Statistics Grid */}
+
+
+
+
+ {stats.totalSales.toLocaleString()}
+ Total Sales (PEZ)
+
+
+
+ {stats.todaySales.toLocaleString()}
+ Today's Sales
+
+
+
+ {stats.pendingPayments.toLocaleString()}
+ Pending
+
+
+
+ {stats.totalCustomers}
+ Customers
+
+
+
+
+ {/* Quick Actions */}
+
+ Quick Actions
+
+
+
+
+
+ Generate QR
+
+
+
+
+
+ Create Invoice
+
+
+
+
+
+ Analytics
+
+
+
+
+
+ Payment Link
+
+
+
+
+ {/* Payment Request Form */}
+
+ Create Payment Request
+
+
+ Amount
+
+
+
+
+ Token
+
+ setSelectedToken('PEZ')}
+ >
+
+ PEZ
+
+
+ setSelectedToken('HEZ')}
+ >
+
+ HEZ
+
+
+
+
+
+
+ Note (Optional)
+
+
+
+
+
+
+ Generate Payment QR
+
+
+
+
+
+ {/* Recent Transactions */}
+
+
+ Recent Transactions
+
+ View All
+
+
+
+ {transactions.map((transaction) => (
+
+
+
+
+
+
+
+ {transaction.customer}
+
+ {transaction.date}
+
+ {transaction.invoiceId}
+
+
+
+
+ {transaction.amount.toLocaleString()}
+
+ {transaction.token}
+
+
+
+
+ {transaction.status.charAt(0).toUpperCase() +
+ transaction.status.slice(1)}
+
+
+
+ ))}
+
+
+ {/* Merchant Info */}
+
+ Merchant Information
+
+
+
+ Your Merchant Address
+
+
+
+ {merchantAddress}
+
+
+
+
+ Share this address with customers to receive payments
+
+
+
+
+
+
+
+ {/* Payment QR Modal */}
+ setShowPaymentModal(false)}
+ >
+
+
+
+ Payment QR Code
+ setShowPaymentModal(false)}>
+
+
+
+
+
+
+
+
+
+
+ Amount:
+
+ {paymentAmount} {selectedToken}
+
+
+ {paymentNote ? (
+
+ Note:
+ {paymentNote}
+
+ ) : null}
+
+
+
+ Ask customer to scan this QR code with their PezkuwiChain app
+
+
+ setShowPaymentModal(false)}
+ >
+ Done
+
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: Colors.background,
+ },
+ header: {
+ paddingHorizontal: 20,
+ paddingTop: 20,
+ paddingBottom: 24,
+ borderBottomLeftRadius: 24,
+ borderBottomRightRadius: 24,
+ },
+ headerContent: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ },
+ headerTitle: {
+ fontSize: 32,
+ fontWeight: '700',
+ color: 'white',
+ marginBottom: 4,
+ },
+ headerSubtitle: {
+ fontSize: 16,
+ color: 'rgba(255, 255, 255, 0.9)',
+ },
+ settingsButton: {
+ width: 48,
+ height: 48,
+ borderRadius: 24,
+ backgroundColor: 'rgba(255, 255, 255, 0.2)',
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ statsContainer: {
+ paddingHorizontal: 20,
+ marginTop: -30,
+ marginBottom: 20,
+ },
+ statsGrid: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ gap: 12,
+ },
+ statCard: {
+ flex: 1,
+ minWidth: '47%',
+ backgroundColor: 'white',
+ borderRadius: 14,
+ padding: 16,
+ alignItems: 'center',
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 2 },
+ shadowOpacity: 0.05,
+ shadowRadius: 8,
+ elevation: 2,
+ },
+ statValue: {
+ fontSize: 24,
+ fontWeight: '700',
+ color: Colors.textDark,
+ marginTop: 8,
+ marginBottom: 4,
+ },
+ statLabel: {
+ fontSize: 13,
+ color: Colors.textGray,
+ textAlign: 'center',
+ },
+ section: {
+ paddingHorizontal: 20,
+ marginBottom: 24,
+ },
+ sectionHeader: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ marginBottom: 12,
+ },
+ sectionTitle: {
+ fontSize: 20,
+ fontWeight: '700',
+ color: Colors.textDark,
+ marginBottom: 12,
+ },
+ viewAllText: {
+ fontSize: 14,
+ fontWeight: '600',
+ color: Colors.primary,
+ },
+ actionsGrid: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ gap: 12,
+ },
+ actionCard: {
+ flex: 1,
+ minWidth: '47%',
+ backgroundColor: 'white',
+ borderRadius: 14,
+ padding: 16,
+ alignItems: 'center',
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 1 },
+ shadowOpacity: 0.04,
+ shadowRadius: 6,
+ elevation: 1,
+ },
+ actionIcon: {
+ width: 64,
+ height: 64,
+ borderRadius: 16,
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginBottom: 12,
+ },
+ actionLabel: {
+ fontSize: 14,
+ fontWeight: '600',
+ color: Colors.textDark,
+ textAlign: 'center',
+ },
+ formCard: {
+ backgroundColor: 'white',
+ borderRadius: 14,
+ padding: 20,
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 1 },
+ shadowOpacity: 0.04,
+ shadowRadius: 6,
+ elevation: 1,
+ },
+ inputGroup: {
+ marginBottom: 16,
+ },
+ inputLabel: {
+ fontSize: 14,
+ fontWeight: '600',
+ color: Colors.textDark,
+ marginBottom: 8,
+ },
+ input: {
+ backgroundColor: Colors.background,
+ borderRadius: 10,
+ paddingHorizontal: 16,
+ paddingVertical: 12,
+ fontSize: 15,
+ color: Colors.textDark,
+ },
+ textArea: {
+ height: 80,
+ textAlignVertical: 'top',
+ },
+ tokenSelector: {
+ flexDirection: 'row',
+ gap: 12,
+ },
+ tokenOption: {
+ flex: 1,
+ paddingVertical: 12,
+ borderRadius: 10,
+ backgroundColor: Colors.background,
+ alignItems: 'center',
+ },
+ tokenOptionActive: {
+ backgroundColor: Colors.primary,
+ },
+ tokenOptionText: {
+ fontSize: 15,
+ fontWeight: '600',
+ color: Colors.textGray,
+ },
+ tokenOptionTextActive: {
+ color: 'white',
+ },
+ generateButton: {
+ borderRadius: 10,
+ overflow: 'hidden',
+ marginTop: 8,
+ },
+ generateButtonGradient: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'center',
+ paddingVertical: 14,
+ gap: 8,
+ },
+ generateButtonText: {
+ fontSize: 16,
+ fontWeight: '600',
+ color: 'white',
+ },
+ transactionCard: {
+ backgroundColor: 'white',
+ borderRadius: 14,
+ padding: 16,
+ marginBottom: 12,
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 1 },
+ shadowOpacity: 0.04,
+ shadowRadius: 6,
+ elevation: 1,
+ },
+ transactionHeader: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ marginBottom: 12,
+ },
+ transactionIcon: {
+ marginRight: 12,
+ },
+ transactionInfo: {
+ flex: 1,
+ },
+ transactionCustomer: {
+ fontSize: 16,
+ fontWeight: '600',
+ color: Colors.textDark,
+ marginBottom: 2,
+ },
+ transactionDate: {
+ fontSize: 12,
+ color: Colors.textGray,
+ marginBottom: 2,
+ },
+ transactionInvoice: {
+ fontSize: 11,
+ color: Colors.textGray,
+ fontFamily: 'monospace',
+ },
+ transactionAmount: {
+ alignItems: 'flex-end',
+ },
+ amountValue: {
+ fontSize: 18,
+ fontWeight: '700',
+ color: Colors.textDark,
+ },
+ amountToken: {
+ fontSize: 12,
+ color: Colors.textGray,
+ marginTop: 2,
+ },
+ statusBadge: {
+ alignSelf: 'flex-start',
+ paddingHorizontal: 10,
+ paddingVertical: 4,
+ borderRadius: 8,
+ },
+ statusText: {
+ fontSize: 12,
+ fontWeight: '600',
+ },
+ merchantCard: {
+ backgroundColor: 'white',
+ borderRadius: 14,
+ padding: 20,
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 1 },
+ shadowOpacity: 0.04,
+ shadowRadius: 6,
+ elevation: 1,
+ },
+ merchantHeader: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: 8,
+ marginBottom: 12,
+ },
+ merchantTitle: {
+ fontSize: 16,
+ fontWeight: '600',
+ color: Colors.textDark,
+ },
+ addressBox: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ backgroundColor: Colors.background,
+ borderRadius: 10,
+ padding: 12,
+ marginBottom: 8,
+ },
+ addressText: {
+ flex: 1,
+ fontSize: 13,
+ color: Colors.textDark,
+ fontFamily: 'monospace',
+ marginRight: 8,
+ },
+ merchantNote: {
+ fontSize: 12,
+ color: Colors.textGray,
+ lineHeight: 18,
+ },
+ modalOverlay: {
+ flex: 1,
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
+ justifyContent: 'center',
+ alignItems: 'center',
+ padding: 20,
+ },
+ modalContent: {
+ backgroundColor: 'white',
+ borderRadius: 20,
+ padding: 24,
+ width: '100%',
+ maxWidth: 400,
+ },
+ modalHeader: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ marginBottom: 24,
+ },
+ modalTitle: {
+ fontSize: 22,
+ fontWeight: '700',
+ color: Colors.textDark,
+ },
+ qrContainer: {
+ alignItems: 'center',
+ padding: 20,
+ backgroundColor: Colors.background,
+ borderRadius: 16,
+ marginBottom: 20,
+ },
+ paymentDetails: {
+ backgroundColor: Colors.background,
+ borderRadius: 12,
+ padding: 16,
+ marginBottom: 16,
+ gap: 8,
+ },
+ paymentDetailRow: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ },
+ paymentDetailLabel: {
+ fontSize: 14,
+ color: Colors.textGray,
+ },
+ paymentDetailValue: {
+ fontSize: 14,
+ fontWeight: '600',
+ color: Colors.textDark,
+ },
+ qrInstruction: {
+ fontSize: 13,
+ color: Colors.textGray,
+ textAlign: 'center',
+ marginBottom: 20,
+ lineHeight: 20,
+ },
+ doneButton: {
+ backgroundColor: Colors.primary,
+ borderRadius: 10,
+ paddingVertical: 14,
+ alignItems: 'center',
+ },
+ doneButtonText: {
+ fontSize: 16,
+ fontWeight: '600',
+ color: 'white',
+ },
+});
+
diff --git a/frontend/src/screens/Education/EducationScreen.tsx b/frontend/src/screens/Education/EducationScreen.tsx
new file mode 100644
index 00000000..6ace9549
--- /dev/null
+++ b/frontend/src/screens/Education/EducationScreen.tsx
@@ -0,0 +1,626 @@
+import React, { useState } from 'react';
+import {
+ View,
+ Text,
+ StyleSheet,
+ SafeAreaView,
+ ScrollView,
+ TouchableOpacity,
+ Share,
+ Alert,
+} from 'react-native';
+import { Ionicons } from '@expo/vector-icons';
+import { LinearGradient } from 'expo-linear-gradient';
+import Colors from '../../constants/colors';
+
+interface Certificate {
+ id: string;
+ title: string;
+ institution: string;
+ issueDate: string;
+ certificateId: string;
+ type: 'degree' | 'course' | 'skill' | 'achievement';
+ verified: boolean;
+ ipfsHash?: string;
+}
+
+interface EducationStats {
+ totalCertificates: number;
+ verifiedCertificates: number;
+ skillsAcquired: number;
+ learningHours: number;
+}
+
+export default function EducationScreen({ navigation }: any) {
+ const [stats] = useState({
+ totalCertificates: 8,
+ verifiedCertificates: 6,
+ skillsAcquired: 15,
+ learningHours: 240,
+ });
+
+ const [certificates] = useState([
+ {
+ id: '1',
+ title: 'Bachelor of Computer Science',
+ institution: 'University of Kurdistan',
+ issueDate: '2022-06-15',
+ certificateId: 'UOK-CS-2022-1234',
+ type: 'degree',
+ verified: true,
+ ipfsHash: 'QmX7Y8Z9...',
+ },
+ {
+ id: '2',
+ title: 'Blockchain Development Certificate',
+ institution: 'Digital Kurdistan Academy',
+ issueDate: '2023-03-20',
+ certificateId: 'DKA-BC-2023-5678',
+ type: 'course',
+ verified: true,
+ ipfsHash: 'QmA1B2C3...',
+ },
+ {
+ id: '3',
+ title: 'Kurdish Language Proficiency',
+ institution: 'Kurdistan Cultural Institute',
+ issueDate: '2023-08-10',
+ certificateId: 'KCI-KL-2023-9012',
+ type: 'skill',
+ verified: true,
+ ipfsHash: 'QmD4E5F6...',
+ },
+ {
+ id: '4',
+ title: 'Smart Contract Security',
+ institution: 'PezkuwiChain Foundation',
+ issueDate: '2024-01-15',
+ certificateId: 'PKW-SCS-2024-3456',
+ type: 'course',
+ verified: false,
+ },
+ ]);
+
+ const getCertificateIcon = (type: string) => {
+ switch (type) {
+ case 'degree':
+ return 'school';
+ case 'course':
+ return 'book';
+ case 'skill':
+ return 'ribbon';
+ case 'achievement':
+ return 'trophy';
+ default:
+ return 'document';
+ }
+ };
+
+ const getCertificateColor = (type: string) => {
+ switch (type) {
+ case 'degree':
+ return Colors.primary;
+ case 'course':
+ return Colors.success;
+ case 'skill':
+ return Colors.kurdishGold;
+ case 'achievement':
+ return Colors.coral;
+ default:
+ return Colors.textGray;
+ }
+ };
+
+ const shareCertificate = async (certificate: Certificate) => {
+ try {
+ await Share.share({
+ message: `🎓 ${certificate.title}\n\nIssued by: ${certificate.institution}\nDate: ${certificate.issueDate}\nCertificate ID: ${certificate.certificateId}\n\nVerified on PezkuwiChain - Digital Kurdistan's Blockchain Platform`,
+ });
+ } catch (error) {
+ console.error('Error sharing:', error);
+ }
+ };
+
+ const verifyCertificate = (certificate: Certificate) => {
+ if (certificate.verified) {
+ Alert.alert(
+ '✓ Verified Certificate',
+ `This certificate is verified on PezkuwiChain blockchain.\n\nIPFS Hash: ${certificate.ipfsHash}\nCertificate ID: ${certificate.certificateId}`,
+ [{ text: 'OK' }]
+ );
+ } else {
+ Alert.alert(
+ 'Pending Verification',
+ 'This certificate is pending blockchain verification. Please check back later.',
+ [{ text: 'OK' }]
+ );
+ }
+ };
+
+ return (
+
+
+ {/* Header */}
+
+
+
+ Perwerde
+ Education & Certificates
+
+
+ Alert.alert(
+ 'Add Certificate',
+ 'Request your institution to issue a certificate on PezkuwiChain',
+ [{ text: 'OK' }]
+ )
+ }
+ >
+
+
+
+
+
+ {/* Statistics Grid */}
+
+
+
+
+ {stats.totalCertificates}
+ Certificates
+
+
+
+ {stats.verifiedCertificates}
+ Verified
+
+
+
+ {stats.skillsAcquired}
+ Skills
+
+
+
+ {stats.learningHours}
+ Hours
+
+
+
+
+ {/* Certificates Section */}
+
+
+ My Certificates
+
+ View All
+
+
+
+ {certificates.map((certificate) => (
+ verifyCertificate(certificate)}
+ activeOpacity={0.7}
+ >
+
+
+
+
+
+
+ {certificate.title}
+
+
+ {certificate.institution}
+
+
+ Issued: {certificate.issueDate}
+
+
+
+
+
+
+
+
+ {certificate.certificateId}
+
+
+
+ {certificate.verified && (
+
+
+ Verified
+
+ )}
+ shareCertificate(certificate)}
+ style={styles.shareButton}
+ >
+
+
+
+
+
+ ))}
+
+
+ {/* Learning Paths */}
+
+ Recommended Learning Paths
+
+
+
+
+
+
+
+
+
+ Blockchain Developer Path
+
+
+ Master Substrate & Polkadot development
+
+
+
+
+ 8 Courses
+
+
+
+ 120 Hours
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Kurdish Culture & Heritage
+
+ Learn Kurdish language and history
+
+
+
+
+ 5 Courses
+
+
+
+ 60 Hours
+
+
+
+
+
+
+
+
+
+ {/* Info Section */}
+
+
+
+
+ All certificates are stored on PezkuwiChain blockchain and IPFS,
+ ensuring permanent verification and authenticity.
+
+
+
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: Colors.background,
+ },
+ header: {
+ paddingHorizontal: 20,
+ paddingTop: 20,
+ paddingBottom: 24,
+ borderBottomLeftRadius: 24,
+ borderBottomRightRadius: 24,
+ },
+ headerContent: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ },
+ headerTitle: {
+ fontSize: 32,
+ fontWeight: '700',
+ color: 'white',
+ marginBottom: 4,
+ },
+ headerSubtitle: {
+ fontSize: 16,
+ color: 'rgba(255, 255, 255, 0.9)',
+ },
+ addButton: {
+ width: 48,
+ height: 48,
+ borderRadius: 24,
+ backgroundColor: 'rgba(255, 255, 255, 0.2)',
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ statsContainer: {
+ paddingHorizontal: 20,
+ marginTop: -30,
+ marginBottom: 20,
+ },
+ statsGrid: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ gap: 12,
+ },
+ statCard: {
+ flex: 1,
+ minWidth: '47%',
+ backgroundColor: 'white',
+ borderRadius: 14,
+ padding: 16,
+ alignItems: 'center',
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 2 },
+ shadowOpacity: 0.05,
+ shadowRadius: 8,
+ elevation: 2,
+ },
+ statValue: {
+ fontSize: 24,
+ fontWeight: '700',
+ color: Colors.textDark,
+ marginTop: 8,
+ marginBottom: 4,
+ },
+ statLabel: {
+ fontSize: 13,
+ color: Colors.textGray,
+ textAlign: 'center',
+ },
+ section: {
+ paddingHorizontal: 20,
+ marginBottom: 24,
+ },
+ sectionHeader: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ marginBottom: 12,
+ },
+ sectionTitle: {
+ fontSize: 20,
+ fontWeight: '700',
+ color: Colors.textDark,
+ },
+ viewAllText: {
+ fontSize: 14,
+ fontWeight: '600',
+ color: Colors.primary,
+ },
+ certificateCard: {
+ backgroundColor: 'white',
+ borderRadius: 14,
+ padding: 16,
+ marginBottom: 12,
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 1 },
+ shadowOpacity: 0.04,
+ shadowRadius: 6,
+ elevation: 1,
+ },
+ certificateHeader: {
+ flexDirection: 'row',
+ marginBottom: 12,
+ },
+ certificateIconContainer: {
+ width: 56,
+ height: 56,
+ borderRadius: 12,
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginRight: 12,
+ },
+ certificateInfo: {
+ flex: 1,
+ },
+ certificateTitle: {
+ fontSize: 16,
+ fontWeight: '600',
+ color: Colors.textDark,
+ marginBottom: 4,
+ },
+ certificateInstitution: {
+ fontSize: 14,
+ color: Colors.textGray,
+ marginBottom: 2,
+ },
+ certificateDate: {
+ fontSize: 12,
+ color: Colors.textGray,
+ },
+ certificateFooter: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ paddingTop: 12,
+ borderTopWidth: 1,
+ borderTopColor: Colors.background,
+ },
+ certificateId: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: 6,
+ flex: 1,
+ },
+ certificateIdText: {
+ fontSize: 12,
+ color: Colors.textGray,
+ fontFamily: 'monospace',
+ },
+ certificateActions: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: 12,
+ },
+ verifiedBadge: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: 4,
+ backgroundColor: Colors.success + '20',
+ paddingHorizontal: 8,
+ paddingVertical: 4,
+ borderRadius: 8,
+ },
+ verifiedText: {
+ fontSize: 12,
+ fontWeight: '600',
+ color: Colors.success,
+ },
+ shareButton: {
+ padding: 4,
+ },
+ pathCard: {
+ marginBottom: 12,
+ borderRadius: 14,
+ overflow: 'hidden',
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 1 },
+ shadowOpacity: 0.04,
+ shadowRadius: 6,
+ elevation: 1,
+ },
+ pathGradient: {
+ padding: 16,
+ },
+ pathContent: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ pathIcon: {
+ width: 56,
+ height: 56,
+ borderRadius: 12,
+ backgroundColor: 'white',
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginRight: 12,
+ },
+ pathInfo: {
+ flex: 1,
+ },
+ pathTitle: {
+ fontSize: 16,
+ fontWeight: '600',
+ color: Colors.textDark,
+ marginBottom: 4,
+ },
+ pathDescription: {
+ fontSize: 13,
+ color: Colors.textGray,
+ marginBottom: 8,
+ },
+ pathMeta: {
+ flexDirection: 'row',
+ gap: 16,
+ },
+ pathMetaItem: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: 4,
+ },
+ pathMetaText: {
+ fontSize: 12,
+ color: Colors.textGray,
+ },
+ infoSection: {
+ paddingHorizontal: 20,
+ marginBottom: 24,
+ },
+ infoCard: {
+ flexDirection: 'row',
+ backgroundColor: Colors.primary + '10',
+ borderRadius: 12,
+ padding: 16,
+ gap: 12,
+ },
+ infoText: {
+ flex: 1,
+ fontSize: 13,
+ color: Colors.textDark,
+ lineHeight: 20,
+ },
+});
+
diff --git a/frontend/src/screens/Exchange/ExchangeScreen.tsx b/frontend/src/screens/Exchange/ExchangeScreen.tsx
new file mode 100644
index 00000000..00363ffe
--- /dev/null
+++ b/frontend/src/screens/Exchange/ExchangeScreen.tsx
@@ -0,0 +1,792 @@
+import React, { useState, useEffect } from 'react';
+import {
+ View,
+ Text,
+ StyleSheet,
+ SafeAreaView,
+ ScrollView,
+ TouchableOpacity,
+ TextInput,
+ Alert,
+} from 'react-native';
+import { Ionicons } from '@expo/vector-icons';
+import { LinearGradient } from 'expo-linear-gradient';
+import Colors from '../../constants/colors';
+
+interface ExchangeRate {
+ hezToPez: number;
+ pezToHez: number;
+ lastUpdated: string;
+}
+
+interface SwapHistory {
+ id: string;
+ fromToken: 'HEZ' | 'PEZ';
+ toToken: 'HEZ' | 'PEZ';
+ fromAmount: number;
+ toAmount: number;
+ rate: number;
+ date: string;
+ txHash: string;
+}
+
+export default function ExchangeScreen({ navigation }: any) {
+ const [fromToken, setFromToken] = useState<'HEZ' | 'PEZ'>('HEZ');
+ const [toToken, setToToken] = useState<'HEZ' | 'PEZ'>('PEZ');
+ const [fromAmount, setFromAmount] = useState('');
+ const [toAmount, setToAmount] = useState('');
+ const [slippage, setSlippage] = useState('0.5');
+
+ const [balances] = useState({
+ hez: 45750.5,
+ pez: 1234567,
+ });
+
+ const [exchangeRate] = useState({
+ hezToPez: 27.5,
+ pezToHez: 0.0364,
+ lastUpdated: new Date().toLocaleTimeString(),
+ });
+
+ const [swapHistory] = useState([
+ {
+ id: '1',
+ fromToken: 'HEZ',
+ toToken: 'PEZ',
+ fromAmount: 100,
+ toAmount: 2750,
+ rate: 27.5,
+ date: '2024-01-23 14:30',
+ txHash: '0x1a2b3c...',
+ },
+ {
+ id: '2',
+ fromToken: 'PEZ',
+ toToken: 'HEZ',
+ fromAmount: 5000,
+ toAmount: 182,
+ rate: 0.0364,
+ date: '2024-01-22 10:15',
+ txHash: '0x4d5e6f...',
+ },
+ ]);
+
+ useEffect(() => {
+ calculateToAmount();
+ }, [fromAmount, fromToken, toToken]);
+
+ const calculateToAmount = () => {
+ if (!fromAmount || parseFloat(fromAmount) <= 0) {
+ setToAmount('');
+ return;
+ }
+
+ const amount = parseFloat(fromAmount);
+ let result = 0;
+
+ if (fromToken === 'HEZ' && toToken === 'PEZ') {
+ result = amount * exchangeRate.hezToPez;
+ } else if (fromToken === 'PEZ' && toToken === 'HEZ') {
+ result = amount * exchangeRate.pezToHez;
+ }
+
+ // Apply slippage
+ const slippagePercent = parseFloat(slippage) / 100;
+ result = result * (1 - slippagePercent);
+
+ setToAmount(result.toFixed(4));
+ };
+
+ const swapTokens = () => {
+ const newFromToken = toToken;
+ const newToToken = fromToken;
+ setFromToken(newFromToken);
+ setToToken(newToToken);
+ setFromAmount(toAmount);
+ };
+
+ const executeSwap = () => {
+ if (!fromAmount || parseFloat(fromAmount) <= 0) {
+ Alert.alert('Invalid Amount', 'Please enter a valid amount to swap');
+ return;
+ }
+
+ const amount = parseFloat(fromAmount);
+ const currentBalance = fromToken === 'HEZ' ? balances.hez : balances.pez;
+
+ if (amount > currentBalance) {
+ Alert.alert('Insufficient Balance', `You don't have enough ${fromToken}`);
+ return;
+ }
+
+ Alert.alert(
+ 'Confirm Swap',
+ `Swap ${fromAmount} ${fromToken} for ${toAmount} ${toToken}?\n\nRate: 1 ${fromToken} = ${
+ fromToken === 'HEZ' ? exchangeRate.hezToPez : exchangeRate.pezToHez
+ } ${toToken}\nSlippage: ${slippage}%`,
+ [
+ { text: 'Cancel', style: 'cancel' },
+ {
+ text: 'Confirm',
+ onPress: () => {
+ Alert.alert(
+ 'Success!',
+ `Swap executed successfully!\n\nTransaction hash: 0x${Math.random()
+ .toString(16)
+ .substr(2, 8)}...`
+ );
+ setFromAmount('');
+ setToAmount('');
+ },
+ },
+ ]
+ );
+ };
+
+ const setMaxAmount = () => {
+ const maxBalance = fromToken === 'HEZ' ? balances.hez : balances.pez;
+ setFromAmount(maxBalance.toString());
+ };
+
+ const getCurrentRate = () => {
+ return fromToken === 'HEZ' ? exchangeRate.hezToPez : exchangeRate.pezToHez;
+ };
+
+ return (
+
+
+ {/* Header */}
+
+
+
+ Exchange
+ Swap HEZ ↔ PEZ Tokens
+
+ Alert.alert('History', 'Full swap history coming soon')}
+ >
+
+
+
+
+
+ {/* Exchange Rate Card */}
+
+
+
+ Current Exchange Rate
+
+
+ Live
+
+
+
+
+ 1 HEZ =
+ {exchangeRate.hezToPez} PEZ
+
+
+
+ 1 PEZ =
+ {exchangeRate.pezToHez} HEZ
+
+
+
+ Last updated: {exchangeRate.lastUpdated}
+
+
+
+
+ {/* Swap Interface */}
+
+ Swap Tokens
+
+ {/* From Token */}
+
+
+ From
+
+ Balance: {fromToken === 'HEZ' ? balances.hez.toLocaleString() : balances.pez.toLocaleString()} {fromToken}
+
+
+
+
+
+
+ {fromToken}
+
+
+ MAX
+
+
+
+
+
+ {/* Swap Button */}
+
+
+
+
+
+
+ {/* To Token */}
+
+
+ To
+
+ Balance: {toToken === 'HEZ' ? balances.hez.toLocaleString() : balances.pez.toLocaleString()} {toToken}
+
+
+
+
+
+
+ {toToken}
+
+
+
+
+
+ {/* Swap Details */}
+ {fromAmount && toAmount && (
+
+
+ Rate
+
+ 1 {fromToken} = {getCurrentRate()} {toToken}
+
+
+
+ Slippage Tolerance
+
+ setSlippage('0.5')}
+ >
+
+ 0.5%
+
+
+ setSlippage('1.0')}
+ >
+
+ 1.0%
+
+
+ setSlippage('2.0')}
+ >
+
+ 2.0%
+
+
+
+
+
+ Network Fee
+ ~0.01 HEZ
+
+
+ )}
+
+ {/* Execute Swap Button */}
+
+
+
+ Swap Tokens
+
+
+
+
+ {/* Recent Swaps */}
+
+
+ Recent Swaps
+
+ View All
+
+
+
+ {swapHistory.map((swap) => (
+
+
+
+
+
+
+
+ {swap.fromToken} → {swap.toToken}
+
+ {swap.date}
+ Tx: {swap.txHash}
+
+
+
+ -{swap.fromAmount} {swap.fromToken}
+
+
+ +{swap.toAmount} {swap.toToken}
+
+
+
+
+
+ Rate: 1 {swap.fromToken} = {swap.rate} {swap.toToken}
+
+
+
+
+
+
+ ))}
+
+
+ {/* Info Section */}
+
+
+
+
+ About Token Swap
+
+ Exchange rates are determined by the on-chain liquidity pool. HEZ is the security layer token, while PEZ is the governance token. Swap fees support network validators and liquidity providers.
+
+
+
+
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: Colors.background,
+ },
+ header: {
+ paddingHorizontal: 20,
+ paddingTop: 20,
+ paddingBottom: 24,
+ borderBottomLeftRadius: 24,
+ borderBottomRightRadius: 24,
+ },
+ headerContent: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ },
+ headerTitle: {
+ fontSize: 32,
+ fontWeight: '700',
+ color: 'white',
+ marginBottom: 4,
+ },
+ headerSubtitle: {
+ fontSize: 16,
+ color: 'rgba(255, 255, 255, 0.9)',
+ },
+ historyButton: {
+ width: 48,
+ height: 48,
+ borderRadius: 24,
+ backgroundColor: 'rgba(255, 255, 255, 0.2)',
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ rateContainer: {
+ paddingHorizontal: 20,
+ marginTop: -30,
+ marginBottom: 20,
+ },
+ rateCard: {
+ backgroundColor: 'white',
+ borderRadius: 16,
+ padding: 20,
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 2 },
+ shadowOpacity: 0.05,
+ shadowRadius: 8,
+ elevation: 2,
+ },
+ rateHeader: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ marginBottom: 16,
+ },
+ rateTitle: {
+ fontSize: 16,
+ fontWeight: '600',
+ color: Colors.textDark,
+ },
+ updateBadge: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: 4,
+ backgroundColor: Colors.success + '20',
+ paddingHorizontal: 8,
+ paddingVertical: 4,
+ borderRadius: 8,
+ },
+ updateText: {
+ fontSize: 12,
+ fontWeight: '600',
+ color: Colors.success,
+ },
+ rateContent: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ marginBottom: 12,
+ },
+ rateItem: {
+ flex: 1,
+ alignItems: 'center',
+ },
+ rateLabel: {
+ fontSize: 14,
+ color: Colors.textGray,
+ marginBottom: 4,
+ },
+ rateValue: {
+ fontSize: 18,
+ fontWeight: '700',
+ color: Colors.primary,
+ },
+ rateDivider: {
+ width: 1,
+ height: 40,
+ backgroundColor: Colors.background,
+ },
+ rateUpdate: {
+ fontSize: 12,
+ color: Colors.textGray,
+ textAlign: 'center',
+ },
+ section: {
+ paddingHorizontal: 20,
+ marginBottom: 24,
+ },
+ sectionHeader: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ marginBottom: 12,
+ },
+ sectionTitle: {
+ fontSize: 20,
+ fontWeight: '700',
+ color: Colors.textDark,
+ marginBottom: 12,
+ },
+ viewAllText: {
+ fontSize: 14,
+ fontWeight: '600',
+ color: Colors.primary,
+ },
+ swapCard: {
+ backgroundColor: 'white',
+ borderRadius: 14,
+ padding: 16,
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 1 },
+ shadowOpacity: 0.04,
+ shadowRadius: 6,
+ elevation: 1,
+ },
+ swapHeader: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ marginBottom: 12,
+ },
+ swapLabel: {
+ fontSize: 14,
+ fontWeight: '600',
+ color: Colors.textGray,
+ },
+ balanceText: {
+ fontSize: 12,
+ color: Colors.textGray,
+ },
+ inputContainer: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: 12,
+ },
+ amountInput: {
+ flex: 1,
+ fontSize: 24,
+ fontWeight: '600',
+ color: Colors.textDark,
+ },
+ amountInputDisabled: {
+ color: Colors.textGray,
+ },
+ tokenSelector: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: 8,
+ },
+ tokenBadge: {
+ backgroundColor: Colors.primary + '20',
+ paddingHorizontal: 16,
+ paddingVertical: 8,
+ borderRadius: 10,
+ },
+ tokenText: {
+ fontSize: 16,
+ fontWeight: '700',
+ color: Colors.primary,
+ },
+ maxButton: {
+ backgroundColor: Colors.background,
+ paddingHorizontal: 12,
+ paddingVertical: 6,
+ borderRadius: 8,
+ },
+ maxButtonText: {
+ fontSize: 12,
+ fontWeight: '700',
+ color: Colors.primary,
+ },
+ swapButtonContainer: {
+ alignItems: 'center',
+ marginVertical: -12,
+ zIndex: 10,
+ },
+ swapIconButton: {
+ width: 48,
+ height: 48,
+ borderRadius: 24,
+ backgroundColor: 'white',
+ alignItems: 'center',
+ justifyContent: 'center',
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 2 },
+ shadowOpacity: 0.1,
+ shadowRadius: 8,
+ elevation: 3,
+ },
+ detailsCard: {
+ backgroundColor: Colors.background,
+ borderRadius: 12,
+ padding: 16,
+ marginTop: 16,
+ gap: 12,
+ },
+ detailRow: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ },
+ detailLabel: {
+ fontSize: 14,
+ color: Colors.textGray,
+ },
+ detailValue: {
+ fontSize: 14,
+ fontWeight: '600',
+ color: Colors.textDark,
+ },
+ slippageSelector: {
+ flexDirection: 'row',
+ gap: 8,
+ },
+ slippageOption: {
+ paddingHorizontal: 12,
+ paddingVertical: 6,
+ borderRadius: 8,
+ backgroundColor: 'white',
+ },
+ slippageOptionActive: {
+ backgroundColor: Colors.primary,
+ },
+ slippageText: {
+ fontSize: 12,
+ fontWeight: '600',
+ color: Colors.textGray,
+ },
+ slippageTextActive: {
+ color: 'white',
+ },
+ executeButton: {
+ borderRadius: 12,
+ overflow: 'hidden',
+ marginTop: 20,
+ },
+ executeButtonGradient: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'center',
+ paddingVertical: 16,
+ gap: 8,
+ },
+ executeButtonText: {
+ fontSize: 16,
+ fontWeight: '700',
+ color: 'white',
+ },
+ historyCard: {
+ backgroundColor: 'white',
+ borderRadius: 14,
+ padding: 16,
+ marginBottom: 12,
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 1 },
+ shadowOpacity: 0.04,
+ shadowRadius: 6,
+ elevation: 1,
+ },
+ historyHeader: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ marginBottom: 12,
+ },
+ historyIcon: {
+ width: 44,
+ height: 44,
+ borderRadius: 22,
+ backgroundColor: Colors.primary + '20',
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginRight: 12,
+ },
+ historyInfo: {
+ flex: 1,
+ },
+ historyTitle: {
+ fontSize: 16,
+ fontWeight: '600',
+ color: Colors.textDark,
+ marginBottom: 2,
+ },
+ historyDate: {
+ fontSize: 12,
+ color: Colors.textGray,
+ marginBottom: 2,
+ },
+ historyHash: {
+ fontSize: 11,
+ color: Colors.textGray,
+ fontFamily: 'monospace',
+ },
+ historyAmount: {
+ alignItems: 'flex-end',
+ },
+ historyFromAmount: {
+ fontSize: 14,
+ fontWeight: '600',
+ color: Colors.error,
+ marginBottom: 2,
+ },
+ historyToAmount: {
+ fontSize: 14,
+ fontWeight: '600',
+ color: Colors.success,
+ },
+ historyFooter: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ paddingTop: 12,
+ borderTopWidth: 1,
+ borderTopColor: Colors.background,
+ },
+ historyRate: {
+ fontSize: 12,
+ color: Colors.textGray,
+ },
+ infoSection: {
+ paddingHorizontal: 20,
+ marginBottom: 24,
+ },
+ infoCard: {
+ flexDirection: 'row',
+ backgroundColor: Colors.primary + '10',
+ borderRadius: 14,
+ padding: 16,
+ gap: 12,
+ },
+ infoContent: {
+ flex: 1,
+ },
+ infoTitle: {
+ fontSize: 14,
+ fontWeight: '600',
+ color: Colors.textDark,
+ marginBottom: 4,
+ },
+ infoText: {
+ fontSize: 13,
+ color: Colors.textDark,
+ lineHeight: 20,
+ },
+});
+
diff --git a/frontend/src/screens/Governance/GovernanceScreen.tsx b/frontend/src/screens/Governance/GovernanceScreen.tsx
new file mode 100644
index 00000000..fa4202fb
--- /dev/null
+++ b/frontend/src/screens/Governance/GovernanceScreen.tsx
@@ -0,0 +1,416 @@
+import React, { useState, useEffect } from 'react';
+import {
+ View,
+ Text,
+ StyleSheet,
+ TouchableOpacity,
+ SafeAreaView,
+ ScrollView,
+ Alert,
+} from 'react-native';
+import { Ionicons } from '@expo/vector-icons';
+import AsyncStorage from '@react-native-async-storage/async-storage';
+import Colors from '../../constants/colors';
+import { Typography, Spacing, BorderRadius, Shadow } from '../../constants/theme';
+
+interface GovernanceService {
+ id: string;
+ name: string;
+ nameKu: string;
+ icon: keyof typeof Ionicons.glyphMap;
+ color: string;
+ description: string;
+ route?: string;
+}
+
+export default function GovernanceScreen({ navigation }: any) {
+ const [isHemwelati, setIsHemwelati] = useState(false);
+ const [loading, setLoading] = useState(true);
+
+ useEffect(() => {
+ checkKYCStatus();
+ }, []);
+
+ const checkKYCStatus = async () => {
+ try {
+ const kycData = await AsyncStorage.getItem('kyc_data');
+ const kycStatus = await AsyncStorage.getItem('kyc_status');
+
+ if (kycData && kycStatus === 'approved') {
+ setIsHemwelati(true);
+ } else {
+ setIsHemwelati(false);
+ }
+ } catch (error) {
+ console.error('Error checking KYC status:', error);
+ setIsHemwelati(false);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ // Main governance services (not ministries)
+ const services: GovernanceService[] = [
+ {
+ id: 'presidency',
+ name: 'Presidency',
+ nameKu: 'Serokayetî',
+ icon: 'business',
+ color: '#E74C3C',
+ description: 'Office of the President',
+ },
+ {
+ id: 'parliament',
+ name: 'Parliament',
+ nameKu: 'Meclîs',
+ icon: 'people',
+ color: '#3498DB',
+ description: 'Legislative Assembly - 201 MPs',
+ },
+ {
+ id: 'ministries',
+ name: 'Ministries',
+ nameKu: 'Wezaretî',
+ icon: 'briefcase',
+ color: '#9B59B6',
+ description: 'All Cabinet Ministries',
+ route: 'Ministries',
+ },
+ {
+ id: 'voting',
+ name: 'Voting',
+ nameKu: 'Dengdan',
+ icon: 'checkmark-circle',
+ color: '#1ABC9C',
+ description: 'Proposals & Democratic Voting',
+ },
+ {
+ id: 'p2p',
+ name: 'P2P Services',
+ nameKu: 'Karûbarên P2P',
+ icon: 'people-circle',
+ color: '#26A69A',
+ description: 'Peer-to-Peer Transactions',
+ },
+ {
+ id: 'b2b',
+ name: 'B2B Services',
+ nameKu: 'Karûbarên B2B',
+ icon: 'business-outline',
+ color: '#FF9800',
+ description: 'Business-to-Business Platform',
+ },
+ {
+ id: 'digital',
+ name: 'Digital Infrastructure',
+ nameKu: 'Binyata Dîjîtal',
+ icon: 'server',
+ color: '#26C6DA',
+ description: 'Technology & Innovation Hub',
+ },
+ {
+ id: 'citizenship',
+ name: 'Citizenship Affairs',
+ nameKu: 'Karûbarên Hemwelatî',
+ icon: 'card',
+ color: '#66BB6A',
+ description: 'Identity & Registration Services',
+ },
+ {
+ id: 'treasury',
+ name: 'Public Treasury',
+ nameKu: 'Xizêneya Giştî',
+ icon: 'wallet',
+ color: '#F39C12',
+ description: 'National Budget & Spending',
+ },
+ {
+ id: 'judiciary',
+ name: 'Judiciary',
+ nameKu: 'Dadwerî',
+ icon: 'scale',
+ color: '#34495E',
+ description: 'Court System & Justice',
+ },
+ {
+ id: 'elections',
+ name: 'Elections',
+ nameKu: 'Hilbijartinî',
+ icon: 'ballot',
+ color: '#5C6BC0',
+ description: 'Electoral Commission',
+ },
+ {
+ id: 'ombudsman',
+ name: 'Ombudsman',
+ nameKu: 'Parêzerê Mafan',
+ icon: 'shield-checkmark',
+ color: '#EC407A',
+ description: 'Citizens Rights Protection',
+ },
+ ];
+
+ const handleServicePress = (service: GovernanceService) => {
+ if (!isHemwelati) {
+ Alert.alert(
+ 'Access Restricted',
+ 'You must complete Identity KYC verification to access Governance features.',
+ [
+ { text: 'Cancel', style: 'cancel' },
+ {
+ text: 'Complete KYC',
+ onPress: () => navigation.navigate('Identity'),
+ },
+ ]
+ );
+ return;
+ }
+
+ // Navigate to specific route if available
+ if (service.route) {
+ navigation.navigate(service.route);
+ return;
+ }
+
+ // Show placeholder for other services
+ Alert.alert(
+ service.name,
+ `${service.nameKu}\n\n${service.description}\n\nThis feature is under development.`,
+ [{ text: 'OK' }]
+ );
+ };
+
+ if (loading) {
+ return (
+
+
+ Loading...
+
+
+ );
+ }
+
+ if (!isHemwelati) {
+ return (
+
+
+
+ Access Restricted
+
+ Governance features are only available to verified Hemwelatî (Digital Citizens).
+
+
+ Complete your Identity KYC verification to access:
+
+
+ • Vote on proposals
+ • Participate in governance
+ • Access government services
+ • View parliamentary sessions
+
+ navigation.navigate('Identity')}
+ >
+
+ Complete Identity KYC
+
+
+
+ );
+ }
+
+ return (
+
+ {/* Header */}
+
+
+ Welati Governance
+ Komara Kurdistanê
+
+
+
+ Verified Citizen
+
+
+
+
+ {/* Services Grid */}
+
+ {services.map((service) => (
+ handleServicePress(service)}
+ activeOpacity={0.7}
+ >
+
+
+
+ {service.name}
+ {service.nameKu}
+
+ ))}
+
+
+ {/* Info Footer */}
+
+
+
+ As a verified Hemwelatî, you have full access to all governance features.
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: Colors.background,
+ },
+ loadingContainer: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ loadingText: {
+ fontSize: Typography.sizes.lg,
+ color: Colors.textLight,
+ },
+ restrictedContainer: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ padding: Spacing.xl,
+ },
+ restrictedTitle: {
+ fontSize: Typography.sizes.xxl,
+ fontWeight: Typography.weights.bold,
+ color: Colors.textDark,
+ marginTop: Spacing.lg,
+ marginBottom: Spacing.md,
+ },
+ restrictedText: {
+ fontSize: Typography.sizes.md,
+ color: Colors.textLight,
+ textAlign: 'center',
+ marginBottom: Spacing.md,
+ lineHeight: 22,
+ },
+ featureList: {
+ marginTop: Spacing.md,
+ marginBottom: Spacing.xl,
+ },
+ featureItem: {
+ fontSize: Typography.sizes.md,
+ color: Colors.textDark,
+ marginBottom: Spacing.xs,
+ },
+ kycButton: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ backgroundColor: Colors.primary,
+ paddingHorizontal: Spacing.xl,
+ paddingVertical: Spacing.md,
+ borderRadius: BorderRadius.lg,
+ ...Shadow.medium,
+ },
+ kycButtonText: {
+ fontSize: Typography.sizes.lg,
+ fontWeight: Typography.weights.bold,
+ color: '#FFFFFF',
+ marginLeft: Spacing.sm,
+ },
+ header: {
+ backgroundColor: '#FFFFFF',
+ paddingHorizontal: Spacing.lg,
+ paddingVertical: Spacing.md,
+ borderBottomWidth: 1,
+ borderBottomColor: '#E0E0E0',
+ ...Shadow.small,
+ },
+ headerContent: {
+ marginBottom: Spacing.sm,
+ },
+ headerTitle: {
+ fontSize: Typography.sizes.xxl,
+ fontWeight: Typography.weights.bold,
+ color: Colors.textDark,
+ },
+ headerSubtitle: {
+ fontSize: Typography.sizes.md,
+ color: Colors.textLight,
+ marginTop: Spacing.xs,
+ },
+ verifiedBadge: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ backgroundColor: '#E8F5E9',
+ paddingHorizontal: Spacing.md,
+ paddingVertical: Spacing.xs,
+ borderRadius: BorderRadius.md,
+ alignSelf: 'flex-start',
+ },
+ verifiedText: {
+ fontSize: Typography.sizes.sm,
+ fontWeight: Typography.weights.semibold,
+ color: '#27AE60',
+ marginLeft: Spacing.xs,
+ },
+ content: {
+ flex: 1,
+ },
+ grid: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ padding: Spacing.md,
+ },
+ serviceCard: {
+ width: '31%',
+ marginHorizontal: '1%',
+ marginBottom: Spacing.lg,
+ backgroundColor: '#FFFFFF',
+ borderRadius: BorderRadius.lg,
+ padding: Spacing.md,
+ alignItems: 'center',
+ ...Shadow.small,
+ },
+ iconContainer: {
+ width: 64,
+ height: 64,
+ borderRadius: BorderRadius.lg,
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginBottom: Spacing.sm,
+ },
+ serviceName: {
+ fontSize: Typography.sizes.xs,
+ fontWeight: Typography.weights.semibold,
+ color: Colors.textDark,
+ textAlign: 'center',
+ marginBottom: Spacing.xs,
+ },
+ serviceNameKu: {
+ fontSize: Typography.sizes.xs,
+ color: Colors.textLight,
+ textAlign: 'center',
+ },
+ infoFooter: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ backgroundColor: '#E3F2FD',
+ margin: Spacing.lg,
+ padding: Spacing.md,
+ borderRadius: BorderRadius.md,
+ },
+ infoText: {
+ flex: 1,
+ fontSize: Typography.sizes.sm,
+ color: Colors.primary,
+ marginLeft: Spacing.sm,
+ lineHeight: 18,
+ },
+});
+
diff --git a/frontend/src/screens/Governance/GovernanceScreen_old.tsx b/frontend/src/screens/Governance/GovernanceScreen_old.tsx
new file mode 100644
index 00000000..e03aaa65
--- /dev/null
+++ b/frontend/src/screens/Governance/GovernanceScreen_old.tsx
@@ -0,0 +1,117 @@
+import React, { useState, useEffect } from 'react';
+import { View, Text, StyleSheet, TouchableOpacity, SafeAreaView, ActivityIndicator } from 'react-native';
+import { Ionicons } from '@expo/vector-icons';
+import Colors from '../../constants/colors';
+import { Typography, Spacing, BorderRadius, Shadow } from '../../constants/theme';
+import { kycService } from '../../services/kycService';
+
+export default function GovernanceScreen({ navigation }: any) {
+ const [loading, setLoading] = useState(true);
+ const [hasAccess, setHasAccess] = useState(false);
+
+ useEffect(() => {
+ checkAccess();
+ }, []);
+
+ const checkAccess = async () => {
+ try {
+ const access = await kycService.hasGovernanceAccess();
+ setHasAccess(access);
+ } catch (error) {
+ console.error('Failed to check governance access:', error);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ if (loading) {
+ return (
+
+
+
+ );
+ }
+
+ // If user doesn't have access (KYC not approved)
+ if (!hasAccess) {
+ return (
+
+
+ Governance (Welati)
+
+
+
+
+
+ Access Restricted
+
+ You need to complete Identity KYC verification to access Governance features.
+
+
+
+
+ Requirements:
+
+
+ Complete Identity KYC form
+
+
+
+ Get KYC approval on blockchain
+
+
+
+ Receive Kurdistan Digital Citizen card
+
+
+
+ navigation.navigate('Identity')}
+ >
+ Complete Identity KYC
+
+
+
+
+ );
+ }
+
+ // If user has access, show governance features
+ return (
+
+
+ Governance (Welati)
+
+
+ Verified Citizen
+
+
+
+
+ Active Proposals
+ Coming soon...
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: { flex: 1, backgroundColor: Colors.background },
+ header: { padding: Spacing.xl, borderBottomWidth: 1, borderBottomColor: '#F0F0F0' },
+ title: { fontSize: 28, fontWeight: '700', color: Colors.textDark },
+ content: { flex: 1, padding: Spacing.xl },
+ lockedCard: { backgroundColor: Colors.card, padding: Spacing.xxxl, borderRadius: BorderRadius.xlarge, alignItems: 'center', ...Shadow.soft },
+ lockedTitle: { fontSize: 24, fontWeight: '700', color: Colors.textDark, marginTop: Spacing.lg },
+ lockedSubtitle: { fontSize: 16, color: Colors.textGray, marginTop: Spacing.sm, textAlign: 'center', lineHeight: 24 },
+ requirementsCard: { backgroundColor: Colors.teal + '20', padding: Spacing.xl, borderRadius: BorderRadius.large, marginTop: Spacing.xl },
+ requirementsTitle: { fontSize: 18, fontWeight: '600', color: Colors.textDark, marginBottom: Spacing.md },
+ requirementItem: { flexDirection: 'row', alignItems: 'center', marginTop: Spacing.sm, gap: Spacing.sm },
+ requirementText: { fontSize: 16, color: Colors.textDark },
+ completeButton: { flexDirection: 'row', backgroundColor: Colors.teal, borderRadius: BorderRadius.xxlarge, paddingVertical: Spacing.lg, paddingHorizontal: Spacing.xxxl, alignItems: 'center', justifyContent: 'center', marginTop: Spacing.xl, gap: Spacing.sm, ...Shadow.soft },
+ completeButtonText: { fontSize: 18, fontWeight: '600', color: '#FFFFFF' },
+ citizenBadge: { flexDirection: 'row', alignItems: 'center', backgroundColor: Colors.mint + '20', paddingVertical: Spacing.sm, paddingHorizontal: Spacing.md, borderRadius: BorderRadius.large, marginTop: Spacing.sm, gap: Spacing.xs, alignSelf: 'flex-start' },
+ citizenBadgeText: { fontSize: 14, fontWeight: '600', color: Colors.mint },
+ sectionTitle: { fontSize: 20, fontWeight: '600', color: Colors.textDark, marginBottom: Spacing.md },
+ comingSoon: { fontSize: 16, color: Colors.textGray, textAlign: 'center', marginTop: Spacing.xl },
+});
diff --git a/frontend/src/screens/Governance/MinistriesScreen.tsx b/frontend/src/screens/Governance/MinistriesScreen.tsx
new file mode 100644
index 00000000..a047cee4
--- /dev/null
+++ b/frontend/src/screens/Governance/MinistriesScreen.tsx
@@ -0,0 +1,320 @@
+import React from 'react';
+import {
+ View,
+ Text,
+ StyleSheet,
+ TouchableOpacity,
+ SafeAreaView,
+ ScrollView,
+ Alert,
+} from 'react-native';
+import { Ionicons } from '@expo/vector-icons';
+import Colors from '../../constants/colors';
+import { Typography, Spacing, BorderRadius, Shadow } from '../../constants/theme';
+
+interface Ministry {
+ id: string;
+ name: string;
+ nameKu: string;
+ icon: keyof typeof Ionicons.glyphMap;
+ color: string;
+ description: string;
+ minister?: string;
+}
+
+export default function MinistriesScreen({ navigation }: any) {
+ const ministries: Ministry[] = [
+ {
+ id: 'finance',
+ name: 'Finance',
+ nameKu: 'Maliye',
+ icon: 'cash',
+ color: '#F39C12',
+ description: 'Treasury, Budget & Economic Policy',
+ minister: 'Dr. Heval Azad',
+ },
+ {
+ id: 'justice',
+ name: 'Justice',
+ nameKu: 'Adalet',
+ icon: 'scale',
+ color: '#34495E',
+ description: 'Legal System & Courts',
+ minister: 'Av. Leyla Şoreş',
+ },
+ {
+ id: 'health',
+ name: 'Health',
+ nameKu: 'Tenduristî',
+ icon: 'medical',
+ color: '#E91E63',
+ description: 'Healthcare Services & Public Health',
+ minister: 'Dr. Roj Berxwedan',
+ },
+ {
+ id: 'education',
+ name: 'Education',
+ nameKu: 'Perwerde',
+ icon: 'school',
+ color: '#5C6BC0',
+ description: 'Education System & Universities',
+ minister: 'Prof. Aram Zana',
+ },
+ {
+ id: 'commerce',
+ name: 'Commerce',
+ nameKu: 'Bazirganî',
+ icon: 'cart',
+ color: '#26A69A',
+ description: 'Trade, Business & Industry',
+ minister: 'Berivan Qazi',
+ },
+ {
+ id: 'media',
+ name: 'Media & Communications',
+ nameKu: 'Medya û Ragihandin',
+ icon: 'newspaper',
+ color: '#FF9800',
+ description: 'Press, Broadcasting & Information',
+ minister: 'Jiyan Newroz',
+ },
+ {
+ id: 'culture',
+ name: 'Culture & Arts',
+ nameKu: 'Çand û Huner',
+ icon: 'color-palette',
+ color: '#EC407A',
+ description: 'Cultural Heritage & Arts',
+ minister: 'Şêrko Dilan',
+ },
+ {
+ id: 'tourism',
+ name: 'Tourism',
+ nameKu: 'Gerîyan',
+ icon: 'airplane',
+ color: '#00ACC1',
+ description: 'Tourism Development & Promotion',
+ minister: 'Azad Çiya',
+ },
+ {
+ id: 'foreign',
+ name: 'Foreign Affairs',
+ nameKu: 'Karûbarên Derve',
+ icon: 'globe',
+ color: '#7E57C2',
+ description: 'International Relations & Diplomacy',
+ minister: 'Dilşa Rojava',
+ },
+ {
+ id: 'interior',
+ name: 'Interior',
+ nameKu: 'Karûbarên Navxwe',
+ icon: 'shield',
+ color: '#8D6E63',
+ description: 'Internal Security & Public Order',
+ minister: 'Baran Zagros',
+ },
+ {
+ id: 'defense',
+ name: 'Defense',
+ nameKu: 'Bergiranî',
+ icon: 'shield-checkmark',
+ color: '#455A64',
+ description: 'National Defense & Security',
+ minister: 'Gen. Kendal Şoreş',
+ },
+ {
+ id: 'agriculture',
+ name: 'Agriculture',
+ nameKu: 'Çandinî',
+ icon: 'leaf',
+ color: '#8BC34A',
+ description: 'Farming, Food Security & Rural Development',
+ minister: 'Hêvî Berxwedan',
+ },
+ {
+ id: 'environment',
+ name: 'Environment',
+ nameKu: 'Jîngeha',
+ icon: 'earth',
+ color: '#66BB6A',
+ description: 'Environmental Protection & Climate',
+ minister: 'Çiya Newroz',
+ },
+ {
+ id: 'energy',
+ name: 'Energy',
+ nameKu: 'Wize',
+ icon: 'flash',
+ color: '#FFA726',
+ description: 'Energy Resources & Infrastructure',
+ minister: 'Roj Azad',
+ },
+ {
+ id: 'transport',
+ name: 'Transport',
+ nameKu: 'Veguhestin',
+ icon: 'car',
+ color: '#42A5F5',
+ description: 'Transportation & Infrastructure',
+ minister: 'Beritan Qazi',
+ },
+ {
+ id: 'labor',
+ name: 'Labor & Social Affairs',
+ nameKu: 'Kar û Karûbarên Civakî',
+ icon: 'people',
+ color: '#AB47BC',
+ description: 'Employment & Social Welfare',
+ minister: 'Heval Dilan',
+ },
+ ];
+
+ const handleMinistryPress = (ministry: Ministry) => {
+ Alert.alert(
+ ministry.name,
+ `${ministry.nameKu}\n\nMinister: ${ministry.minister}\n\n${ministry.description}\n\nThis feature is under development.`,
+ [{ text: 'OK' }]
+ );
+ };
+
+ return (
+
+ {/* Header */}
+
+ navigation.goBack()} style={styles.backButton}>
+
+
+
+ Ministries
+ Wezaretî
+
+
+
+
+ {/* Ministries Grid */}
+
+ {ministries.map((ministry) => (
+ handleMinistryPress(ministry)}
+ activeOpacity={0.7}
+ >
+
+
+
+ {ministry.name}
+ {ministry.nameKu}
+ {ministry.minister && (
+ {ministry.minister}
+ )}
+
+ ))}
+
+
+ {/* Info Footer */}
+
+
+
+ Cabinet of {ministries.length} ministries serving the people of Kurdistan.
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: Colors.background,
+ },
+ header: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ backgroundColor: '#FFFFFF',
+ paddingHorizontal: Spacing.lg,
+ paddingVertical: Spacing.md,
+ borderBottomWidth: 1,
+ borderBottomColor: '#E0E0E0',
+ ...Shadow.small,
+ },
+ backButton: {
+ marginRight: Spacing.md,
+ },
+ headerContent: {
+ flex: 1,
+ },
+ headerTitle: {
+ fontSize: Typography.sizes.xxl,
+ fontWeight: Typography.weights.bold,
+ color: Colors.textDark,
+ },
+ headerSubtitle: {
+ fontSize: Typography.sizes.md,
+ color: Colors.textLight,
+ marginTop: Spacing.xs,
+ },
+ content: {
+ flex: 1,
+ },
+ grid: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ padding: Spacing.md,
+ },
+ ministryCard: {
+ width: '31%',
+ marginHorizontal: '1%',
+ marginBottom: Spacing.lg,
+ backgroundColor: '#FFFFFF',
+ borderRadius: BorderRadius.lg,
+ padding: Spacing.md,
+ alignItems: 'center',
+ ...Shadow.small,
+ },
+ iconContainer: {
+ width: 64,
+ height: 64,
+ borderRadius: BorderRadius.lg,
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginBottom: Spacing.sm,
+ },
+ ministryName: {
+ fontSize: Typography.sizes.xs,
+ fontWeight: Typography.weights.semibold,
+ color: Colors.textDark,
+ textAlign: 'center',
+ marginBottom: Spacing.xs,
+ },
+ ministryNameKu: {
+ fontSize: Typography.sizes.xs,
+ color: Colors.textLight,
+ textAlign: 'center',
+ marginBottom: Spacing.xs,
+ },
+ ministerName: {
+ fontSize: 10,
+ color: Colors.primary,
+ textAlign: 'center',
+ fontStyle: 'italic',
+ },
+ infoFooter: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ backgroundColor: '#E3F2FD',
+ margin: Spacing.lg,
+ padding: Spacing.md,
+ borderRadius: BorderRadius.md,
+ },
+ infoText: {
+ flex: 1,
+ fontSize: Typography.sizes.sm,
+ color: Colors.primary,
+ marginLeft: Spacing.sm,
+ lineHeight: 18,
+ },
+});
+
diff --git a/frontend/src/screens/Home/HomeScreen.tsx b/frontend/src/screens/Home/HomeScreen.tsx
new file mode 100644
index 00000000..7b5f20b8
--- /dev/null
+++ b/frontend/src/screens/Home/HomeScreen.tsx
@@ -0,0 +1,372 @@
+import React, { useEffect, useState } from 'react';
+import {
+ View,
+ Text,
+ StyleSheet,
+ TouchableOpacity,
+ ScrollView,
+ SafeAreaView,
+ Image,
+} from 'react-native';
+import { LinearGradient } from 'expo-linear-gradient';
+import { Ionicons } from '@expo/vector-icons';
+import Colors from '../../constants/colors';
+import { Typography, Spacing, BorderRadius, Shadow, IconSizes } from '../../constants/theme';
+import { blockchainService } from '../../services/blockchain';
+import { Balance } from '../../types';
+
+interface QuickAction {
+ id: string;
+ label: string;
+ icon: keyof typeof Ionicons.glyphMap;
+ color: string;
+ onPress: () => void;
+}
+
+export default function HomeScreen({ navigation }: any) {
+ const [balance, setBalance] = useState(null);
+ const [trustScore] = useState(750);
+
+ useEffect(() => {
+ loadBalance();
+ }, []);
+
+ const loadBalance = async () => {
+ try {
+ // Try to connect to blockchain
+ const connected = await blockchainService.connect();
+ if (connected) {
+ const bal = await blockchainService.getBalances(
+ '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'
+ );
+ setBalance(bal);
+ }
+ } catch (error) {
+ console.log('Using mock data');
+ // Use mock data
+ setBalance({
+ hez: '45,750.5',
+ pez: '1,234,567',
+ hezStaked: '30,000',
+ hezUsd: '45,234',
+ pezUsd: '123,456',
+ governancePower: '2.5',
+ });
+ }
+ };
+
+ const quickActions: QuickAction[] = [
+ {
+ id: 'send',
+ label: 'Send',
+ icon: 'arrow-forward',
+ color: Colors.coral,
+ onPress: () => navigation.navigate('Send', { token: 'HEZ' }),
+ },
+ {
+ id: 'receive',
+ label: 'Receive',
+ icon: 'arrow-down',
+ color: Colors.blue,
+ onPress: () => navigation.navigate('Receive', { token: 'HEZ' }),
+ },
+ {
+ id: 'vote',
+ label: 'Vote',
+ icon: 'checkmark-circle',
+ color: Colors.mint,
+ onPress: () => navigation.navigate('Governance'),
+ },
+ {
+ id: 'proposals',
+ label: 'Proposals',
+ icon: 'bulb',
+ color: Colors.peach,
+ onPress: () => navigation.navigate('Governance'),
+ },
+ {
+ id: 'identity',
+ label: 'Identity',
+ icon: 'person',
+ color: Colors.teal,
+ onPress: () => navigation.navigate('Identity'),
+ },
+ {
+ id: 'certificates',
+ label: 'Certificates',
+ icon: 'school',
+ color: Colors.gold,
+ onPress: () => navigation.navigate('Education'),
+ },
+ {
+ id: 'exchange',
+ label: 'Exchange',
+ icon: 'swap-horizontal',
+ color: Colors.cyan,
+ onPress: () => navigation.navigate('Exchange'),
+ },
+ {
+ id: 'rewards',
+ label: 'Rewards',
+ icon: 'star',
+ color: Colors.lavender,
+ onPress: () => navigation.navigate('Wallet'),
+ },
+ {
+ id: 'trust',
+ label: 'Trust',
+ icon: 'heart',
+ color: Colors.emerald,
+ onPress: () => navigation.navigate('Profile'),
+ },
+ ];
+
+ return (
+
+
+ {/* Header */}
+
+
+ {/* Profile Avatar */}
+ navigation.navigate('Profile')}
+ activeOpacity={0.7}
+ >
+
+
+
+
+ {/* Trust Score Badge */}
+ navigation.navigate('TrustScore')}
+ activeOpacity={0.7}
+ >
+
+ {trustScore}
+
+
+
+ {/* Action Icons */}
+
+ navigation.navigate('QRScanner')}
+ >
+
+
+
+ navigation.navigate('Notifications')}
+ >
+
+
+
+ navigation.navigate('Profile')}
+ >
+
+
+
+
+
+
+ {/* Balance Card */}
+
+ navigation.navigate('Wallet')}
+ activeOpacity={0.8}
+ >
+
+ navigation.navigate('Wallet', { tab: 'HEZ' })}
+ activeOpacity={0.7}
+ >
+ HEZ Balance
+ {balance?.hez || '0'}
+
+
+
+ navigation.navigate('Wallet', { tab: 'PEZ' })}
+ activeOpacity={0.7}
+ >
+ PEZ Balance
+ {balance?.pez || '0'}
+
+
+
+
+
+
+ {/* Quick Actions */}
+
+ Quick Actions
+
+
+ {quickActions.map((action) => (
+
+
+
+
+ {action.label}
+
+ ))}
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: Colors.background,
+ },
+ header: {
+ paddingHorizontal: Spacing.xl,
+ paddingTop: Spacing.xl,
+ paddingBottom: Spacing.xxxl * 2,
+ borderBottomLeftRadius: BorderRadius.xxlarge,
+ borderBottomRightRadius: BorderRadius.xxlarge,
+ },
+ headerTop: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ },
+ profileSection: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: Spacing.sm,
+ },
+ avatar: {
+ width: 50,
+ height: 50,
+ borderRadius: 25,
+ backgroundColor: 'rgba(255, 255, 255, 0.3)',
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ trustBadge: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ backgroundColor: Colors.gold,
+ paddingHorizontal: Spacing.md,
+ paddingVertical: Spacing.xs,
+ borderRadius: BorderRadius.round,
+ gap: Spacing.xs,
+ },
+ trustScore: {
+ fontSize: Typography.sizes.body,
+ fontWeight: Typography.weights.semibold,
+ color: '#FFFFFF',
+ },
+ headerActions: {
+ flexDirection: 'row',
+ gap: Spacing.md,
+ },
+ headerIcon: {
+ width: 40,
+ height: 40,
+ borderRadius: 20,
+ backgroundColor: 'rgba(255, 255, 255, 0.2)',
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ balanceCardContainer: {
+ paddingHorizontal: Spacing.xl,
+ marginTop: -Spacing.xxxl,
+ },
+ balanceCard: {
+ backgroundColor: '#F5F3FF',
+ borderRadius: BorderRadius.large,
+ padding: Spacing.xl,
+ ...Shadow.soft,
+ },
+ balanceRow: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ },
+ balanceItem: {
+ flex: 1,
+ },
+ balanceLabel: {
+ fontSize: Typography.sizes.body,
+ color: Colors.textGray,
+ marginBottom: Spacing.xs,
+ },
+ balanceAmount: {
+ fontSize: Typography.sizes.hero,
+ fontWeight: Typography.weights.bold,
+ color: Colors.textDark,
+ marginBottom: Spacing.xs,
+ },
+ balanceAmountSecondary: {
+ fontSize: Typography.sizes.heading,
+ fontWeight: Typography.weights.semibold,
+ color: Colors.textDark,
+ marginBottom: Spacing.xs,
+ },
+ underline: {
+ width: 80,
+ height: 3,
+ backgroundColor: Colors.teal,
+ borderRadius: 2,
+ },
+ quickActionsSection: {
+ paddingHorizontal: Spacing.xl,
+ marginTop: Spacing.xl,
+ marginBottom: Spacing.xl,
+ },
+ sectionTitle: {
+ fontSize: Typography.sizes.large,
+ fontWeight: Typography.weights.semibold,
+ color: Colors.textDark,
+ marginBottom: Spacing.lg,
+ },
+ quickActionsGrid: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ gap: Spacing.md,
+ },
+ quickActionButton: {
+ width: '31%',
+ backgroundColor: Colors.card,
+ borderRadius: BorderRadius.large,
+ padding: Spacing.lg,
+ alignItems: 'center',
+ ...Shadow.soft,
+ },
+ quickActionIcon: {
+ width: IconSizes.xxlarge,
+ height: IconSizes.xxlarge,
+ borderRadius: IconSizes.xxlarge / 2,
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginBottom: Spacing.sm,
+ },
+ quickActionLabel: {
+ fontSize: Typography.sizes.small,
+ color: Colors.textGray,
+ textAlign: 'center',
+ },
+});
+
diff --git a/frontend/src/screens/Home/NotificationsScreen.tsx b/frontend/src/screens/Home/NotificationsScreen.tsx
new file mode 100644
index 00000000..94ade090
--- /dev/null
+++ b/frontend/src/screens/Home/NotificationsScreen.tsx
@@ -0,0 +1,292 @@
+import React, { useState, useEffect } from 'react';
+import {
+ View,
+ Text,
+ StyleSheet,
+ TouchableOpacity,
+ SafeAreaView,
+ ScrollView,
+ ActivityIndicator,
+} from 'react-native';
+import { Ionicons } from '@expo/vector-icons';
+import Colors from '../../constants/colors';
+import { Typography, Spacing, BorderRadius, Shadow } from '../../constants/theme';
+
+interface Notification {
+ id: string;
+ type: 'transaction' | 'governance' | 'reward' | 'system';
+ title: string;
+ message: string;
+ timestamp: number;
+ read: boolean;
+}
+
+export default function NotificationsScreen({ navigation }: any) {
+ const [loading, setLoading] = useState(true);
+ const [notifications, setNotifications] = useState([]);
+
+ useEffect(() => {
+ loadNotifications();
+ }, []);
+
+ const loadNotifications = async () => {
+ // Mock data - replace with actual API call
+ setTimeout(() => {
+ setNotifications([
+ {
+ id: '1',
+ type: 'transaction',
+ title: 'Transaction Confirmed',
+ message: 'You received 1,000 PEZ from 5Grw...KutQY',
+ timestamp: Date.now() - 3600000,
+ read: false,
+ },
+ {
+ id: '2',
+ type: 'governance',
+ title: 'New Proposal',
+ message: 'Proposal #47: Increase PEZ rewards by 10%',
+ timestamp: Date.now() - 7200000,
+ read: false,
+ },
+ {
+ id: '3',
+ type: 'reward',
+ title: 'Staking Rewards',
+ message: 'You earned 245 PEZ from staking',
+ timestamp: Date.now() - 86400000,
+ read: true,
+ },
+ {
+ id: '4',
+ type: 'system',
+ title: 'KYC Approved',
+ message: 'Your Kurdistan Citizen Card is ready',
+ timestamp: Date.now() - 172800000,
+ read: true,
+ },
+ ]);
+ setLoading(false);
+ }, 1000);
+ };
+
+ const getNotificationIcon = (type: string) => {
+ switch (type) {
+ case 'transaction':
+ return 'swap-horizontal';
+ case 'governance':
+ return 'megaphone';
+ case 'reward':
+ return 'star';
+ case 'system':
+ return 'information-circle';
+ default:
+ return 'notifications';
+ }
+ };
+
+ const getNotificationColor = (type: string) => {
+ switch (type) {
+ case 'transaction':
+ return Colors.blue;
+ case 'governance':
+ return Colors.peach;
+ case 'reward':
+ return Colors.gold;
+ case 'system':
+ return Colors.teal;
+ default:
+ return Colors.textGray;
+ }
+ };
+
+ const formatTime = (timestamp: number) => {
+ const date = new Date(timestamp);
+ const now = new Date();
+ const diff = now.getTime() - date.getTime();
+ const hours = Math.floor(diff / (1000 * 60 * 60));
+ const days = Math.floor(hours / 24);
+
+ if (hours < 1) return 'Just now';
+ if (hours < 24) return `${hours}h ago`;
+ if (days === 1) return 'Yesterday';
+ return `${days}d ago`;
+ };
+
+ const markAsRead = (id: string) => {
+ setNotifications((prev) =>
+ prev.map((notif) => (notif.id === id ? { ...notif, read: true } : notif))
+ );
+ };
+
+ const unreadCount = notifications.filter((n) => !n.read).length;
+
+ return (
+
+
+ navigation.goBack()} style={styles.backButton}>
+
+
+ Notifications
+ {unreadCount > 0 && (
+
+ {unreadCount}
+
+ )}
+
+
+
+ {loading ? (
+
+ ) : notifications.length === 0 ? (
+
+
+ No notifications yet
+
+ ) : (
+ notifications.map((notification) => (
+ markAsRead(notification.id)}
+ activeOpacity={0.7}
+ >
+
+
+
+
+
+
+ {notification.title}
+ {!notification.read && }
+
+ {notification.message}
+ {formatTime(notification.timestamp)}
+
+
+ ))
+ )}
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: Colors.background,
+ },
+ header: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ paddingHorizontal: Spacing.xl,
+ paddingVertical: Spacing.lg,
+ borderBottomWidth: 1,
+ borderBottomColor: '#F0F0F0',
+ },
+ backButton: {
+ width: 40,
+ height: 40,
+ borderRadius: 20,
+ backgroundColor: Colors.card,
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginRight: Spacing.md,
+ },
+ headerTitle: {
+ fontSize: Typography.sizes.large,
+ fontWeight: Typography.weights.semibold,
+ color: Colors.textDark,
+ flex: 1,
+ },
+ badge: {
+ backgroundColor: Colors.coral,
+ width: 24,
+ height: 24,
+ borderRadius: 12,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ badgeText: {
+ fontSize: 12,
+ fontWeight: Typography.weights.semibold,
+ color: '#FFFFFF',
+ },
+ content: {
+ flex: 1,
+ padding: Spacing.lg,
+ },
+ notificationCard: {
+ flexDirection: 'row',
+ backgroundColor: Colors.card,
+ padding: Spacing.lg,
+ borderRadius: BorderRadius.large,
+ marginBottom: Spacing.md,
+ ...Shadow.small,
+ },
+ unreadCard: {
+ borderLeftWidth: 4,
+ borderLeftColor: Colors.teal,
+ },
+ iconContainer: {
+ width: 50,
+ height: 50,
+ borderRadius: 25,
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginRight: Spacing.md,
+ },
+ notificationContent: {
+ flex: 1,
+ },
+ notificationHeader: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ marginBottom: 4,
+ },
+ notificationTitle: {
+ fontSize: Typography.sizes.medium,
+ fontWeight: Typography.weights.semibold,
+ color: Colors.textDark,
+ flex: 1,
+ },
+ unreadDot: {
+ width: 8,
+ height: 8,
+ borderRadius: 4,
+ backgroundColor: Colors.teal,
+ },
+ notificationMessage: {
+ fontSize: Typography.sizes.small,
+ color: Colors.textGray,
+ marginBottom: 4,
+ },
+ notificationTime: {
+ fontSize: Typography.sizes.small,
+ color: Colors.textGray,
+ opacity: 0.7,
+ },
+ emptyState: {
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginTop: 100,
+ },
+ emptyText: {
+ fontSize: Typography.sizes.medium,
+ color: Colors.textGray,
+ marginTop: Spacing.lg,
+ },
+});
+
diff --git a/frontend/src/screens/Identity/CitizenCardScreen.tsx b/frontend/src/screens/Identity/CitizenCardScreen.tsx
new file mode 100644
index 00000000..a559a7fb
--- /dev/null
+++ b/frontend/src/screens/Identity/CitizenCardScreen.tsx
@@ -0,0 +1,459 @@
+import React, { useState, useEffect } from 'react';
+import {
+ View,
+ Text,
+ StyleSheet,
+ TouchableOpacity,
+ SafeAreaView,
+ Image,
+ ActivityIndicator,
+ ScrollView,
+} from 'react-native';
+import { Ionicons } from '@expo/vector-icons';
+import QRCode from 'react-native-qrcode-svg';
+import Colors from '../../constants/colors';
+import { Typography, Spacing, BorderRadius, Shadow } from '../../constants/theme';
+import { kycService } from '../../services/kycService';
+import { KurdistanCitizen, REGION_LABELS } from '../../types/kyc';
+
+export default function CitizenCardScreen({ navigation }: any) {
+ const [loading, setLoading] = useState(true);
+ const [citizen, setCitizen] = useState(null);
+
+ useEffect(() => {
+ loadCitizen();
+ }, []);
+
+ const loadCitizen = async () => {
+ try {
+ const data = await kycService.getCitizen();
+ setCitizen(data);
+ } catch (error) {
+ console.error('Failed to load citizen data:', error);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ if (loading) {
+ return (
+
+
+
+ );
+ }
+
+ if (!citizen) {
+ return (
+
+ No citizen data found
+ navigation.navigate('IdentityKYCForm')}
+ >
+ Complete KYC
+
+
+ );
+ }
+
+ const formatDate = (timestamp: number) => {
+ const date = new Date(timestamp);
+ return date.toLocaleDateString('en-GB');
+ };
+
+ return (
+
+
+ navigation.goBack()} style={styles.backButton}>
+
+
+ Digital Hemwelatî
+
+
+
+
+
+
+ {/* Official Citizen Card */}
+
+ {/* Burgundy Header */}
+
+ KOMARA KURDISTANÊ
+ HEMWELATÎ
+
+
+ {/* Main Content - White Background */}
+
+ {/* Photo and Info Section */}
+
+ {/* Photo */}
+
+ {citizen.photo ? (
+
+ ) : (
+
+
+
+ )}
+
+
+ {/* Info List */}
+
+
+ NAV/NAME
+ {citizen.fullName}
+
+
+ {citizen.fatherName && (
+
+ BAV/FATHER
+ {citizen.fatherName}
+
+ )}
+
+ {citizen.grandfatherName && (
+
+ DAPÎR/GRANDFATHER
+ {citizen.grandfatherName}
+
+ )}
+
+ {citizen.greatGrandfatherName && (
+
+ DAPÎRA BIRA/G.GRANDFATHER
+ {citizen.greatGrandfatherName}
+
+ )}
+
+ {citizen.motherName && (
+
+ DAY/MOTHER
+ {citizen.motherName}
+
+ )}
+
+
+ ZEWICÎN/MARITAL
+
+ {citizen.maritalStatus === 'married' ? 'Zewicî' : 'Nezewicî'}
+
+
+
+ {citizen.maritalStatus === 'married' && citizen.spouseName && (
+
+ HEVJÎN/SPOUSE
+ {citizen.spouseName}
+
+ )}
+
+ {citizen.children && citizen.children.length > 0 && (
+
+ ZAROK/CHILDREN
+ {citizen.children.length}
+
+ )}
+
+
+
+ {/* PEZ Sun Logo */}
+
+
+
+
+ {/* Region and Citizen ID */}
+
+
+ HEREM/REGION
+ {REGION_LABELS[citizen.region].en}
+
+
+
+ JIMARA HEMWELATÎ/CITIZEN ID
+ {citizen.citizenId}
+
+
+
+
+ {/* Green Footer */}
+
+
+
+ NASNAMA DIJÎTAL/DIGITAL ID
+ {citizen.citizenId.replace(/-/g, '')}
+
+
+
+ JIMARA VEKIRAN/ACCOUNT#
+ {citizen.qrCode.substring(0, 12)}
+
+
+
+ DAXWAZ/ISSUED
+ {formatDate(citizen.approvedAt)}
+
+
+
+
+
+
+
+
+
+ {/* Status Badge */}
+
+
+ Verified Kurdistan Citizen
+
+
+ {/* Info Text */}
+
+ This official digital citizenship card grants you full access to Governance (Welati) and all citizen-only features on PezkuwiChain.
+
+
+ {/* Action Buttons */}
+
+
+
+ Download
+
+
+
+
+ Show QR
+
+
+
+
+ Share
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: Colors.background,
+ },
+ header: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ paddingHorizontal: Spacing.xl,
+ paddingVertical: Spacing.lg,
+ borderBottomWidth: 1,
+ borderBottomColor: '#F0F0F0',
+ },
+ backButton: {
+ width: 40,
+ height: 40,
+ borderRadius: 20,
+ backgroundColor: Colors.card,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ shareButton: {
+ width: 40,
+ height: 40,
+ borderRadius: 20,
+ backgroundColor: Colors.card,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ headerTitle: {
+ fontSize: Typography.sizes.large,
+ fontWeight: Typography.weights.semibold,
+ color: Colors.textDark,
+ },
+ content: {
+ flex: 1,
+ padding: Spacing.xl,
+ },
+ card: {
+ backgroundColor: '#FFFFFF',
+ borderRadius: BorderRadius.xlarge,
+ overflow: 'hidden',
+ ...Shadow.medium,
+ },
+ cardHeader: {
+ backgroundColor: '#8B1538', // Burgundy
+ paddingVertical: Spacing.xl,
+ alignItems: 'center',
+ },
+ headerText1: {
+ fontSize: 20,
+ fontWeight: '700',
+ color: '#D4A017', // Gold
+ letterSpacing: 1,
+ },
+ headerText2: {
+ fontSize: 24,
+ fontWeight: '700',
+ color: '#FFFFFF',
+ letterSpacing: 2,
+ marginTop: 4,
+ },
+ cardBody: {
+ backgroundColor: '#FFFFFF',
+ padding: Spacing.lg,
+ },
+ topSection: {
+ flexDirection: 'row',
+ marginBottom: Spacing.md,
+ },
+ photoContainer: {
+ width: 100,
+ height: 100,
+ borderRadius: 50,
+ overflow: 'hidden',
+ backgroundColor: '#D0D0D0',
+ marginRight: Spacing.md,
+ },
+ photo: {
+ width: '100%',
+ height: '100%',
+ },
+ photoPlaceholder: {
+ width: '100%',
+ height: '100%',
+ justifyContent: 'center',
+ alignItems: 'center',
+ backgroundColor: '#D0D0D0',
+ },
+ infoList: {
+ flex: 1,
+ },
+ infoRow: {
+ marginBottom: 6,
+ },
+ infoLabel: {
+ fontSize: 9,
+ fontWeight: '600',
+ color: '#333',
+ letterSpacing: 0.3,
+ },
+ infoValue: {
+ fontSize: 11,
+ fontWeight: '700',
+ color: '#000',
+ },
+ sunContainer: {
+ alignItems: 'center',
+ marginVertical: Spacing.md,
+ },
+ middleSection: {
+ marginTop: Spacing.sm,
+ },
+ regionRow: {
+ marginBottom: Spacing.sm,
+ },
+ regionLabel: {
+ fontSize: 11,
+ fontWeight: '600',
+ color: '#333',
+ },
+ regionValue: {
+ fontSize: 13,
+ fontWeight: '700',
+ color: '#000',
+ },
+ citizenIdRow: {
+ marginTop: Spacing.sm,
+ },
+ citizenIdLabel: {
+ fontSize: 11,
+ fontWeight: '600',
+ color: '#333',
+ },
+ citizenIdValue: {
+ fontSize: 15,
+ fontWeight: '700',
+ color: '#000',
+ letterSpacing: 1,
+ },
+ cardFooter: {
+ backgroundColor: '#007A3D', // Green
+ flexDirection: 'row',
+ padding: Spacing.lg,
+ justifyContent: 'space-between',
+ },
+ footerLeft: {
+ flex: 1,
+ },
+ footerRow: {
+ marginBottom: 6,
+ },
+ footerLabel: {
+ fontSize: 9,
+ fontWeight: '600',
+ color: '#FFFFFF',
+ opacity: 0.9,
+ },
+ footerValue: {
+ fontSize: 11,
+ fontWeight: '700',
+ color: '#D4A017', // Gold
+ },
+ footerRight: {
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ statusBadge: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'center',
+ backgroundColor: Colors.mint + '20',
+ padding: Spacing.md,
+ borderRadius: BorderRadius.large,
+ marginTop: Spacing.xl,
+ gap: Spacing.sm,
+ },
+ statusText: {
+ fontSize: Typography.sizes.medium,
+ fontWeight: Typography.weights.semibold,
+ color: Colors.mint,
+ },
+ infoText: {
+ fontSize: Typography.sizes.small,
+ color: Colors.textGray,
+ textAlign: 'center',
+ marginTop: Spacing.lg,
+ lineHeight: 20,
+ },
+ actions: {
+ flexDirection: 'row',
+ justifyContent: 'space-around',
+ marginTop: Spacing.xl,
+ marginBottom: Spacing.xl,
+ },
+ actionButton: {
+ alignItems: 'center',
+ gap: Spacing.sm,
+ },
+ actionText: {
+ fontSize: Typography.sizes.small,
+ color: Colors.teal,
+ fontWeight: Typography.weights.medium,
+ },
+ errorText: {
+ fontSize: Typography.sizes.medium,
+ color: Colors.textGray,
+ textAlign: 'center',
+ },
+ button: {
+ backgroundColor: Colors.teal,
+ paddingVertical: Spacing.lg,
+ paddingHorizontal: Spacing.xxxl,
+ borderRadius: BorderRadius.xxlarge,
+ marginTop: Spacing.xl,
+ },
+ buttonText: {
+ fontSize: Typography.sizes.medium,
+ fontWeight: Typography.weights.semibold,
+ color: '#FFFFFF',
+ },
+});
+
diff --git a/frontend/src/screens/Identity/IdentityKYCFormScreen.tsx b/frontend/src/screens/Identity/IdentityKYCFormScreen.tsx
new file mode 100644
index 00000000..09057091
--- /dev/null
+++ b/frontend/src/screens/Identity/IdentityKYCFormScreen.tsx
@@ -0,0 +1,435 @@
+import React, { useState } from 'react';
+import {
+ View,
+ Text,
+ StyleSheet,
+ TextInput,
+ TouchableOpacity,
+ ScrollView,
+ SafeAreaView,
+ Alert,
+ ActivityIndicator,
+} from 'react-native';
+import { Ionicons } from '@expo/vector-icons';
+import { Picker } from '@react-native-picker/picker';
+import Colors from '../../constants/colors';
+import { Typography, Spacing, BorderRadius, Shadow } from '../../constants/theme';
+import { KYCFormData, Region, MaritalStatus, REGION_LABELS } from '../../types/kyc';
+import { kycService } from '../../services/kycService';
+
+export default function IdentityKYCFormScreen({ navigation }: any) {
+ const [loading, setLoading] = useState(false);
+ const [formData, setFormData] = useState({
+ fullName: '',
+ fatherName: '',
+ grandfatherName: '',
+ greatGrandfatherName: '',
+ motherName: '',
+ maritalStatus: 'single',
+ region: 'basur',
+ });
+
+ const updateField = (field: keyof KYCFormData, value: any) => {
+ setFormData({ ...formData, [field]: value });
+ };
+
+ const updateChild = (index: number, name: string) => {
+ const children = formData.children || [];
+ children[index] = { name, order: index + 1 };
+ setFormData({ ...formData, children });
+ };
+
+ const handleSubmit = async () => {
+ // Validation
+ if (!formData.fullName || !formData.fatherName || !formData.motherName) {
+ Alert.alert('Error', 'Please fill in all required fields');
+ return;
+ }
+
+ if (formData.maritalStatus === 'married' && !formData.spouseName) {
+ Alert.alert('Error', 'Please enter your spouse name');
+ return;
+ }
+
+ setLoading(true);
+ try {
+ // Submit KYC
+ const submission = await kycService.submitKYC(formData, null); // TODO: Add signer
+
+ Alert.alert(
+ 'KYC Submitted',
+ 'Your KYC application has been submitted for review. You will be notified once approved.',
+ [
+ {
+ text: 'OK',
+ onPress: () => navigation.goBack(),
+ },
+ ]
+ );
+ } catch (error) {
+ Alert.alert('Error', 'Failed to submit KYC. Please try again.');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ const renderChildInputs = () => {
+ if (!formData.numberOfChildren || formData.numberOfChildren === 0) return null;
+
+ return Array.from({ length: formData.numberOfChildren }, (_, index) => (
+
+ {index + 1}. Child's Name
+
+
+ updateChild(index, text)}
+ />
+
+
+ ));
+ };
+
+ return (
+
+
+ navigation.goBack()} style={styles.backButton}>
+
+
+ Identity KYC
+
+
+
+
+
+
+
+ Complete this form to become a verified Kurdistan Digital Citizen and access Governance features.
+
+
+
+ {/* Personal Information */}
+ Personal Information
+
+
+ Full Name *
+
+
+ updateField('fullName', text)}
+ />
+
+
+
+
+ Father's Name *
+
+
+ updateField('fatherName', text)}
+ />
+
+
+
+
+ Grandfather's Name
+
+
+ updateField('grandfatherName', text)}
+ />
+
+
+
+
+ Great-Grandfather's Name
+
+
+ updateField('greatGrandfatherName', text)}
+ />
+
+
+
+
+ Mother's Name *
+
+
+ updateField('motherName', text)}
+ />
+
+
+
+ {/* Marital Status */}
+ Marital Status
+
+
+ updateField('maritalStatus', 'single')}
+ >
+
+ Single
+
+
+ updateField('maritalStatus', 'married')}
+ >
+
+ Married
+
+
+
+ {formData.maritalStatus === 'married' && (
+ <>
+
+ Spouse's Name *
+
+
+ updateField('spouseName', text)}
+ />
+
+
+
+
+ Number of Children
+
+
+ {
+ const num = parseInt(text) || 0;
+ updateField('numberOfChildren', num);
+ if (num > 0) {
+ updateField('children', Array(num).fill({ name: '', order: 0 }));
+ }
+ }}
+ />
+
+
+
+ {renderChildInputs()}
+ >
+ )}
+
+ {/* Region */}
+ Region
+
+
+ Select Your Region *
+
+ updateField('region', value)}
+ style={styles.picker}
+ >
+ {Object.entries(REGION_LABELS).map(([key, value]) => (
+
+ ))}
+
+
+
+
+ {/* Submit Button */}
+
+ {loading ? (
+
+ ) : (
+ <>
+ Submit KYC Application
+
+ >
+ )}
+
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: Colors.background,
+ },
+ header: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ paddingHorizontal: Spacing.xl,
+ paddingVertical: Spacing.lg,
+ borderBottomWidth: 1,
+ borderBottomColor: '#F0F0F0',
+ },
+ backButton: {
+ width: 40,
+ height: 40,
+ borderRadius: 20,
+ backgroundColor: Colors.card,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ headerTitle: {
+ fontSize: Typography.sizes.large,
+ fontWeight: Typography.weights.semibold,
+ color: Colors.textDark,
+ },
+ scrollView: {
+ flex: 1,
+ paddingHorizontal: Spacing.xl,
+ },
+ infoCard: {
+ flexDirection: 'row',
+ backgroundColor: Colors.teal + '20',
+ padding: Spacing.lg,
+ borderRadius: BorderRadius.medium,
+ marginVertical: Spacing.lg,
+ gap: Spacing.md,
+ },
+ infoText: {
+ flex: 1,
+ fontSize: Typography.sizes.small,
+ color: Colors.textDark,
+ lineHeight: 20,
+ },
+ sectionTitle: {
+ fontSize: Typography.sizes.large,
+ fontWeight: Typography.weights.semibold,
+ color: Colors.textDark,
+ marginTop: Spacing.xl,
+ marginBottom: Spacing.md,
+ },
+ inputContainer: {
+ marginBottom: Spacing.lg,
+ },
+ label: {
+ fontSize: Typography.sizes.body,
+ fontWeight: Typography.weights.medium,
+ color: Colors.textDark,
+ marginBottom: Spacing.sm,
+ },
+ inputWrapper: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ backgroundColor: Colors.card,
+ borderRadius: BorderRadius.medium,
+ paddingHorizontal: Spacing.md,
+ paddingVertical: Spacing.sm,
+ borderWidth: 1,
+ borderColor: '#E0E0E0',
+ },
+ input: {
+ flex: 1,
+ fontSize: Typography.sizes.medium,
+ color: Colors.textDark,
+ marginLeft: Spacing.sm,
+ },
+ radioGroup: {
+ flexDirection: 'row',
+ gap: Spacing.md,
+ marginBottom: Spacing.lg,
+ },
+ radioButton: {
+ flex: 1,
+ flexDirection: 'row',
+ alignItems: 'center',
+ backgroundColor: Colors.card,
+ padding: Spacing.lg,
+ borderRadius: BorderRadius.medium,
+ borderWidth: 1,
+ borderColor: '#E0E0E0',
+ gap: Spacing.sm,
+ },
+ radioButtonActive: {
+ borderColor: Colors.teal,
+ backgroundColor: Colors.teal + '10',
+ },
+ radioLabel: {
+ fontSize: Typography.sizes.medium,
+ color: Colors.textDark,
+ },
+ pickerWrapper: {
+ backgroundColor: Colors.card,
+ borderRadius: BorderRadius.medium,
+ borderWidth: 1,
+ borderColor: '#E0E0E0',
+ overflow: 'hidden',
+ },
+ picker: {
+ height: 50,
+ },
+ submitButton: {
+ flexDirection: 'row',
+ backgroundColor: Colors.teal,
+ borderRadius: BorderRadius.xxlarge,
+ paddingVertical: Spacing.lg,
+ paddingHorizontal: Spacing.xxxl,
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginTop: Spacing.xl,
+ gap: Spacing.sm,
+ ...Shadow.soft,
+ },
+ submitButtonDisabled: {
+ opacity: 0.6,
+ },
+ submitButtonText: {
+ fontSize: Typography.sizes.large,
+ fontWeight: Typography.weights.semibold,
+ color: '#FFFFFF',
+ },
+});
+
diff --git a/frontend/src/screens/Identity/IdentityScreen.tsx b/frontend/src/screens/Identity/IdentityScreen.tsx
new file mode 100644
index 00000000..d1749f7c
--- /dev/null
+++ b/frontend/src/screens/Identity/IdentityScreen.tsx
@@ -0,0 +1,316 @@
+import React, { useState, useEffect } from 'react';
+import { View, Text, StyleSheet, TouchableOpacity, SafeAreaView, ActivityIndicator } from 'react-native';
+import { Ionicons } from '@expo/vector-icons';
+import Colors from '../../constants/colors';
+import { Typography, Spacing, BorderRadius, Shadow } from '../../constants/theme';
+import { kycService } from '../../services/kycService';
+import { KYCStatus } from '../../types/kyc';
+
+export default function IdentityScreen({ navigation }: any) {
+ const [loading, setLoading] = useState(true);
+ const [kycStatus, setKycStatus] = useState({
+ started: false,
+ submitted: false,
+ approved: false,
+ });
+
+ useEffect(() => {
+ loadKYCStatus();
+ }, []);
+
+ const loadKYCStatus = async () => {
+ try {
+ const status = await kycService.getKYCStatus();
+ setKycStatus(status);
+ } catch (error) {
+ console.error('Failed to load KYC status:', error);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ if (loading) {
+ return (
+
+
+
+ );
+ }
+
+ // If KYC approved, show citizen card access
+ if (kycStatus.approved && kycStatus.citizen) {
+ return (
+
+
+ Digital Identity
+
+
+
+
+
+ KYC Approved
+ You are a verified Kurdistan Digital Citizen
+
+
+ navigation.navigate('CitizenCard')}
+ >
+
+ View Citizen Card
+
+
+
+
+
+ Your citizen card grants you access to Governance (Welati) and other citizen-only features.
+
+
+
+
+ );
+ }
+
+ // If KYC submitted but not approved
+ if (kycStatus.submitted && !kycStatus.approved) {
+ return (
+
+
+ Digital Identity
+
+
+
+
+
+ KYC Under Review
+
+ Your application is being reviewed. You will be notified once approved.
+
+
+
+
+
+ Check Status
+
+
+
+ );
+ }
+
+ // If KYC not started
+ return (
+
+
+ Digital Identity
+
+
+
+
+
+ Become a Digital Citizen
+
+ Complete KYC verification to access Governance (Welati) and become a verified Kurdistan Digital Citizen.
+
+
+
+
+ Benefits:
+
+
+ Vote on governance proposals
+
+
+
+ Access Parliamentary NFT elections
+
+
+
+ Digital citizenship certificate
+
+
+
+ Verified trust score
+
+
+
+ navigation.navigate('IdentityKYCForm')}
+ >
+ Start KYC Verification
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: Colors.background,
+ },
+ header: {
+ padding: Spacing.xl,
+ borderBottomWidth: 1,
+ borderBottomColor: '#F0F0F0',
+ },
+ title: {
+ fontSize: 28,
+ fontWeight: '700',
+ color: Colors.textDark,
+ },
+ content: {
+ flex: 1,
+ padding: Spacing.xl,
+ },
+ welcomeCard: {
+ backgroundColor: Colors.card,
+ padding: Spacing.xxxl,
+ borderRadius: BorderRadius.xlarge,
+ alignItems: 'center',
+ ...Shadow.soft,
+ },
+ welcomeTitle: {
+ fontSize: 24,
+ fontWeight: '700',
+ color: Colors.textDark,
+ marginTop: Spacing.lg,
+ textAlign: 'center',
+ },
+ welcomeSubtitle: {
+ fontSize: 16,
+ color: Colors.textGray,
+ marginTop: Spacing.md,
+ textAlign: 'center',
+ lineHeight: 24,
+ },
+ benefitsCard: {
+ backgroundColor: Colors.mint + '20',
+ padding: Spacing.xl,
+ borderRadius: BorderRadius.large,
+ marginTop: Spacing.xl,
+ },
+ benefitsTitle: {
+ fontSize: 18,
+ fontWeight: '600',
+ color: Colors.textDark,
+ marginBottom: Spacing.md,
+ },
+ benefitItem: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ marginTop: Spacing.sm,
+ gap: Spacing.sm,
+ },
+ benefitText: {
+ fontSize: 16,
+ color: Colors.textDark,
+ },
+ startButton: {
+ flexDirection: 'row',
+ backgroundColor: Colors.teal,
+ borderRadius: BorderRadius.xxlarge,
+ paddingVertical: Spacing.lg,
+ paddingHorizontal: Spacing.xxxl,
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginTop: Spacing.xl,
+ gap: Spacing.sm,
+ ...Shadow.soft,
+ },
+ startButtonText: {
+ fontSize: 18,
+ fontWeight: '600',
+ color: '#FFFFFF',
+ },
+ approvedCard: {
+ backgroundColor: Colors.mint + '20',
+ padding: Spacing.xxxl,
+ borderRadius: BorderRadius.xlarge,
+ alignItems: 'center',
+ ...Shadow.soft,
+ },
+ approvedTitle: {
+ fontSize: 24,
+ fontWeight: '700',
+ color: Colors.mint,
+ marginTop: Spacing.lg,
+ },
+ approvedSubtitle: {
+ fontSize: 16,
+ color: Colors.textGray,
+ marginTop: Spacing.sm,
+ textAlign: 'center',
+ },
+ viewCardButton: {
+ flexDirection: 'row',
+ backgroundColor: Colors.teal,
+ borderRadius: BorderRadius.xxlarge,
+ paddingVertical: Spacing.lg,
+ paddingHorizontal: Spacing.xxxl,
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginTop: Spacing.xl,
+ gap: Spacing.sm,
+ ...Shadow.soft,
+ },
+ viewCardButtonText: {
+ fontSize: 18,
+ fontWeight: '600',
+ color: '#FFFFFF',
+ },
+ infoBox: {
+ flexDirection: 'row',
+ backgroundColor: Colors.teal + '20',
+ padding: Spacing.lg,
+ borderRadius: BorderRadius.medium,
+ marginTop: Spacing.xl,
+ gap: Spacing.md,
+ },
+ infoText: {
+ flex: 1,
+ fontSize: 14,
+ color: Colors.textDark,
+ lineHeight: 20,
+ },
+ pendingCard: {
+ backgroundColor: Colors.gold + '20',
+ padding: Spacing.xxxl,
+ borderRadius: BorderRadius.xlarge,
+ alignItems: 'center',
+ ...Shadow.soft,
+ },
+ pendingTitle: {
+ fontSize: 24,
+ fontWeight: '700',
+ color: Colors.gold,
+ marginTop: Spacing.lg,
+ },
+ pendingSubtitle: {
+ fontSize: 16,
+ color: Colors.textGray,
+ marginTop: Spacing.sm,
+ textAlign: 'center',
+ lineHeight: 24,
+ },
+ refreshButton: {
+ flexDirection: 'row',
+ backgroundColor: Colors.card,
+ borderRadius: BorderRadius.large,
+ paddingVertical: Spacing.md,
+ paddingHorizontal: Spacing.xl,
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginTop: Spacing.xl,
+ gap: Spacing.sm,
+ borderWidth: 1,
+ borderColor: Colors.teal,
+ },
+ refreshButtonText: {
+ fontSize: 16,
+ fontWeight: '600',
+ color: Colors.teal,
+ },
+});
+
diff --git a/frontend/src/screens/Profile/ProfileScreen.tsx b/frontend/src/screens/Profile/ProfileScreen.tsx
new file mode 100644
index 00000000..79fdedf1
--- /dev/null
+++ b/frontend/src/screens/Profile/ProfileScreen.tsx
@@ -0,0 +1,410 @@
+import React, { useState } from 'react';
+import {
+ View,
+ Text,
+ StyleSheet,
+ TouchableOpacity,
+ SafeAreaView,
+ ScrollView,
+ Switch,
+ Alert,
+} from 'react-native';
+import { Ionicons } from '@expo/vector-icons';
+import { LinearGradient } from 'expo-linear-gradient';
+import Colors from '../../constants/colors';
+import { Typography, Spacing, BorderRadius, Shadow } from '../../constants/theme';
+
+interface MenuItem {
+ id: string;
+ icon: keyof typeof Ionicons.glyphMap;
+ title: string;
+ subtitle?: string;
+ onPress: () => void;
+ showArrow?: boolean;
+ showSwitch?: boolean;
+ switchValue?: boolean;
+}
+
+export default function ProfileScreen({ navigation }: any) {
+ const [notificationsEnabled, setNotificationsEnabled] = useState(true);
+ const [biometricEnabled, setBiometricEnabled] = useState(false);
+
+ const accountMenuItems: MenuItem[] = [
+ {
+ id: 'edit-profile',
+ icon: 'person-outline',
+ title: 'Edit Profile',
+ subtitle: 'Update your personal information',
+ onPress: () => Alert.alert('Edit Profile', 'Coming soon'),
+ showArrow: true,
+ },
+ {
+ id: 'identity',
+ icon: 'card-outline',
+ title: 'Digital Identity',
+ subtitle: 'View your Kurdistan Citizen Card',
+ onPress: () => navigation.navigate('Identity'),
+ showArrow: true,
+ },
+ {
+ id: 'trust-score',
+ icon: 'star-outline',
+ title: 'Trust Score',
+ subtitle: '750 points',
+ onPress: () => navigation.navigate('TrustScore'),
+ showArrow: true,
+ },
+ ];
+
+ const securityMenuItems: MenuItem[] = [
+ {
+ id: 'change-password',
+ icon: 'lock-closed-outline',
+ title: 'Change Password',
+ onPress: () => Alert.alert('Change Password', 'Coming soon'),
+ showArrow: true,
+ },
+ {
+ id: 'biometric',
+ icon: 'finger-print-outline',
+ title: 'Biometric Authentication',
+ onPress: () => {},
+ showSwitch: true,
+ switchValue: biometricEnabled,
+ },
+ {
+ id: 'backup',
+ icon: 'cloud-upload-outline',
+ title: 'Backup Wallet',
+ subtitle: 'Secure your recovery phrase',
+ onPress: () => Alert.alert('Backup Wallet', 'This feature will help you backup your wallet securely.'),
+ showArrow: true,
+ },
+ ];
+
+ const preferencesMenuItems: MenuItem[] = [
+ {
+ id: 'notifications',
+ icon: 'notifications-outline',
+ title: 'Push Notifications',
+ onPress: () => {},
+ showSwitch: true,
+ switchValue: notificationsEnabled,
+ },
+ {
+ id: 'language',
+ icon: 'language-outline',
+ title: 'Language',
+ subtitle: 'English',
+ onPress: () => navigation.navigate('LanguageSelection'),
+ showArrow: true,
+ },
+ {
+ id: 'currency',
+ icon: 'cash-outline',
+ title: 'Currency',
+ subtitle: 'USD',
+ onPress: () => Alert.alert('Currency', 'Currency selection coming soon'),
+ showArrow: true,
+ },
+ ];
+
+ const supportMenuItems: MenuItem[] = [
+ {
+ id: 'help',
+ icon: 'help-circle-outline',
+ title: 'Help Center',
+ onPress: () => Alert.alert('Help Center', 'Visit help.pezkuwichain.io'),
+ showArrow: true,
+ },
+ {
+ id: 'about',
+ icon: 'information-circle-outline',
+ title: 'About PezkuwiChain',
+ subtitle: 'Version 1.0.0',
+ onPress: () => Alert.alert('About', 'PezkuwiChain v1.0.0\nBuilding the future of Kurdish digital infrastructure'),
+ showArrow: true,
+ },
+ {
+ id: 'terms',
+ icon: 'document-text-outline',
+ title: 'Terms & Privacy',
+ onPress: () => Alert.alert('Terms', 'View terms and privacy policy'),
+ showArrow: true,
+ },
+ ];
+
+ const handleLogout = () => {
+ Alert.alert(
+ 'Logout',
+ 'Are you sure you want to logout?',
+ [
+ { text: 'Cancel', style: 'cancel' },
+ {
+ text: 'Logout',
+ style: 'destructive',
+ onPress: () => navigation.navigate('LanguageSelection'),
+ },
+ ]
+ );
+ };
+
+ const renderMenuItem = (item: MenuItem) => (
+
+
+
+
+
+
+ {item.title}
+ {item.subtitle && {item.subtitle}}
+
+
+ {item.showArrow && (
+
+ )}
+
+ {item.showSwitch && (
+ {
+ if (item.id === 'notifications') {
+ setNotificationsEnabled(value);
+ } else if (item.id === 'biometric') {
+ setBiometricEnabled(value);
+ }
+ }}
+ trackColor={{ false: '#D0D0D0', true: Colors.teal }}
+ thumbColor="#FFFFFF"
+ />
+ )}
+
+ );
+
+ return (
+
+
+ {/* Profile Header */}
+
+
+
+
+
+
+
+ Satoshi Qazi Muhammed
+ satoshi@pezkuwichain.io
+
+
+ Alert.alert('Edit Profile', 'Coming soon')}
+ >
+
+
+
+
+ {/* Stats */}
+
+
+ 750
+ Trust Score
+
+
+
+
+
+ 24
+ Referrals
+
+
+
+
+
+ 5
+ Certificates
+
+
+
+
+ {/* Account Section */}
+
+ Account
+ {accountMenuItems.map(renderMenuItem)}
+
+
+ {/* Security Section */}
+
+ Security
+ {securityMenuItems.map(renderMenuItem)}
+
+
+ {/* Preferences Section */}
+
+ Preferences
+ {preferencesMenuItems.map(renderMenuItem)}
+
+
+ {/* Support Section */}
+
+ Support
+ {supportMenuItems.map(renderMenuItem)}
+
+
+ {/* Logout Button */}
+
+
+ Logout
+
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: Colors.background,
+ },
+ header: {
+ paddingHorizontal: Spacing.xl,
+ paddingTop: Spacing.xxxl,
+ paddingBottom: Spacing.xl,
+ borderBottomLeftRadius: BorderRadius.xxlarge,
+ borderBottomRightRadius: BorderRadius.xxlarge,
+ },
+ profileInfo: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ marginBottom: Spacing.xl,
+ },
+ avatar: {
+ width: 70,
+ height: 70,
+ borderRadius: 35,
+ backgroundColor: 'rgba(255, 255, 255, 0.3)',
+ justifyContent: 'center',
+ alignItems: 'center',
+ borderWidth: 3,
+ borderColor: '#FFFFFF',
+ },
+ userInfo: {
+ flex: 1,
+ marginLeft: Spacing.lg,
+ },
+ userName: {
+ fontSize: Typography.sizes.xlarge,
+ fontWeight: Typography.weights.bold,
+ color: '#FFFFFF',
+ marginBottom: 4,
+ },
+ userEmail: {
+ fontSize: Typography.sizes.small,
+ color: 'rgba(255, 255, 255, 0.9)',
+ },
+ editButton: {
+ width: 40,
+ height: 40,
+ borderRadius: 20,
+ backgroundColor: 'rgba(255, 255, 255, 0.3)',
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ statsContainer: {
+ flexDirection: 'row',
+ backgroundColor: 'rgba(255, 255, 255, 0.2)',
+ borderRadius: BorderRadius.large,
+ padding: Spacing.lg,
+ },
+ statItem: {
+ flex: 1,
+ alignItems: 'center',
+ },
+ statValue: {
+ fontSize: 24,
+ fontWeight: Typography.weights.bold,
+ color: '#FFFFFF',
+ marginBottom: 4,
+ },
+ statLabel: {
+ fontSize: Typography.sizes.small,
+ color: 'rgba(255, 255, 255, 0.9)',
+ },
+ statDivider: {
+ width: 1,
+ backgroundColor: 'rgba(255, 255, 255, 0.3)',
+ marginHorizontal: Spacing.md,
+ },
+ section: {
+ marginTop: Spacing.xl,
+ paddingHorizontal: Spacing.xl,
+ },
+ sectionTitle: {
+ fontSize: Typography.sizes.medium,
+ fontWeight: Typography.weights.semibold,
+ color: Colors.textGray,
+ marginBottom: Spacing.md,
+ textTransform: 'uppercase',
+ letterSpacing: 0.5,
+ },
+ menuItem: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ backgroundColor: Colors.card,
+ padding: Spacing.lg,
+ borderRadius: BorderRadius.large,
+ marginBottom: Spacing.sm,
+ ...Shadow.small,
+ },
+ menuIconContainer: {
+ width: 40,
+ height: 40,
+ borderRadius: 20,
+ backgroundColor: Colors.teal + '20',
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginRight: Spacing.md,
+ },
+ menuContent: {
+ flex: 1,
+ },
+ menuTitle: {
+ fontSize: Typography.sizes.medium,
+ fontWeight: Typography.weights.medium,
+ color: Colors.textDark,
+ marginBottom: 2,
+ },
+ menuSubtitle: {
+ fontSize: Typography.sizes.small,
+ color: Colors.textGray,
+ },
+ logoutButton: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'center',
+ backgroundColor: Colors.coral + '20',
+ marginHorizontal: Spacing.xl,
+ marginTop: Spacing.xxxl,
+ padding: Spacing.lg,
+ borderRadius: BorderRadius.large,
+ gap: Spacing.sm,
+ },
+ logoutText: {
+ fontSize: Typography.sizes.medium,
+ fontWeight: Typography.weights.semibold,
+ color: Colors.coral,
+ },
+});
+
diff --git a/frontend/src/screens/Profile/ProfileScreen_old.tsx b/frontend/src/screens/Profile/ProfileScreen_old.tsx
new file mode 100644
index 00000000..13e6a50a
--- /dev/null
+++ b/frontend/src/screens/Profile/ProfileScreen_old.tsx
@@ -0,0 +1,18 @@
+import React from 'react';
+import { View, Text, StyleSheet, SafeAreaView } from 'react-native';
+import Colors from '../../constants/colors';
+
+export default function ProfileScreen() {
+ return (
+
+ Profile
+ Coming soon...
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: { flex: 1, backgroundColor: Colors.background, justifyContent: 'center', alignItems: 'center' },
+ title: { fontSize: 28, fontWeight: '700', color: Colors.textDark, marginBottom: 8 },
+ subtitle: { fontSize: 16, color: Colors.textGray },
+});
diff --git a/frontend/src/screens/Profile/TrustScoreScreen.tsx b/frontend/src/screens/Profile/TrustScoreScreen.tsx
new file mode 100644
index 00000000..a99439fa
--- /dev/null
+++ b/frontend/src/screens/Profile/TrustScoreScreen.tsx
@@ -0,0 +1,378 @@
+import React, { useState, useEffect } from 'react';
+import {
+ View,
+ Text,
+ StyleSheet,
+ TouchableOpacity,
+ SafeAreaView,
+ ScrollView,
+ ActivityIndicator,
+} from 'react-native';
+import { Ionicons } from '@expo/vector-icons';
+import { LinearGradient } from 'expo-linear-gradient';
+import Colors from '../../constants/colors';
+import { Typography, Spacing, BorderRadius, Shadow } from '../../constants/theme';
+
+interface TrustActivity {
+ id: string;
+ type: 'vote' | 'proposal' | 'stake' | 'community';
+ description: string;
+ points: number;
+ timestamp: number;
+}
+
+export default function TrustScoreScreen({ navigation }: any) {
+ const [loading, setLoading] = useState(true);
+ const [trustScore] = useState(750);
+ const [activities, setActivities] = useState([]);
+
+ useEffect(() => {
+ loadTrustData();
+ }, []);
+
+ const loadTrustData = async () => {
+ // Mock data - replace with blockchain data
+ setTimeout(() => {
+ setActivities([
+ {
+ id: '1',
+ type: 'vote',
+ description: 'Voted on Proposal #42',
+ points: 10,
+ timestamp: Date.now() - 86400000,
+ },
+ {
+ id: '2',
+ type: 'stake',
+ description: 'Staked 10,000 HEZ',
+ points: 50,
+ timestamp: Date.now() - 172800000,
+ },
+ {
+ id: '3',
+ type: 'proposal',
+ description: 'Created Proposal #45',
+ points: 25,
+ timestamp: Date.now() - 259200000,
+ },
+ {
+ id: '4',
+ type: 'community',
+ description: 'Referred 3 new citizens',
+ points: 30,
+ timestamp: Date.now() - 345600000,
+ },
+ ]);
+ setLoading(false);
+ }, 1000);
+ };
+
+ const getActivityIcon = (type: string) => {
+ switch (type) {
+ case 'vote':
+ return 'checkmark-circle';
+ case 'proposal':
+ return 'bulb';
+ case 'stake':
+ return 'lock-closed';
+ case 'community':
+ return 'people';
+ default:
+ return 'star';
+ }
+ };
+
+ const getActivityColor = (type: string) => {
+ switch (type) {
+ case 'vote':
+ return Colors.mint;
+ case 'proposal':
+ return Colors.peach;
+ case 'stake':
+ return Colors.blue;
+ case 'community':
+ return Colors.lavender;
+ default:
+ return Colors.teal;
+ }
+ };
+
+ const formatDate = (timestamp: number) => {
+ const date = new Date(timestamp);
+ const now = new Date();
+ const diff = now.getTime() - date.getTime();
+ const days = Math.floor(diff / (1000 * 60 * 60 * 24));
+
+ if (days === 0) return 'Today';
+ if (days === 1) return 'Yesterday';
+ return `${days} days ago`;
+ };
+
+ return (
+
+
+ navigation.goBack()} style={styles.backButton}>
+
+
+ Trust Score
+
+
+
+
+ {/* Trust Score Card */}
+
+
+ {trustScore}
+ Your Trust Score
+
+
+ 🏆 Gold Tier
+
+
+
+ {/* Benefits */}
+
+ Benefits
+
+
+
+
+ Higher PEZ Rewards
+
+ Earn 1.5x more PEZ rewards from staking
+
+
+
+
+
+
+
+ Validator Priority
+
+ Higher chance of being selected as validator
+
+
+
+
+
+
+
+ Governance Weight
+
+ Your votes carry more weight in proposals
+
+
+
+
+
+ {/* Recent Activities */}
+
+ Recent Activities
+
+ {loading ? (
+
+ ) : (
+ activities.map((activity) => (
+
+
+
+
+
+
+ {activity.description}
+ {formatDate(activity.timestamp)}
+
+
+
+ +{activity.points}
+ points
+
+
+ ))
+ )}
+
+
+ {/* How to Increase */}
+
+ How to Increase Trust Score
+
+
+ ✓ Vote on governance proposals
+
+
+ ✓ Stake HEZ tokens
+
+
+ ✓ Create valuable proposals
+
+
+ ✓ Refer new citizens
+
+
+ ✓ Maintain long-term participation
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: Colors.background,
+ },
+ header: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ paddingHorizontal: Spacing.xl,
+ paddingVertical: Spacing.lg,
+ borderBottomWidth: 1,
+ borderBottomColor: '#F0F0F0',
+ },
+ backButton: {
+ width: 40,
+ height: 40,
+ borderRadius: 20,
+ backgroundColor: Colors.card,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ headerTitle: {
+ fontSize: Typography.sizes.large,
+ fontWeight: Typography.weights.semibold,
+ color: Colors.textDark,
+ },
+ content: {
+ flex: 1,
+ padding: Spacing.xl,
+ },
+ scoreCard: {
+ borderRadius: BorderRadius.xlarge,
+ padding: Spacing.xxxl,
+ alignItems: 'center',
+ ...Shadow.large,
+ },
+ scoreValue: {
+ fontSize: 64,
+ fontWeight: '700',
+ color: '#FFFFFF',
+ marginTop: Spacing.md,
+ },
+ scoreLabel: {
+ fontSize: Typography.sizes.medium,
+ color: '#FFFFFF',
+ opacity: 0.9,
+ },
+ scoreBadge: {
+ backgroundColor: 'rgba(255, 255, 255, 0.3)',
+ paddingHorizontal: Spacing.lg,
+ paddingVertical: Spacing.sm,
+ borderRadius: BorderRadius.xxlarge,
+ marginTop: Spacing.lg,
+ },
+ badgeText: {
+ fontSize: Typography.sizes.medium,
+ fontWeight: Typography.weights.semibold,
+ color: '#FFFFFF',
+ },
+ section: {
+ marginTop: Spacing.xxxl,
+ },
+ sectionTitle: {
+ fontSize: Typography.sizes.large,
+ fontWeight: Typography.weights.semibold,
+ color: Colors.textDark,
+ marginBottom: Spacing.lg,
+ },
+ benefitCard: {
+ flexDirection: 'row',
+ backgroundColor: Colors.card,
+ padding: Spacing.lg,
+ borderRadius: BorderRadius.large,
+ marginBottom: Spacing.md,
+ ...Shadow.small,
+ },
+ benefitText: {
+ flex: 1,
+ marginLeft: Spacing.md,
+ },
+ benefitTitle: {
+ fontSize: Typography.sizes.medium,
+ fontWeight: Typography.weights.semibold,
+ color: Colors.textDark,
+ marginBottom: 4,
+ },
+ benefitDescription: {
+ fontSize: Typography.sizes.small,
+ color: Colors.textGray,
+ },
+ activityCard: {
+ flexDirection: 'row',
+ backgroundColor: Colors.card,
+ padding: Spacing.lg,
+ borderRadius: BorderRadius.large,
+ marginBottom: Spacing.md,
+ alignItems: 'center',
+ ...Shadow.small,
+ },
+ activityIcon: {
+ width: 50,
+ height: 50,
+ borderRadius: 25,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ activityInfo: {
+ flex: 1,
+ marginLeft: Spacing.md,
+ },
+ activityDescription: {
+ fontSize: Typography.sizes.medium,
+ fontWeight: Typography.weights.medium,
+ color: Colors.textDark,
+ marginBottom: 4,
+ },
+ activityDate: {
+ fontSize: Typography.sizes.small,
+ color: Colors.textGray,
+ },
+ activityPoints: {
+ alignItems: 'flex-end',
+ },
+ pointsValue: {
+ fontSize: Typography.sizes.large,
+ fontWeight: Typography.weights.semibold,
+ color: Colors.mint,
+ },
+ pointsLabel: {
+ fontSize: Typography.sizes.small,
+ color: Colors.textGray,
+ },
+ tipCard: {
+ backgroundColor: Colors.mint + '10',
+ padding: Spacing.md,
+ borderRadius: BorderRadius.medium,
+ marginBottom: Spacing.sm,
+ },
+ tipText: {
+ fontSize: Typography.sizes.medium,
+ color: Colors.textDark,
+ },
+});
+
diff --git a/frontend/src/screens/Referral/ReferralScreen.tsx b/frontend/src/screens/Referral/ReferralScreen.tsx
new file mode 100644
index 00000000..40464d88
--- /dev/null
+++ b/frontend/src/screens/Referral/ReferralScreen.tsx
@@ -0,0 +1,587 @@
+import React, { useState } from 'react';
+import {
+ View,
+ Text,
+ StyleSheet,
+ SafeAreaView,
+ ScrollView,
+ TouchableOpacity,
+ Share,
+ Alert,
+} from 'react-native';
+import * as Clipboard from 'expo-clipboard';
+import QRCode from 'react-native-qrcode-svg';
+import { Ionicons } from '@expo/vector-icons';
+import Colors from '../../constants/colors';
+
+interface ReferralStats {
+ totalReferrals: number;
+ activeReferrals: number;
+ totalRewards: number;
+ pendingRewards: number;
+}
+
+interface Referral {
+ id: string;
+ name: string;
+ joinDate: string;
+ status: 'active' | 'pending' | 'inactive';
+ rewardEarned: number;
+ tier: number;
+}
+
+export default function ReferralScreen() {
+ const [referralCode] = useState('PKW-2024-KURD-5X7Y');
+ const [stats] = useState({
+ totalReferrals: 12,
+ activeReferrals: 8,
+ totalRewards: 2450,
+ pendingRewards: 350,
+ });
+
+ const [referrals] = useState([
+ {
+ id: '1',
+ name: 'Ahmed Karwan',
+ joinDate: '2024-01-15',
+ status: 'active',
+ rewardEarned: 500,
+ tier: 1,
+ },
+ {
+ id: '2',
+ name: 'Layla Sherzad',
+ joinDate: '2024-01-20',
+ status: 'active',
+ rewardEarned: 500,
+ tier: 1,
+ },
+ {
+ id: '3',
+ name: 'Saman Aziz',
+ joinDate: '2024-02-05',
+ status: 'active',
+ rewardEarned: 250,
+ tier: 2,
+ },
+ {
+ id: '4',
+ name: 'Hana Dilshad',
+ joinDate: '2024-02-18',
+ status: 'pending',
+ rewardEarned: 0,
+ tier: 1,
+ },
+ ]);
+
+ const copyToClipboard = async () => {
+ await Clipboard.setStringAsync(referralCode);
+ Alert.alert('✓ Copied!', 'Referral code copied to clipboard');
+ };
+
+ const shareReferralCode = async () => {
+ try {
+ await Share.share({
+ message: `Join PezkuwiChain - Digital Kurdistan's Blockchain Platform!\n\nUse my referral code: ${referralCode}\n\nEarn rewards and be part of building Digital Kurdistan! 🦅`,
+ });
+ } catch (error) {
+ console.error('Error sharing:', error);
+ }
+ };
+
+ const getStatusColor = (status: string) => {
+ switch (status) {
+ case 'active':
+ return Colors.success;
+ case 'pending':
+ return Colors.warning;
+ case 'inactive':
+ return Colors.textGray;
+ default:
+ return Colors.textGray;
+ }
+ };
+
+ const getTierReward = (tier: number) => {
+ switch (tier) {
+ case 1:
+ return '500 PEZ';
+ case 2:
+ return '250 PEZ';
+ case 3:
+ return '100 PEZ';
+ default:
+ return '50 PEZ';
+ }
+ };
+
+ return (
+
+
+ {/* Header */}
+
+ Referral Program
+
+ Invite friends and earn rewards together
+
+
+
+ {/* Referral Code Card */}
+
+ Your Referral Code
+
+
+
+
+ {referralCode}
+
+
+
+
+ Copy Code
+
+
+
+ Share
+
+
+
+
+ {/* Statistics Grid */}
+
+
+
+ {stats.totalReferrals}
+ Total Referrals
+
+
+
+ {stats.activeReferrals}
+ Active
+
+
+
+ {stats.totalRewards}
+ Total Rewards (PEZ)
+
+
+
+ {stats.pendingRewards}
+ Pending (PEZ)
+
+
+
+ {/* Reward Tiers */}
+
+ Reward Tiers
+
+
+
+ Tier 1
+
+ Direct Referrals
+ 500 PEZ
+
+
+
+ Tier 2
+
+ 2nd Level Referrals
+ 250 PEZ
+
+
+
+ Tier 3
+
+ 3rd Level Referrals
+ 100 PEZ
+
+
+
+
+ {/* Referral List */}
+
+ Your Referrals
+ {referrals.map((referral) => (
+
+
+
+
+ {referral.name.charAt(0)}
+
+
+
+ {referral.name}
+
+ Joined: {referral.joinDate}
+
+
+
+
+ {referral.status.charAt(0).toUpperCase() +
+ referral.status.slice(1)}
+
+
+
+
+
+
+ Tier {referral.tier}
+
+
+ Earned: {referral.rewardEarned} PEZ
+
+
+
+ ))}
+
+
+ {/* How It Works */}
+
+ How It Works
+
+
+
+ 1
+
+
+ Share your unique referral code with friends
+
+
+
+
+ 2
+
+
+ They sign up and complete KYC verification
+
+
+
+
+ 3
+
+
+ Both of you earn PEZ rewards based on tier level
+
+
+
+
+ 4
+
+
+ Rewards are distributed automatically to your wallet
+
+
+
+
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: Colors.background,
+ },
+ header: {
+ paddingHorizontal: 20,
+ paddingTop: 20,
+ paddingBottom: 16,
+ },
+ headerTitle: {
+ fontSize: 28,
+ fontWeight: '700',
+ color: Colors.textDark,
+ marginBottom: 4,
+ },
+ headerSubtitle: {
+ fontSize: 15,
+ color: Colors.textGray,
+ },
+ codeCard: {
+ backgroundColor: 'white',
+ marginHorizontal: 20,
+ marginBottom: 20,
+ borderRadius: 16,
+ padding: 24,
+ alignItems: 'center',
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 2 },
+ shadowOpacity: 0.05,
+ shadowRadius: 8,
+ elevation: 2,
+ },
+ codeLabel: {
+ fontSize: 16,
+ fontWeight: '600',
+ color: Colors.textDark,
+ marginBottom: 20,
+ },
+ qrContainer: {
+ padding: 16,
+ backgroundColor: Colors.background,
+ borderRadius: 12,
+ marginBottom: 20,
+ },
+ codeBox: {
+ backgroundColor: Colors.background,
+ paddingHorizontal: 20,
+ paddingVertical: 12,
+ borderRadius: 10,
+ marginBottom: 20,
+ },
+ codeText: {
+ fontSize: 18,
+ fontWeight: '700',
+ color: Colors.primary,
+ letterSpacing: 1,
+ },
+ actionButtons: {
+ flexDirection: 'row',
+ gap: 12,
+ width: '100%',
+ },
+ actionButton: {
+ flex: 1,
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'center',
+ paddingVertical: 12,
+ borderRadius: 10,
+ backgroundColor: Colors.background,
+ gap: 6,
+ },
+ actionButtonText: {
+ fontSize: 15,
+ fontWeight: '600',
+ color: Colors.primary,
+ },
+ shareButton: {
+ backgroundColor: Colors.primary,
+ },
+ shareButtonText: {
+ fontSize: 15,
+ fontWeight: '600',
+ color: 'white',
+ },
+ statsGrid: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ paddingHorizontal: 20,
+ gap: 12,
+ marginBottom: 24,
+ },
+ statCard: {
+ flex: 1,
+ minWidth: '47%',
+ backgroundColor: 'white',
+ borderRadius: 14,
+ padding: 16,
+ alignItems: 'center',
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 1 },
+ shadowOpacity: 0.04,
+ shadowRadius: 6,
+ elevation: 1,
+ },
+ statValue: {
+ fontSize: 24,
+ fontWeight: '700',
+ color: Colors.textDark,
+ marginTop: 8,
+ marginBottom: 4,
+ },
+ statLabel: {
+ fontSize: 13,
+ color: Colors.textGray,
+ textAlign: 'center',
+ },
+ section: {
+ paddingHorizontal: 20,
+ marginBottom: 24,
+ },
+ sectionTitle: {
+ fontSize: 20,
+ fontWeight: '700',
+ color: Colors.textDark,
+ marginBottom: 12,
+ },
+ tierCard: {
+ backgroundColor: 'white',
+ borderRadius: 14,
+ padding: 16,
+ gap: 12,
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 1 },
+ shadowOpacity: 0.04,
+ shadowRadius: 6,
+ elevation: 1,
+ },
+ tierRow: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: 12,
+ },
+ tierBadge: {
+ backgroundColor: Colors.primary,
+ paddingHorizontal: 12,
+ paddingVertical: 6,
+ borderRadius: 8,
+ minWidth: 70,
+ alignItems: 'center',
+ },
+ tierBadgeText: {
+ fontSize: 13,
+ fontWeight: '700',
+ color: 'white',
+ },
+ tierDescription: {
+ flex: 1,
+ fontSize: 14,
+ color: Colors.textDark,
+ },
+ tierReward: {
+ fontSize: 15,
+ fontWeight: '700',
+ color: Colors.kurdishGold,
+ },
+ referralCard: {
+ backgroundColor: 'white',
+ borderRadius: 14,
+ padding: 16,
+ marginBottom: 12,
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 1 },
+ shadowOpacity: 0.04,
+ shadowRadius: 6,
+ elevation: 1,
+ },
+ referralHeader: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ marginBottom: 12,
+ },
+ avatarCircle: {
+ width: 44,
+ height: 44,
+ borderRadius: 22,
+ backgroundColor: Colors.primary + '20',
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginRight: 12,
+ },
+ avatarText: {
+ fontSize: 18,
+ fontWeight: '700',
+ color: Colors.primary,
+ },
+ referralInfo: {
+ flex: 1,
+ },
+ referralName: {
+ fontSize: 16,
+ fontWeight: '600',
+ color: Colors.textDark,
+ marginBottom: 2,
+ },
+ referralDate: {
+ fontSize: 13,
+ color: Colors.textGray,
+ },
+ statusBadge: {
+ paddingHorizontal: 10,
+ paddingVertical: 4,
+ borderRadius: 8,
+ },
+ statusText: {
+ fontSize: 12,
+ fontWeight: '600',
+ },
+ referralFooter: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ paddingTop: 12,
+ borderTopWidth: 1,
+ borderTopColor: Colors.background,
+ },
+ tierInfo: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: 6,
+ },
+ tierText: {
+ fontSize: 14,
+ color: Colors.textDark,
+ fontWeight: '500',
+ },
+ rewardText: {
+ fontSize: 14,
+ fontWeight: '600',
+ color: Colors.success,
+ },
+ infoCard: {
+ backgroundColor: 'white',
+ borderRadius: 14,
+ padding: 20,
+ gap: 16,
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 1 },
+ shadowOpacity: 0.04,
+ shadowRadius: 6,
+ elevation: 1,
+ },
+ infoRow: {
+ flexDirection: 'row',
+ alignItems: 'flex-start',
+ gap: 12,
+ },
+ stepNumber: {
+ width: 28,
+ height: 28,
+ borderRadius: 14,
+ backgroundColor: Colors.primary,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ stepNumberText: {
+ fontSize: 14,
+ fontWeight: '700',
+ color: 'white',
+ },
+ infoText: {
+ flex: 1,
+ fontSize: 14,
+ color: Colors.textDark,
+ lineHeight: 20,
+ paddingTop: 4,
+ },
+});
+
diff --git a/frontend/src/screens/Wallet/WalletScreen.tsx b/frontend/src/screens/Wallet/WalletScreen.tsx
new file mode 100644
index 00000000..0840b962
--- /dev/null
+++ b/frontend/src/screens/Wallet/WalletScreen.tsx
@@ -0,0 +1,501 @@
+import React, { useState, useEffect } from 'react';
+import SendModal from '../../components/SendModal';
+import ReceiveModal from '../../components/ReceiveModal';
+import {
+ View,
+ Text,
+ StyleSheet,
+ TouchableOpacity,
+ SafeAreaView,
+ ScrollView,
+ TextInput,
+ Image,
+} from 'react-native';
+import { Ionicons } from '@expo/vector-icons';
+import Colors from '../../constants/colors';
+import { Typography, Spacing, BorderRadius, Shadow } from '../../constants/theme';
+
+interface CoinRow {
+ symbol: string;
+ name: string;
+ amount: string;
+ network: string;
+ icon: any;
+ color: string;
+}
+
+export default function WalletScreen({ navigation, route }: any) {
+ const [withdrawalAddresses, setWithdrawalAddresses] = useState<{ [key: string]: string }>({});
+ const [sendModalVisible, setSendModalVisible] = useState(false);
+ const [receiveModalVisible, setReceiveModalVisible] = useState(false);
+ const [selectedToken, setSelectedToken] = useState(null);
+ const [totalReward] = useState('50000');
+ const [trustScore] = useState('150000');
+ const [totalReferral] = useState('500');
+ const [circleScore] = useState('30000');
+ const [eduScore] = useState('1000');
+ const [stakeAmount] = useState('1000');
+
+ const coins: CoinRow[] = [
+ {
+ symbol: 'PEZ',
+ name: 'PezkuwiChain',
+ amount: '100',
+ network: 'op',
+ icon: require('../../../assets/tokens/pez.png'),
+ color: '#E8C896',
+ },
+ {
+ symbol: 'HEZ',
+ name: 'Hemwelatî',
+ amount: '100',
+ network: 'op',
+ icon: require('../../../assets/tokens/hez.png'),
+ color: '#98D8C8',
+ },
+ ];
+
+ const handleWithdraw = (coin: CoinRow) => {
+ setSelectedToken(coin);
+ setSendModalVisible(true);
+ };
+
+ const handleDeposit = (coin: CoinRow) => {
+ setSelectedToken(coin);
+ setReceiveModalVisible(true);
+ };
+
+ return (
+
+ {/* Colorful Top Band */}
+
+
+
+
+
+
+
+
+
+ {/* NFT Card - Top Right */}
+
+
+ NFT
+ 123456784444444444444444912
+
+
+
+
+
+ Satoshi Qazi M.
+
+
+
+ TOTAL REWARD
+ {totalReward}
+
+
+
+ {/* Coins Table */}
+
+ {/* Table Header */}
+
+ coin
+ amount
+ Network
+ Witdrawal adress
+ withdraw deposit
+
+
+ {/* Table Rows */}
+ {coins.map((coin) => (
+
+ {/* Coin */}
+
+
+ {coin.symbol}
+
+
+ {/* Amount */}
+
+ {coin.amount}
+
+
+ {/* Network */}
+
+ {coin.network}
+
+
+ {/* Withdrawal Address */}
+
+
+ setWithdrawalAddresses({ ...withdrawalAddresses, [coin.symbol]: text })
+ }
+ />
+
+
+ {/* Withdraw/Deposit Buttons */}
+
+ handleWithdraw(coin)}
+ >
+
+
+
+
+
+ handleDeposit(coin)}
+ >
+
+
+
+
+
+
+ ))}
+
+
+
+ {/* Bottom Stats Cards */}
+
+ {/* Stake/Unstake Card */}
+
+
+ STAKE
+ {stakeAmount}
+
+
+
+
+
+
+
+
+ UNSTAKE
+ {stakeAmount}
+
+
+
+
+
+
+ {/* Trust Score */}
+ navigation.navigate('TrustScore')}
+ >
+
+ TRUST SCORE
+ {trustScore}
+
+
+ {/* Total Referral */}
+ navigation.navigate('Referral')}
+ >
+
+ TOTAL REFERAL
+ {totalReferral}
+
+
+ {/* Circle Score */}
+
+
+ CIRCLE SCORE
+ {circleScore}
+
+
+ {/* Edu Score */}
+ navigation.navigate('Education')}
+ >
+
+ EDU. SCORE
+ {eduScore}
+
+
+
+
+ {/* Send Modal */}
+ {selectedToken && (
+ setSendModalVisible(false)}
+ token={{
+ symbol: selectedToken.symbol,
+ name: selectedToken.name,
+ balance: selectedToken.amount,
+ icon: selectedToken.icon,
+ color: selectedToken.color,
+ }}
+ />
+ )}
+
+ {/* Receive Modal */}
+ {selectedToken && (
+ setReceiveModalVisible(false)}
+ token={{
+ symbol: selectedToken.symbol,
+ name: selectedToken.name,
+ icon: selectedToken.icon,
+ color: selectedToken.color,
+ }}
+ />
+ )}
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: '#E8F0F7',
+ },
+ topBand: {
+ flexDirection: 'row',
+ height: 8,
+ },
+ bandSegment: {
+ flex: 1,
+ },
+ content: {
+ flex: 1,
+ },
+ mainSection: {
+ padding: Spacing.lg,
+ position: 'relative',
+ },
+ nftCard: {
+ position: 'absolute',
+ top: Spacing.lg,
+ right: Spacing.lg,
+ width: 140,
+ backgroundColor: '#FFFFFF',
+ borderRadius: BorderRadius.large,
+ padding: Spacing.md,
+ ...Shadow.medium,
+ zIndex: 10,
+ },
+ nftHeader: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ marginBottom: Spacing.sm,
+ },
+ nftLabel: {
+ fontSize: 12,
+ fontWeight: '700',
+ color: Colors.textDark,
+ },
+ nftId: {
+ fontSize: 8,
+ color: Colors.textGray,
+ },
+ nftBody: {
+ alignItems: 'center',
+ marginVertical: Spacing.sm,
+ },
+ nftAvatar: {
+ width: 60,
+ height: 60,
+ borderRadius: 30,
+ backgroundColor: Colors.teal,
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginBottom: Spacing.xs,
+ },
+ nftName: {
+ fontSize: 11,
+ fontWeight: '600',
+ color: Colors.textDark,
+ textAlign: 'center',
+ },
+ nftFooter: {
+ alignItems: 'center',
+ borderTopWidth: 1,
+ borderTopColor: '#F0F0F0',
+ paddingTop: Spacing.sm,
+ },
+ nftRewardLabel: {
+ fontSize: 9,
+ fontWeight: '600',
+ color: Colors.textGray,
+ marginTop: 4,
+ },
+ nftRewardValue: {
+ fontSize: 16,
+ fontWeight: '700',
+ color: Colors.textDark,
+ marginTop: 2,
+ },
+ tableContainer: {
+ backgroundColor: '#FFFFFF',
+ borderRadius: BorderRadius.large,
+ padding: Spacing.md,
+ marginRight: 160,
+ ...Shadow.small,
+ },
+ tableHeader: {
+ flexDirection: 'row',
+ paddingBottom: Spacing.sm,
+ borderBottomWidth: 2,
+ borderBottomColor: '#E0E0E0',
+ marginBottom: Spacing.sm,
+ },
+ headerCell: {
+ fontSize: 11,
+ fontWeight: '700',
+ color: Colors.textDark,
+ textAlign: 'center',
+ },
+ tableRow: {
+ flexDirection: 'row',
+ paddingVertical: Spacing.md,
+ borderBottomWidth: 1,
+ borderBottomColor: '#F0F0F0',
+ alignItems: 'center',
+ },
+ cell: {
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ coinIcon: {
+ width: 32,
+ height: 32,
+ marginBottom: 4,
+ },
+ coinSymbol: {
+ fontSize: 12,
+ fontWeight: '700',
+ color: Colors.textDark,
+ marginTop: 2,
+ },
+ cellText: {
+ fontSize: 12,
+ fontWeight: '600',
+ color: Colors.textDark,
+ },
+ addressInput: {
+ flex: 1,
+ backgroundColor: '#F5F5F5',
+ borderRadius: BorderRadius.small,
+ paddingHorizontal: Spacing.sm,
+ paddingVertical: Spacing.xs,
+ fontSize: 10,
+ color: Colors.textDark,
+ },
+ actionButton: {
+ width: 32,
+ height: 32,
+ borderRadius: 8,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ withdrawButton: {
+ width: '100%',
+ height: '100%',
+ backgroundColor: '#E74C3C',
+ borderRadius: 8,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ depositButton: {
+ width: '100%',
+ height: '100%',
+ backgroundColor: '#27AE60',
+ borderRadius: 8,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ statsSection: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ padding: Spacing.lg,
+ gap: Spacing.md,
+ },
+ statsCard: {
+ backgroundColor: '#F5F5F5',
+ borderRadius: BorderRadius.large,
+ padding: Spacing.lg,
+ ...Shadow.small,
+ },
+ stakeButton: {
+ alignItems: 'center',
+ },
+ stakeLabel: {
+ fontSize: 12,
+ fontWeight: '700',
+ color: Colors.textDark,
+ },
+ stakeValue: {
+ fontSize: 18,
+ fontWeight: '700',
+ color: Colors.textDark,
+ marginVertical: Spacing.xs,
+ },
+ stakeIcon: {
+ width: 28,
+ height: 28,
+ borderRadius: 14,
+ backgroundColor: '#27AE60',
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ stakeDivider: {
+ height: 1,
+ backgroundColor: '#E0E0E0',
+ marginVertical: Spacing.md,
+ },
+ unstakeButton: {
+ alignItems: 'center',
+ },
+ unstakeLabel: {
+ fontSize: 12,
+ fontWeight: '700',
+ color: Colors.textDark,
+ },
+ unstakeValue: {
+ fontSize: 18,
+ fontWeight: '700',
+ color: Colors.textDark,
+ marginVertical: Spacing.xs,
+ },
+ unstakeIcon: {
+ width: 28,
+ height: 28,
+ borderRadius: 14,
+ backgroundColor: '#E74C3C',
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ scoreCard: {
+ alignItems: 'center',
+ minWidth: 110,
+ },
+ scoreLabel: {
+ fontSize: 10,
+ fontWeight: '700',
+ color: Colors.textDark,
+ marginTop: Spacing.sm,
+ textAlign: 'center',
+ },
+ scoreValue: {
+ fontSize: 20,
+ fontWeight: '700',
+ color: Colors.textDark,
+ marginTop: Spacing.xs,
+ },
+});
+
diff --git a/frontend/src/screens/Wallet/WalletScreen_old.tsx b/frontend/src/screens/Wallet/WalletScreen_old.tsx
new file mode 100644
index 00000000..56b8f403
--- /dev/null
+++ b/frontend/src/screens/Wallet/WalletScreen_old.tsx
@@ -0,0 +1,98 @@
+import React from 'react';
+import { View, Text, StyleSheet, TouchableOpacity, ScrollView, SafeAreaView } from 'react-native';
+import { LinearGradient } from 'expo-linear-gradient';
+import { Ionicons } from '@expo/vector-icons';
+import Colors from '../../constants/colors';
+import { Typography, Spacing, BorderRadius, Shadow } from '../../constants/theme';
+
+export default function WalletScreen({ navigation }: any) {
+ return (
+
+
+ Wallet
+
+ {/* HEZ Card */}
+
+
+ HEZ
+ The People's Currency
+
+ 45,750.5
+ $45,234 USD
+ Staked: 30,000 HEZ
+
+
+ {/* PEZ Card */}
+
+
+ PEZ
+ Governance Token
+
+ 1,234,567
+ $123,456 USD
+ Governance Power: 2.5%
+
+
+ {/* Action Buttons */}
+
+
+
+ Send
+
+
+
+ Receive
+
+
+
+ {/* Transactions */}
+
+ Recent Transactions
+
+
+
+
+
+ Sent HEZ
+ Yesterday
+
+ -500 HEZ
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: { flex: 1, backgroundColor: Colors.background },
+ title: { fontSize: 28, fontWeight: '700', color: Colors.textDark, padding: 20 },
+ tokenCard: { margin: 20, padding: 24, borderRadius: 20, ...Shadow.soft },
+ tokenHeader: { marginBottom: 16 },
+ tokenName: { fontSize: 24, fontWeight: '700', color: '#FFFFFF' },
+ tokenSubtitle: { fontSize: 14, color: 'rgba(255,255,255,0.8)' },
+ tokenBalance: { fontSize: 36, fontWeight: '700', color: '#FFFFFF', marginBottom: 8 },
+ tokenUsd: { fontSize: 18, color: 'rgba(255,255,255,0.9)', marginBottom: 8 },
+ tokenStaked: { fontSize: 14, color: 'rgba(255,255,255,0.8)' },
+ actions: { flexDirection: 'row', paddingHorizontal: 20, gap: 12 },
+ actionButton: { flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: 'center', padding: 16, borderRadius: 16, gap: 8 },
+ actionText: { fontSize: 16, fontWeight: '600', color: '#FFFFFF' },
+ section: { padding: 20 },
+ sectionTitle: { fontSize: 18, fontWeight: '600', color: Colors.textDark, marginBottom: 16 },
+ transactionItem: { flexDirection: 'row', alignItems: 'center', backgroundColor: Colors.card, padding: 16, borderRadius: 12, marginBottom: 12 },
+ transactionIcon: { width: 40, height: 40, borderRadius: 20, backgroundColor: Colors.background, justifyContent: 'center', alignItems: 'center', marginRight: 12 },
+ transactionInfo: { flex: 1 },
+ transactionTitle: { fontSize: 16, fontWeight: '600', color: Colors.textDark },
+ transactionDate: { fontSize: 14, color: Colors.textGray, marginTop: 4 },
+ transactionAmount: { fontSize: 16, fontWeight: '600', color: Colors.coral },
+});
diff --git a/frontend/src/services/blockchain.ts b/frontend/src/services/blockchain.ts
new file mode 100644
index 00000000..dd4368a2
--- /dev/null
+++ b/frontend/src/services/blockchain.ts
@@ -0,0 +1,307 @@
+/**
+ * PezkuwiChain Blockchain Service
+ * Handles all interactions with the PezkuwiChain blockchain via Polkadot.js
+ */
+
+import { ApiPromise, WsProvider } from '@polkadot/api';
+import { CURRENT_CHAIN_CONFIG, ASSET_IDS } from '../constants/blockchain';
+import { Balance, Transaction, Proposal } from '../types';
+
+class BlockchainService {
+ private api: ApiPromise | null = null;
+ private provider: WsProvider | null = null;
+ private isConnected: boolean = false;
+
+ /**
+ * Initialize connection to PezkuwiChain
+ */
+ async connect(): Promise {
+ try {
+ console.log(`Connecting to ${CURRENT_CHAIN_CONFIG.name}...`);
+ console.log(`RPC URL: ${CURRENT_CHAIN_CONFIG.rpcUrl}`);
+
+ this.provider = new WsProvider(CURRENT_CHAIN_CONFIG.rpcUrl);
+ this.api = await ApiPromise.create({ provider: this.provider });
+
+ await this.api.isReady;
+ this.isConnected = true;
+
+ console.log('✅ Connected to PezkuwiChain');
+ console.log(`Chain: ${await this.api.rpc.system.chain()}`);
+ console.log(`Node: ${await this.api.rpc.system.name()}`);
+ console.log(`Version: ${await this.api.rpc.system.version()}`);
+
+ return true;
+ } catch (error) {
+ console.error('❌ Failed to connect to PezkuwiChain:', error);
+ this.isConnected = false;
+ return false;
+ }
+ }
+
+ /**
+ * Disconnect from blockchain
+ */
+ async disconnect(): Promise {
+ if (this.api) {
+ await this.api.disconnect();
+ this.api = null;
+ this.provider = null;
+ this.isConnected = false;
+ console.log('Disconnected from PezkuwiChain');
+ }
+ }
+
+ /**
+ * Check if connected to blockchain
+ */
+ isApiConnected(): boolean {
+ return this.isConnected && this.api !== null;
+ }
+
+ /**
+ * Get API instance (throws if not connected)
+ */
+ private getApi(): ApiPromise {
+ if (!this.api || !this.isConnected) {
+ throw new Error('Not connected to blockchain. Call connect() first.');
+ }
+ return this.api;
+ }
+
+ /**
+ * Get account balances (HEZ and PEZ)
+ */
+ async getBalances(address: string): Promise {
+ try {
+ const api = this.getApi();
+
+ // Get HEZ balance (native token)
+ const { data: hezBalance } = await api.query.system.account(address);
+ const hezFree = hezBalance.free.toString();
+ const hezReserved = hezBalance.reserved.toString();
+
+ // Get PEZ balance (asset)
+ const pezBalance = await api.query.assets.account(ASSET_IDS.PEZ, address);
+ const pezFree = pezBalance.isSome ? pezBalance.unwrap().balance.toString() : '0';
+
+ // Get staked HEZ
+ const stakingInfo = await api.query.staking.ledger(address);
+ const hezStaked = stakingInfo.isSome ? stakingInfo.unwrap().active.toString() : '0';
+
+ // Calculate governance power (PEZ balance as percentage)
+ const totalPezSupply = '5000000000000000000000'; // 5 billion
+ const governancePower = (parseFloat(pezFree) / parseFloat(totalPezSupply) * 100).toFixed(2);
+
+ // Mock USD values (would come from price oracle in production)
+ const hezUsd = (parseFloat(hezFree) / 1e12 * 1.0).toFixed(2);
+ const pezUsd = (parseFloat(pezFree) / 1e12 * 0.1).toFixed(2);
+
+ return {
+ hez: this.formatBalance(hezFree, 12),
+ pez: this.formatBalance(pezFree, 12),
+ hezStaked: this.formatBalance(hezStaked, 12),
+ hezUsd,
+ pezUsd,
+ governancePower,
+ };
+ } catch (error) {
+ console.error('Error fetching balances:', error);
+ // Return mock data if blockchain not available
+ return this.getMockBalances();
+ }
+ }
+
+ /**
+ * Get transaction history
+ */
+ async getTransactions(address: string, limit: number = 10): Promise {
+ try {
+ // This would query blockchain events and filter for transfers
+ // For now, return mock data
+ return this.getMockTransactions();
+ } catch (error) {
+ console.error('Error fetching transactions:', error);
+ return this.getMockTransactions();
+ }
+ }
+
+ /**
+ * Get active governance proposals
+ */
+ async getProposals(): Promise {
+ try {
+ const api = this.getApi();
+
+ // Query welati pallet for active proposals
+ const proposals = await api.query.welati.proposals.entries();
+
+ return proposals.map(([key, value]: any) => {
+ const proposalId = key.args[0].toNumber();
+ const proposal = value.unwrap();
+
+ return {
+ id: proposalId,
+ title: `Proposal ${proposalId}`,
+ description: proposal.description?.toString() || 'No description',
+ proposer: proposal.proposer.toString(),
+ votingDeadline: proposal.deadline.toNumber(),
+ yesVotes: proposal.yesVotes.toString(),
+ noVotes: proposal.noVotes.toString(),
+ status: proposal.status.toString() as any,
+ };
+ });
+ } catch (error) {
+ console.error('Error fetching proposals:', error);
+ return this.getMockProposals();
+ }
+ }
+
+ /**
+ * Send HEZ or PEZ tokens
+ */
+ async sendTokens(
+ from: string,
+ to: string,
+ amount: string,
+ token: 'HEZ' | 'PEZ',
+ signer: any
+ ): Promise {
+ try {
+ const api = this.getApi();
+
+ let tx;
+ if (token === 'HEZ') {
+ tx = api.tx.balances.transfer(to, amount);
+ } else {
+ tx = api.tx.assets.transfer(ASSET_IDS.PEZ, to, amount);
+ }
+
+ const hash = await tx.signAndSend(signer);
+ return hash.toString();
+ } catch (error) {
+ console.error('Error sending tokens:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Stake HEZ tokens
+ */
+ async stakeTokens(
+ address: string,
+ amount: string,
+ signer: any
+ ): Promise {
+ try {
+ const api = this.getApi();
+ const tx = api.tx.staking.bond(address, amount, 'Staked');
+ const hash = await tx.signAndSend(signer);
+ return hash.toString();
+ } catch (error) {
+ console.error('Error staking tokens:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Vote on governance proposal
+ */
+ async voteOnProposal(
+ proposalId: number,
+ vote: 'yes' | 'no',
+ amount: string,
+ signer: any
+ ): Promise {
+ try {
+ const api = this.getApi();
+ const tx = api.tx.welati.vote(proposalId, vote === 'yes', amount);
+ const hash = await tx.signAndSend(signer);
+ return hash.toString();
+ } catch (error) {
+ console.error('Error voting on proposal:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Format balance with decimals
+ */
+ private formatBalance(balance: string, decimals: number): string {
+ const value = parseFloat(balance) / Math.pow(10, decimals);
+ return value.toLocaleString('en-US', { maximumFractionDigits: 2 });
+ }
+
+ /**
+ * Mock data for development/testing
+ */
+ private getMockBalances(): Balance {
+ return {
+ hez: '45,750.5',
+ pez: '1,234,567',
+ hezStaked: '30,000',
+ hezUsd: '45,234',
+ pezUsd: '123,456',
+ governancePower: '2.5',
+ };
+ }
+
+ private getMockTransactions(): Transaction[] {
+ return [
+ {
+ id: '1',
+ type: 'send' as any,
+ amount: '500',
+ token: 'HEZ',
+ from: '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
+ to: '5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty',
+ timestamp: Date.now() - 86400000,
+ blockNumber: 123456,
+ hash: '0x1234567890abcdef',
+ status: 'confirmed',
+ },
+ {
+ id: '2',
+ type: 'receive' as any,
+ amount: '300',
+ token: 'PEZ',
+ from: '5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty',
+ to: '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
+ timestamp: Date.now() - 172800000,
+ blockNumber: 123450,
+ hash: '0xabcdef1234567890',
+ status: 'confirmed',
+ },
+ ];
+ }
+
+ private getMockProposals(): Proposal[] {
+ return [
+ {
+ id: 1,
+ title: 'Proposal 1',
+ description: 'Description of proposal 1',
+ proposer: '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
+ votingDeadline: Date.now() + 172800000,
+ yesVotes: '10400',
+ noVotes: '4600',
+ status: 'active',
+ },
+ {
+ id: 2,
+ title: 'Proposal 2',
+ description: 'Description of proposal 2',
+ proposer: '5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty',
+ votingDeadline: Date.now() + 432000000,
+ yesVotes: '198',
+ noVotes: '0',
+ status: 'active',
+ },
+ ];
+ }
+}
+
+// Export singleton instance
+export const blockchainService = new BlockchainService();
+export default blockchainService;
+
diff --git a/frontend/src/services/kycService.ts b/frontend/src/services/kycService.ts
new file mode 100644
index 00000000..ea83d321
--- /dev/null
+++ b/frontend/src/services/kycService.ts
@@ -0,0 +1,262 @@
+/**
+ * KYC Service
+ * Handles Identity-KYC form submission, encryption, and blockchain interaction
+ */
+
+import * as SecureStore from 'expo-secure-store';
+import { KYCFormData, KYCSubmission, KurdistanCitizen, KYCStatus } from '../types/kyc';
+import { blockchainService } from './blockchain';
+
+const KYC_DATA_KEY = 'pezkuwi_kyc_data';
+const CITIZEN_DATA_KEY = 'pezkuwi_citizen_data';
+const KYC_STATUS_KEY = 'pezkuwi_kyc_status';
+
+class KYCService {
+ /**
+ * Generate hash from KYC data
+ * This hash will be submitted to blockchain
+ */
+ private async generateHash(data: KYCFormData): Promise {
+ // In production, use proper cryptographic hash (SHA-256)
+ const dataString = JSON.stringify(data);
+
+ // Simple hash for development (replace with proper crypto in production)
+ let hash = 0;
+ for (let i = 0; i < dataString.length; i++) {
+ const char = dataString.charCodeAt(i);
+ hash = (hash << 5) - hash + char;
+ hash = hash & hash;
+ }
+
+ return `0x${Math.abs(hash).toString(16).padStart(64, '0')}`;
+ }
+
+ /**
+ * Save KYC form data locally (encrypted)
+ */
+ async saveKYCData(data: KYCFormData): Promise {
+ try {
+ const encrypted = JSON.stringify(data);
+ await SecureStore.setItemAsync(KYC_DATA_KEY, encrypted);
+ console.log('✅ KYC data saved locally (encrypted)');
+ } catch (error) {
+ console.error('❌ Failed to save KYC data:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Get saved KYC data
+ */
+ async getKYCData(): Promise {
+ try {
+ const encrypted = await SecureStore.getItemAsync(KYC_DATA_KEY);
+ if (!encrypted) return null;
+
+ return JSON.parse(encrypted);
+ } catch (error) {
+ console.error('❌ Failed to get KYC data:', error);
+ return null;
+ }
+ }
+
+ /**
+ * Submit KYC to blockchain
+ * Only hash is sent, not the actual data
+ */
+ async submitKYC(data: KYCFormData, signer: any): Promise {
+ try {
+ // 1. Save data locally first
+ await this.saveKYCData(data);
+
+ // 2. Generate hash
+ const dataHash = await this.generateHash(data);
+ console.log('📝 Generated KYC hash:', dataHash);
+
+ // 3. Submit hash to blockchain (identity-kyc pallet)
+ // TODO: Replace with actual blockchain call when testnet is active
+ const txHash = await this.submitHashToBlockchain(dataHash, signer);
+
+ const submission: KYCSubmission = {
+ dataHash,
+ submittedAt: Date.now(),
+ txHash,
+ };
+
+ // 4. Update KYC status
+ await this.updateKYCStatus({ started: true, submitted: true, approved: false });
+
+ console.log('✅ KYC submitted to blockchain');
+ return submission;
+ } catch (error) {
+ console.error('❌ Failed to submit KYC:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Submit hash to blockchain (identity-kyc pallet)
+ */
+ private async submitHashToBlockchain(dataHash: string, signer: any): Promise {
+ try {
+ // Check if blockchain is connected
+ if (!blockchainService.isApiConnected()) {
+ console.log('⚠️ Blockchain not connected, using mock submission');
+ // Mock transaction hash for development
+ return `0x${Math.random().toString(16).substr(2, 64)}`;
+ }
+
+ // TODO: Actual blockchain submission
+ // const api = blockchainService.getApi();
+ // const tx = api.tx.identityKyc.submitKyc(dataHash);
+ // const hash = await tx.signAndSend(signer);
+ // return hash.toString();
+
+ // Mock for now
+ return `0x${Math.random().toString(16).substr(2, 64)}`;
+ } catch (error) {
+ console.error('❌ Failed to submit to blockchain:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Check KYC approval status on blockchain
+ */
+ async checkApprovalStatus(address: string): Promise {
+ try {
+ // TODO: Query blockchain for approval status
+ // const api = blockchainService.getApi();
+ // const approval = await api.query.identityKyc.approvals(address);
+ // return approval.isSome;
+
+ // Mock: Auto-approve after 5 seconds (for development)
+ const status = await this.getKYCStatus();
+ if (status.submitted) {
+ const timeSinceSubmission = Date.now() - (status.citizen?.approvedAt || 0);
+ return timeSinceSubmission > 5000; // 5 seconds
+ }
+
+ return false;
+ } catch (error) {
+ console.error('❌ Failed to check approval status:', error);
+ return false;
+ }
+ }
+
+ /**
+ * Generate Kurdistan Digital Citizen certificate
+ * Called after KYC is approved on blockchain
+ */
+ async generateCitizen(data: KYCFormData, dataHash: string): Promise {
+ try {
+ // Generate unique Citizen ID
+ const citizenId = `KRD-${Date.now()}-${Math.random().toString(36).substr(2, 9).toUpperCase()}`;
+
+ // Generate QR code data
+ const qrData = JSON.stringify({
+ citizenId,
+ name: data.fullName,
+ region: data.region,
+ hash: dataHash,
+ });
+
+ const citizen: KurdistanCitizen = {
+ citizenId,
+ fullName: data.fullName,
+ photo: data.photo || '',
+ region: data.region,
+ kycApproved: true,
+ approvedAt: Date.now(),
+ dataHash,
+ qrCode: qrData,
+ };
+
+ // Save citizen data locally (encrypted)
+ await SecureStore.setItemAsync(CITIZEN_DATA_KEY, JSON.stringify(citizen));
+
+ // Update KYC status
+ await this.updateKYCStatus({
+ started: true,
+ submitted: true,
+ approved: true,
+ citizen,
+ });
+
+ console.log('✅ Kurdistan Digital Citizen generated:', citizenId);
+ return citizen;
+ } catch (error) {
+ console.error('❌ Failed to generate citizen:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Get citizen data
+ */
+ async getCitizen(): Promise {
+ try {
+ const data = await SecureStore.getItemAsync(CITIZEN_DATA_KEY);
+ if (!data) return null;
+
+ return JSON.parse(data);
+ } catch (error) {
+ console.error('❌ Failed to get citizen data:', error);
+ return null;
+ }
+ }
+
+ /**
+ * Get KYC status
+ */
+ async getKYCStatus(): Promise {
+ try {
+ const statusData = await SecureStore.getItemAsync(KYC_STATUS_KEY);
+ if (!statusData) {
+ return { started: false, submitted: false, approved: false };
+ }
+
+ return JSON.parse(statusData);
+ } catch (error) {
+ console.error('❌ Failed to get KYC status:', error);
+ return { started: false, submitted: false, approved: false };
+ }
+ }
+
+ /**
+ * Update KYC status
+ */
+ private async updateKYCStatus(status: KYCStatus): Promise {
+ try {
+ await SecureStore.setItemAsync(KYC_STATUS_KEY, JSON.stringify(status));
+ } catch (error) {
+ console.error('❌ Failed to update KYC status:', error);
+ }
+ }
+
+ /**
+ * Check if user has access to Governance
+ */
+ async hasGovernanceAccess(): Promise {
+ const status = await this.getKYCStatus();
+ return status.approved;
+ }
+
+ /**
+ * Clear all KYC data (for testing)
+ */
+ async clearKYCData(): Promise {
+ try {
+ await SecureStore.deleteItemAsync(KYC_DATA_KEY);
+ await SecureStore.deleteItemAsync(CITIZEN_DATA_KEY);
+ await SecureStore.deleteItemAsync(KYC_STATUS_KEY);
+ console.log('✅ KYC data cleared');
+ } catch (error) {
+ console.error('❌ Failed to clear KYC data:', error);
+ }
+ }
+}
+
+export const kycService = new KYCService();
+export default kycService;
+
diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts
new file mode 100644
index 00000000..810fa5ce
--- /dev/null
+++ b/frontend/src/types/index.ts
@@ -0,0 +1,197 @@
+/**
+ * PezkuwiChain Mobile App - Type Definitions
+ */
+
+// User Types
+export interface User {
+ id: string;
+ name: string;
+ email: string;
+ address: string;
+ trustScore: number;
+ kycLevel: number;
+ avatar?: string;
+}
+
+// Balance Types
+export interface Balance {
+ hez: string;
+ pez: string;
+ hezStaked: string;
+ hezUsd: string;
+ pezUsd: string;
+ governancePower: string;
+}
+
+// Transaction Types
+export enum TransactionType {
+ SEND = 'send',
+ RECEIVE = 'receive',
+ STAKE = 'stake',
+ UNSTAKE = 'unstake',
+ REWARD = 'reward',
+ GOVERNANCE = 'governance',
+}
+
+export interface Transaction {
+ id: string;
+ type: TransactionType;
+ amount: string;
+ token: 'HEZ' | 'PEZ';
+ from: string;
+ to: string;
+ timestamp: number;
+ blockNumber: number;
+ hash: string;
+ status: 'pending' | 'confirmed' | 'failed';
+}
+
+// Governance Types
+export interface Proposal {
+ id: number;
+ title: string;
+ description: string;
+ proposer: string;
+ votingDeadline: number;
+ yesVotes: string;
+ noVotes: string;
+ status: 'active' | 'passed' | 'rejected' | 'executed';
+}
+
+export interface Vote {
+ proposalId: number;
+ voter: string;
+ vote: 'yes' | 'no';
+ amount: string;
+ conviction: number;
+ timestamp: number;
+}
+
+// Parliamentary NFT Types
+export interface ParliamentaryNFT {
+ tokenId: number;
+ owner: string;
+ monthlySalary: string;
+ electionDate: number;
+ termEnd: number;
+ status: 'active' | 'inactive';
+}
+
+// Identity Types
+export interface DigitalIdentity {
+ idNumber: string;
+ name: string;
+ photo: string;
+ trustScore: number;
+ kycLevel: number;
+ verifications: {
+ identity: boolean;
+ education: boolean;
+ kyc: boolean;
+ };
+ qrCode: string;
+}
+
+// Education Certificate Types
+export interface Certificate {
+ id: string;
+ title: string;
+ institution: string;
+ issueDate: number;
+ certificateType: 'bachelor' | 'master' | 'phd' | 'diploma' | 'certificate';
+ verified: boolean;
+ nftId?: number;
+ qrCode: string;
+}
+
+// Referral Types
+export interface Referral {
+ code: string;
+ totalReferrals: number;
+ activeReferrals: number;
+ rewardsEarned: string;
+ referrals: ReferralUser[];
+}
+
+export interface ReferralUser {
+ name: string;
+ avatar: string;
+ joinDate: number;
+ reward: string;
+ status: 'active' | 'inactive';
+}
+
+// Business Types
+export interface MerchantDashboard {
+ monthlyRevenue: string;
+ transactions: number;
+ customers: number;
+ recentTransactions: MerchantTransaction[];
+}
+
+export interface MerchantTransaction {
+ customerName: string;
+ amount: string;
+ token: 'HEZ' | 'PEZ';
+ timestamp: number;
+}
+
+// Exchange Types
+export interface ExchangeRate {
+ from: 'HEZ' | 'PEZ';
+ to: 'HEZ' | 'PEZ';
+ rate: number;
+ timestamp: number;
+}
+
+export interface SwapTransaction {
+ fromToken: 'HEZ' | 'PEZ';
+ toToken: 'HEZ' | 'PEZ';
+ fromAmount: string;
+ toAmount: string;
+ rate: number;
+ slippage: number;
+ timestamp: number;
+}
+
+// Navigation Types
+export type RootStackParamList = {
+ LanguageSelection: undefined;
+ SignIn: undefined;
+ SignUp: undefined;
+ MainTabs: undefined;
+ Send: { token: 'HEZ' | 'PEZ' };
+ Receive: { token: 'HEZ' | 'PEZ' };
+ ProposalDetail: { proposalId: number };
+ CertificateDetail: { certificateId: string };
+ QRScanner: undefined;
+};
+
+export type MainTabsParamList = {
+ Home: undefined;
+ Wallet: undefined;
+ Governance: undefined;
+ Referral: undefined;
+ Profile: undefined;
+};
+
+// Blockchain Types
+export interface ChainConfig {
+ name: string;
+ rpcUrl: string;
+ chainId: string;
+ genesisHash: string;
+ decimals: {
+ hez: number;
+ pez: number;
+ };
+}
+
+// API Response Types
+export interface ApiResponse {
+ success: boolean;
+ data?: T;
+ error?: string;
+ message?: string;
+}
+
diff --git a/frontend/src/types/kyc.ts b/frontend/src/types/kyc.ts
new file mode 100644
index 00000000..a5f9a8d7
--- /dev/null
+++ b/frontend/src/types/kyc.ts
@@ -0,0 +1,89 @@
+/**
+ * Identity KYC Types
+ */
+
+export type Region = 'basur' | 'bakur' | 'rojava' | 'rojhelat' | 'kurdistan_a_sor' | 'diaspora';
+
+export type MaritalStatus = 'single' | 'married';
+
+export interface Child {
+ name: string;
+ order: number; // 1st child, 2nd child, etc.
+}
+
+export interface KYCFormData {
+ // Personal Information
+ fullName: string;
+ fatherName: string;
+ grandfatherName: string;
+ greatGrandfatherName: string;
+ motherName: string;
+
+ // Marital Status
+ maritalStatus: MaritalStatus;
+ spouseName?: string;
+ numberOfChildren?: number;
+ children?: Child[];
+
+ // Region
+ region: Region;
+
+ // Photo (base64 or file URI)
+ photo?: string;
+}
+
+export interface KYCSubmission {
+ // Hash of the KYC data (sent to blockchain)
+ dataHash: string;
+
+ // Timestamp
+ submittedAt: number;
+
+ // Blockchain transaction hash
+ txHash?: string;
+}
+
+export interface KurdistanCitizen {
+ // Citizen ID (generated after KYC approval)
+ citizenId: string;
+
+ // Personal Info (stored locally, encrypted)
+ fullName: string;
+ photo: string;
+ region: Region;
+
+ // KYC Status
+ kycApproved: boolean;
+ approvedAt: number;
+
+ // Blockchain reference (only hash)
+ dataHash: string;
+
+ // QR Code for verification
+ qrCode: string;
+}
+
+export interface KYCStatus {
+ // Has user started KYC?
+ started: boolean;
+
+ // Has user submitted KYC?
+ submitted: boolean;
+
+ // Is KYC approved on blockchain?
+ approved: boolean;
+
+ // Citizen data (only if approved)
+ citizen?: KurdistanCitizen;
+}
+
+// Region labels for UI
+export const REGION_LABELS: Record = {
+ basur: { en: 'Başur (South Kurdistan)', ku: 'باشوور (کوردستانی باشوور)' },
+ bakur: { en: 'Bakur (North Kurdistan)', ku: 'باکوور (کوردستانی باکوور)' },
+ rojava: { en: 'Rojava (West Kurdistan)', ku: 'رۆژاڤا (کوردستانی رۆژاڤا)' },
+ rojhelat: { en: 'Rojhelat (East Kurdistan)', ku: 'رۆژهەڵات (کوردستانی رۆژهەڵات)' },
+ kurdistan_a_sor: { en: 'Kurdistan a Sor (Red Kurdistan)', ku: 'کوردستانا سور' },
+ diaspora: { en: 'Diaspora', ku: 'دیاسپۆرا' },
+};
+