diff --git a/frontend/src/components/ReceiveModal.tsx b/frontend/src/components/ReceiveModal.tsx deleted file mode 100644 index 5ae96243..00000000 --- a/frontend/src/components/ReceiveModal.tsx +++ /dev/null @@ -1,225 +0,0 @@ -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 deleted file mode 100644 index 62cdfd9d..00000000 --- a/frontend/src/components/SendModal.tsx +++ /dev/null @@ -1,300 +0,0 @@ -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 deleted file mode 100644 index 56b37cb9..00000000 --- a/frontend/src/constants/blockchain.ts +++ /dev/null @@ -1,92 +0,0 @@ -/** - * 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 deleted file mode 100644 index 5a87bc95..00000000 --- a/frontend/src/constants/colors.ts +++ /dev/null @@ -1,57 +0,0 @@ -/** - * 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 deleted file mode 100644 index 3101e58b..00000000 --- a/frontend/src/constants/theme.ts +++ /dev/null @@ -1,87 +0,0 @@ -/** - * 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/contexts/PolkadotContext.tsx b/frontend/src/contexts/PolkadotContext.tsx deleted file mode 100644 index 0c517d5a..00000000 --- a/frontend/src/contexts/PolkadotContext.tsx +++ /dev/null @@ -1,114 +0,0 @@ -import React, { createContext, useContext, useEffect, useState, ReactNode } from 'react'; -import { Platform } from 'react-native'; -import AsyncStorage from '@react-native-async-storage/async-storage'; - -// ======================================== -// TYPES - Simplified for backend proxy approach -// ======================================== - -export interface Account { - address: string; - name?: string; -} - -interface PolkadotContextType { - // No API connection - using backend proxy instead - accounts: Account[]; - selectedAccount: Account | null; - setSelectedAccount: (account: Account | null) => void; - saveAccount: (account: Account) => Promise; - error: string | null; -} - -const PolkadotContext = createContext(undefined); - -// ======================================== -// PROVIDER - Simplified localStorage only -// ======================================== - -interface PolkadotProviderProps { - children: ReactNode; -} - -export const PolkadotProvider: React.FC = ({ children }) => { - const [accounts, setAccounts] = useState([]); - const [selectedAccount, setSelectedAccount] = useState(null); - const [error, setError] = useState(null); - - // Load saved accounts from AsyncStorage - useEffect(() => { - loadAccounts(); - }, []); - - const loadAccounts = async () => { - try { - const savedAccounts = await AsyncStorage.getItem('pezkuwi_accounts'); - if (savedAccounts) { - const parsedAccounts = JSON.parse(savedAccounts); - setAccounts(parsedAccounts); - - // Auto-select first account if available - if (parsedAccounts.length > 0) { - setSelectedAccount(parsedAccounts[0]); - } - } - } catch (error) { - console.error('Error loading accounts:', error); - setError('Failed to load accounts'); - } - }; - - // Save account to AsyncStorage - const saveAccount = async (account: Account) => { - try { - // Check if account already exists - const existingIndex = accounts.findIndex(acc => acc.address === account.address); - - let updatedAccounts: Account[]; - if (existingIndex >= 0) { - // Update existing account - updatedAccounts = [...accounts]; - updatedAccounts[existingIndex] = account; - } else { - // Add new account - updatedAccounts = [...accounts, account]; - } - - setAccounts(updatedAccounts); - setSelectedAccount(account); - - await AsyncStorage.setItem('pezkuwi_accounts', JSON.stringify(updatedAccounts)); - - console.log('✅ Account saved:', account.address); - } catch (error) { - console.error('Error saving account:', error); - setError('Failed to save account'); - } - }; - - const value: PolkadotContextType = { - accounts, - selectedAccount, - setSelectedAccount, - saveAccount, - error, - }; - - return ( - - {children} - - ); -}; - -// ======================================== -// HOOK -// ======================================== - -export const usePolkadot = (): PolkadotContextType => { - const context = useContext(PolkadotContext); - if (!context) { - throw new Error('usePolkadot must be used within PolkadotProvider'); - } - return context; -}; diff --git a/frontend/src/lib/wallet.ts b/frontend/src/lib/wallet.ts deleted file mode 100644 index dd197af0..00000000 --- a/frontend/src/lib/wallet.ts +++ /dev/null @@ -1,150 +0,0 @@ -// ======================================== -// PezkuwiChain - Mobile Wallet Configuration -// ======================================== -// React Native compatible wallet configuration - -import Constants from 'expo-constants'; -import type { InjectedAccountWithMeta } from '@polkadot/extension-inject/types'; - -// ======================================== -// NETWORK ENDPOINTS -// ======================================== -export const NETWORK_ENDPOINTS = { - local: 'ws://127.0.0.1:9944', - testnet: 'wss://testnet.pezkuwichain.io', - beta: 'wss://beta.pezkuwichain.io', - mainnet: 'wss://mainnet.pezkuwichain.io', - staging: 'wss://staging.pezkuwichain.io', -}; - -// ======================================== -// CHAIN CONFIGURATION -// ======================================== -export const CHAIN_CONFIG = { - name: 'PezkuwiChain', - symbol: 'PEZ', - decimals: 12, - ss58Format: 42, -}; - -// ======================================== -// SUBSTRATE ASSET IDs (Assets Pallet) -// ======================================== -// ⚠️ IMPORTANT: HEZ is the native token and does NOT have an Asset ID -// Only wrapped/asset tokens are listed here -export const ASSET_IDS = { - WHEZ: 0, // Wrapped HEZ - PEZ: 1, // PEZ utility token - WUSDT: 2, // Wrapped USDT (multisig backed) - USDT: 3, - BTC: 4, - ETH: 5, - DOT: 6, -} as const; - -// ======================================== -// EXPLORER URLS -// ======================================== -export const EXPLORER_URLS = { - polkadotJs: 'https://polkadot.js.org/apps/?rpc=', - custom: 'https://explorer.pezkuwichain.io', -}; - -// ======================================== -// WALLET ERROR MESSAGES -// ======================================== -export const WALLET_ERRORS = { - NO_EXTENSION: 'No wallet detected. Please create or import a wallet.', - NO_ACCOUNTS: 'No accounts found. Please create an account first.', - CONNECTION_FAILED: 'Failed to connect wallet. Please try again.', - TRANSACTION_FAILED: 'Transaction failed. Please check your balance and try again.', - USER_REJECTED: 'User rejected the request.', - INSUFFICIENT_BALANCE: 'Insufficient balance to complete transaction.', - INVALID_ADDRESS: 'Invalid address format.', - API_NOT_READY: 'Blockchain API not ready. Please wait...', -}; - -// ======================================== -// UTILITY FUNCTIONS -// ======================================== - -/** - * Format Substrate address for display (SS58 format) - * @param address - Full substrate address - * @returns Shortened address string (e.g., "5GrwV...xQjz") - */ -export const formatAddress = (address: string): string => { - if (!address) return ''; - return `${address.slice(0, 6)}...${address.slice(-4)}`; -}; - -/** - * Format balance from planck to human-readable format - * @param balance - Balance in smallest unit (planck) - * @param decimals - Token decimals (default 12 for PEZ) - * @returns Formatted balance string - */ -export const formatBalance = (balance: string | number, decimals = 12): string => { - if (!balance) return '0'; - const value = typeof balance === 'string' ? parseFloat(balance) : balance; - const formatted = (value / Math.pow(10, decimals)).toFixed(4); - - // Remove trailing zeros - return parseFloat(formatted).toString(); -}; - -/** - * Parse human-readable amount to planck (smallest unit) - * @param amount - Human-readable amount - * @param decimals - Token decimals - * @returns Amount in planck - */ -export const parseAmount = (amount: string | number, decimals = 12): bigint => { - const value = typeof amount === 'string' ? parseFloat(amount) : amount; - return BigInt(Math.floor(value * Math.pow(10, decimals))); -}; - -/** - * Get asset symbol by ID - * @param assetId - Asset ID from Assets pallet - * @returns Asset symbol or 'UNKNOWN' - */ -export const getAssetSymbol = (assetId: number): string => { - const entry = Object.entries(ASSET_IDS).find(([_, id]) => id === assetId); - return entry ? entry[0] : 'UNKNOWN'; -}; - -/** - * Get current network endpoint - * Defaults to beta network for testing - * @returns WebSocket endpoint URL - */ -export const getCurrentEndpoint = (): string => { - // For mobile, we default to beta network - return NETWORK_ENDPOINTS.beta; -}; - -// ======================================== -// TYPE DEFINITIONS -// ======================================== - -export interface PolkadotWalletState { - isConnected: boolean; - accounts: InjectedAccountWithMeta[]; - selectedAccount: InjectedAccountWithMeta | null; - balance: string; - error: string | null; -} - -export const initialPolkadotWalletState: PolkadotWalletState = { - isConnected: false, - accounts: [], - selectedAccount: null, - balance: '0', - error: null, -}; - -// ======================================== -// FOUNDER ADDRESS -// ======================================== -export const FOUNDER_ADDRESS = '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'; // Satoshi Qazi Muhammed diff --git a/frontend/src/navigation/BottomTabNavigator.tsx b/frontend/src/navigation/BottomTabNavigator.tsx deleted file mode 100644 index 67b65e87..00000000 --- a/frontend/src/navigation/BottomTabNavigator.tsx +++ /dev/null @@ -1,63 +0,0 @@ -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 deleted file mode 100644 index 09f8d4f1..00000000 --- a/frontend/src/navigation/RootNavigator.tsx +++ /dev/null @@ -1,56 +0,0 @@ -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'; - -// Wallet Screens -import WalletSetupScreen from '../screens/Wallet/WalletSetupScreen'; - -// 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 */} - - - {/* Wallet Setup Flow - WalletConnect */} - - - {/* Main App */} - - - {/* Identity & KYC */} - - - - {/* Additional Screens */} - - - - - - - ); -} diff --git a/frontend/src/screens/Auth/LanguageSelectionScreen.tsx b/frontend/src/screens/Auth/LanguageSelectionScreen.tsx deleted file mode 100644 index 691f578d..00000000 --- a/frontend/src/screens/Auth/LanguageSelectionScreen.tsx +++ /dev/null @@ -1,199 +0,0 @@ -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('WalletSetup'); - }; - - 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 deleted file mode 100644 index fff9ba06..00000000 --- a/frontend/src/screens/Auth/SignUpScreen.tsx +++ /dev/null @@ -1,326 +0,0 @@ -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 deleted file mode 100644 index ce34fb4e..00000000 --- a/frontend/src/screens/Business/BusinessScreen.tsx +++ /dev/null @@ -1,794 +0,0 @@ -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 deleted file mode 100644 index 6ace9549..00000000 --- a/frontend/src/screens/Education/EducationScreen.tsx +++ /dev/null @@ -1,626 +0,0 @@ -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 deleted file mode 100644 index 00363ffe..00000000 --- a/frontend/src/screens/Exchange/ExchangeScreen.tsx +++ /dev/null @@ -1,792 +0,0 @@ -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 deleted file mode 100644 index fa4202fb..00000000 --- a/frontend/src/screens/Governance/GovernanceScreen.tsx +++ /dev/null @@ -1,416 +0,0 @@ -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 deleted file mode 100644 index e03aaa65..00000000 --- a/frontend/src/screens/Governance/GovernanceScreen_old.tsx +++ /dev/null @@ -1,117 +0,0 @@ -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 deleted file mode 100644 index a047cee4..00000000 --- a/frontend/src/screens/Governance/MinistriesScreen.tsx +++ /dev/null @@ -1,320 +0,0 @@ -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 deleted file mode 100644 index 021571cf..00000000 --- a/frontend/src/screens/Home/HomeScreen.tsx +++ /dev/null @@ -1,383 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { - View, - Text, - StyleSheet, - TouchableOpacity, - ScrollView, - SafeAreaView, - ActivityIndicator, -} 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 { usePolkadot } from '../../contexts/PolkadotContext'; -import pezkuwiAPI from '../../services/api'; - -interface QuickAction { - id: string; - label: string; - icon: keyof typeof Ionicons.glyphMap; - color: string; - onPress: () => void; -} - -export default function HomeScreen({ navigation }: any) { - const { selectedAccount } = usePolkadot(); - const [balance, setBalance] = useState(null); - const [loading, setLoading] = useState(true); - const [trustScore] = useState(750); - - useEffect(() => { - if (selectedAccount) { - loadBalance(); - } - }, [selectedAccount]); - - const loadBalance = async () => { - try { - setLoading(true); - if (selectedAccount?.address) { - const balanceData = await pezkuwiAPI.getBalance(selectedAccount.address); - setBalance(balanceData); - } - } catch (error) { - console.error('Error loading balance:', error); - } finally { - setLoading(false); - } - }; - - 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} - > - {loading ? ( - - - Loading balance... - - ) : ( - - navigation.navigate('Wallet', { tab: 'HEZ' })} - activeOpacity={0.7} - > - HEZ Balance - {balance?.hez || '0.0000'} - - - - navigation.navigate('Wallet', { tab: 'PEZ' })} - activeOpacity={0.7} - > - PEZ Balance - {balance?.pez || '0.0000'} - - - - )} - - - - {/* 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, - }, - loadingContainer: { - padding: Spacing.xxl, - alignItems: 'center', - justifyContent: 'center', - }, - loadingText: { - marginTop: Spacing.md, - fontSize: Typography.sizes.medium, - color: Colors.textGray, - }, - 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 deleted file mode 100644 index 94ade090..00000000 --- a/frontend/src/screens/Home/NotificationsScreen.tsx +++ /dev/null @@ -1,292 +0,0 @@ -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 deleted file mode 100644 index a559a7fb..00000000 --- a/frontend/src/screens/Identity/CitizenCardScreen.tsx +++ /dev/null @@ -1,459 +0,0 @@ -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 deleted file mode 100644 index 09057091..00000000 --- a/frontend/src/screens/Identity/IdentityKYCFormScreen.tsx +++ /dev/null @@ -1,435 +0,0 @@ -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 deleted file mode 100644 index d1749f7c..00000000 --- a/frontend/src/screens/Identity/IdentityScreen.tsx +++ /dev/null @@ -1,316 +0,0 @@ -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 deleted file mode 100644 index 79fdedf1..00000000 --- a/frontend/src/screens/Profile/ProfileScreen.tsx +++ /dev/null @@ -1,410 +0,0 @@ -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 deleted file mode 100644 index 13e6a50a..00000000 --- a/frontend/src/screens/Profile/ProfileScreen_old.tsx +++ /dev/null @@ -1,18 +0,0 @@ -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 deleted file mode 100644 index a99439fa..00000000 --- a/frontend/src/screens/Profile/TrustScoreScreen.tsx +++ /dev/null @@ -1,378 +0,0 @@ -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 deleted file mode 100644 index 40464d88..00000000 --- a/frontend/src/screens/Referral/ReferralScreen.tsx +++ /dev/null @@ -1,587 +0,0 @@ -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/CreateWalletScreen.tsx b/frontend/src/screens/Wallet/CreateWalletScreen.tsx deleted file mode 100644 index c6a4e060..00000000 --- a/frontend/src/screens/Wallet/CreateWalletScreen.tsx +++ /dev/null @@ -1,398 +0,0 @@ -import React, { useState } from 'react'; -import { - View, - Text, - StyleSheet, - TouchableOpacity, - SafeAreaView, - TextInput, - ScrollView, - Alert, - ActivityIndicator, - Clipboard, -} from 'react-native'; -import { Ionicons } from '@expo/vector-icons'; -import { LinearGradient } from 'expo-linear-gradient'; -import { usePolkadot } from '../../contexts/PolkadotContext'; - -export default function CreateWalletScreen({ navigation }: any) { - const { createWallet, isLoading } = usePolkadot(); - - const [walletName, setWalletName] = useState('My Wallet'); - const [password, setPassword] = useState(''); - const [confirmPassword, setConfirmPassword] = useState(''); - const [step, setStep] = useState<'form' | 'seed'>('form'); - const [seedPhrase, setSeedPhrase] = useState(''); - const [seedConfirmed, setSeedConfirmed] = useState(false); - - const handleCreateWallet = async () => { - // Validations - if (!walletName.trim()) { - Alert.alert('Error', 'Please enter a wallet name'); - return; - } - - if (password.length < 6) { - Alert.alert('Error', 'Password must be at least 6 characters'); - return; - } - - if (password !== confirmPassword) { - Alert.alert('Error', 'Passwords do not match'); - return; - } - - // Create wallet - const result = await createWallet(walletName, password); - - if (result.success && result.mnemonic) { - setSeedPhrase(result.mnemonic); - setStep('seed'); - } else { - Alert.alert('Error', result.error || 'Failed to create wallet'); - } - }; - - const handleCopySeed = () => { - Clipboard.setString(seedPhrase); - Alert.alert('Copied!', 'Seed phrase copied to clipboard'); - }; - - const handleComplete = () => { - if (!seedConfirmed) { - Alert.alert( - 'Important!', - 'Please confirm that you have backed up your seed phrase. You will need it to recover your wallet.', - [ - { text: 'Cancel', style: 'cancel' }, - { - text: 'I Have Backed It Up', - onPress: () => { - setSeedConfirmed(true); - navigation.navigate('MainTabs'); - }, - }, - ] - ); - } else { - navigation.navigate('MainTabs'); - } - }; - - if (step === 'seed') { - return ( - - - - - - Your Seed Phrase - - Write down these 12 words in order. Keep them safe and secret. - - - - - - - - Never share your seed phrase with anyone! - - - - - {seedPhrase.split(' ').map((word, index) => ( - - {index + 1}. - {word} - - ))} - - - - - Copy to Clipboard - - - - - setSeedConfirmed(!seedConfirmed)} - > - {seedConfirmed && ( - - )} - - - I have written down my seed phrase in a safe place - - - - - Continue - - - - - - ); - } - - return ( - - - - navigation.goBack()} - > - - - - - - Create New Wallet - - Set up your new PezkuwiChain wallet - - - - - - Wallet Name - - - - - Password - - - - - Confirm Password - - - - - {isLoading ? ( - - ) : ( - <> - Create Wallet - - - )} - - - - - - ); -} - -const styles = StyleSheet.create({ - container: { - flex: 1, - }, - gradient: { - flex: 1, - }, - scrollContent: { - padding: 20, - }, - backButton: { - width: 40, - height: 40, - borderRadius: 20, - backgroundColor: 'rgba(255,255,255,0.3)', - alignItems: 'center', - justifyContent: 'center', - marginBottom: 20, - }, - header: { - alignItems: 'center', - marginBottom: 30, - }, - title: { - fontSize: 28, - fontWeight: 'bold', - color: '#FFF', - marginTop: 16, - }, - subtitle: { - fontSize: 16, - color: '#FFF', - marginTop: 8, - textAlign: 'center', - opacity: 0.9, - }, - card: { - backgroundColor: '#FFF', - borderRadius: 20, - padding: 24, - }, - inputGroup: { - marginBottom: 20, - }, - label: { - fontSize: 16, - fontWeight: '600', - color: '#333', - marginBottom: 8, - }, - input: { - backgroundColor: '#F5F5F5', - borderRadius: 12, - padding: 16, - fontSize: 16, - color: '#333', - }, - createButton: { - backgroundColor: '#F08080', - borderRadius: 12, - padding: 16, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - gap: 8, - marginTop: 10, - }, - createButtonText: { - color: '#FFF', - fontSize: 18, - fontWeight: '600', - }, - warningBanner: { - backgroundColor: '#FFF5F5', - borderRadius: 12, - padding: 16, - flexDirection: 'row', - alignItems: 'center', - gap: 12, - marginBottom: 20, - borderWidth: 1, - borderColor: '#FFE0E0', - }, - warningText: { - flex: 1, - fontSize: 14, - color: '#FF6B6B', - fontWeight: '600', - }, - seedContainer: { - flexDirection: 'row', - flexWrap: 'wrap', - gap: 12, - marginBottom: 20, - }, - seedWord: { - width: '30%', - backgroundColor: '#F5F5F5', - borderRadius: 8, - padding: 12, - flexDirection: 'row', - alignItems: 'center', - gap: 6, - }, - seedNumber: { - fontSize: 12, - color: '#999', - fontWeight: '600', - }, - seedText: { - fontSize: 14, - color: '#333', - fontWeight: '600', - }, - copyButton: { - backgroundColor: '#7DD3C0', - borderRadius: 12, - padding: 14, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - gap: 8, - }, - copyButtonText: { - color: '#FFF', - fontSize: 16, - fontWeight: '600', - }, - checkboxContainer: { - flexDirection: 'row', - alignItems: 'center', - gap: 12, - marginTop: 20, - }, - checkbox: { - width: 24, - height: 24, - borderRadius: 6, - borderWidth: 2, - borderColor: '#FFF', - backgroundColor: 'rgba(255,255,255,0.2)', - alignItems: 'center', - justifyContent: 'center', - }, - checkboxLabel: { - flex: 1, - fontSize: 14, - color: '#FFF', - }, - continueButton: { - backgroundColor: '#FFF', - borderRadius: 12, - padding: 16, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - gap: 8, - marginTop: 20, - }, - continueButtonDisabled: { - opacity: 0.5, - }, - continueButtonText: { - color: '#F08080', - fontSize: 18, - fontWeight: '700', - }, -}); diff --git a/frontend/src/screens/Wallet/ImportWalletScreen.tsx b/frontend/src/screens/Wallet/ImportWalletScreen.tsx deleted file mode 100644 index 6d632ff5..00000000 --- a/frontend/src/screens/Wallet/ImportWalletScreen.tsx +++ /dev/null @@ -1,267 +0,0 @@ -import React, { useState } from 'react'; -import { - View, - Text, - StyleSheet, - TouchableOpacity, - SafeAreaView, - TextInput, - ScrollView, - Alert, - ActivityIndicator, -} from 'react-native'; -import { Ionicons } from '@expo/vector-icons'; -import { LinearGradient } from 'expo-linear-gradient'; -import { usePolkadot } from '../../contexts/PolkadotContext'; - -export default function ImportWalletScreen({ navigation }: any) { - const { importWallet, isLoading } = usePolkadot(); - - const [walletName, setWalletName] = useState('Imported Wallet'); - const [seedPhrase, setSeedPhrase] = useState(''); - const [password, setPassword] = useState(''); - const [confirmPassword, setConfirmPassword] = useState(''); - - const handleImportWallet = async () => { - // Validations - if (!walletName.trim()) { - Alert.alert('Error', 'Please enter a wallet name'); - return; - } - - const trimmedSeed = seedPhrase.trim(); - const wordCount = trimmedSeed.split(/\s+/).length; - - if (wordCount !== 12 && wordCount !== 24) { - Alert.alert('Error', 'Seed phrase must be 12 or 24 words'); - return; - } - - if (password.length < 6) { - Alert.alert('Error', 'Password must be at least 6 characters'); - return; - } - - if (password !== confirmPassword) { - Alert.alert('Error', 'Passwords do not match'); - return; - } - - // Import wallet - const result = await importWallet(trimmedSeed, walletName, password); - - if (result.success) { - Alert.alert( - 'Success!', - 'Wallet imported successfully', - [ - { - text: 'OK', - onPress: () => navigation.navigate('MainTabs'), - }, - ] - ); - } else { - Alert.alert('Error', result.error || 'Failed to import wallet'); - } - }; - - return ( - - - - navigation.goBack()} - > - - - - - - Import Wallet - - Restore your wallet using your seed phrase - - - - - - Wallet Name - - - - - Seed Phrase (12 or 24 words) - - - Separate each word with a space - - - - - Password - - - - - Confirm Password - - - - - - - Make sure you're in a safe place. Never share your seed phrase with anyone. - - - - - {isLoading ? ( - - ) : ( - <> - Import Wallet - - - )} - - - - - - ); -} - -const styles = StyleSheet.create({ - container: { - flex: 1, - }, - gradient: { - flex: 1, - }, - scrollContent: { - padding: 20, - }, - backButton: { - width: 40, - height: 40, - borderRadius: 20, - backgroundColor: 'rgba(255,255,255,0.3)', - alignItems: 'center', - justifyContent: 'center', - marginBottom: 20, - }, - header: { - alignItems: 'center', - marginBottom: 30, - }, - title: { - fontSize: 28, - fontWeight: 'bold', - color: '#FFF', - marginTop: 16, - }, - subtitle: { - fontSize: 16, - color: '#FFF', - marginTop: 8, - textAlign: 'center', - opacity: 0.9, - }, - card: { - backgroundColor: '#FFF', - borderRadius: 20, - padding: 24, - }, - inputGroup: { - marginBottom: 20, - }, - label: { - fontSize: 16, - fontWeight: '600', - color: '#333', - marginBottom: 8, - }, - input: { - backgroundColor: '#F5F5F5', - borderRadius: 12, - padding: 16, - fontSize: 16, - color: '#333', - }, - seedInput: { - minHeight: 100, - textAlignVertical: 'top', - }, - hint: { - fontSize: 12, - color: '#999', - marginTop: 6, - }, - warningBox: { - backgroundColor: '#F0F9F7', - borderRadius: 12, - padding: 16, - flexDirection: 'row', - alignItems: 'center', - gap: 12, - marginBottom: 20, - borderWidth: 1, - borderColor: '#D0F0E8', - }, - warningText: { - flex: 1, - fontSize: 14, - color: '#5DBEA3', - lineHeight: 20, - }, - importButton: { - backgroundColor: '#7DD3C0', - borderRadius: 12, - padding: 16, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - gap: 8, - }, - importButtonText: { - color: '#FFF', - fontSize: 18, - fontWeight: '600', - }, -}); diff --git a/frontend/src/screens/Wallet/WalletScreen.tsx b/frontend/src/screens/Wallet/WalletScreen.tsx deleted file mode 100644 index 0840b962..00000000 --- a/frontend/src/screens/Wallet/WalletScreen.tsx +++ /dev/null @@ -1,501 +0,0 @@ -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 deleted file mode 100644 index 56b8f403..00000000 --- a/frontend/src/screens/Wallet/WalletScreen_old.tsx +++ /dev/null @@ -1,98 +0,0 @@ -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/screens/Wallet/WalletSetupScreen.tsx b/frontend/src/screens/Wallet/WalletSetupScreen.tsx deleted file mode 100644 index 46fafd75..00000000 --- a/frontend/src/screens/Wallet/WalletSetupScreen.tsx +++ /dev/null @@ -1,223 +0,0 @@ -import React, { useState } from 'react'; -import { - View, - Text, - StyleSheet, - TouchableOpacity, - SafeAreaView, - TextInput, - Alert, -} from 'react-native'; -import { Ionicons } from '@expo/vector-icons'; -import { LinearGradient } from 'expo-linear-gradient'; -import { usePolkadot } from '../../contexts/PolkadotContext'; - -export default function WalletSetupScreen({ navigation }: any) { - const { saveAccount } = usePolkadot(); - const [walletAddress, setWalletAddress] = useState('5DFwqK698vL4gXHEcanaewnAqhxJ2rjhAogpSTHw3iwGDwd3'); - const [walletName, setWalletName] = useState('My Wallet'); - - const handleConnectWithAddress = async () => { - if (!walletAddress.trim()) { - Alert.alert('Error', 'Please enter a valid wallet address'); - return; - } - - // Save the account - await saveAccount({ - address: walletAddress.trim(), - name: walletName.trim() || 'My Wallet', - }); - - navigation.navigate('MainTabs'); - }; - - return ( - - - - {/* Header */} - - - Connect Your Wallet - - Enter your PezkuwiChain wallet address to get started - - - - {/* Main Card */} - - - - Wallet Details - - - Wallet Name (optional) - - - Wallet Address - - - - Continue - - - - - - - Your wallet address is only stored locally on your device. We never access your private keys. - - - - - {/* Footer */} - - - - All blockchain data fetched securely via backend API - - - - - - ); -} - -const styles = StyleSheet.create({ - container: { - flex: 1, - }, - gradient: { - flex: 1, - }, - content: { - flex: 1, - padding: 20, - justifyContent: 'space-between', - }, - header: { - alignItems: 'center', - marginTop: 40, - }, - title: { - fontSize: 28, - fontWeight: 'bold', - color: '#FFF', - marginTop: 20, - textAlign: 'center', - }, - subtitle: { - fontSize: 16, - color: '#FFF', - marginTop: 12, - textAlign: 'center', - opacity: 0.9, - paddingHorizontal: 20, - }, - card: { - backgroundColor: '#FFF', - borderRadius: 24, - padding: 24, - shadowColor: '#000', - shadowOffset: { width: 0, height: 4 }, - shadowOpacity: 0.15, - shadowRadius: 12, - elevation: 8, - }, - optionHeader: { - flexDirection: 'row', - alignItems: 'center', - gap: 12, - marginBottom: 20, - }, - optionTitle: { - fontSize: 20, - fontWeight: '700', - color: '#333', - }, - label: { - fontSize: 14, - fontWeight: '600', - color: '#666', - marginBottom: 8, - marginTop: 12, - }, - input: { - backgroundColor: '#F5F5F5', - borderRadius: 12, - padding: 16, - fontSize: 14, - color: '#333', - }, - addressInput: { - minHeight: 60, - textAlignVertical: 'top', - }, - primaryButton: { - backgroundColor: '#F08080', - borderRadius: 12, - padding: 16, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - gap: 8, - marginTop: 20, - }, - primaryButtonText: { - color: '#FFF', - fontSize: 18, - fontWeight: '600', - }, - infoBox: { - backgroundColor: '#F0F9F7', - borderRadius: 12, - padding: 12, - flexDirection: 'row', - alignItems: 'flex-start', - gap: 8, - marginTop: 16, - borderWidth: 1, - borderColor: '#D0F0E8', - }, - infoText: { - flex: 1, - fontSize: 12, - color: '#5DBEA3', - lineHeight: 16, - }, - footer: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - gap: 8, - marginBottom: 20, - }, - footerText: { - fontSize: 12, - color: '#FFF', - opacity: 0.9, - }, -}); diff --git a/frontend/src/services/api.ts b/frontend/src/services/api.ts deleted file mode 100644 index f1d43da6..00000000 --- a/frontend/src/services/api.ts +++ /dev/null @@ -1,107 +0,0 @@ -// PezkuwiChain API Service -// Connects to our FastAPI backend (proxy to blockchain) - -import Constants from 'expo-constants'; - -const BACKEND_URL = Constants.expoConfig?.extra?.EXPO_PUBLIC_BACKEND_URL || 'http://localhost:8001'; -const API_BASE = `${BACKEND_URL}/api`; - -interface WalletBalance { - address: string; - hez: string; - pez: string; - transferrable: string; - reserved: string; -} - -interface Transaction { - hash: string; - from: string; - to: string; - amount: string; - asset: string; - timestamp: string; - status: string; -} - -class PezkuwiAPI { - private baseUrl: string; - - constructor() { - this.baseUrl = API_BASE; - console.log('✅ PezkuwiAPI initialized:', this.baseUrl); - } - - // Get wallet balance - async getBalance(address: string): Promise { - try { - const response = await fetch(`${this.baseUrl}/blockchain/balance`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ address }), - }); - - if (!response.ok) { - throw new Error('Failed to fetch balance'); - } - - return await response.json(); - } catch (error) { - console.error('Error fetching balance:', error); - throw error; - } - } - - // Get transaction history - async getTransactions(address: string): Promise<{ address: string; transactions: Transaction[] }> { - try { - const response = await fetch(`${this.baseUrl}/blockchain/transactions/${address}`); - - if (!response.ok) { - throw new Error('Failed to fetch transactions'); - } - - return await response.json(); - } catch (error) { - console.error('Error fetching transactions:', error); - throw error; - } - } - - // Get citizenship status - async getCitizenshipStatus(address: string) { - try { - const response = await fetch(`${this.baseUrl}/citizenship/status/${address}`); - - if (!response.ok) { - throw new Error('Failed to fetch citizenship status'); - } - - return await response.json(); - } catch (error) { - console.error('Error fetching citizenship status:', error); - throw error; - } - } - - // Get governance proposals - async getProposals() { - try { - const response = await fetch(`${this.baseUrl}/governance/proposals`); - - if (!response.ok) { - throw new Error('Failed to fetch proposals'); - } - - return await response.json(); - } catch (error) { - console.error('Error fetching proposals:', error); - throw error; - } - } -} - -export const pezkuwiAPI = new PezkuwiAPI(); -export default pezkuwiAPI; diff --git a/frontend/src/services/blockchain.ts b/frontend/src/services/blockchain.ts deleted file mode 100644 index 0ae1674c..00000000 --- a/frontend/src/services/blockchain.ts +++ /dev/null @@ -1,317 +0,0 @@ -/** - * PezkuwiChain Blockchain Service - * Handles all interactions with the PezkuwiChain blockchain via Polkadot.js - */ - -import { Platform } from 'react-native'; -import { CURRENT_CHAIN_CONFIG, ASSET_IDS } from '../constants/blockchain'; -import { Balance, Transaction, Proposal } from '../types'; - -// Only import Polkadot.js on native platforms (not web) to avoid import.meta issues -let ApiPromise: any = null; -let WsProvider: any = null; - -if (Platform.OS !== 'web') { - const polkadotApi = require('@polkadot/api'); - ApiPromise = polkadotApi.ApiPromise; - WsProvider = polkadotApi.WsProvider; -} - -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 deleted file mode 100644 index ea83d321..00000000 --- a/frontend/src/services/kycService.ts +++ /dev/null @@ -1,262 +0,0 @@ -/** - * 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/citizenship.ts b/frontend/src/types/citizenship.ts deleted file mode 100644 index 3a30bddc..00000000 --- a/frontend/src/types/citizenship.ts +++ /dev/null @@ -1,155 +0,0 @@ -// ======================================== -// Citizenship Type Definitions -// ======================================== - -export type KycStatus = 'NotStarted' | 'Pending' | 'Approved' | 'Rejected'; - -export type Region = - | 'bakur' // North (Turkey) - | 'basur' // South (Iraq) - | 'rojava' // West (Syria) - | 'rojhelat' // East (Iran) - | 'diaspora' // Diaspora - | 'kurdistan_a_sor'; // Red Kurdistan (Armenia/Azerbaijan) - -export type MaritalStatus = 'zewici' | 'nezewici'; // Married / Unmarried - -export interface ChildInfo { - name: string; - birthYear: number; -} - -export interface CitizenshipData { - // Personal Identity - fullName: string; - fatherName: string; - grandfatherName: string; - motherName: string; - - // Tribal Affiliation - tribe: string; - - // Family Status - maritalStatus: MaritalStatus; - childrenCount?: number; - children?: ChildInfo[]; - - // Geographic Origin - region: Region; - - // Contact & Profession - email: string; - profession: string; - - // Referral - referralCode?: string; - - // Metadata - walletAddress: string; - timestamp: number; -} - -export interface CitizenshipCommitment { - commitmentHash: string; // SHA256 hash of all data - nullifierHash: string; // Prevents double-registration - ipfsCid: string; // IPFS CID of encrypted data - publicKey: string; // User's encryption public key - timestamp: number; -} - -export interface TikiInfo { - id: string; - role: string; - metadata?: any; -} - -export interface CitizenshipStatus { - kycStatus: KycStatus; - hasCitizenTiki: boolean; - tikiNumber?: string; - stakingScoreTracking: boolean; - ipfsCid?: string; - nextAction: 'APPLY_KYC' | 'CLAIM_TIKI' | 'START_TRACKING' | 'COMPLETE'; -} - -// Region Display Names -export const REGION_NAMES: Record = { - bakur: { - en: 'Bakur (North Kurdistan)', - ku: 'Bakur (Kurdistana Bakur)', - tr: 'Bakur (Kuzey Kürdistan)', - }, - basur: { - en: 'Basur (South Kurdistan)', - ku: 'Basur (Kurdistana Başûr)', - tr: 'Basur (Güney Kürdistan)', - }, - rojava: { - en: 'Rojava (West Kurdistan)', - ku: 'Rojava (Kurdistana Rojava)', - tr: 'Rojava (Batı Kürdistan)', - }, - rojhelat: { - en: 'Rojhelat (East Kurdistan)', - ku: 'Rojhelat (Kurdistana Rojhilat)', - tr: 'Rojhelat (Doğu Kürdistan)', - }, - diaspora: { - en: 'Diaspora', - ku: 'Diyaspora', - tr: 'Diaspora', - }, - kurdistan_a_sor: { - en: 'Red Kurdistan', - ku: 'Kurdistana Sor', - tr: 'Kızıl Kürdistan', - }, -}; - -// Tiki Roles (from pallet-tiki) -export const TIKI_ROLES = [ - 'Hemwelatî', // 0: Citizen - 'Parlementer', // 1: Parliament Member - 'SerokiMeclise', // 2: Parliament Speaker - 'Serok', // 3: President - 'Wezir', // 4: Minister - 'EndameDiwane', // 5: Council Member - 'Dadger', // 6: Judge - 'Dozger', // 7: Prosecutor - 'Hiquqnas', // 8: Lawyer - 'Noter', // 9: Notary - 'Xezinedar', // 10: Treasurer - 'Bacgir', // 11: Tax Collector - 'GerinendeyeCavkaniye', // 12: Resource Manager - 'OperatorêTorê', // 13: Network Operator - 'PisporêEwlehiyaSîber', // 14: Cybersecurity Expert - 'GerinendeyeDaneye', // 15: Data Manager - 'Berdevk', // 16: Spokesperson - 'Qeydkar', // 17: Registrar - 'Balyoz', // 18: Ambassador - 'Navbeynkar', // 19: Mediator - 'ParêzvaneÇandî', // 20: Cultural Protector - 'Mufetîs', // 21: Inspector - 'KalîteKontrolker', // 22: Quality Controller - 'Mela', // 23: Mullah - 'Feqî', // 24: Scholar - 'Perwerdekar', // 25: Educator - 'Rewsenbîr', // 26: Intellectual - 'RêveberêProjeyê', // 27: Project Manager - 'SerokêKomele', // 28: Community Leader - 'ModeratorêCivakê', // 29: Community Moderator - 'Axa', // 30: Landlord - 'Pêseng', // 31: Pioneer - 'Sêwirmend', // 32: Advisor - 'Hekem', // 33: Wise - 'Mamoste', // 34: Teacher - 'Bazargan', // 35: Merchant - 'SerokWeziran', // 36: Prime Minister - 'WezireDarayiye', // 37: Finance Minister - 'WezireParez', // 38: Defense Minister - 'WezireDad', // 39: Justice Minister - 'WezireBelaw', // 40: Education Minister - 'WezireTend', // 41: Health Minister - 'WezireAva', // 42: Infrastructure Minister - 'WezireCand', // 43: Culture Minister -]; diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts deleted file mode 100644 index 810fa5ce..00000000 --- a/frontend/src/types/index.ts +++ /dev/null @@ -1,197 +0,0 @@ -/** - * 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 deleted file mode 100644 index a5f9a8d7..00000000 --- a/frontend/src/types/kyc.ts +++ /dev/null @@ -1,89 +0,0 @@ -/** - * 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: 'دیاسپۆرا' }, -}; -