import React, { useState, useEffect } from 'react'; import { View, Text, StyleSheet, ScrollView, RefreshControl, Alert, Pressable, TouchableOpacity, FlatList, } from 'react-native'; import { usePolkadot } from '../contexts/PolkadotContext'; import { AppColors, KurdistanColors } from '../theme/colors'; import { Card, Button, BottomSheet, Badge, CardSkeleton, } from '../components'; interface Proposal { index: number; proposer: string; description: string; value: string; beneficiary: string; bond: string; ayes: number; nays: number; status: 'active' | 'approved' | 'rejected'; endBlock: number; } interface Election { id: number; type: 'Presidential' | 'Parliamentary' | 'Constitutional Court'; status: 'Registration' | 'Campaign' | 'Voting' | 'Completed'; candidates: Candidate[]; totalVotes: number; endBlock: number; currentBlock: number; } interface Candidate { id: string; name: string; votes: number; percentage: number; party?: string; trustScore: number; } type TabType = 'proposals' | 'elections' | 'parliament'; /** * Governance Screen * View proposals, vote, participate in governance * Inspired by Polkadot governance and modern DAO interfaces */ export default function GovernanceScreen() { const { api, selectedAccount, isApiReady } = usePolkadot(); const [activeTab, setActiveTab] = useState('proposals'); const [proposals, setProposals] = useState([]); const [elections, setElections] = useState([]); const [loading, setLoading] = useState(true); const [refreshing, setRefreshing] = useState(false); const [selectedProposal, setSelectedProposal] = useState(null); const [selectedElection, setSelectedElection] = useState(null); const [voteSheetVisible, setVoteSheetVisible] = useState(false); const [electionSheetVisible, setElectionSheetVisible] = useState(false); const [voting, setVoting] = useState(false); const [votedCandidates, setVotedCandidates] = useState([]); useEffect(() => { if (isApiReady && selectedAccount) { fetchProposals(); fetchElections(); } }, [isApiReady, selectedAccount]); const fetchProposals = async () => { try { setLoading(true); if (!api) return; // Fetch democracy proposals const proposalEntries = await api.query.democracy?.publicProps(); if (!proposalEntries || proposalEntries.isEmpty) { setProposals([]); return; } const proposalsList: Proposal[] = []; // Parse proposals const publicProps = proposalEntries.toJSON() as any[]; for (const [index, proposal, proposer] of publicProps) { // Get proposal hash and details const proposalHash = proposal; // For demo, create sample proposals // In production, decode actual proposal data proposalsList.push({ index: index as number, proposer: proposer as string, description: `Proposal #${index}: Infrastructure Development`, value: '10000', beneficiary: '5GrwvaEF...', bond: '1000', ayes: Math.floor(Math.random() * 1000), nays: Math.floor(Math.random() * 200), status: 'active', endBlock: 1000000, }); } setProposals(proposalsList); } catch (error) { console.error('Error fetching proposals:', error); Alert.alert('Error', 'Failed to load proposals'); } finally { setLoading(false); setRefreshing(false); } }; const fetchElections = async () => { try { // Mock elections data // In production, this would fetch from pallet-tiki or election pallet const mockElections: Election[] = [ { id: 1, type: 'Presidential', status: 'Voting', totalVotes: 45678, endBlock: 1000000, currentBlock: 995000, candidates: [ { id: '1', name: 'Candidate A', votes: 23456, percentage: 51.3, trustScore: 850 }, { id: '2', name: 'Candidate B', votes: 22222, percentage: 48.7, trustScore: 780 } ] }, { id: 2, type: 'Parliamentary', status: 'Campaign', totalVotes: 12340, endBlock: 1200000, currentBlock: 995000, candidates: [ { id: '3', name: 'Candidate C', votes: 5678, percentage: 46.0, party: 'Green Party', trustScore: 720 }, { id: '4', name: 'Candidate D', votes: 4567, percentage: 37.0, party: 'Democratic Alliance', trustScore: 690 }, { id: '5', name: 'Candidate E', votes: 2095, percentage: 17.0, party: 'Independent', trustScore: 650 } ] } ]; setElections(mockElections); } catch (error) { console.error('Error fetching elections:', error); } }; const handleVote = async (approve: boolean) => { if (!selectedProposal) return; try { setVoting(true); if (!api || !selectedAccount) return; // Vote on proposal (referendum) const tx = approve ? api.tx.democracy.vote(selectedProposal.index, { Standard: { vote: { aye: true, conviction: 'None' }, balance: '1000000000000' } }) : api.tx.democracy.vote(selectedProposal.index, { Standard: { vote: { aye: false, conviction: 'None' }, balance: '1000000000000' } }); await tx.signAndSend(selectedAccount.address, ({ status }) => { if (status.isInBlock) { Alert.alert( 'Success', `Vote ${approve ? 'FOR' : 'AGAINST'} recorded successfully!` ); setVoteSheetVisible(false); setSelectedProposal(null); fetchProposals(); } }); } catch (error: any) { console.error('Voting error:', error); Alert.alert('Error', error.message || 'Failed to submit vote'); } finally { setVoting(false); } }; const handleElectionVote = (candidateId: string) => { if (!selectedElection) return; if (selectedElection.type === 'Parliamentary') { // Multiple selection for Parliamentary setVotedCandidates(prev => prev.includes(candidateId) ? prev.filter(id => id !== candidateId) : [...prev, candidateId] ); } else { // Single selection for Presidential setVotedCandidates([candidateId]); } }; const submitElectionVote = async () => { if (votedCandidates.length === 0) { Alert.alert('Error', 'Please select at least one candidate'); return; } try { setVoting(true); // TODO: Submit votes to blockchain via pallet-tiki // await api.tx.tiki.voteInElection(electionId, candidateIds).signAndSend(...) Alert.alert('Success', 'Your vote has been recorded!'); setElectionSheetVisible(false); setSelectedElection(null); setVotedCandidates([]); fetchElections(); } catch (error: any) { console.error('Election voting error:', error); Alert.alert('Error', error.message || 'Failed to submit vote'); } finally { setVoting(false); } }; if (loading && proposals.length === 0) { return ( ); } return ( {/* Header */} Governance Participate in digital democracy {/* Tabs */} setActiveTab('proposals')} > Proposals ({proposals.length}) setActiveTab('elections')} > Elections ({elections.length}) setActiveTab('parliament')} > Parliament { setRefreshing(true); fetchProposals(); fetchElections(); }} /> } > {/* Stats */} {proposals.length} Active Proposals {elections.length} Active Elections {/* Tab Content */} {activeTab === 'proposals' && ( <> Active Proposals {proposals.length === 0 ? ( No active proposals Check back later for new governance proposals ) : ( proposals.map((proposal) => ( { setSelectedProposal(proposal); setVoteSheetVisible(true); }} /> )) )} )} {activeTab === 'elections' && ( <> Active Elections {elections.length === 0 ? ( No active elections Check back later for upcoming elections ) : ( elections.map((election) => ( { setSelectedElection(election); setVotedCandidates([]); setElectionSheetVisible(true); }} /> )) )} )} {activeTab === 'parliament' && ( <> Parliament Status Active Members 0 / 27 Current Session Pending Votes 5 Dîwan (Constitutional Court) Active Judges 0 / 9 Pending Reviews 3 Recent Decisions 12 )} {/* Info Card */} 🗳️ How Voting Works Each HEZ token equals one vote. Your vote helps shape the future of Digital Kurdistan. Proposals need majority approval to pass. {/* Vote Bottom Sheet */} setVoteSheetVisible(false)} title="Vote on Proposal" height={500} > {selectedProposal && ( {selectedProposal.description} {/* Vote Progress */} {selectedProposal.ayes} For {selectedProposal.nays} Against {/* Vote Buttons */}