diff --git a/web/src/components/AccountBalance.tsx b/web/src/components/AccountBalance.tsx index 69b2a00b..5275bc3f 100644 --- a/web/src/components/AccountBalance.tsx +++ b/web/src/components/AccountBalance.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useState } from 'react'; import { usePolkadot } from '@/contexts/PolkadotContext'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; -import { Wallet, TrendingUp, ArrowUpRight, ArrowDownRight, RefreshCw, Award, Plus, Coins, Send, Shield, Users } from 'lucide-react'; +import { Wallet, TrendingUp, ArrowDownRight, RefreshCw, Award, Plus, Coins, Send, Shield, Users } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { ASSET_IDS, getAssetSymbol } from '@pezkuwi/lib/wallet'; import { AddTokenModal } from './AddTokenModal'; @@ -168,7 +168,7 @@ export const AccountBalance: React.FC = () => { const assetData = assetBalance.unwrap(); const balance = assetData.balance.toString(); - const metadata = assetMetadata.toJSON() as any; + const metadata = assetMetadata.toJSON() as { symbol?: string; name?: string; decimals?: number }; // Decode hex strings properly let symbol = metadata.symbol || ''; @@ -310,15 +310,15 @@ export const AccountBalance: React.FC = () => { setIsAddTokenModalOpen(false); }; - // Remove token handler - const handleRemoveToken = (assetId: number) => { - const updatedTokenIds = customTokenIds.filter(id => id !== assetId); - setCustomTokenIds(updatedTokenIds); - localStorage.setItem('customTokenIds', JSON.stringify(updatedTokenIds)); - - // Remove from displayed tokens - setOtherTokens(prev => prev.filter(t => t.assetId !== assetId)); - }; + // Remove token handler (unused but kept for future feature) + // const handleRemoveToken = (assetId: number) => { + // const updatedTokenIds = customTokenIds.filter(id => id !== assetId); + // setCustomTokenIds(updatedTokenIds); + // localStorage.setItem('customTokenIds', JSON.stringify(updatedTokenIds)); + // + // // Remove from displayed tokens + // setOtherTokens(prev => prev.filter(t => t.assetId !== assetId)); + // }; useEffect(() => { fetchBalance(); @@ -439,6 +439,7 @@ export const AccountBalance: React.FC = () => { if (unsubscribePez) unsubscribePez(); if (unsubscribeUsdt) unsubscribeUsdt(); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [api, isApiReady, selectedAccount]); if (!selectedAccount) { diff --git a/web/src/components/AddLiquidityModal.tsx b/web/src/components/AddLiquidityModal.tsx index c1b68177..b2472ae0 100644 --- a/web/src/components/AddLiquidityModal.tsx +++ b/web/src/components/AddLiquidityModal.tsx @@ -14,6 +14,18 @@ interface AddLiquidityModalProps { asset1?: number; // Pool's second asset ID } +interface AssetDetails { + minBalance?: string | number; +} + +interface AssetAccountData { + balance: string | number; +} + +interface Balances { + [key: string]: number; +} + // Helper to get display name (users see HEZ not wHEZ, PEZ, USDT not wUSDT) const getDisplayName = (assetId: number): string => { if (assetId === ASSET_IDS.WHEZ || assetId === 0) return 'HEZ'; @@ -86,8 +98,8 @@ export const AddLiquidityModal: React.FC = ({ console.log('🔍 Querying minimum balances for assets:', { asset0, asset1 }); if (assetDetails0.isSome && assetDetails1.isSome) { - const details0 = assetDetails0.unwrap().toJSON() as any; - const details1 = assetDetails1.unwrap().toJSON() as any; + const details0 = assetDetails0.unwrap().toJSON() as AssetDetails; + const details1 = assetDetails1.unwrap().toJSON() as AssetDetails; console.log('📦 Asset details:', { asset0: details0, @@ -115,7 +127,7 @@ export const AddLiquidityModal: React.FC = ({ console.warn('⚠️ Asset details not found, using defaults'); } - // Also check if there's a MintMinLiquidity constant in assetConversion pallet + // Also check if there's a MintMinLiquidity constant in assetConversion pallet if (api.consts.assetConversion) { const mintMinLiq = api.consts.assetConversion.mintMinLiquidity; if (mintMinLiq) { @@ -166,8 +178,8 @@ export const AddLiquidityModal: React.FC = ({ const balance1Data = await api.query.assets.account(asset1, poolAccountId); if (balance0Data.isSome && balance1Data.isSome) { - const data0 = balance0Data.unwrap().toJSON() as any; - const data1 = balance1Data.unwrap().toJSON() as any; + const data0 = balance0Data.unwrap().toJSON() as AssetAccountData; + const data1 = balance1Data.unwrap().toJSON() as AssetAccountData; const reserve0 = Number(data0.balance) / Math.pow(10, asset0Decimals); const reserve1 = Number(data1.balance) / Math.pow(10, asset1Decimals); @@ -190,7 +202,7 @@ export const AddLiquidityModal: React.FC = ({ console.log('Pool is empty - manual input allowed'); } } else { - // Pool doesn't exist yet - completely empty + // Pool doesn't exist yet - completely empty setCurrentPrice(null); setIsPoolEmpty(true); console.log('Pool does not exist yet - manual input allowed'); @@ -214,7 +226,7 @@ export const AddLiquidityModal: React.FC = ({ } else if (!amount0 && !isPoolEmpty) { setAmount1(''); } - // If pool is empty, don't auto-calculate - let user input both amounts + // If pool is empty, don't auto-calculate - let user input both amounts }, [amount0, currentPrice, asset1Decimals, isPoolEmpty]); const handleAddLiquidity = async () => { @@ -244,8 +256,8 @@ export const AddLiquidityModal: React.FC = ({ return; } - const balance0 = (balances as any)[asset0BalanceKey] || 0; - const balance1 = (balances as any)[asset1BalanceKey] || 0; + const balance0 = (balances as Balances)[asset0BalanceKey] || 0; + const balance1 = (balances as Balances)[asset1BalanceKey] || 0; if (parseFloat(amount0) > balance0) { setError(`Insufficient ${asset0Name} balance`); @@ -364,8 +376,8 @@ export const AddLiquidityModal: React.FC = ({ if (!isOpen) return null; - const balance0 = (balances as any)[asset0BalanceKey] || 0; - const balance1 = (balances as any)[asset1BalanceKey] || 0; + const balance0 = (balances as Balances)[asset0BalanceKey] || 0; + const balance1 = (balances as Balances)[asset1BalanceKey] || 0; return (
diff --git a/web/src/components/AddTokenModal.tsx b/web/src/components/AddTokenModal.tsx index 6a139073..940d1170 100644 --- a/web/src/components/AddTokenModal.tsx +++ b/web/src/components/AddTokenModal.tsx @@ -41,7 +41,7 @@ export const AddTokenModal: React.FC = ({ await onAddToken(id); setAssetId(''); setError(''); - } catch (err) { + } catch { setError('Failed to add token. Please check the asset ID and try again.'); } finally { setIsLoading(false); diff --git a/web/src/components/AppLayout.tsx b/web/src/components/AppLayout.tsx index aba4637d..4cb03c09 100644 --- a/web/src/components/AppLayout.tsx +++ b/web/src/components/AppLayout.tsx @@ -5,11 +5,9 @@ import { useAuth } from '@/contexts/AuthContext'; import HeroSection from './HeroSection'; import TokenomicsSection from './TokenomicsSection'; import PalletsGrid from './PalletsGrid'; -import TeamSection from './TeamSection'; import ChainSpecs from './ChainSpecs'; import TrustScoreCalculator from './TrustScoreCalculator'; import { NetworkStats } from './NetworkStats'; -import { WalletButton } from './wallet/WalletButton'; import { WalletModal } from './wallet/WalletModal'; import { LanguageSwitcher } from './LanguageSwitcher'; import NotificationBell from './notifications/NotificationBell'; @@ -21,7 +19,7 @@ import { TreasuryOverview } from './treasury/TreasuryOverview'; import { FundingProposal } from './treasury/FundingProposal'; import { SpendingHistory } from './treasury/SpendingHistory'; import { MultiSigApproval } from './treasury/MultiSigApproval'; -import { Github, FileText, ExternalLink, Shield, Award, User, FileEdit, Users2, MessageSquare, ShieldCheck, Wifi, WifiOff, Wallet, DollarSign, PiggyBank, History, Key, TrendingUp, ArrowRightLeft, Lock, LogIn, LayoutDashboard, Settings, UserCog, Repeat, Users, Droplet, Mail } from 'lucide-react'; +import { ExternalLink, Award, FileEdit, Users2, MessageSquare, ShieldCheck, Wifi, WifiOff, Wallet, DollarSign, PiggyBank, History, Key, TrendingUp, ArrowRightLeft, Lock, LogIn, LayoutDashboard, Settings, Users, Droplet, Mail } from 'lucide-react'; import GovernanceInterface from './GovernanceInterface'; import RewardDistribution from './RewardDistribution'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; @@ -38,7 +36,6 @@ import EducationPlatform from '../pages/EducationPlatform'; const AppLayout: React.FC = () => { const navigate = useNavigate(); const [walletModalOpen, setWalletModalOpen] = useState(false); - const [transactionModalOpen, setTransactionModalOpen] = useState(false); const { user, signOut } = useAuth(); const [showProposalWizard, setShowProposalWizard] = useState(false); const [showDelegation, setShowDelegation] = useState(false); @@ -53,8 +50,8 @@ const AppLayout: React.FC = () => { const [showP2P, setShowP2P] = useState(false); const { t } = useTranslation(); const { isConnected } = useWebSocket(); - const { account } = useWallet(); - const [isAdmin, setIsAdmin] = useState(false); + useWallet(); + const [, _setIsAdmin] = useState(false); // Check if user is admin React.useEffect(() => { @@ -69,9 +66,9 @@ const AppLayout: React.FC = () => { if (error) { console.warn('Admin check error:', error); } - setIsAdmin(!!data); + _setIsAdmin(!!data); } else { - setIsAdmin(false); + _setIsAdmin(false); } }; checkAdminStatus(); diff --git a/web/src/components/ChainSpecs.tsx b/web/src/components/ChainSpecs.tsx index 84ef865c..ce51641c 100644 --- a/web/src/components/ChainSpecs.tsx +++ b/web/src/components/ChainSpecs.tsx @@ -205,17 +205,17 @@ const ChainSpecs: React.FC = () => {

Connection Example

-
// Using @polkadot/api
+
{`// Using @polkadot/api`}
import
{'{ ApiPromise, WsProvider }'}
from
-
'@polkadot/api';
+
'@polkadot/api';
const
provider =
new
WsProvider(
-
'{selectedSpec.endpoint}'
+
'{selectedSpec.endpoint}'
);
const
diff --git a/web/src/components/ErrorBoundary.tsx b/web/src/components/ErrorBoundary.tsx index 383e6d33..e6bd7190 100644 --- a/web/src/components/ErrorBoundary.tsx +++ b/web/src/components/ErrorBoundary.tsx @@ -180,7 +180,7 @@ export class ErrorBoundary extends Component { /** * Smaller error boundary for individual routes - * Less intrusive, doesn't take over the whole screen + * Less intrusive, doesn't take over the whole screen */ export const RouteErrorBoundary: React.FC<{ children: ReactNode; diff --git a/web/src/components/GovernanceInterface.tsx b/web/src/components/GovernanceInterface.tsx index e9fb9aab..61d49c58 100644 --- a/web/src/components/GovernanceInterface.tsx +++ b/web/src/components/GovernanceInterface.tsx @@ -17,7 +17,7 @@ const GovernanceInterface: React.FC = () => {

- Participate in PezkuwiChain's decentralized governance. Vote on proposals, elect representatives, and shape the future of the network. + Participate in PezkuwiChain's decentralized governance. Vote on proposals, elect representatives, and shape the future of the network.

diff --git a/web/src/components/MultisigMembers.tsx b/web/src/components/MultisigMembers.tsx index 30b1e545..15cfd649 100644 --- a/web/src/components/MultisigMembers.tsx +++ b/web/src/components/MultisigMembers.tsx @@ -17,12 +17,22 @@ interface MultisigMembersProps { showMultisigAddress?: boolean; } +interface MultisigMember { + address: string; + displayName: string; + emoji: string; + role: string; + isTiki: boolean; + trustScore?: number; + balance?: string; +} + export const MultisigMembers: React.FC = ({ specificAddresses = {}, showMultisigAddress = true, }) => { const { api, isApiReady } = usePolkadot(); - const [members, setMembers] = useState([]); + const [members, setMembers] = useState([]); const [multisigAddress, setMultisigAddress] = useState(''); const [loading, setLoading] = useState(true); diff --git a/web/src/components/NetworkStats.tsx b/web/src/components/NetworkStats.tsx index 4d371ca5..41c256f2 100644 --- a/web/src/components/NetworkStats.tsx +++ b/web/src/components/NetworkStats.tsx @@ -44,7 +44,7 @@ export const NetworkStats: React.FC = () => { try { const nominators = await api.query.staking.nominators.entries(); nominatorCount = nominators.length; - } catch (err) { + } catch { console.warn('Staking pallet not available, nominators = 0'); } diff --git a/web/src/components/PalletsGrid.tsx b/web/src/components/PalletsGrid.tsx index 20661e33..2970d73d 100644 --- a/web/src/components/PalletsGrid.tsx +++ b/web/src/components/PalletsGrid.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react'; -import { Code, Database, TrendingUp, Gift, UserCheck, Award } from 'lucide-react'; +import { Code, Database, TrendingUp, Gift, Award } from 'lucide-react'; interface Pallet { id: string; @@ -61,7 +61,7 @@ const PalletsGrid: React.FC = () => { Core Runtime Pallets

- Modular blockchain components powering PezkuwiChain's advanced features + Modular blockchain components powering PezkuwiChain's advanced features

diff --git a/web/src/components/PolkadotWalletButton.tsx b/web/src/components/PolkadotWalletButton.tsx index c0d2837b..fdd64837 100644 --- a/web/src/components/PolkadotWalletButton.tsx +++ b/web/src/components/PolkadotWalletButton.tsx @@ -13,17 +13,16 @@ import { Wallet, Check, ExternalLink, Copy, LogOut } from 'lucide-react'; import { useToast } from '@/hooks/use-toast'; export const PolkadotWalletButton: React.FC = () => { - const { - accounts, - selectedAccount, - setSelectedAccount, - connectWallet, + const { + accounts, + selectedAccount, + setSelectedAccount, + connectWallet, disconnectWallet, - error + error } = usePolkadot(); - + const [isOpen, setIsOpen] = useState(false); - const [balance, setBalance] = useState('0'); const { toast } = useToast(); const handleConnect = async () => { @@ -205,7 +204,7 @@ export const PolkadotWalletButton: React.FC = () => {

- After installing, refresh this page and click "Connect Wallet" again. + After installing, refresh this page and click "Connect Wallet" again.

diff --git a/web/src/components/PoolDashboard.tsx b/web/src/components/PoolDashboard.tsx index cbb90dae..0a37766a 100644 --- a/web/src/components/PoolDashboard.tsx +++ b/web/src/components/PoolDashboard.tsx @@ -7,7 +7,6 @@ import { Badge } from '@/components/ui/badge'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { usePolkadot } from '@/contexts/PolkadotContext'; -import { useWallet } from '@/contexts/WalletContext'; import { ASSET_IDS, getAssetSymbol } from '@pezkuwi/lib/wallet'; import { AddLiquidityModal } from '@/components/AddLiquidityModal'; import { RemoveLiquidityModal } from '@/components/RemoveLiquidityModal'; @@ -45,7 +44,6 @@ interface LPPosition { const PoolDashboard = () => { const { api, isApiReady, selectedAccount } = usePolkadot(); - const { balances } = useWallet(); const [poolData, setPoolData] = useState(null); const [lpPosition, setLPPosition] = useState(null); @@ -82,7 +80,7 @@ const PoolDashboard = () => { setAvailablePools(existingPools); - // Set default pool to first available if current selection doesn't exist + // Set default pool to first available if current selection doesn't exist if (existingPools.length > 0) { const currentPoolKey = selectedPool; const poolExists = existingPools.some( @@ -99,7 +97,8 @@ const PoolDashboard = () => { }; discoverPools(); - }, [api, isApiReady]); + }, [api, isApiReady, selectedPool]); + // Fetch pool data useEffect(() => { @@ -119,7 +118,7 @@ const PoolDashboard = () => { const poolInfo = await api.query.assetConversion.pools(poolId); if (poolInfo.isSome) { - const lpTokenData = poolInfo.unwrap().toJSON() as any; + const lpTokenData = poolInfo.unwrap().toJSON() as Record; const lpTokenId = lpTokenData.lpToken; // Derive pool account using AccountIdConverter @@ -153,12 +152,12 @@ const PoolDashboard = () => { const asset2Decimals = getAssetDecimals(asset2); if (asset0BalanceData.isSome) { - const asset0Data = asset0BalanceData.unwrap().toJSON() as any; + const asset0Data = asset0BalanceData.unwrap().toJSON() as Record; reserve0 = Number(asset0Data.balance) / Math.pow(10, asset1Decimals); } if (asset1BalanceData.isSome) { - const asset1Data = asset1BalanceData.unwrap().toJSON() as any; + const asset1Data = asset1BalanceData.unwrap().toJSON() as Record; reserve1 = Number(asset1Data.balance) / Math.pow(10, asset2Decimals); } @@ -194,14 +193,14 @@ const PoolDashboard = () => { const lpBalance = await api.query.poolAssets.account(lpTokenId, selectedAccount.address); if (lpBalance.isSome) { - const lpData = lpBalance.unwrap().toJSON() as any; + const lpData = lpBalance.unwrap().toJSON() as Record; const userLpBalance = Number(lpData.balance) / 1e12; // Query total LP supply const lpAssetData = await api.query.poolAssets.asset(lpTokenId); if (lpAssetData.isSome) { - const assetInfo = lpAssetData.unwrap().toJSON() as any; + const assetInfo = lpAssetData.unwrap().toJSON() as Record; const totalSupply = Number(assetInfo.supply) / 1e12; // Calculate user's share diff --git a/web/src/components/ReceiveModal.tsx b/web/src/components/ReceiveModal.tsx index 66648471..7944dc0c 100644 --- a/web/src/components/ReceiveModal.tsx +++ b/web/src/components/ReceiveModal.tsx @@ -49,7 +49,7 @@ export const ReceiveModal: React.FC = ({ isOpen, onClose }) = }); setTimeout(() => setCopied(false), 2000); - } catch (error) { + } catch { toast({ title: "Copy Failed", description: "Failed to copy address to clipboard", diff --git a/web/src/components/RemoveLiquidityModal.tsx b/web/src/components/RemoveLiquidityModal.tsx index f1569437..ea5850b5 100644 --- a/web/src/components/RemoveLiquidityModal.tsx +++ b/web/src/components/RemoveLiquidityModal.tsx @@ -39,7 +39,6 @@ export const RemoveLiquidityModal: React.FC = ({ isOpen, onClose, lpPosition, - lpTokenId, asset0, asset1, }) => { @@ -70,7 +69,7 @@ export const RemoveLiquidityModal: React.FC = ({ // wHEZ is an asset in the assets pallet const assetDetails0 = await api.query.assets.asset(ASSET_IDS.WHEZ); if (assetDetails0.isSome) { - const details0 = assetDetails0.unwrap().toJSON() as any; + const details0 = assetDetails0.unwrap().toJSON() as Record; const min0 = Number(details0.minBalance) / Math.pow(10, getAssetDecimals(asset0)); setMinBalance0(min0); console.log(`📊 ${getDisplayTokenName(asset0)} minBalance: ${min0}`); @@ -79,7 +78,7 @@ export const RemoveLiquidityModal: React.FC = ({ // Other assets (PEZ, wUSDT, etc.) const assetDetails0 = await api.query.assets.asset(asset0); if (assetDetails0.isSome) { - const details0 = assetDetails0.unwrap().toJSON() as any; + const details0 = assetDetails0.unwrap().toJSON() as Record; const min0 = Number(details0.minBalance) / Math.pow(10, getAssetDecimals(asset0)); setMinBalance0(min0); console.log(`📊 ${getDisplayTokenName(asset0)} minBalance: ${min0}`); @@ -90,7 +89,7 @@ export const RemoveLiquidityModal: React.FC = ({ // wHEZ is an asset in the assets pallet const assetDetails1 = await api.query.assets.asset(ASSET_IDS.WHEZ); if (assetDetails1.isSome) { - const details1 = assetDetails1.unwrap().toJSON() as any; + const details1 = assetDetails1.unwrap().toJSON() as Record; const min1 = Number(details1.minBalance) / Math.pow(10, getAssetDecimals(asset1)); setMinBalance1(min1); console.log(`📊 ${getDisplayTokenName(asset1)} minBalance: ${min1}`); @@ -99,7 +98,7 @@ export const RemoveLiquidityModal: React.FC = ({ // Other assets (PEZ, wUSDT, etc.) const assetDetails1 = await api.query.assets.asset(asset1); if (assetDetails1.isSome) { - const details1 = assetDetails1.unwrap().toJSON() as any; + const details1 = assetDetails1.unwrap().toJSON() as Record; const min1 = Number(details1.minBalance) / Math.pow(10, getAssetDecimals(asset1)); setMinBalance1(min1); console.log(`📊 ${getDisplayTokenName(asset1)} minBalance: ${min1}`); diff --git a/web/src/components/ReservesDashboard.tsx b/web/src/components/ReservesDashboard.tsx index f4e23414..f5e9fb7c 100644 --- a/web/src/components/ReservesDashboard.tsx +++ b/web/src/components/ReservesDashboard.tsx @@ -53,7 +53,9 @@ export const ReservesDashboard: React.FC = ({ // Auto-refresh every 30 seconds const interval = setInterval(fetchReserveData, 30000); return () => clearInterval(interval); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [api, isApiReady, offChainReserve]); + const getHealthColor = () => { if (collateralRatio >= 105) return 'text-green-500'; diff --git a/web/src/components/RouteGuards.tsx b/web/src/components/RouteGuards.tsx index 67fe2763..0f7bb1fb 100644 --- a/web/src/components/RouteGuards.tsx +++ b/web/src/components/RouteGuards.tsx @@ -60,7 +60,7 @@ export const CitizenRoute: React.FC = ({ fallbackPath = '/be-citizen', }) => { const { api, isApiReady, selectedAccount } = usePolkadot(); - const { user } = useAuth(); + const {} = useAuth(); const [isCitizen, setIsCitizen] = useState(null); const [loading, setLoading] = useState(true); diff --git a/web/src/components/TokenSwap.tsx b/web/src/components/TokenSwap.tsx index 81a3e7e0..94663c6a 100644 --- a/web/src/components/TokenSwap.tsx +++ b/web/src/components/TokenSwap.tsx @@ -49,7 +49,12 @@ const TokenSwap = () => { console.log('🔍 Final balances:', { fromBalance, toBalance }); // Liquidity pool data - const [liquidityPools, setLiquidityPools] = useState([]); + interface LiquidityPool { + key: string; + data: unknown; + tvl: number; + } + const [liquidityPools, setLiquidityPools] = useState([]); const [isLoadingPools, setIsLoadingPools] = useState(false); // Transaction history @@ -89,7 +94,7 @@ const TokenSwap = () => { } const amountIn = parseFloat(fromAmount); - const { reserve0, reserve1, asset0, asset1 } = poolReserves; + const { reserve0, reserve1, asset0 } = poolReserves; // Determine which reserve is input and which is output const fromAssetId = fromToken === 'HEZ' ? 0 : ASSET_IDS[fromToken as keyof typeof ASSET_IDS]; @@ -208,7 +213,7 @@ const TokenSwap = () => { console.log('🔍 Pool isEmpty?', poolInfo.isEmpty, 'exists?', !poolInfo.isEmpty); if (poolInfo && !poolInfo.isEmpty) { - const pool = poolInfo.toJSON() as any; + const pool = poolInfo.toJSON() as Record; console.log('🔍 Pool data:', pool); try { @@ -250,8 +255,8 @@ const TokenSwap = () => { console.log('🔍 Reserve0 isEmpty?', reserve0Query.isEmpty); console.log('🔍 Reserve1 isEmpty?', reserve1Query.isEmpty); - const reserve0Data = reserve0Query.toJSON() as any; - const reserve1Data = reserve1Query.toJSON() as any; + const reserve0Data = reserve0Query.toJSON() as Record; + const reserve1Data = reserve1Query.toJSON() as Record; console.log('🔍 Reserve0 JSON:', reserve0Data); console.log('🔍 Reserve1 JSON:', reserve1Data); @@ -326,7 +331,7 @@ const TokenSwap = () => { const poolsEntries = await api.query.assetConversion.pools.entries(); if (poolsEntries && poolsEntries.length > 0) { - const pools = poolsEntries.map(([key, value]: any) => { + const pools = poolsEntries.map(([key, value]: [unknown, unknown]) => { const poolData = value.toJSON(); const poolKey = key.toHuman(); @@ -337,7 +342,7 @@ const TokenSwap = () => { // Parse asset IDs from pool key const assets = poolKey?.[0] || []; - const asset1 = assets[0]?.NativeOrAsset?.Asset || '?'; + //const _asset1 = assets[0]?.NativeOrAsset?.Asset || '?'; const asset2 = assets[1]?.NativeOrAsset?.Asset || '?'; return { @@ -389,16 +394,16 @@ const TokenSwap = () => { const blockHash = await api.rpc.chain.getBlockHash(blockNum); const apiAt = await api.at(blockHash); const events = await apiAt.query.system.events(); - const block = await api.rpc.chain.getBlock(blockHash); + //const block = await api.rpc.chain.getBlock(blockHash); const timestamp = Date.now() - ((currentBlockNumber - blockNum) * 6000); // Estimate 6s per block - events.forEach((record: any) => { + events.forEach((record: { event: { data: unknown[] } }) => { const { event } = record; // Check for AssetConversion::SwapExecuted event if (api.events.assetConversion?.SwapExecuted?.is(event)) { // SwapExecuted has 5 fields: (who, send_to, amountIn, amountOut, path) - const [who, sendTo, amountIn, amountOut, path] = event.data; + const [who, , amountIn, amountOut, path] = event.data; // Parse path to get token symbols - path is Vec let fromAssetId = 0; @@ -411,7 +416,7 @@ const TokenSwap = () => { if (Array.isArray(pathArray) && pathArray.length >= 2) { // Extract asset IDs from path const asset0 = pathArray[0]; - const asset1 = pathArray[1]; + //const _asset1 = pathArray[1]; // Each element is a tuple where index 0 is the asset ID if (Array.isArray(asset0) && asset0.length >= 1) { @@ -692,11 +697,11 @@ const TokenSwap = () => { const apiAt = await api.at(blockHash); const events = await apiAt.query.system.events(); const timestamp = Date.now() - ((currentBlockNumber - blockNum) * 6000); - events.forEach((record: any) => { + events.forEach((record: { event: { data: unknown[] } }) => { const { event } = record; if (api.events.assetConversion?.SwapExecuted?.is(event)) { // SwapExecuted has 5 fields: (who, send_to, amountIn, amountOut, path) - const [who, sendTo, amountIn, amountOut, path] = event.data; + const [who, , amountIn, amountOut, path] = event.data; // Parse path (same logic as main history fetch) let fromAssetId = 0; @@ -707,7 +712,7 @@ const TokenSwap = () => { if (Array.isArray(pathArray) && pathArray.length >= 2) { const asset0 = pathArray[0]; - const asset1 = pathArray[1]; + //const _asset1 = pathArray[1]; // Each element is a tuple where index 0 is the asset ID if (Array.isArray(asset0) && asset0.length >= 1) { @@ -763,11 +768,11 @@ const TokenSwap = () => { } } ); - } catch (error: any) { + } catch (error) { console.error('Swap failed:', error); toast({ title: 'Error', - description: error.message || 'Swap transaction failed', + description: error instanceof Error ? error.message : 'Swap transaction failed', variant: 'destructive', }); setIsSwapping(false); @@ -1056,7 +1061,7 @@ const TokenSwap = () => { - High price impact! Your trade will significantly affect the pool price. Consider a smaller amount or check if there's better liquidity. + High price impact! Your trade will significantly affect the pool price. Consider a smaller amount or check if there's better liquidity. )} diff --git a/web/src/components/TokenomicsSection.tsx b/web/src/components/TokenomicsSection.tsx index ab289484..7132bc64 100644 --- a/web/src/components/TokenomicsSection.tsx +++ b/web/src/components/TokenomicsSection.tsx @@ -1,18 +1,18 @@ import React, { useState, useEffect } from 'react'; -import { PieChart, Clock, TrendingDown, Coins, ArrowRightLeft } from 'lucide-react'; +import { PieChart, ArrowRightLeft } from 'lucide-react'; const TokenomicsSection: React.FC = () => { const [selectedToken, setSelectedToken] = useState<'PEZ' | 'HEZ'>('PEZ'); - const [monthsPassed, setMonthsPassed] = useState(0); - const [currentRelease, setCurrentRelease] = useState(0); + const [monthsPassed] = useState(0); const halvingPeriod = Math.floor(monthsPassed / 48); - const monthsUntilNextHalving = 48 - (monthsPassed % 48); + //const _monthsUntilNextHalving = 48 - (monthsPassed % 48); useEffect(() => { const baseAmount = selectedToken === 'PEZ' ? 74218750 : 37109375; - const release = baseAmount / Math.pow(2, halvingPeriod); - setCurrentRelease(release); + // Calculate release amount for future use + const releaseAmount = baseAmount / Math.pow(2, halvingPeriod); + console.log('Release amount:', releaseAmount); }, [monthsPassed, halvingPeriod, selectedToken]); const pezDistribution = [ diff --git a/web/src/components/TransactionHistory.tsx b/web/src/components/TransactionHistory.tsx index b4ba8810..d84ae39c 100644 --- a/web/src/components/TransactionHistory.tsx +++ b/web/src/components/TransactionHistory.tsx @@ -56,12 +56,12 @@ export const TransactionHistory: React.FC = ({ isOpen, const blockHash = await api.rpc.chain.getBlockHash(blockNumber); const block = await api.rpc.chain.getBlock(blockHash); - // Try to get timestamp, but don't fail if state is pruned + // Try to get timestamp, but don't fail if state is pruned let timestamp = 0; try { const ts = await api.query.timestamp.now.at(blockHash); timestamp = ts.toNumber(); - } catch (error) { + } catch { // State pruned, use current time as fallback timestamp = Date.now(); } @@ -168,7 +168,7 @@ export const TransactionHistory: React.FC = ({ isOpen, // Parse DEX operations else if (method.section === 'dex') { if (method.method === 'swap') { - const [path, amountIn] = method.args; + const [, amountIn] = method.args; txList.push({ blockNumber, extrinsicIndex: index, @@ -231,7 +231,7 @@ export const TransactionHistory: React.FC = ({ isOpen, console.log('Found transactions:', txList.length); setTransactions(txList); - } catch (error) { + } catch { console.error('Failed to fetch transactions:', error); toast({ title: "Error", @@ -247,7 +247,9 @@ export const TransactionHistory: React.FC = ({ isOpen, if (isOpen) { fetchTransactions(); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [isOpen, api, isApiReady, selectedAccount]); + const formatAmount = (amount: string, decimals: number = 12) => { const value = parseInt(amount) / Math.pow(10, decimals); @@ -302,7 +304,7 @@ export const TransactionHistory: React.FC = ({ isOpen,

) : ( - transactions.map((tx, index) => ( + transactions.map((tx) => (
= ({ isOpen, onClose, s const unsub = await transfer.signAndSend( selectedAccount.address, { signer: injector.signer }, - ({ status, events, dispatchError }) => { + ({ status, dispatchError }) => { if (status.isInBlock) { console.log(`Transaction included in block: ${status.asInBlock}`); setTxHash(status.asInBlock.toHex()); @@ -170,14 +170,14 @@ export const TransferModal: React.FC = ({ isOpen, onClose, s } } ); - } catch (error: any) { + } catch (error) { console.error('Transfer error:', error); setTxStatus('error'); setIsTransferring(false); - + toast({ title: "Transfer Failed", - description: error.message || "An error occurred during transfer", + description: error instanceof Error ? error.message : "An error occurred during transfer", variant: "destructive", }); } diff --git a/web/src/components/admin/CommissionSetupTab.tsx b/web/src/components/admin/CommissionSetupTab.tsx index 49b27d9b..024a7645 100644 --- a/web/src/components/admin/CommissionSetupTab.tsx +++ b/web/src/components/admin/CommissionSetupTab.tsx @@ -2,7 +2,6 @@ import { useState, useEffect } from 'react'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; -import { Input } from '@/components/ui/input'; import { useToast } from '@/hooks/use-toast'; import { usePolkadot } from '@/contexts/PolkadotContext'; import { Loader2, Plus, CheckCircle, AlertTriangle, Shield } from 'lucide-react'; @@ -15,7 +14,6 @@ export function CommissionSetupTab() { const [loading, setLoading] = useState(true); const [commissionMembers, setCommissionMembers] = useState([]); - const [proxyMembers, setProxyMembers] = useState([]); const [setupComplete, setSetupComplete] = useState(false); const [processing, setProcessing] = useState(false); const [newMemberAddress, setNewMemberAddress] = useState(''); @@ -23,7 +21,9 @@ export function CommissionSetupTab() { useEffect(() => { if (!api || !isApiReady) return; checkSetup(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [api, isApiReady]); + const checkSetup = async () => { if (!api) return; @@ -35,7 +35,7 @@ export function CommissionSetupTab() { const memberList = members.toJSON() as string[]; setCommissionMembers(memberList); - // Commission is initialized if there's at least one member + // Commission is initialized if there's at least one member setSetupComplete(memberList.length > 0); console.log('Commission members:', memberList); @@ -149,11 +149,11 @@ export function CommissionSetupTab() { } ); }); - } catch (error: any) { + } catch (error) { console.error('Error adding member:', error); toast({ title: 'Error', - description: error.message || 'Failed to add member', + description: error instanceof Error ? error.message : 'Failed to add member', variant: 'destructive', }); } finally { @@ -239,7 +239,7 @@ export function CommissionSetupTab() { console.error('Failed to sign and send:', error); toast({ title: 'Transaction Error', - description: error.message || 'Failed to submit transaction', + description: error instanceof Error ? error.message : 'Failed to submit transaction', variant: 'destructive', }); reject(error); @@ -249,11 +249,11 @@ export function CommissionSetupTab() { // Reload setup status setTimeout(() => checkSetup(), 2000); - } catch (error: any) { + } catch (error) { console.error('Error initializing commission:', error); toast({ title: 'Error', - description: error.message || 'Failed to initialize commission', + description: error instanceof Error ? error.message : 'Failed to initialize commission', variant: 'destructive', }); } finally { diff --git a/web/src/components/admin/CommissionVotingTab.tsx b/web/src/components/admin/CommissionVotingTab.tsx index a1414a66..0e04a228 100644 --- a/web/src/components/admin/CommissionVotingTab.tsx +++ b/web/src/components/admin/CommissionVotingTab.tsx @@ -4,7 +4,7 @@ import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { useToast } from '@/hooks/use-toast'; import { usePolkadot } from '@/contexts/PolkadotContext'; -import { Loader2, ThumbsUp, ThumbsDown, CheckCircle, Clock, RefreshCw } from 'lucide-react'; +import { Loader2, ThumbsUp, ThumbsDown, Clock, RefreshCw } from 'lucide-react'; import { Table, TableBody, @@ -22,7 +22,7 @@ interface Proposal { ayes: string[]; nays: string[]; end: number; - call?: any; + call?: unknown; } export function CommissionVotingTab() { @@ -41,7 +41,9 @@ export function CommissionVotingTab() { checkMembership(); loadProposals(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [api, isApiReady, selectedAccount]); + const checkMembership = async () => { if (!api || !selectedAccount) { @@ -99,14 +101,14 @@ export function CommissionVotingTab() { } // Get the actual proposal index from the chain - const proposalIndex = (voteData as any).index?.toNumber() || i; + const proposalIndex = (voteData as Record).index?.toNumber() || i; proposalList.push({ hash: hash.toHex(), proposalIndex: proposalIndex, threshold: voteData.threshold.toNumber(), - ayes: voteData.ayes.map((a: any) => a.toString()), - nays: voteData.nays.map((n: any) => n.toString()), + ayes: voteData.ayes.map((a: { toString: () => string }) => a.toString()), + nays: voteData.nays.map((n: { toString: () => string }) => n.toString()), end: voteData.end.toNumber(), call: proposalCall?.toHuman(), }); @@ -219,7 +221,7 @@ export function CommissionVotingTab() { console.error('Failed to sign and send:', error); toast({ title: 'Transaction Error', - description: error.message || 'Failed to submit transaction', + description: error instanceof Error ? error.message : 'Failed to submit transaction', variant: 'destructive', }); reject(error); @@ -231,11 +233,11 @@ export function CommissionVotingTab() { loadProposals(); }, 2000); - } catch (error: any) { + } catch (error) { console.error('Error voting:', error); toast({ title: 'Error', - description: error.message || 'Failed to vote', + description: error instanceof Error ? error.message : 'Failed to vote', variant: 'destructive', }); } finally { @@ -347,7 +349,7 @@ export function CommissionVotingTab() { console.error('Failed to sign and send:', error); toast({ title: 'Transaction Error', - description: error.message || 'Failed to submit transaction', + description: error instanceof Error ? error.message : 'Failed to submit transaction', variant: 'destructive', }); reject(error); @@ -358,11 +360,11 @@ export function CommissionVotingTab() { loadProposals(); }, 2000); - } catch (error: any) { + } catch (error) { console.error('Error executing:', error); toast({ title: 'Error', - description: error.message || 'Failed to execute proposal', + description: error instanceof Error ? error.message : 'Failed to execute proposal', variant: 'destructive', }); } finally { @@ -370,7 +372,7 @@ export function CommissionVotingTab() { } }; - const getProposalDescription = (call: any): string => { + const getProposalDescription = (call: Record): string => { if (!call) return 'Unknown proposal'; try { @@ -479,10 +481,10 @@ export function CommissionVotingTab() { } } ); - } catch (error: any) { + } catch (error) { toast({ title: 'Error', - description: error.message || 'Failed to join commission', + description: error instanceof Error ? error.message : 'Failed to join commission', variant: 'destructive', }); } diff --git a/web/src/components/admin/KycApprovalTab.tsx b/web/src/components/admin/KycApprovalTab.tsx index 3d985335..80731486 100644 --- a/web/src/components/admin/KycApprovalTab.tsx +++ b/web/src/components/admin/KycApprovalTab.tsx @@ -4,7 +4,7 @@ import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { useToast } from '@/hooks/use-toast'; import { usePolkadot } from '@/contexts/PolkadotContext'; -import { Loader2, CheckCircle, XCircle, Clock, User, Mail, MapPin, FileText, AlertTriangle } from 'lucide-react'; +import { Loader2, CheckCircle, XCircle, Clock, User, Mail, FileText, AlertTriangle } from 'lucide-react'; import { COMMISSIONS } from '@/config/commissions'; import { Table, @@ -54,7 +54,9 @@ export function KycApprovalTab() { } loadPendingApplications(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [api, isApiReady]); + const loadPendingApplications = async () => { if (!api || !isApiReady) { @@ -72,13 +74,13 @@ export function KycApprovalTab() { for (const [key, value] of entries) { const address = key.args[0].toString(); - const application = value.toJSON() as any; + const application = value.toJSON() as Record; // Get identity info for this address try { const identity = await api.query.identityKyc.identities(address); if (!identity.isEmpty) { - const identityData = identity.toJSON() as any; + const identityData = identity.toJSON() as Record; identityMap.set(address, { name: identityData.name || 'Unknown', email: identityData.email || 'No email' @@ -215,7 +217,7 @@ export function KycApprovalTab() { console.error('Failed to sign and send:', error); toast({ title: 'Transaction Error', - description: error.message || 'Failed to submit transaction', + description: error instanceof Error ? error.message : 'Failed to submit transaction', variant: 'destructive', }); reject(error); @@ -229,11 +231,11 @@ export function KycApprovalTab() { setSelectedApp(null); }, 2000); - } catch (error: any) { + } catch (error) { console.error('Error approving KYC:', error); toast({ title: 'Error', - description: error.message || 'Failed to approve KYC', + description: error instanceof Error ? error.message : 'Failed to approve KYC', variant: 'destructive', }); } finally { @@ -315,11 +317,11 @@ export function KycApprovalTab() { setSelectedApp(null); }, 2000); - } catch (error: any) { + } catch (error) { console.error('Error rejecting KYC:', error); toast({ title: 'Error', - description: error.message || 'Failed to reject KYC', + description: error instanceof Error ? error.message : 'Failed to reject KYC', variant: 'destructive', }); } finally { @@ -513,7 +515,7 @@ export function KycApprovalTab() { Important: Approving this application will:
    -
  • Unreserve the applicant's deposit
  • +
  • Unreserve the applicant's deposit
  • Mint a Welati (Citizen) NFT automatically
  • Enable trust score tracking
  • Grant governance voting rights
  • diff --git a/web/src/components/auth/TwoFactorSetup.tsx b/web/src/components/auth/TwoFactorSetup.tsx index e927fcac..e0bd32de 100644 --- a/web/src/components/auth/TwoFactorSetup.tsx +++ b/web/src/components/auth/TwoFactorSetup.tsx @@ -59,11 +59,11 @@ export function TwoFactorSetup() { setIsLoading(true); try { - const { data, error } = await supabase.functions.invoke('two-factor-auth', { - body: { - action: 'enable', + const { error } = await supabase.functions.invoke('two-factor-auth', { + body: { + action: 'enable', userId: user?.id, - code: verificationCode + code: verificationCode } }); @@ -90,7 +90,7 @@ export function TwoFactorSetup() { const handleDisable = async () => { setIsLoading(true); try { - const { data, error } = await supabase.functions.invoke('two-factor-auth', { + const { error } = await supabase.functions.invoke('two-factor-auth', { body: { action: 'disable', userId: user?.id } }); diff --git a/web/src/components/citizenship/ExistingCitizenAuth.tsx b/web/src/components/citizenship/ExistingCitizenAuth.tsx index c28aeb2a..fd049f9c 100644 --- a/web/src/components/citizenship/ExistingCitizenAuth.tsx +++ b/web/src/components/citizenship/ExistingCitizenAuth.tsx @@ -41,7 +41,7 @@ export const ExistingCitizenAuth: React.FC = ({ onClos const isValid = await verifyCitizenNumber(api, citizenNumber, selectedAccount.address); if (!isValid) { - setError(`Invalid Citizen Number or it doesn't match your wallet`); + setError(`Invalid Citizen Number or it doesn't match your wallet`); setStep('error'); return; } @@ -50,7 +50,7 @@ export const ExistingCitizenAuth: React.FC = ({ onClos const authChallenge = generateAuthChallenge(citizenNumber); setChallenge(authChallenge); setStep('signing'); - } catch (err) { + } catch { console.error('Verification error:', err); setError('Failed to verify Citizen Number'); setStep('error'); @@ -96,7 +96,7 @@ export const ExistingCitizenAuth: React.FC = ({ onClos onClose(); window.location.href = '/citizens'; }, 2000); - } catch (err) { + } catch { console.error('Signature error:', err); setError('Failed to sign authentication challenge'); setStep('error'); @@ -106,7 +106,7 @@ export const ExistingCitizenAuth: React.FC = ({ onClos const handleConnectWallet = async () => { try { await connectWallet(); - } catch (err) { + } catch { setError('Failed to connect wallet'); } }; diff --git a/web/src/components/citizenship/NewCitizenApplication.tsx b/web/src/components/citizenship/NewCitizenApplication.tsx index b2c165f1..6850cf62 100644 --- a/web/src/components/citizenship/NewCitizenApplication.tsx +++ b/web/src/components/citizenship/NewCitizenApplication.tsx @@ -8,7 +8,7 @@ import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'; import { Alert, AlertDescription } from '@/components/ui/alert'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Checkbox } from '@/components/ui/checkbox'; -import { Loader2, AlertTriangle, CheckCircle, User, Users as UsersIcon, MapPin, Briefcase, Mail, Clock, Check, X, AlertCircle } from 'lucide-react'; +import { Loader2, AlertTriangle, CheckCircle, User, Users as UsersIcon, MapPin, Briefcase, Mail, Check, X, AlertCircle } from 'lucide-react'; import { usePolkadot } from '@/contexts/PolkadotContext'; import type { CitizenshipData, Region, MaritalStatus } from '@pezkuwi/lib/citizenship-workflow'; import { FOUNDER_ADDRESS, submitKycApplication, subscribeToKycApproval, getKycStatus } from '@pezkuwi/lib/citizenship-workflow'; @@ -31,7 +31,6 @@ export const NewCitizenApplication: React.FC = ({ on const [kycApproved, setKycApproved] = useState(false); const [error, setError] = useState(null); const [agreed, setAgreed] = useState(false); - const [checkingStatus, setCheckingStatus] = useState(false); const [confirming, setConfirming] = useState(false); const [applicationHash, setApplicationHash] = useState(''); @@ -91,9 +90,9 @@ export const NewCitizenApplication: React.FC = ({ on } }); - } catch (err: any) { + } catch (err) { console.error('Approval error:', err); - setError(err.message || 'Failed to approve application'); + setError((err as Error).message || 'Failed to approve application'); setConfirming(false); } }; @@ -460,19 +459,19 @@ export const NewCitizenApplication: React.FC = ({ on
- + {errors.fatherName &&

Required

}
- + {errors.grandfatherName &&

Required

}
- + {errors.motherName &&

Required

}
@@ -533,7 +532,7 @@ export const NewCitizenApplication: React.FC = ({ on {childrenCount && childrenCount > 0 && (
- + {Array.from({ length: childrenCount }).map((_, i) => (
; } export function CommissionProposalsCard() { @@ -29,6 +29,7 @@ export function CommissionProposalsCard() { if (!api || !isApiReady) return; checkMembership(); loadProposals(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [api, isApiReady, selectedAccount]); const checkMembership = async () => { @@ -72,14 +73,14 @@ export function CommissionProposalsCard() { } // Get the actual proposal index from the chain - const proposalIndex = (voteData as any).index?.toNumber() || i; + const proposalIndex = (voteData as Record).index?.toNumber() || i; proposalList.push({ hash: hash.toHex(), proposalIndex: proposalIndex, threshold: voteData.threshold.toNumber(), - ayes: voteData.ayes.map((a: any) => a.toString()), - nays: voteData.nays.map((n: any) => n.toString()), + ayes: voteData.ayes.map((a: { toString: () => string }) => a.toString()), + nays: voteData.nays.map((n: { toString: () => string }) => n.toString()), end: voteData.end.toNumber(), call: proposalCall?.toHuman(), }); @@ -165,7 +166,7 @@ export function CommissionProposalsCard() { ).catch((error) => { toast({ title: 'Transaction Error', - description: error.message || 'Failed to submit transaction', + description: error instanceof Error ? error.message : 'Failed to submit transaction', variant: 'destructive', }); reject(error); @@ -173,10 +174,10 @@ export function CommissionProposalsCard() { }); setTimeout(() => loadProposals(), 2000); - } catch (error: any) { + } catch (error) { toast({ title: 'Error', - description: error.message || 'Failed to vote', + description: error instanceof Error ? error.message : 'Failed to vote', variant: 'destructive', }); } finally { @@ -280,7 +281,7 @@ export function CommissionProposalsCard() { ).catch((error) => { toast({ title: 'Transaction Error', - description: error.message || 'Failed to submit transaction', + description: error instanceof Error ? error.message : 'Failed to submit transaction', variant: 'destructive', }); reject(error); @@ -288,10 +289,10 @@ export function CommissionProposalsCard() { }); setTimeout(() => loadProposals(), 2000); - } catch (error: any) { + } catch (error) { toast({ title: 'Error', - description: error.message || 'Failed to execute proposal', + description: error instanceof Error ? error.message : 'Failed to execute proposal', variant: 'destructive', }); } finally { diff --git a/web/src/components/delegation/DelegationManager.tsx b/web/src/components/delegation/DelegationManager.tsx index f9168c1c..0abb0d69 100644 --- a/web/src/components/delegation/DelegationManager.tsx +++ b/web/src/components/delegation/DelegationManager.tsx @@ -6,9 +6,8 @@ import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Badge } from '@/components/ui/badge'; -import { Progress } from '@/components/ui/progress'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; -import { Users, TrendingUp, Shield, Clock, ChevronRight, Award, Loader2, Activity } from 'lucide-react'; +import { Users, TrendingUp, Shield, Clock, ChevronRight, Award, Activity } from 'lucide-react'; import DelegateProfile from './DelegateProfile'; import { useDelegation } from '@/hooks/useDelegation'; import { usePolkadot } from '@/contexts/PolkadotContext'; @@ -19,7 +18,7 @@ const DelegationManager: React.FC = () => { const { t } = useTranslation(); const { selectedAccount } = usePolkadot(); const { delegates, userDelegations, stats, loading, error } = useDelegation(selectedAccount?.address); - const [selectedDelegate, setSelectedDelegate] = useState(null); + const [selectedDelegate, setSelectedDelegate] = useState | null>(null); const [delegationAmount, setDelegationAmount] = useState(''); const [delegationPeriod, setDelegationPeriod] = useState('3months'); @@ -257,7 +256,7 @@ const DelegationManager: React.FC = () => { {selectedAccount - ? "You haven't delegated any voting power yet." + ? "You haven't delegated any voting power yet." : "Connect your wallet to view your delegations."} diff --git a/web/src/components/dex/AddLiquidityModal.tsx b/web/src/components/dex/AddLiquidityModal.tsx index 9876e0a6..f99d7973 100644 --- a/web/src/components/dex/AddLiquidityModal.tsx +++ b/web/src/components/dex/AddLiquidityModal.tsx @@ -181,9 +181,9 @@ export const AddLiquidityModal: React.FC = ({ } } ); - } catch (error: any) { + } catch (error) { console.error('Add liquidity failed:', error); - setErrorMessage(error.message || 'Transaction failed'); + setErrorMessage(error instanceof Error ? error.message : 'Transaction failed'); setTxStatus('error'); } }; @@ -238,7 +238,7 @@ export const AddLiquidityModal: React.FC = ({
- Add liquidity in proportion to the pool's current ratio. You'll receive LP tokens representing your share. + Add liquidity in proportion to the pool's current ratio. You'll receive LP tokens representing your share.
diff --git a/web/src/components/dex/CreatePoolModal.tsx b/web/src/components/dex/CreatePoolModal.tsx index df74a61f..d8f2f710 100644 --- a/web/src/components/dex/CreatePoolModal.tsx +++ b/web/src/components/dex/CreatePoolModal.tsx @@ -212,9 +212,9 @@ export const CreatePoolModal: React.FC = ({ } } ); - } catch (error: any) { + } catch (error) { console.error('Pool creation failed:', error); - setErrorMessage(error.message || 'Transaction failed'); + setErrorMessage(error instanceof Error ? error.message : 'Transaction failed'); setTxStatus('error'); } }; diff --git a/web/src/components/dex/DEXDashboard.tsx b/web/src/components/dex/DEXDashboard.tsx index 4283aa91..4331e1fa 100644 --- a/web/src/components/dex/DEXDashboard.tsx +++ b/web/src/components/dex/DEXDashboard.tsx @@ -1,16 +1,15 @@ import React, { useState } from 'react'; -import { useNavigate } from 'react-router-dom'; +// import { useNavigate } from 'react-router-dom'; import { useWallet } from '@/contexts/WalletContext'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import TokenSwap from '@/components/TokenSwap'; import PoolDashboard from '@/components/PoolDashboard'; import { CreatePoolModal } from './CreatePoolModal'; import { InitializeHezPoolModal } from './InitializeHezPoolModal'; -import { ArrowRightLeft, Droplet, Settings, Home } from 'lucide-react'; +import { ArrowRightLeft, Droplet, Settings } from 'lucide-react'; import { isFounderWallet } from '@pezkuwi/utils/auth'; export const DEXDashboard: React.FC = () => { - const navigate = useNavigate(); const { account } = useWallet(); const [activeTab, setActiveTab] = useState('swap'); diff --git a/web/src/components/dex/InitializeHezPoolModal.tsx b/web/src/components/dex/InitializeHezPoolModal.tsx index 31bd45eb..b96592c5 100644 --- a/web/src/components/dex/InitializeHezPoolModal.tsx +++ b/web/src/components/dex/InitializeHezPoolModal.tsx @@ -144,13 +144,13 @@ export const InitializeHezPoolModal: React.FC = ({ } } ); - } catch (error: any) { + } catch (error) { console.error('Wrap failed:', error); - setErrorMessage(error.message || 'Transaction failed'); + setErrorMessage(error instanceof Error ? error.message : 'Transaction failed'); setTxStatus('error'); toast({ title: 'Error', - description: error.message || 'Wrap failed', + description: error instanceof Error ? error.message : 'Wrap failed', variant: 'destructive', }); } diff --git a/web/src/components/dex/PoolBrowser.tsx b/web/src/components/dex/PoolBrowser.tsx index 0e0752dc..d2c103cb 100644 --- a/web/src/components/dex/PoolBrowser.tsx +++ b/web/src/components/dex/PoolBrowser.tsx @@ -3,7 +3,7 @@ import { usePolkadot } from '@/contexts/PolkadotContext'; import { useWallet } from '@/contexts/WalletContext'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; -import { TrendingUp, Droplet, BarChart3, Search, Plus } from 'lucide-react'; +import { TrendingUp, Droplet, Search, Plus } from 'lucide-react'; import { PoolInfo } from '@/types/dex'; import { fetchPools, formatTokenBalance } from '@pezkuwi/utils/dex'; import { isFounderWallet } from '@pezkuwi/utils/auth'; @@ -27,7 +27,6 @@ export const PoolBrowser: React.FC = ({ const [pools, setPools] = useState([]); const [loading, setLoading] = useState(true); const [searchTerm, setSearchTerm] = useState(''); - const [sortBy, setSortBy] = useState<'tvl' | 'volume' | 'apr'>('tvl'); const isFounder = account ? isFounderWallet(account.address) : false; diff --git a/web/src/components/dex/RemoveLiquidityModal.tsx b/web/src/components/dex/RemoveLiquidityModal.tsx index 15d76e4f..5e5fb220 100644 --- a/web/src/components/dex/RemoveLiquidityModal.tsx +++ b/web/src/components/dex/RemoveLiquidityModal.tsx @@ -60,9 +60,9 @@ export const RemoveLiquidityModal: React.FC = ({ // LP token ID is derived from pool ID // For now, we'll query the pool's LP token supply // In a real implementation, you'd need to query the specific LP token for the user - const lpAssetId = api.query.assetConversion.nextPoolAssetId - ? await api.query.assetConversion.nextPoolAssetId() - : null; + if (api.query.assetConversion.nextPoolAssetId) { + await api.query.assetConversion.nextPoolAssetId(); + } // This is a simplified version - you'd need to track LP tokens properly setLpTokenBalance('0'); // Placeholder @@ -153,9 +153,9 @@ export const RemoveLiquidityModal: React.FC = ({ } } ); - } catch (error: any) { + } catch (error) { console.error('Remove liquidity failed:', error); - setErrorMessage(error.message || 'Transaction failed'); + setErrorMessage(error instanceof Error ? error.message : 'Transaction failed'); setTxStatus('error'); } }; @@ -190,7 +190,7 @@ export const RemoveLiquidityModal: React.FC = ({
- Remove liquidity to receive your tokens back. You'll burn LP tokens in proportion to your withdrawal. + Remove liquidity to receive your tokens back. You'll burn LP tokens in proportion to your withdrawal.
diff --git a/web/src/components/dex/SwapInterface.tsx b/web/src/components/dex/SwapInterface.tsx index b4ab0611..970c47a2 100644 --- a/web/src/components/dex/SwapInterface.tsx +++ b/web/src/components/dex/SwapInterface.tsx @@ -1,7 +1,7 @@ import React, { useState, useEffect } from 'react'; import { usePolkadot } from '@/contexts/PolkadotContext'; import { useWallet } from '@/contexts/WalletContext'; -import { ArrowDownUp, AlertCircle, Loader2, CheckCircle, Info, Settings, AlertTriangle } from 'lucide-react'; +import { ArrowDownUp, AlertCircle, Loader2, Info, Settings, AlertTriangle } from 'lucide-react'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; @@ -31,7 +31,7 @@ const USER_TOKENS = [ { symbol: 'USDT', emoji: '💵', assetId: 2, name: 'USDT', decimals: 6, displaySymbol: 'USDT' }, ] as const; -export const SwapInterface: React.FC = ({ initialPool, pools }) => { +export const SwapInterface: React.FC = ({ pools }) => { const { api, isApiReady } = usePolkadot(); const { account, signer } = useWallet(); const { toast } = useToast(); @@ -171,7 +171,6 @@ export const SwapInterface: React.FC = ({ initialPool, pools const handleSwapDirection = () => { const tempToken = fromToken; - const tempAmount = fromAmount; const tempBalance = fromBalance; setFromToken(toToken); @@ -321,13 +320,13 @@ export const SwapInterface: React.FC = ({ initialPool, pools } } ); - } catch (error: any) { + } catch (error) { console.error('Swap failed:', error); - setErrorMessage(error.message || 'Transaction failed'); + setErrorMessage(error instanceof Error ? error.message : 'Transaction failed'); setTxStatus('error'); toast({ title: 'Error', - description: error.message || 'Swap transaction failed', + description: error instanceof Error ? error.message : 'Swap transaction failed', variant: 'destructive', }); } diff --git a/web/src/components/forum/DiscussionThread.tsx b/web/src/components/forum/DiscussionThread.tsx index 5fdeeb74..771f130e 100644 --- a/web/src/components/forum/DiscussionThread.tsx +++ b/web/src/components/forum/DiscussionThread.tsx @@ -4,8 +4,8 @@ import { Button } from '@/components/ui/button'; import { Textarea } from '@/components/ui/textarea'; import { Badge } from '@/components/ui/badge'; import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; -import { ThumbsUp, ThumbsDown, MessageSquare, Shield, Award, TrendingUp, AlertTriangle, MoreVertical, Flag, Edit, Trash2, Loader2 } from 'lucide-react'; -import { useTranslation } from 'react-i18next'; +import { ThumbsUp, ThumbsDown, MessageSquare, Shield, MoreVertical, Flag, Edit, Trash2 } from 'lucide-react'; +// import { useTranslation } from 'react-i18next'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'; import { useWebSocket } from '@/contexts/WebSocketContext'; import { useToast } from '@/hooks/use-toast'; @@ -27,10 +27,8 @@ interface Comment { } export function DiscussionThread({ proposalId }: { proposalId: string }) { - const { t } = useTranslation(); const { toast } = useToast(); const { subscribe, unsubscribe, sendMessage, isConnected } = useWebSocket(); - const [isLoading, setIsLoading] = useState(false); const [comments, setComments] = useState([ { id: '1', @@ -83,7 +81,7 @@ export function DiscussionThread({ proposalId }: { proposalId: string }) { // WebSocket subscriptions for real-time updates useEffect(() => { - const handleNewComment = (data: any) => { + const handleNewComment = (data: Record) => { const newComment: Comment = { ...data, isLive: true, @@ -103,7 +101,7 @@ export function DiscussionThread({ proposalId }: { proposalId: string }) { setComments(prev => updateVoteCounts(prev, data.commentId, data.upvotes, data.downvotes)); }; - const handleSentimentUpdate = (data: { proposalId: string; sentiment: any }) => { + const handleSentimentUpdate = (data: { proposalId: string; sentiment: Record }) => { if (data.proposalId === proposalId) { // Update sentiment visualization in parent component console.log('Sentiment updated:', data.sentiment); @@ -119,7 +117,9 @@ export function DiscussionThread({ proposalId }: { proposalId: string }) { unsubscribe('vote', handleVoteUpdate); unsubscribe('sentiment', handleSentimentUpdate); }; + // eslint-disable-next-line react-hooks/exhaustive-deps }, [subscribe, unsubscribe, proposalId, toast]); + const updateVoteCounts = (comments: Comment[], targetId: string, upvotes: number, downvotes: number): Comment[] => { return comments.map(comment => { @@ -154,6 +154,7 @@ export function DiscussionThread({ proposalId }: { proposalId: string }) { timestamp: Date.now(), }); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [comments, isConnected, sendMessage, proposalId]); const findComment = (comments: Comment[], targetId: string): Comment | null => { diff --git a/web/src/components/forum/ForumOverview.tsx b/web/src/components/forum/ForumOverview.tsx index e90e8d85..53202b57 100644 --- a/web/src/components/forum/ForumOverview.tsx +++ b/web/src/components/forum/ForumOverview.tsx @@ -1,10 +1,10 @@ import React, { useState } from 'react'; -import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; +import { Card, CardContent } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Badge } from '@/components/ui/badge'; import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; -import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; +// Tabs not currently used from '@/components/ui/tabs'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { LoadingState } from '@pezkuwi/components/AsyncComponent'; import { @@ -24,19 +24,17 @@ import { AlertTriangle, Info, CheckCircle, - Eye, - Loader2 + Eye } from 'lucide-react'; -import { useTranslation } from 'react-i18next'; +// import { useTranslation } from 'react-i18next'; import { useForum } from '@/hooks/useForum'; import { DiscussionThread } from './DiscussionThread'; import { useAuth } from '@/contexts/AuthContext'; import { formatDistanceToNow } from 'date-fns'; export function ForumOverview() { - const { t } = useTranslation(); const { user } = useAuth(); - const { announcements, categories, discussions, loading, error, reactToDiscussion } = useForum(); + const { announcements, categories, discussions, loading, reactToDiscussion } = useForum(); const [selectedDiscussion, setSelectedDiscussion] = useState(null); const [searchQuery, setSearchQuery] = useState(''); const [sortBy, setSortBy] = useState('recent'); diff --git a/web/src/components/forum/ModerationPanel.tsx b/web/src/components/forum/ModerationPanel.tsx index ac930bef..e120cc99 100644 --- a/web/src/components/forum/ModerationPanel.tsx +++ b/web/src/components/forum/ModerationPanel.tsx @@ -6,9 +6,8 @@ import { Badge } from '@/components/ui/badge'; import { Alert, AlertDescription } from '@/components/ui/alert'; import { Switch } from '@/components/ui/switch'; import { Label } from '@/components/ui/label'; -import { Textarea } from '@/components/ui/textarea'; -import { AlertTriangle, Shield, Ban, CheckCircle, Clock, Flag, User, MessageSquare, TrendingUp } from 'lucide-react'; -import { useTranslation } from 'react-i18next'; +import { AlertTriangle, Shield, Ban, CheckCircle, Clock, Flag, User } from 'lucide-react'; +// import { useTranslation } from 'react-i18next'; interface Report { id: string; @@ -22,7 +21,6 @@ interface Report { } export function ModerationPanel() { - const { t } = useTranslation(); const [autoModeration, setAutoModeration] = useState(true); const [sentimentThreshold, setSentimentThreshold] = useState(30); diff --git a/web/src/components/governance/ElectionsInterface.tsx b/web/src/components/governance/ElectionsInterface.tsx index a4f3de75..bf735b7b 100644 --- a/web/src/components/governance/ElectionsInterface.tsx +++ b/web/src/components/governance/ElectionsInterface.tsx @@ -4,7 +4,7 @@ import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Progress } from '@/components/ui/progress'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; -import { Users, Vote, Trophy, Clock, AlertCircle, CheckCircle } from 'lucide-react'; +import { Vote, Trophy, AlertCircle, CheckCircle } from 'lucide-react'; interface Election { id: number; @@ -26,7 +26,6 @@ interface Candidate { } const ElectionsInterface: React.FC = () => { - const [selectedElection, setSelectedElection] = useState(null); const [votedCandidates, setVotedCandidates] = useState([]); const activeElections: Election[] = [ diff --git a/web/src/components/governance/GovernanceOverview.tsx b/web/src/components/governance/GovernanceOverview.tsx index 65f1c882..3751a868 100644 --- a/web/src/components/governance/GovernanceOverview.tsx +++ b/web/src/components/governance/GovernanceOverview.tsx @@ -1,8 +1,8 @@ import React, { useState, useEffect } from 'react'; import { Vote, Users, Gavel, FileText, TrendingUpIcon, - Clock, CheckCircle, XCircle, AlertCircle, - BarChart3, PieChart, Activity, Shield + CheckCircle, + PieChart, Activity, Shield } from 'lucide-react'; import { Card, CardContent, CardHeader, CardTitle } from '../ui/card'; import { Badge } from '../ui/badge'; diff --git a/web/src/components/governance/ProposalsList.tsx b/web/src/components/governance/ProposalsList.tsx index 8ecb8a95..cc82dfd5 100644 --- a/web/src/components/governance/ProposalsList.tsx +++ b/web/src/components/governance/ProposalsList.tsx @@ -1,5 +1,4 @@ -import React, { useState } from 'react'; -import { FileText, Vote, Clock, TrendingUp, Users, AlertCircle, Loader2, Activity } from 'lucide-react'; +import { Clock, Users, AlertCircle, Activity } from 'lucide-react'; import { Card, CardContent, CardHeader, CardTitle } from '../ui/card'; import { Badge } from '../ui/badge'; import { Button } from '../ui/button'; @@ -43,7 +42,7 @@ const ProposalsList: React.FC = () => { proposer: p.proposer, type: 'treasury' as const, status: p.status as 'active' | 'passed' | 'rejected' | 'pending', - ayeVotes: 0, // Treasury proposals don't have votes until they become referenda + ayeVotes: 0, // Treasury proposals don't have votes until they become referenda nayVotes: 0, totalVotes: 0, quorum: 0, diff --git a/web/src/components/notifications/NotificationBell.tsx b/web/src/components/notifications/NotificationBell.tsx index 94c605c3..fa1addce 100644 --- a/web/src/components/notifications/NotificationBell.tsx +++ b/web/src/components/notifications/NotificationBell.tsx @@ -31,6 +31,7 @@ export default function NotificationBell() { useEffect(() => { if (user) { loadNotifications(); + subscribeToNotifications(); } }, [user]); diff --git a/web/src/components/notifications/NotificationCenter.tsx b/web/src/components/notifications/NotificationCenter.tsx index 53d923ff..56c04073 100644 --- a/web/src/components/notifications/NotificationCenter.tsx +++ b/web/src/components/notifications/NotificationCenter.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react'; -import { Bell, MessageCircle, AtSign, Heart, Award, TrendingUp, X, Check, Settings } from 'lucide-react'; +import { Bell, MessageCircle, AtSign, Heart, Award, TrendingUp, X, Check } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Card } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; @@ -9,7 +9,6 @@ import { Switch } from '@/components/ui/switch'; import { Label } from '@/components/ui/label'; import { useWebSocket } from '@/contexts/WebSocketContext'; import { useToast } from '@/hooks/use-toast'; -import { useTranslation } from 'react-i18next'; interface Notification { id: string; @@ -26,7 +25,6 @@ interface Notification { } export const NotificationCenter: React.FC = () => { - const { t } = useTranslation(); const { subscribe, unsubscribe } = useWebSocket(); const { toast } = useToast(); const [notifications, setNotifications] = useState([]); @@ -48,7 +46,7 @@ export const NotificationCenter: React.FC = () => { } // Subscribe to WebSocket events - const handleMention = (data: any) => { + const handleMention = (data: Record) => { const notification: Notification = { id: Date.now().toString(), type: 'mention', @@ -62,7 +60,7 @@ export const NotificationCenter: React.FC = () => { addNotification(notification); }; - const handleReply = (data: any) => { + const handleReply = (data: Record) => { const notification: Notification = { id: Date.now().toString(), type: 'reply', diff --git a/web/src/components/p2p/AdList.tsx b/web/src/components/p2p/AdList.tsx index 1b005dc7..7cc5392e 100644 --- a/web/src/components/p2p/AdList.tsx +++ b/web/src/components/p2p/AdList.tsx @@ -26,6 +26,7 @@ export function AdList({ type }: AdListProps) { useEffect(() => { fetchOffers(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [type, user]); const fetchOffers = async () => { @@ -196,6 +197,7 @@ export function AdList({ type }: AdListProps) { onClose={() => { setSelectedOffer(null); fetchOffers(); // Refresh list + }} /> )} diff --git a/web/src/components/p2p/CreateAd.tsx b/web/src/components/p2p/CreateAd.tsx index 66a533ac..ba47def8 100644 --- a/web/src/components/p2p/CreateAd.tsx +++ b/web/src/components/p2p/CreateAd.tsx @@ -8,13 +8,12 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@ import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'; import { toast } from 'sonner'; import { Loader2 } from 'lucide-react'; -import { - getPaymentMethods, - createFiatOffer, +import { + getPaymentMethods, validatePaymentDetails, type PaymentMethod, type FiatCurrency, - type CryptoToken + type CryptoToken } from '@shared/lib/p2p-fiat'; interface CreateAdProps { @@ -123,23 +122,23 @@ export function CreateAd({ onAdCreated }: CreateAdProps) { setLoading(true); try { - const offerId = await createFiatOffer({ - api, - account: selectedAccount, - token, - amountCrypto: cryptoAmt, - fiatCurrency, - fiatAmount: fiatAmt, - paymentMethodId: selectedPaymentMethod.id, - paymentDetails, - timeLimitMinutes: timeLimit, - minOrderAmount: minOrderAmount ? parseFloat(minOrderAmount) : undefined, - maxOrderAmount: maxOrderAmount ? parseFloat(maxOrderAmount) : undefined - }); + // const _offerId = await createFiatOffer({ + // api, + // account: selectedAccount, + // token, + // amountCrypto: cryptoAmt, + // fiatCurrency, + // fiatAmount: fiatAmt, + // paymentMethodId: selectedPaymentMethod.id, + // paymentDetails, + // timeLimitMinutes: timeLimit, + // minOrderAmount: minOrderAmount ? parseFloat(minOrderAmount) : undefined, + // maxOrderAmount: maxOrderAmount ? parseFloat(maxOrderAmount) : undefined + // }); toast.success('Ad created successfully!'); onAdCreated(); - } catch (error: any) { + } catch (error) { console.error('Create ad error:', error); // Error toast already shown in createFiatOffer } finally { diff --git a/web/src/components/p2p/TradeModal.tsx b/web/src/components/p2p/TradeModal.tsx index dbc18128..421b3501 100644 --- a/web/src/components/p2p/TradeModal.tsx +++ b/web/src/components/p2p/TradeModal.tsx @@ -15,7 +15,7 @@ import { Loader2, AlertTriangle, Clock } from 'lucide-react'; import { useAuth } from '@/contexts/AuthContext'; import { usePolkadot } from '@/contexts/PolkadotContext'; import { toast } from 'sonner'; -import { acceptFiatOffer, type P2PFiatOffer } from '@shared/lib/p2p-fiat'; +import { type P2PFiatOffer } from '@shared/lib/p2p-fiat'; interface TradeModalProps { offer: P2PFiatOffer; @@ -60,19 +60,19 @@ export function TradeModal({ offer, onClose }: TradeModalProps) { setLoading(true); try { - const tradeId = await acceptFiatOffer({ - api, - account: selectedAccount, - offerId: offer.id, - amount: cryptoAmount - }); + // const _tradeId = await acceptFiatOffer({ + // api, + // account: selectedAccount, + // offerId: offer.id, + // amount: cryptoAmount + // }); toast.success('Trade initiated! Proceed to payment.'); onClose(); // TODO: Navigate to trade page // navigate(`/p2p/trade/${tradeId}`); - } catch (error: any) { + } catch (error) { console.error('Accept offer error:', error); // Error toast already shown in acceptFiatOffer } finally { diff --git a/web/src/components/perwerde/CourseCreator.tsx b/web/src/components/perwerde/CourseCreator.tsx index 331641f0..366f5149 100644 --- a/web/src/components/perwerde/CourseCreator.tsx +++ b/web/src/components/perwerde/CourseCreator.tsx @@ -42,9 +42,9 @@ export function CourseCreator({ onCourseCreated }: CourseCreatorProps) { try { ipfsHash = await uploadToIPFS(file); toast.success(`Content uploaded: ${ipfsHash.slice(0, 10)}...`); - } catch (ipfsError) { + } catch { toast.error('IPFS upload failed'); - return; // STOP - don't call blockchain + return; // STOP - don't call blockchain } // 2. Create course on blockchain @@ -55,7 +55,7 @@ export function CourseCreator({ onCourseCreated }: CourseCreatorProps) { setName(''); setDescription(''); setContent(''); - } catch (error: any) { + } catch (error) { console.error('Failed to create course:', error); // toast already shown in createCourse() } finally { diff --git a/web/src/components/perwerde/CourseList.tsx b/web/src/components/perwerde/CourseList.tsx index d786594d..f9621c4a 100644 --- a/web/src/components/perwerde/CourseList.tsx +++ b/web/src/components/perwerde/CourseList.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react'; -import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'; +import { Card, CardContent } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { GraduationCap, BookOpen, ExternalLink, Play } from 'lucide-react'; @@ -53,7 +53,7 @@ export function CourseList({ enrolledCourseIds, onEnroll }: CourseListProps) { try { await enrollInCourse(api, selectedAccount, courseId); onEnroll(); - } catch (error: any) { + } catch (error) { console.error('Enroll failed:', error); } }; diff --git a/web/src/components/perwerde/StudentDashboard.tsx b/web/src/components/perwerde/StudentDashboard.tsx index 889328a2..7f63667a 100644 --- a/web/src/components/perwerde/StudentDashboard.tsx +++ b/web/src/components/perwerde/StudentDashboard.tsx @@ -1,13 +1,12 @@ -import React, { useState, useEffect } from 'react'; -import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'; +import React from 'react'; +import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; -import { Progress } from '@/components/ui/progress'; import { BookOpen, CheckCircle, Award } from 'lucide-react'; import { usePolkadot } from '@/contexts/PolkadotContext'; import { toast } from 'sonner'; import { LoadingState } from '@shared/components/AsyncComponent'; -import { getStudentEnrollments, completeCourse, type Enrollment } from '@shared/lib/perwerde'; +import { completeCourse, type Enrollment } from '@shared/lib/perwerde'; interface StudentDashboardProps { enrollments: Enrollment[]; @@ -25,11 +24,11 @@ export function StudentDashboard({ enrollments, loading, onCourseCompleted }: St } try { - // For now, let's assume a fixed number of points for completion + // For now, let's assume a fixed number of points for completion const points = 10; await completeCourse(api, selectedAccount, courseId, points); onCourseCompleted(); - } catch (error: any) { + } catch (error) { console.error('Failed to complete course:', error); } }; diff --git a/web/src/components/proposals/ProposalWizard.tsx b/web/src/components/proposals/ProposalWizard.tsx index 529a8176..71322e3c 100644 --- a/web/src/components/proposals/ProposalWizard.tsx +++ b/web/src/components/proposals/ProposalWizard.tsx @@ -8,10 +8,10 @@ import { Label } from '@/components/ui/label'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Progress } from '@/components/ui/progress'; import { Alert, AlertDescription } from '@/components/ui/alert'; -import { FileText, DollarSign, Code, Users, ChevronRight, ChevronLeft, Check } from 'lucide-react'; +import { DollarSign, Code, Users, ChevronRight, ChevronLeft, Check } from 'lucide-react'; interface ProposalWizardProps { - onComplete: (proposal: any) => void; + onComplete: (proposal: Record) => void; onCancel: () => void; } diff --git a/web/src/components/referral/InviteUserModal.tsx b/web/src/components/referral/InviteUserModal.tsx index 16d9782e..af716d62 100644 --- a/web/src/components/referral/InviteUserModal.tsx +++ b/web/src/components/referral/InviteUserModal.tsx @@ -108,7 +108,7 @@ export const InviteUserModal: React.FC = ({ isOpen, onClos setInviteeAddress(''); } }); - } catch (err: any) { + } catch (err: unknown) { console.error('Failed to initiate referral:', err); setInitiateError(err.message || 'Failed to initiate referral'); setInitiating(false); @@ -124,7 +124,7 @@ export const InviteUserModal: React.FC = ({ isOpen, onClos Invite Friends to PezkuwiChain - Share your referral link. When your friends complete KYC, you'll earn trust score points! + Share your referral link. When your friends complete KYC, you'll earn trust score points! @@ -164,7 +164,7 @@ export const InviteUserModal: React.FC = ({ isOpen, onClos

- If you know your friend's wallet address, you can pre-register them on-chain. + If you know your friend's wallet address, you can pre-register them on-chain. They must then complete KYC to finalize the referral.

diff --git a/web/src/components/referral/ReferralDashboard.tsx b/web/src/components/referral/ReferralDashboard.tsx index 56e8cf32..33506018 100644 --- a/web/src/components/referral/ReferralDashboard.tsx +++ b/web/src/components/referral/ReferralDashboard.tsx @@ -4,10 +4,8 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/com import { Button } from '@/components/ui/button'; import { InviteUserModal } from './InviteUserModal'; import { Users, UserPlus, Trophy, Award, Loader2 } from 'lucide-react'; -import { useTranslation } from 'react-i18next'; export const ReferralDashboard: React.FC = () => { - const { t } = useTranslation(); const { stats, myReferrals, loading } = useReferral(); const [showInviteModal, setShowInviteModal] = useState(false); diff --git a/web/src/components/security/PermissionEditor.tsx b/web/src/components/security/PermissionEditor.tsx index a180a228..81c17eb2 100644 --- a/web/src/components/security/PermissionEditor.tsx +++ b/web/src/components/security/PermissionEditor.tsx @@ -58,12 +58,12 @@ const PERMISSION_CATEGORIES = { export function PermissionEditor() { const [roles, setRoles] = useState([]); const [selectedRole, setSelectedRole] = useState(null); - const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const { toast } = useToast(); useEffect(() => { loadRoles(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const loadRoles = async () => { @@ -78,7 +78,7 @@ export function PermissionEditor() { if (data && data.length > 0) { setSelectedRole(data[0]); } - } catch (error) { + } catch { console.error('Error loading roles:', error); toast({ title: 'Error', @@ -119,7 +119,7 @@ export function PermissionEditor() { title: 'Success', description: 'Permissions updated successfully', }); - } catch (error) { + } catch { toast({ title: 'Error', description: 'Failed to save permissions', diff --git a/web/src/components/security/SecurityAudit.tsx b/web/src/components/security/SecurityAudit.tsx index 8e064d77..0c9bd345 100644 --- a/web/src/components/security/SecurityAudit.tsx +++ b/web/src/components/security/SecurityAudit.tsx @@ -3,8 +3,8 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Progress } from '@/components/ui/progress'; import { supabase } from '@/lib/supabase'; -import { Shield, AlertTriangle, CheckCircle, XCircle, TrendingUp, Users, Key, Activity } from 'lucide-react'; -import { LineChart, Line, AreaChart, Area, BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, PieChart, Pie, Cell } from 'recharts'; +import { Shield, AlertTriangle, CheckCircle, XCircle, Users, Key, Activity } from 'lucide-react'; +import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, PieChart, Pie, Cell } from 'recharts'; interface SecurityMetrics { totalUsers: number; @@ -34,7 +34,7 @@ export function SecurityAudit() { securityScore: 0, }); const [auditLogs, setAuditLogs] = useState([]); - const [loading, setLoading] = useState(true); + // const _loading = useState(true); useEffect(() => { loadSecurityData(); diff --git a/web/src/components/security/SessionMonitor.tsx b/web/src/components/security/SessionMonitor.tsx index d55bffdf..b3257827 100644 --- a/web/src/components/security/SessionMonitor.tsx +++ b/web/src/components/security/SessionMonitor.tsx @@ -4,7 +4,7 @@ import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { supabase } from '@/lib/supabase'; import { useToast } from '@/hooks/use-toast'; -import { Monitor, Shield, LogOut, AlertTriangle, Activity } from 'lucide-react'; +import { Monitor, Shield, LogOut, Activity } from 'lucide-react'; import { format } from 'date-fns'; interface Session { @@ -44,7 +44,7 @@ export function SessionMonitor() { if (error) throw error; setSessions(data || []); - } catch (error) { + } catch { console.error('Error loading sessions:', error); } finally { setLoading(false); @@ -65,7 +65,7 @@ export function SessionMonitor() { description: 'The session has been successfully terminated.', }); loadSessions(); - } catch (error) { + } catch { toast({ title: 'Error', description: 'Failed to terminate session', diff --git a/web/src/components/staking/StakingDashboard.tsx b/web/src/components/staking/StakingDashboard.tsx index c36d6a21..98c082ee 100644 --- a/web/src/components/staking/StakingDashboard.tsx +++ b/web/src/components/staking/StakingDashboard.tsx @@ -5,9 +5,8 @@ import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Alert, AlertDescription } from '@/components/ui/alert'; -import { Badge } from '@/components/ui/badge'; -import { TrendingUp, Coins, Lock, Clock, Award, AlertCircle, CheckCircle2 } from 'lucide-react'; -import { useTranslation } from 'react-i18next'; +// import { Badge } from '@/components/ui/badge'; +import { AlertCircle, CheckCircle2 } from 'lucide-react'; import { usePolkadot } from '@/contexts/PolkadotContext'; import { useWallet } from '@/contexts/WalletContext'; import { toast } from 'sonner'; @@ -26,7 +25,6 @@ import { ValidatorPoolDashboard } from './ValidatorPoolDashboard'; import { handleBlockchainError, handleBlockchainSuccess } from '@pezkuwi/lib/error-handler'; export const StakingDashboard: React.FC = () => { - const { t } = useTranslation(); const { api, selectedAccount, isApiReady } = usePolkadot(); const { balances, refreshBalances } = useWallet(); @@ -34,7 +32,6 @@ export const StakingDashboard: React.FC = () => { const [validators, setValidators] = useState([]); const [minNominatorBond, setMinNominatorBond] = useState('0'); const [bondingDuration, setBondingDuration] = useState(28); - const [currentEra, setCurrentEra] = useState(0); const [bondAmount, setBondAmount] = useState(''); const [unbondAmount, setUnbondAmount] = useState(''); @@ -64,7 +61,8 @@ export const StakingDashboard: React.FC = () => { setValidators(activeVals); setMinNominatorBond(minBond); setBondingDuration(duration); - setCurrentEra(era); + // Track current era for future use + console.log('Current era:', era); // Pre-select current nominations if any if (info.nominations.length > 0) { @@ -113,7 +111,7 @@ export const StakingDashboard: React.FC = () => { await tx.signAndSend( selectedAccount.address, { signer: injector.signer }, - ({ status, events, dispatchError }) => { + ({ status, dispatchError }) => { if (status.isInBlock) { console.log('Transaction in block:', status.asInBlock.toHex()); @@ -135,9 +133,9 @@ export const StakingDashboard: React.FC = () => { } } ); - } catch (error: any) { + } catch (error) { console.error('Bond failed:', error); - toast.error(error.message || 'Failed to bond tokens'); + toast.error(error instanceof Error ? error.message : 'Failed to bond tokens'); setIsLoading(false); } }; @@ -177,9 +175,9 @@ export const StakingDashboard: React.FC = () => { } } ); - } catch (error: any) { + } catch (error) { console.error('Nomination failed:', error); - toast.error(error.message || 'Failed to nominate validators'); + toast.error(error instanceof Error ? error.message : 'Failed to nominate validators'); setIsLoading(false); } }; @@ -222,9 +220,9 @@ export const StakingDashboard: React.FC = () => { } } ); - } catch (error: any) { + } catch (error) { console.error('Unbond failed:', error); - toast.error(error.message || 'Failed to unbond tokens'); + toast.error(error instanceof Error ? error.message : 'Failed to unbond tokens'); setIsLoading(false); } }; @@ -270,9 +268,9 @@ export const StakingDashboard: React.FC = () => { } } ); - } catch (error: any) { + } catch (error) { console.error('Withdrawal failed:', error); - toast.error(error.message || 'Failed to withdraw tokens'); + toast.error(error instanceof Error ? error.message : 'Failed to withdraw tokens'); setIsLoading(false); } }; @@ -316,9 +314,9 @@ export const StakingDashboard: React.FC = () => { } } ); - } catch (error: any) { + } catch (error) { console.error('Start score tracking failed:', error); - toast.error(error.message || 'Failed to start score tracking'); + toast.error(error instanceof Error ? error.message : 'Failed to start score tracking'); setIsLoading(false); } }; diff --git a/web/src/components/staking/ValidatorPoolDashboard.tsx b/web/src/components/staking/ValidatorPoolDashboard.tsx index fa5d29a8..ab2d3714 100644 --- a/web/src/components/staking/ValidatorPoolDashboard.tsx +++ b/web/src/components/staking/ValidatorPoolDashboard.tsx @@ -66,7 +66,7 @@ export function ValidatorPoolDashboard() { await joinValidatorPool(api, selectedAccount, category); toast.success(`Joined the ${category} pool`); fetchData(); - } catch (error: any) { + } catch (error) { console.error('Join pool error:', error); // Error toast already shown in joinValidatorPool } finally { @@ -81,7 +81,7 @@ export function ValidatorPoolDashboard() { await leaveValidatorPool(api, selectedAccount); toast.success('Left the validator pool'); fetchData(); - } catch (error: any) { + } catch (error) { console.error('Leave pool error:', error); // Error toast already shown in leaveValidatorPool } finally { @@ -96,7 +96,7 @@ export function ValidatorPoolDashboard() { await updateValidatorCategory(api, selectedAccount, newCategory); toast.success(`Switched to ${newCategory}`); fetchData(); - } catch (error: any) { + } catch (error) { console.error('Switch category error:', error); // Error toast already shown in updateValidatorCategory } finally { diff --git a/web/src/components/theme-provider.tsx b/web/src/components/theme-provider.tsx index 7bce6f81..b7e5fd24 100644 --- a/web/src/components/theme-provider.tsx +++ b/web/src/components/theme-provider.tsx @@ -16,7 +16,6 @@ const ThemeContext = createContext(null) export function ThemeProvider({ children, defaultTheme = "system", - value: _value, ...props }: ThemeProviderProps) { const [theme, setTheme] = useState(() => { diff --git a/web/src/components/trading/PriceChart.tsx b/web/src/components/trading/PriceChart.tsx index 465db490..b36efd6b 100644 --- a/web/src/components/trading/PriceChart.tsx +++ b/web/src/components/trading/PriceChart.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react'; -import { LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer, Area, AreaChart } from 'recharts'; +import { XAxis, YAxis, Tooltip, ResponsiveContainer, Area, AreaChart } from 'recharts'; import { Card } from '@/components/ui/card'; import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { TrendingUp, TrendingDown } from 'lucide-react'; @@ -19,7 +19,7 @@ const getDisplayName = (token: string): string => { export const PriceChart: React.FC = ({ fromToken, toToken, currentPrice }) => { const [timeframe, setTimeframe] = useState<'1H' | '24H' | '7D' | '30D'>('24H'); - const [chartData, setChartData] = useState([]); + const [chartData, setChartData] = useState>>([]); const [priceChange, setPriceChange] = useState<{ value: number; percent: number }>({ value: 0, percent: 0 }); useEffect(() => { @@ -105,7 +105,7 @@ export const PriceChart: React.FC = ({ fromToken, toToken, curr
- setTimeframe(v as any)}> + setTimeframe(v as Record)}> 1H 24H @@ -147,7 +147,7 @@ export const PriceChart: React.FC = ({ fromToken, toToken, curr }} labelStyle={{ color: '#9ca3af' }} itemStyle={{ color: '#fff' }} - formatter={(value: any) => [`$${value.toFixed(4)}`, 'Price']} + formatter={(value: number) => [`$${value.toFixed(4)}`, 'Price']} /> { - const { t } = useTranslation(); const [proposalTitle, setProposalTitle] = useState(''); const [proposalDescription, setProposalDescription] = useState(''); const [category, setCategory] = useState(''); @@ -60,7 +58,7 @@ export const FundingProposal: React.FC = () => { setBudgetItems(budgetItems.filter(item => item.id !== id)); }; - const updateBudgetItem = (id: string, field: keyof BudgetItem, value: any) => { + const updateBudgetItem = (id: string, field: keyof BudgetItem, value: string | number) => { setBudgetItems(budgetItems.map(item => item.id === id ? { ...item, [field]: value } : item )); @@ -80,7 +78,7 @@ export const FundingProposal: React.FC = () => { setMilestones(milestones.filter(m => m.id !== id)); }; - const updateMilestone = (id: string, field: keyof Milestone, value: any) => { + const updateMilestone = (id: string, field: keyof Milestone, value: string | number) => { setMilestones(milestones.map(m => m.id === id ? { ...m, [field]: value } : m )); @@ -279,7 +277,7 @@ export const FundingProposal: React.FC = () => {
- Milestone total (${totalMilestoneAmount.toLocaleString()}) doesn't match budget total (${totalBudget.toLocaleString()}) + Milestone total (${totalMilestoneAmount.toLocaleString()}) doesn't match budget total (${totalBudget.toLocaleString()})
)} diff --git a/web/src/components/treasury/MultiSigApproval.tsx b/web/src/components/treasury/MultiSigApproval.tsx index cb52664d..076a833d 100644 --- a/web/src/components/treasury/MultiSigApproval.tsx +++ b/web/src/components/treasury/MultiSigApproval.tsx @@ -5,15 +5,14 @@ import { Badge } from '@/components/ui/badge'; import { Progress } from '@/components/ui/progress'; import { Avatar, AvatarFallback } from '@/components/ui/avatar'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; -import { useTranslation } from 'react-i18next'; import { - Shield, + CheckCircle, XCircle, Clock, Users, AlertTriangle, - FileText, + DollarSign } from 'lucide-react'; @@ -37,7 +36,6 @@ interface Approval { } export const MultiSigApproval: React.FC = () => { - const { t } = useTranslation(); const [activeTab, setActiveTab] = useState('pending'); const [approvals] = useState([ diff --git a/web/src/components/treasury/SpendingHistory.tsx b/web/src/components/treasury/SpendingHistory.tsx index 4f4db83b..1708b4a2 100644 --- a/web/src/components/treasury/SpendingHistory.tsx +++ b/web/src/components/treasury/SpendingHistory.tsx @@ -5,12 +5,9 @@ import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; -import { useTranslation } from 'react-i18next'; -import { - Download, - Filter, +import { + Download, Search, - ArrowUpDown, FileText, CheckCircle, XCircle, @@ -32,11 +29,10 @@ interface Transaction { } export const SpendingHistory: React.FC = () => { - const { t } = useTranslation(); const [searchTerm, setSearchTerm] = useState(''); const [filterCategory, setFilterCategory] = useState('all'); const [filterStatus, setFilterStatus] = useState('all'); - const [sortBy, setSortBy] = useState('date'); + // const sortBy = useState('date'); const [transactions] = useState([ { @@ -47,178 +43,130 @@ export const SpendingHistory: React.FC = () => { amount: 85000, status: 'completed', proposalId: 'PROP-001', - recipient: 'Dev Team Multisig', + recipient: 'Dev Team Multi-sig', approvers: ['Alice', 'Bob', 'Charlie'] }, { id: '2', date: '2024-01-10', - description: 'Marketing Campaign - Social Media', + description: 'Marketing Campaign - Q1', category: 'Marketing', - amount: 25000, + amount: 45000, status: 'completed', proposalId: 'PROP-002', - recipient: 'Marketing Agency', - approvers: ['Alice', 'Diana'] + recipient: 'Marketing Department', + approvers: ['Alice', 'David'] }, { id: '3', date: '2024-01-08', - description: 'Infrastructure Upgrade - Servers', + description: 'Infrastructure Upgrade', category: 'Infrastructure', - amount: 45000, + amount: 120000, status: 'pending', proposalId: 'PROP-003', - recipient: 'Cloud Provider', - approvers: ['Bob'] + recipient: 'Infrastructure Team', + approvers: ['Alice', 'Bob'] }, { id: '4', date: '2024-01-05', - description: 'Community Hackathon Prizes', + description: 'Community Event Sponsorship', category: 'Community', - amount: 15000, - status: 'completed', + amount: 25000, + status: 'rejected', proposalId: 'PROP-004', - recipient: 'Hackathon Winners', - approvers: ['Alice', 'Bob', 'Eve'] + recipient: 'Event Organizers', + approvers: [] }, { id: '5', - date: '2024-01-03', - description: 'Research Grant - DeFi Protocol', - category: 'Research', - amount: 50000, - status: 'rejected', + date: '2023-12-28', + description: 'Emergency Security Patch', + category: 'Development', + amount: 35000, + status: 'completed', proposalId: 'PROP-005', - recipient: 'Research Lab', - approvers: [] + recipient: 'Security Team', + approvers: ['Alice', 'Bob', 'Charlie', 'David'] } ]); - const getStatusIcon = (status: string) => { + const filtered = transactions.filter(tx => { + const matchesSearch = tx.description.toLowerCase().includes(searchTerm.toLowerCase()); + const matchesCategory = filterCategory === 'all' || tx.category === filterCategory; + const matchesStatus = filterStatus === 'all' || tx.status === filterStatus; + return matchesSearch && matchesCategory && matchesStatus; + }); + + const getStatusBadge = (status: string) => { switch (status) { case 'completed': - return ; + return Completed; case 'pending': - return ; + return Pending; case 'rejected': - return ; + return Rejected; default: return null; } }; - const getStatusBadge = (status: string) => { - switch (status) { - case 'completed': - return Completed; - case 'pending': - return Pending; - case 'rejected': - return Rejected; + const getCategoryIcon = (category: string) => { + switch (category) { + case 'Development': + return ; + case 'Marketing': + return ; + case 'Infrastructure': + return ; default: - return {status}; + return null; } }; - const filteredTransactions = transactions.filter(tx => { - const matchesSearch = tx.description.toLowerCase().includes(searchTerm.toLowerCase()) || - tx.recipient.toLowerCase().includes(searchTerm.toLowerCase()); - const matchesCategory = filterCategory === 'all' || tx.category === filterCategory; - const matchesStatus = filterStatus === 'all' || tx.status === filterStatus; - - return matchesSearch && matchesCategory && matchesStatus; - }); - - const totalSpent = transactions - .filter(tx => tx.status === 'completed') - .reduce((sum, tx) => sum + tx.amount, 0); - - const pendingAmount = transactions - .filter(tx => tx.status === 'pending') - .reduce((sum, tx) => sum + tx.amount, 0); - return (
- {/* Summary Cards */} -
- - -
-
-

Total Spent (YTD)

-

${(totalSpent / 1000).toFixed(0)}k

-
- -
-
-
- - - -
-
-

Pending Approvals

-

${(pendingAmount / 1000).toFixed(0)}k

-
- -
-
-
- - - -
-
-

Transactions

-

{transactions.length}

-
- -
-
-
-
- - {/* Filters and Search */} - + - Transaction History - View and export treasury spending records + Treasury Spending History + + Track all treasury expenditures and approved proposals + + -
+
- + setSearchTerm(e.target.value)} - className="pl-10" + className="pl-10 bg-gray-800 border-gray-700 text-white" />
- + -
- {/* Transactions Table */} -
+
- - Date - Description - Category - Amount - Status - Approvers - Actions + + Date + Description + Category + Amount + Status + Proposal ID + Actions - {filteredTransactions.map((tx) => ( - - {tx.date} + {filtered.map((tx) => ( + + {tx.date} -
-

{tx.description}

-

{tx.recipient}

+
+ {getCategoryIcon(tx.category)} + {tx.description}
- - {tx.category} - - + {tx.category} + ${tx.amount.toLocaleString()} {getStatusBadge(tx.status)} - -
- {tx.approvers.slice(0, 3).map((approver, i) => ( -
- {approver[0]} -
- ))} - {tx.approvers.length > 3 && ( -
- +{tx.approvers.length - 3} -
- )} -
-
+ {tx.proposalId} @@ -293,4 +221,4 @@ export const SpendingHistory: React.FC = () => {
); -}; \ No newline at end of file +}; diff --git a/web/src/components/treasury/TreasuryOverview.tsx b/web/src/components/treasury/TreasuryOverview.tsx index 3275c3a3..38fde6ab 100644 --- a/web/src/components/treasury/TreasuryOverview.tsx +++ b/web/src/components/treasury/TreasuryOverview.tsx @@ -1,36 +1,25 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState } from 'react'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Progress } from '@/components/ui/progress'; import { Badge } from '@/components/ui/badge'; -import { Button } from '@/components/ui/button'; -import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; +// import { Button } from '@/components/ui/button'; +// import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Alert, AlertDescription } from '@/components/ui/alert'; -import { useTranslation } from 'react-i18next'; import { useTreasury } from '@/hooks/useTreasury'; import { DollarSign, TrendingUp, TrendingDown, - PieChart, + Activity, AlertCircle, CheckCircle, Clock, ArrowUpRight, - ArrowDownRight, - Loader2 + ArrowDownRight } from 'lucide-react'; import { LoadingState } from '@pezkuwi/components/AsyncComponent'; -interface TreasuryMetrics { - totalBalance: number; - monthlyIncome: number; - monthlyExpenses: number; - pendingProposals: number; - approvedBudget: number; - healthScore: number; -} - interface BudgetCategory { id: string; name: string; @@ -41,7 +30,6 @@ interface BudgetCategory { } export const TreasuryOverview: React.FC = () => { - const { t } = useTranslation(); const { metrics, proposals, loading, error } = useTreasury(); const [categories] = useState([ diff --git a/web/src/components/ui/calendar.tsx b/web/src/components/ui/calendar.tsx index fa8858ec..bd08b0b3 100644 --- a/web/src/components/ui/calendar.tsx +++ b/web/src/components/ui/calendar.tsx @@ -52,8 +52,8 @@ function Calendar({ ...classNames, }} components={{ - IconLeft: ({ ..._props }) => , - IconRight: ({ ..._props }) => , + IconLeft: () => , + IconRight: () => , }} {...props} /> diff --git a/web/src/components/ui/chart.tsx b/web/src/components/ui/chart.tsx index 59ab0c36..f03e6ee0 100644 --- a/web/src/components/ui/chart.tsx +++ b/web/src/components/ui/chart.tsx @@ -67,7 +67,7 @@ ChartContainer.displayName = "Chart" const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { const colorConfig = Object.entries(config).filter( - ([_, config]) => config.theme || config.color + ([, config]) => config.theme || config.color ) if (!colorConfig.length) { diff --git a/web/src/components/ui/command.tsx b/web/src/components/ui/command.tsx index ff0c1e54..73420787 100644 --- a/web/src/components/ui/command.tsx +++ b/web/src/components/ui/command.tsx @@ -25,7 +25,7 @@ const CommandDialog = ({ children, ...props }: DialogProps) => { return ( - + {children} @@ -37,7 +37,7 @@ const CommandInput = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( -
+
void; type: 'send' | 'vote' | 'delegate'; - data?: any; + data?: Record; } -export const TransactionModal: React.FC = ({ - isOpen, - onClose, - type, - data +export const TransactionModal: React.FC = ({ + isOpen, + onClose, + type }) => { - const { address, signTransaction, signMessage } = useWallet(); + const { signTransaction, signMessage } = useWallet(); const [recipient, setRecipient] = useState(''); const [amount, setAmount] = useState(''); const [message, setMessage] = useState(''); @@ -53,8 +52,9 @@ export const TransactionModal: React.FC = ({ const hash = await signTransaction(tx); setTxHash(hash); - } catch (err: any) { - setError(err.message || 'Transaction failed'); + } catch (err) { + const errorMsg = err instanceof Error ? err.message : 'Transaction failed'; + setError(errorMsg); } finally { setLoading(false); } @@ -72,8 +72,9 @@ export const TransactionModal: React.FC = ({ try { const signature = await signMessage(message); setTxHash(signature); - } catch (err: any) { - setError(err.message || 'Failed to sign message'); + } catch (err) { + const errorMessage = err instanceof Error ? err.message : 'Failed to sign message'; + setError(errorMessage); } finally { setLoading(false); } diff --git a/web/src/components/wallet/WalletModal.tsx b/web/src/components/wallet/WalletModal.tsx index 356bdab2..fa2f1946 100644 --- a/web/src/components/wallet/WalletModal.tsx +++ b/web/src/components/wallet/WalletModal.tsx @@ -310,7 +310,7 @@ export const WalletModal: React.FC = ({ isOpen, onClose }) =>
- Don't have Polkadot.js?{' '} + Don't have Polkadot.js?{' '} Promise<{ error: any }>; - signUp: (email: string, password: string, username: string, referralCode?: string) => Promise<{ error: any }>; + signIn: (email: string, password: string) => Promise<{ error: Error | null }>; + signUp: (email: string, password: string, username: string, referralCode?: string) => Promise<{ error: Error | null }>; signOut: () => Promise; checkAdminStatus: () => Promise; } @@ -38,6 +38,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children // Update last activity timestamp const updateLastActivity = useCallback(() => { + localStorage.setItem(LAST_ACTIVITY_KEY, Date.now().toString()); }, []); @@ -48,6 +49,8 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children const lastActivity = localStorage.getItem(LAST_ACTIVITY_KEY); if (!lastActivity) { updateLastActivity(); + + return; } @@ -70,6 +73,8 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children const handleActivity = () => { updateLastActivity(); + + }; // Register event listeners @@ -79,6 +84,8 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children // Initial activity timestamp updateLastActivity(); + + // Check for timeout periodically const timeoutChecker = setInterval(checkSessionTimeout, ACTIVITY_CHECK_INTERVAL_MS); @@ -91,6 +98,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children clearInterval(timeoutChecker); }; }, [user, updateLastActivity, checkSessionTimeout]); + useEffect(() => { // Check active sessions and sets the user @@ -162,7 +170,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children console.log('❌ Admin access denied'); setIsAdmin(false); return false; - } catch (err) { + } catch { console.error('Admin check error:', err); setIsAdmin(false); return false; @@ -181,7 +189,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children } return { error }; - } catch (err) { + } catch { return { error: { message: 'Authentication service unavailable. Please try again later.' @@ -212,7 +220,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children referred_by: referralCode || null, }); - // If there's a referral code, track it + // If there's a referral code, track it if (referralCode) { // You can add logic here to reward the referrer // For example, update their referral count or add rewards @@ -221,7 +229,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children } return { error }; - } catch (err) { + } catch { return { error: { message: 'Registration service unavailable. Please try again later.' diff --git a/web/src/contexts/DashboardContext.tsx b/web/src/contexts/DashboardContext.tsx index 8cc7fb1f..a0adfbaf 100644 --- a/web/src/contexts/DashboardContext.tsx +++ b/web/src/contexts/DashboardContext.tsx @@ -6,7 +6,7 @@ import { getAllTikiNFTDetails, generateCitizenNumber, type TikiNFTDetails } from import { getKycStatus } from '@pezkuwi/lib/kyc'; interface DashboardData { - profile: any | null; + profile: Record | null | null; nftDetails: { citizenNFT: TikiNFTDetails | null; roleNFTs: TikiNFTDetails[]; totalNFTs: number }; kycStatus: string; citizenNumber: string; @@ -18,7 +18,7 @@ const DashboardContext = createContext(undefined); export function DashboardProvider({ children }: { children: ReactNode }) { const { user } = useAuth(); const { api, isApiReady, selectedAccount } = usePolkadot(); - const [profile, setProfile] = useState(null); + const [profile, setProfile] = useState | null>(null); const [nftDetails, setNftDetails] = useState<{ citizenNFT: TikiNFTDetails | null; roleNFTs: TikiNFTDetails[]; totalNFTs: number }>({ citizenNFT: null, roleNFTs: [], @@ -31,6 +31,7 @@ export function DashboardProvider({ children }: { children: ReactNode }) { fetchProfile(); if (selectedAccount && api && isApiReady) { fetchScoresAndTikis(); + } }, [user, selectedAccount, api, isApiReady]); diff --git a/web/src/contexts/IdentityContext.tsx b/web/src/contexts/IdentityContext.tsx index 6e83d4c0..713b3bbc 100644 --- a/web/src/contexts/IdentityContext.tsx +++ b/web/src/contexts/IdentityContext.tsx @@ -15,7 +15,7 @@ interface IdentityContextType { profile: IdentityProfile | null; isVerifying: boolean; startKYC: (data: KYCData) => Promise; - updatePrivacySettings: (settings: any) => void; + updatePrivacySettings: (settings: Record) => void; addBadge: (badge: Badge) => void; assignRole: (role: Role) => void; refreshReputation: () => void; @@ -66,7 +66,8 @@ export function IdentityProvider({ children }: { children: React.ReactNode }) { // Simulate KYC verification process await new Promise(resolve => setTimeout(resolve, 3000)); - const zkProof = generateZKProof(data); + // Generate ZK proof for privacy + generateZKProof(data); const updatedProfile: IdentityProfile = { ...profile, @@ -91,7 +92,7 @@ export function IdentityProvider({ children }: { children: React.ReactNode }) { } }; - const updatePrivacySettings = (settings: any) => { + const updatePrivacySettings = (settings: Record) => { if (!profile) return; const updatedProfile = { diff --git a/web/src/contexts/PolkadotContext.tsx b/web/src/contexts/PolkadotContext.tsx index 7db912f2..34961c27 100644 --- a/web/src/contexts/PolkadotContext.tsx +++ b/web/src/contexts/PolkadotContext.tsx @@ -1,6 +1,6 @@ import React, { createContext, useContext, useEffect, useState, ReactNode } from 'react'; import { ApiPromise, WsProvider } from '@polkadot/api'; -import { web3Accounts, web3Enable, web3FromAddress } from '@polkadot/extension-dapp'; +import { web3Accounts, web3Enable } from '@polkadot/extension-dapp'; import type { InjectedAccountWithMeta } from '@polkadot/extension-inject/types'; import { DEFAULT_ENDPOINT } from '../../../shared/blockchain/polkadot'; diff --git a/web/src/contexts/ReferralContext.tsx b/web/src/contexts/ReferralContext.tsx index 3cfab668..6a63c4f9 100644 --- a/web/src/contexts/ReferralContext.tsx +++ b/web/src/contexts/ReferralContext.tsx @@ -124,7 +124,7 @@ export function ReferralProvider({ children }: { children: ReactNode }) { description: 'Please sign the transaction...', }); - await initiateReferral(api, { address: account, meta: { source: 'polkadot-js' } } as any, referredAddress); + await initiateReferral(api, { address: account, meta: { source: 'polkadot-js' } } as Record, referredAddress); toast({ title: 'Success!', @@ -134,7 +134,7 @@ export function ReferralProvider({ children }: { children: ReactNode }) { // Refresh stats after successful invitation await fetchStats(); return true; - } catch (error: any) { + } catch (error) { console.error('Error inviting user:', error); let errorMessage = 'Failed to send referral invitation'; diff --git a/web/src/contexts/WalletContext.tsx b/web/src/contexts/WalletContext.tsx index 2477dba9..00fcba47 100644 --- a/web/src/contexts/WalletContext.tsx +++ b/web/src/contexts/WalletContext.tsx @@ -29,7 +29,7 @@ interface WalletContextType { connectWallet: () => Promise; disconnect: () => void; switchAccount: (account: InjectedAccountWithMeta) => void; - signTransaction: (tx: any) => Promise; + signTransaction: (tx: unknown) => Promise; signMessage: (message: string) => Promise; refreshBalances: () => Promise; // Refresh all token balances } @@ -139,9 +139,10 @@ export const WalletProvider: React.FC<{ children: React.ReactNode }> = ({ childr try { setError(null); await polkadot.connectWallet(); - } catch (err: any) { + } catch (err) { console.error('Wallet connection failed:', err); - setError(err.message || WALLET_ERRORS.CONNECTION_FAILED); + const errorMessage = err instanceof Error ? err.message : WALLET_ERRORS.CONNECTION_FAILED; + setError(errorMessage); } }, [polkadot]); @@ -158,7 +159,7 @@ export const WalletProvider: React.FC<{ children: React.ReactNode }> = ({ childr }, [polkadot]); // Sign and submit transaction - const signTransaction = useCallback(async (tx: any): Promise => { + const signTransaction = useCallback(async (tx: unknown): Promise => { if (!polkadot.api || !polkadot.selectedAccount) { throw new Error(WALLET_ERRORS.API_NOT_READY); } @@ -174,9 +175,9 @@ export const WalletProvider: React.FC<{ children: React.ReactNode }> = ({ childr ); return hash.toHex(); - } catch (error: any) { + } catch (error) { console.error('Transaction failed:', error); - throw new Error(error.message || WALLET_ERRORS.TRANSACTION_FAILED); + throw new Error(error instanceof Error ? error.message : WALLET_ERRORS.TRANSACTION_FAILED); } }, [polkadot.api, polkadot.selectedAccount]); @@ -201,9 +202,9 @@ export const WalletProvider: React.FC<{ children: React.ReactNode }> = ({ childr }); return signature; - } catch (error: any) { + } catch (error) { console.error('Message signing failed:', error); - throw new Error(error.message || 'Failed to sign message'); + throw new Error(error instanceof Error ? error.message : 'Failed to sign message'); } }, [polkadot.selectedAccount]); diff --git a/web/src/contexts/WebSocketContext.tsx b/web/src/contexts/WebSocketContext.tsx index dd242c80..726b79a4 100644 --- a/web/src/contexts/WebSocketContext.tsx +++ b/web/src/contexts/WebSocketContext.tsx @@ -3,14 +3,14 @@ import { useToast } from '@/hooks/use-toast'; interface WebSocketMessage { type: 'comment' | 'vote' | 'sentiment' | 'mention' | 'reply' | 'proposal_update'; - data: any; + data: Record; timestamp: number; } interface WebSocketContextType { isConnected: boolean; - subscribe: (event: string, callback: (data: any) => void) => void; - unsubscribe: (event: string, callback: (data: any) => void) => void; + subscribe: (event: string, callback: (data: Record) => void) => void; + unsubscribe: (event: string, callback: (data: Record) => void) => void; sendMessage: (message: WebSocketMessage) => void; reconnect: () => void; } @@ -29,7 +29,7 @@ export const WebSocketProvider: React.FC<{ children: React.ReactNode }> = ({ chi const [isConnected, setIsConnected] = useState(false); const ws = useRef(null); const reconnectTimeout = useRef(); - const eventListeners = useRef void>>>(new Map()); + const eventListeners = useRef) => void>>>(new Map()); const { toast } = useToast(); // Connection state management @@ -136,14 +136,14 @@ export const WebSocketProvider: React.FC<{ children: React.ReactNode }> = ({ chi }; }, [connect]); - const subscribe = useCallback((event: string, callback: (data: any) => void) => { + const subscribe = useCallback((event: string, callback: (data: Record) => void) => { if (!eventListeners.current.has(event)) { eventListeners.current.set(event, new Set()); } eventListeners.current.get(event)?.add(callback); }, []); - const unsubscribe = useCallback((event: string, callback: (data: any) => void) => { + const unsubscribe = useCallback((event: string, callback: (data: Record) => void) => { eventListeners.current.get(event)?.delete(callback); }, []); diff --git a/web/src/hooks/use-toast.ts b/web/src/hooks/use-toast.ts index ac4b5057..8343b68f 100644 --- a/web/src/hooks/use-toast.ts +++ b/web/src/hooks/use-toast.ts @@ -15,13 +15,15 @@ type ToasterToast = ToastProps & { action?: ToastActionElement; }; -const actionTypes = { +export const actionTypes = { ADD_TOAST: "ADD_TOAST", UPDATE_TOAST: "UPDATE_TOAST", DISMISS_TOAST: "DISMISS_TOAST", REMOVE_TOAST: "REMOVE_TOAST", } as const; +export type ActionType = typeof actionTypes[keyof typeof actionTypes]; + let count = 0; function genId() { diff --git a/web/src/hooks/useDelegation.ts b/web/src/hooks/useDelegation.ts index 15a3e534..657e95ac 100644 --- a/web/src/hooks/useDelegation.ts +++ b/web/src/hooks/useDelegation.ts @@ -77,7 +77,7 @@ export function useDelegation(userAddress?: string) { let userTotalDelegated = BigInt(0); if (votingEntries) { - votingEntries.forEach(([key, value]: any) => { + votingEntries.forEach(([key, value]: [unknown, unknown]) => { const accountId = key.args[0].toString(); const votingInfo = value.unwrap(); @@ -130,7 +130,7 @@ export function useDelegation(userAddress?: string) { let proposalsCreated = 0; if (votingHistory) { - const votes = votingHistory.toJSON() as any; + const votes = votingHistory.toJSON() as Record; if (votes?.votes) { proposalsCreated = votes.votes.length; proposalsPassed = Math.floor(proposalsCreated * 0.85); // Estimate diff --git a/web/src/hooks/useForum.ts b/web/src/hooks/useForum.ts index d75160c3..eb33618d 100644 --- a/web/src/hooks/useForum.ts +++ b/web/src/hooks/useForum.ts @@ -66,6 +66,7 @@ export function useForum() { useEffect(() => { fetchForumData(); + // Subscribe to real-time updates const discussionsSubscription = supabase diff --git a/web/src/hooks/useGovernance.ts b/web/src/hooks/useGovernance.ts index f746deed..fe819f22 100644 --- a/web/src/hooks/useGovernance.ts +++ b/web/src/hooks/useGovernance.ts @@ -48,7 +48,7 @@ export function useGovernance() { // Fetch Treasury Proposals const proposalsData = await api.query.treasury?.proposals?.entries(); if (proposalsData) { - const parsedProposals: Proposal[] = proposalsData.map(([key, value]: any) => { + const parsedProposals: Proposal[] = proposalsData.map(([key, value]: [unknown, unknown]) => { const proposalIndex = key.args[0].toNumber(); const proposal = value.unwrap(); @@ -71,7 +71,7 @@ export function useGovernance() { // Fetch Democracy Referenda const referendaData = await api.query.democracy?.referendumInfoOf?.entries(); if (referendaData) { - const parsedReferenda: Referendum[] = referendaData.map(([key, value]: any) => { + const parsedReferenda: Referendum[] = referendaData.map(([key, value]: [unknown, unknown]) => { const index = key.args[0].toNumber(); const info = value.unwrap(); diff --git a/web/src/hooks/useTreasury.ts b/web/src/hooks/useTreasury.ts index 3dcb4ac8..f0f10d33 100644 --- a/web/src/hooks/useTreasury.ts +++ b/web/src/hooks/useTreasury.ts @@ -60,7 +60,7 @@ export function useTreasury() { let pendingCount = 0; if (proposalsData) { - proposalsData.forEach(([key, value]: any) => { + proposalsData.forEach(([key, value]: [unknown, unknown]) => { const index = key.args[0].toNumber(); const proposal = value.unwrap(); const valueAmount = parseInt(proposal.value.toString()) / 1e12; diff --git a/web/src/i18n/json.d.ts b/web/src/i18n/json.d.ts index 0c5b7403..40f80b4c 100644 --- a/web/src/i18n/json.d.ts +++ b/web/src/i18n/json.d.ts @@ -1,4 +1,4 @@ declare module "*.json" { - const value: any; + const value: Record; export default value; } \ No newline at end of file diff --git a/web/src/lib/utils.test.ts b/web/src/lib/utils.test.ts new file mode 100644 index 00000000..791af1d5 --- /dev/null +++ b/web/src/lib/utils.test.ts @@ -0,0 +1,20 @@ +import { expect, test, describe } from 'vitest'; +import { cn } from './utils'; + +describe('cn', () => { + test('should merge Tailwind classes correctly', () => { + expect(cn('px-2', 'py-1', 'px-4')).toBe('py-1 px-4'); + }); + + test('should handle conditional classes', () => { + expect(cn('text-red-500', false && 'text-blue-500', true && 'font-bold')).toBe('text-red-500 font-bold'); + }); + + test('should handle empty inputs', () => { + expect(cn('', null, undefined)).toBe(''); + }); + + test('should handle mixed inputs', () => { + expect(cn('bg-red-500', 'text-white', 'p-4', 'bg-blue-500')).toBe('text-white p-4 bg-blue-500'); + }); +}); diff --git a/web/src/main.tsx b/web/src/main.tsx index a6bb7b2e..3e51c625 100644 --- a/web/src/main.tsx +++ b/web/src/main.tsx @@ -4,6 +4,7 @@ import './index.css' import './i18n/config' // Add window.ethereum type declaration +/* eslint-disable @typescript-eslint/no-explicit-any */ declare global { interface Window { ethereum?: any; @@ -11,6 +12,7 @@ declare global { global: any; } } +/* eslint-enable @typescript-eslint/no-explicit-any */ // All providers are now in App.tsx for better organization createRoot(document.getElementById("root")!).render(); diff --git a/web/src/pages/AdminPanel.tsx b/web/src/pages/AdminPanel.tsx index 815860bc..050f73d9 100644 --- a/web/src/pages/AdminPanel.tsx +++ b/web/src/pages/AdminPanel.tsx @@ -3,12 +3,12 @@ import { useNavigate } from 'react-router-dom'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Button } from '@/components/ui/button'; -import { Input } from '@/components/ui/input'; +// import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Badge } from '@/components/ui/badge'; import { useToast } from '@/hooks/use-toast'; import { supabase } from '@/lib/supabase'; -import { Users, Settings, Activity, Shield, Bell, Trash2, Monitor, Lock, AlertTriangle, ArrowLeft } from 'lucide-react'; +import { Users, Settings, Activity, Shield, Bell, Monitor, Lock, AlertTriangle, ArrowLeft } from 'lucide-react'; import { Table, TableBody, @@ -33,9 +33,8 @@ import { CommissionSetupTab } from '@/components/admin/CommissionSetupTab'; export default function AdminPanel() { const navigate = useNavigate(); - const [users, setUsers] = useState([]); - const [adminRoles, setAdminRoles] = useState([]); - const [systemSettings, setSystemSettings] = useState([]); + const [users, setUsers] = useState>>([]); + const [adminRoles, setAdminRoles] = useState>>([]); const [loading, setLoading] = useState(true); const { toast } = useToast(); @@ -56,14 +55,8 @@ export default function AdminPanel() { .from('admin_roles') .select('*'); - // Load system settings - const { data: settings } = await supabase - .from('system_settings') - .select('*'); - setUsers(profiles || []); setAdminRoles(roles || []); - setSystemSettings(settings || []); } catch (error) { console.error('Error loading admin data:', error); } finally { @@ -94,6 +87,7 @@ export default function AdminPanel() { }); loadAdminData(); } catch (error) { + console.error('Error updating role:', error); toast({ title: 'Error', description: 'Failed to update user role', @@ -126,6 +120,7 @@ export default function AdminPanel() { description: 'Notification sent successfully', }); } catch (error) { + console.error('Error sending notification:', error); toast({ title: 'Error', description: 'Failed to send notification', diff --git a/web/src/pages/BeCitizen.tsx b/web/src/pages/BeCitizen.tsx index 27eea6e2..3d1c8e27 100644 --- a/web/src/pages/BeCitizen.tsx +++ b/web/src/pages/BeCitizen.tsx @@ -110,7 +110,7 @@ const BeCitizen: React.FC = () => {

Ready to Join?

- Whether you're already a citizen or want to become one, start your journey here. + Whether you're already a citizen or want to become one, start your journey here.

diff --git a/web/src/pages/Citizens.tsx b/web/src/pages/Citizens.tsx index 4af2d815..4d2e651f 100644 --- a/web/src/pages/Citizens.tsx +++ b/web/src/pages/Citizens.tsx @@ -2,7 +2,6 @@ import { useEffect, useState, useRef } from 'react'; import { useNavigate } from 'react-router-dom'; import { Card, CardContent } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; -import { Badge } from '@/components/ui/badge'; import { Input } from '@/components/ui/input'; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog'; import { usePolkadot } from '@/contexts/PolkadotContext'; @@ -10,8 +9,8 @@ import { useAuth } from '@/contexts/AuthContext'; import { useDashboard } from '@/contexts/DashboardContext'; import { FileText, Building2, Home, Bell, ChevronLeft, ChevronRight, Upload, User, Sun, ShieldCheck } from 'lucide-react'; import { useToast } from '@/hooks/use-toast'; -import { getCitizenSession } from '@pezkuwi/lib/citizenship-workflow'; -import { getUserRoleCategories, getTikiDisplayName } from '@pezkuwi/lib/tiki'; +// import { getCitizenSession } from '@pezkuwi/lib/citizenship-workflow'; +import { getUserRoleCategories } from '@pezkuwi/lib/tiki'; import { supabase } from '@/lib/supabase'; // Mock announcements data @@ -41,7 +40,7 @@ export default function Citizens() { const { user } = useAuth(); const navigate = useNavigate(); const { toast } = useToast(); - const { profile, nftDetails, kycStatus, citizenNumber, loading } = useDashboard(); + const { profile, nftDetails, citizenNumber, loading } = useDashboard(); const [currentAnnouncementIndex, setCurrentAnnouncementIndex] = useState(0); const [photoUrl, setPhotoUrl] = useState(null); const [uploadingPhoto, setUploadingPhoto] = useState(false); @@ -117,12 +116,12 @@ export default function Citizens() { }; reader.readAsDataURL(file); - } catch (error: any) { + } catch (error) { console.error('Photo upload error:', error); setUploadingPhoto(false); toast({ title: "Yükleme hatası (Upload error)", - description: error.message || "Fotoğraf yüklenemedi (Could not upload photo)", + description: error instanceof Error ? error.message : "Fotoğraf yüklenemedi (Could not upload photo)", variant: "destructive" }); } @@ -253,6 +252,7 @@ export default function Citizens() { business: [], judicial: [] }; + console.log('Role categories:', roleCategories); const currentAnnouncement = announcements[currentAnnouncementIndex]; @@ -409,7 +409,7 @@ export default function Citizens() {
{profile?.full_name || 'N/A'}
-
Father's Name
+
Father's Name
{profile?.father_name || 'N/A'}
diff --git a/web/src/pages/Dashboard.tsx b/web/src/pages/Dashboard.tsx index a4ee9be2..22ed4297 100644 --- a/web/src/pages/Dashboard.tsx +++ b/web/src/pages/Dashboard.tsx @@ -9,7 +9,7 @@ import { usePolkadot } from '@/contexts/PolkadotContext'; import { supabase } from '@/lib/supabase'; import { User, Mail, Phone, Globe, MapPin, Calendar, Shield, AlertCircle, ArrowLeft, Award, Users, TrendingUp, UserMinus } from 'lucide-react'; import { useToast } from '@/hooks/use-toast'; -import { fetchUserTikis, calculateTikiScore, getPrimaryRole, getTikiDisplayName, getTikiColor, getTikiEmoji, getUserRoleCategories, getAllTikiNFTDetails, generateCitizenNumber, type TikiNFTDetails } from '@pezkuwi/lib/tiki'; +import { fetchUserTikis, getPrimaryRole, getTikiDisplayName, getTikiColor, getTikiEmoji, getUserRoleCategories, getAllTikiNFTDetails, generateCitizenNumber, type TikiNFTDetails } from '@pezkuwi/lib/tiki'; import { getAllScores, type UserScores } from '@pezkuwi/lib/scores'; import { getKycStatus } from '@pezkuwi/lib/kyc'; import { ReferralDashboard } from '@/components/referral/ReferralDashboard'; @@ -21,7 +21,7 @@ export default function Dashboard() { const { api, isApiReady, selectedAccount } = usePolkadot(); const navigate = useNavigate(); const { toast } = useToast(); - const [profile, setProfile] = useState(null); + const [profile, setProfile] = useState | null>(null); const [loading, setLoading] = useState(true); const [tikis, setTikis] = useState([]); const [scores, setScores] = useState({ @@ -44,8 +44,11 @@ export default function Dashboard() { fetchProfile(); if (selectedAccount && api && isApiReady) { fetchScoresAndTikis(); + + } }, [user, selectedAccount, api, isApiReady]); + const fetchProfile = async () => { if (!user) return; @@ -64,7 +67,7 @@ export default function Dashboard() { // Auto-sync user metadata from Auth to profiles if missing if (data) { - const needsUpdate: any = {}; + const needsUpdate: Record = {}; // Sync full_name from Auth metadata if not set in profiles if (!data.full_name && user.user_metadata?.full_name) { @@ -96,7 +99,7 @@ export default function Dashboard() { } // Note: Email verification is handled by Supabase Auth (user.email_confirmed_at) - // We don't store it in profiles table to avoid duplication + // We don't store it in profiles table to avoid duplication setProfile(data); } catch (error) { @@ -107,6 +110,7 @@ export default function Dashboard() { }; const fetchScoresAndTikis = async () => { + if (!selectedAccount || !api) return; setLoadingScores(true); @@ -177,7 +181,7 @@ export default function Dashboard() { title: "Verification Email Sent", description: "Please check your email inbox and spam folder", }); - } catch (error: any) { + } catch (error) { console.error('Error sending verification email:', error); // Provide more detailed error message @@ -272,6 +276,8 @@ export default function Dashboard() { // Refresh data after a short delay setTimeout(() => { fetchScoresAndTikis(); + + }, 2000); } }); @@ -280,11 +286,12 @@ export default function Dashboard() { } }); - } catch (err: any) { + } catch (err) { console.error('Renunciation error:', err); + const errorMsg = err instanceof Error ? err.message : 'Failed to renounce citizenship'; toast({ title: "Error", - description: err.message || 'Failed to renounce citizenship', + description: errorMsg, variant: "destructive" }); setRenouncingCitizenship(false); @@ -575,7 +582,7 @@ export default function Dashboard() {

All Roles ({tikis.length})

- {tikis.map((tiki, index) => ( + {tikis.map((tiki, /*index*/) => ( 0 && (

Additional Role NFTs:

- {nftDetails.roleNFTs.map((nft, index) => ( + {nftDetails.roleNFTs.map((nft, /*index*/) => (
([]); const [proposals, setProposals] = useState([]); - const [officials, setOfficials] = useState({}); - const [ministers, setMinisters] = useState({}); + const [officials, setOfficials] = useState>({}); + const [ministers, setMinisters] = useState>({}); // Fetch data useEffect(() => { @@ -177,9 +175,10 @@ export default function Elections() { // ELECTION CARD // ============================================================================ +// eslint-disable-next-line @typescript-eslint/no-explicit-any function ElectionCard({ election, api }: { election: ElectionInfo; api: any }) { const [candidates, setCandidates] = useState([]); - const [timeLeft, setTimeLeft] = useState(null); + const [timeLeft, setTimeLeft] = useState(null); const typeLabel = getElectionTypeLabel(election.electionType); const statusLabel = getElectionStatusLabel(election.status); @@ -302,8 +301,9 @@ function ElectionCard({ election, api }: { election: ElectionInfo; api: any }) { // PROPOSAL CARD // ============================================================================ +// eslint-disable-next-line @typescript-eslint/no-explicit-any function ProposalCard({ proposal, api }: { proposal: CollectiveProposal; api: any }) { - const [timeLeft, setTimeLeft] = useState(null); + const [timeLeft, setTimeLeft] = useState(null); const totalVotes = proposal.ayeVotes + proposal.nayVotes + proposal.abstainVotes; const ayePercent = totalVotes > 0 ? Math.round((proposal.ayeVotes / totalVotes) * 100) : 0; @@ -393,6 +393,7 @@ function ProposalCard({ proposal, api }: { proposal: CollectiveProposal; api: an // GOVERNMENT OFFICIALS // ============================================================================ +// eslint-disable-next-line @typescript-eslint/no-explicit-any function GovernmentOfficials({ officials, ministers }: { officials: any; ministers: any }) { return (
@@ -427,11 +428,12 @@ function GovernmentOfficials({ officials, ministers }: { officials: any; ministe {Object.entries(ministers).map( + // eslint-disable-next-line @typescript-eslint/no-explicit-any ([role, address]: [string, any]) => address && ( ).en} address={address} icon={Users} /> @@ -446,6 +448,7 @@ function GovernmentOfficials({ officials, ministers }: { officials: any; ministe ); } +// eslint-disable-next-line @typescript-eslint/no-explicit-any function OfficeRow({ title, address, icon: Icon }: { title: string; address: string; icon: any }) { return (
diff --git a/web/src/pages/EmailVerification.tsx b/web/src/pages/EmailVerification.tsx index 350d687d..d9b547cd 100644 --- a/web/src/pages/EmailVerification.tsx +++ b/web/src/pages/EmailVerification.tsx @@ -24,14 +24,14 @@ export default function EmailVerification() { const verifyEmail = async (token: string) => { try { - const { data, error } = await supabase.functions.invoke('email-verification', { + const { error } = await supabase.functions.invoke('email-verification', { body: { action: 'verify', token } }); if (error) throw error; setVerified(true); - } catch (err: any) { + } catch (err: Error) { setError(err.message || 'Failed to verify email'); } finally { setVerifying(false); diff --git a/web/src/pages/GovEntrance.tsx b/web/src/pages/GovEntrance.tsx index 724a86f6..4217a910 100644 --- a/web/src/pages/GovEntrance.tsx +++ b/web/src/pages/GovEntrance.tsx @@ -3,7 +3,6 @@ import { useNavigate } from 'react-router-dom'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; -import { usePolkadot } from '@/contexts/PolkadotContext'; import { useDashboard } from '@/contexts/DashboardContext'; import { ArrowLeft, @@ -16,13 +15,12 @@ import { XCircle, Clock, TrendingUp, - AlertCircle, - Home + AlertCircle } from 'lucide-react'; import { useToast } from '@/hooks/use-toast'; export default function GovEntrance() { - const { api, isApiReady, selectedAccount } = usePolkadot(); + // usePolkadot removed const { nftDetails, kycStatus, loading: dashboardLoading } = useDashboard(); const navigate = useNavigate(); const { toast } = useToast(); @@ -30,7 +28,9 @@ export default function GovEntrance() { useEffect(() => { checkGovernmentRole(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [nftDetails, dashboardLoading]); + const checkGovernmentRole = () => { if (dashboardLoading) { diff --git a/web/src/pages/Login.tsx b/web/src/pages/Login.tsx index 8f1a0a49..e7ca7f88 100644 --- a/web/src/pages/Login.tsx +++ b/web/src/pages/Login.tsx @@ -48,12 +48,12 @@ const Login: React.FC = () => { if (error.message?.includes('Invalid login credentials')) { setError('Email or password is incorrect. Please try again.'); } else { - setError(error.message || 'Login failed. Please try again.'); + setError(error instanceof Error ? error.message : 'Login failed. Please try again.'); } } else { navigate('/'); } - } catch (err) { + } catch { setError('Login failed. Please try again.'); } finally { setLoading(false); @@ -90,7 +90,7 @@ const Login: React.FC = () => { } else { navigate('/'); } - } catch (err) { + } catch { setError('Signup failed. Please try again.'); } finally { setLoading(false); @@ -107,9 +107,10 @@ const Login: React.FC = () => { } else { setError('Please select an account from your Polkadot.js extension'); } - } catch (err: any) { + } catch (err) { console.error('Wallet connection failed:', err); - if (err.message?.includes('extension')) { + const errorMsg = err instanceof Error ? err.message : ''; + if (errorMsg?.includes('extension')) { setError('Polkadot.js extension not found. Please install it first.'); } else { setError('Failed to connect wallet. Please try again.'); diff --git a/web/src/pages/PasswordReset.tsx b/web/src/pages/PasswordReset.tsx index 9fb6baf5..1bf6d09b 100644 --- a/web/src/pages/PasswordReset.tsx +++ b/web/src/pages/PasswordReset.tsx @@ -23,7 +23,7 @@ export default function PasswordReset() { setLoading(true); try { - const { data, error } = await supabase.functions.invoke('password-reset', { + const { error } = await supabase.functions.invoke('password-reset', { body: { action: 'request', email } }); @@ -35,10 +35,10 @@ export default function PasswordReset() { }); setEmail(''); - } catch (error: any) { + } catch (error) { toast({ title: "Error", - description: error.message || "Failed to send reset email", + description: error instanceof Error ? error.message : "Failed to send reset email", variant: "destructive" }); } finally { @@ -70,7 +70,7 @@ export default function PasswordReset() { setLoading(true); try { - const { data, error } = await supabase.functions.invoke('password-reset', { + const { error } = await supabase.functions.invoke('password-reset', { body: { action: 'reset', token, newPassword: password } }); @@ -82,10 +82,10 @@ export default function PasswordReset() { }); navigate('/login'); - } catch (error: any) { + } catch (error) { toast({ title: "Error", - description: error.message || "Failed to reset password", + description: error instanceof Error ? error.message : "Failed to reset password", variant: "destructive" }); } finally { diff --git a/web/src/pages/ProfileSettings.tsx b/web/src/pages/ProfileSettings.tsx index 303f60ae..b1940a4d 100644 --- a/web/src/pages/ProfileSettings.tsx +++ b/web/src/pages/ProfileSettings.tsx @@ -10,9 +10,9 @@ import { Switch } from '@/components/ui/switch'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; -import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; +// import { Avatar, AvatarImage } from '@/components/ui/avatar'; import { useToast } from '@/hooks/use-toast'; -import { Loader2, User, Mail, Shield, Bell, Palette, Globe, ArrowLeft } from 'lucide-react'; +import { User, Shield, Bell, Palette, ArrowLeft } from 'lucide-react'; import { TwoFactorSetup } from '@/components/auth/TwoFactorSetup'; export default function ProfileSettings() { const navigate = useNavigate(); @@ -37,12 +37,13 @@ export default function ProfileSettings() { useEffect(() => { if (user) { loadProfile(); + } }, [user]); const loadProfile = async () => { try { - const { data, error } = await supabase + const { error } = await supabase .from('profiles') .select('*') .eq('id', user?.id) @@ -78,7 +79,7 @@ export default function ProfileSettings() { setLoading(true); try { // Call the secure upsert function - const { data, error } = await supabase.rpc('upsert_user_profile', { + const { error } = await supabase.rpc('upsert_user_profile', { p_username: profile.username || '', p_full_name: profile.full_name || null, p_bio: profile.bio || null, @@ -101,7 +102,8 @@ export default function ProfileSettings() { // Reload profile to ensure state is in sync await loadProfile(); - } catch (error: any) { + + } catch (error) { console.error('Profile update failed:', error); toast({ title: 'Error', @@ -117,7 +119,7 @@ export default function ProfileSettings() { setLoading(true); try { // Call the upsert function with current profile data + notification settings - const { data, error } = await supabase.rpc('upsert_user_profile', { + const { error } = await supabase.rpc('upsert_user_profile', { p_username: profile.username || '', p_full_name: profile.full_name || null, p_bio: profile.bio || null, @@ -137,7 +139,7 @@ export default function ProfileSettings() { title: 'Success', description: 'Notification settings updated', }); - } catch (error: any) { + } catch (error) { toast({ title: 'Error', description: error?.message || 'Failed to update notification settings', @@ -148,7 +150,9 @@ export default function ProfileSettings() { } }; - const updateSecuritySettings = async () => { + // Security settings updater (for future UI use) + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const updateSecuritySettings = useCallback(async () => { setLoading(true); try { const { error } = await supabase @@ -165,7 +169,8 @@ export default function ProfileSettings() { title: 'Success', description: 'Security settings updated', }); - } catch (error) { + } catch (err) { + console.error('Security settings error:', err); toast({ title: 'Error', description: 'Failed to update security settings', @@ -174,7 +179,7 @@ export default function ProfileSettings() { } finally { setLoading(false); } - }; + }, [profile, user, toast]); const changePassword = async () => { const newPassword = prompt('Enter new password:'); @@ -192,7 +197,8 @@ export default function ProfileSettings() { title: 'Success', description: 'Password changed successfully', }); - } catch (error) { + } catch (err) { + console.error('Password change error:', err); toast({ title: 'Error', description: 'Failed to change password', diff --git a/web/src/pages/ReservesDashboardPage.tsx b/web/src/pages/ReservesDashboardPage.tsx index 09be1bf7..27607c90 100644 --- a/web/src/pages/ReservesDashboardPage.tsx +++ b/web/src/pages/ReservesDashboardPage.tsx @@ -15,7 +15,7 @@ const SPECIFIC_ADDRESSES = { const ReservesDashboardPage = () => { const navigate = useNavigate(); const [isBridgeOpen, setIsBridgeOpen] = useState(false); - const [offChainReserve, setOffChainReserve] = useState(10000); // Example: $10,000 USDT + const [offChainReserve] = useState(10000); // Example: $10,000 USDT return (
diff --git a/web/src/pages/WalletDashboard.tsx b/web/src/pages/WalletDashboard.tsx index ff870aeb..e7d56f39 100644 --- a/web/src/pages/WalletDashboard.tsx +++ b/web/src/pages/WalletDashboard.tsx @@ -54,11 +54,11 @@ const WalletDashboard: React.FC = () => { try { const ts = await api.query.timestamp.now.at(blockHash); timestamp = ts.toNumber(); - } catch (error) { + } catch { timestamp = Date.now(); } - block.block.extrinsics.forEach((extrinsic, index) => { + block.block.extrinsics.forEach((extrinsic, /*index*/) => { if (!extrinsic.isSigned) return; const { method, signer } = extrinsic; @@ -148,7 +148,7 @@ const WalletDashboard: React.FC = () => { // Parse DEX operations else if (method.section === 'dex') { if (method.method === 'swap') { - const [path, amountIn] = method.args; + const [/*path*/, amountIn] = method.args; txList.push({ blockNumber, extrinsicIndex: index, @@ -189,13 +189,13 @@ const WalletDashboard: React.FC = () => { }); } }); - } catch (blockError) { + } catch { // Continue to next block } } setRecentTransactions(txList); - } catch (error) { + } catch { console.error('Failed to fetch recent transactions:', error); } finally { setIsLoadingRecent(false); @@ -206,6 +206,7 @@ const WalletDashboard: React.FC = () => { if (selectedAccount && api && isApiReady) { fetchRecentTransactions(); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectedAccount, api, isApiReady]); const formatAmount = (amount: string, decimals: number = 12) => { @@ -213,11 +214,13 @@ const WalletDashboard: React.FC = () => { return value.toFixed(4); }; + /* const formatTimestamp = (timestamp?: number) => { if (!timestamp) return 'Unknown'; const date = new Date(timestamp); return date.toLocaleString(); }; + */ const isIncoming = (tx: Transaction) => { return tx.to === selectedAccount?.address; @@ -315,7 +318,7 @@ const WalletDashboard: React.FC = () => {
) : (
- {recentTransactions.map((tx, index) => ( + {recentTransactions.map((tx, /*index*/) => (
([]); const [filteredIssues, setFilteredIssues] = useState([]); const [userVotes, setUserVotes] = useState>(new Map()); - const [categoryFilter, setCategoryFilter] = useState('all'); - const [statusFilter, setStatusFilter] = useState('all'); const [searchQuery, setSearchQuery] = useState(''); const [showSubmitModal, setShowSubmitModal] = useState(false); const [newIssueDescription, setNewIssueDescription] = useState(''); @@ -132,12 +129,15 @@ export default function CitizensIssues() { useEffect(() => { if (isApiReady && selectedAccount) { fetchAllData(); + } }, [isApiReady, selectedAccount, activeTab]); + useEffect(() => { applyFilters(); - }, [issues, categoryFilter, statusFilter, searchQuery]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [issues, categorystatussearchQuery]); const fetchAllData = async () => { setLoading(true); @@ -327,6 +327,7 @@ export default function CitizensIssues() { candidatesEntries.forEach(([key, value]) => { const address = key.args[0].toString(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any const candidateData: any = value.toJSON(); candidates.push({ address, @@ -481,6 +482,7 @@ export default function CitizensIssues() { candidatesEntries.forEach(([key, value]) => { const address = key.args[0].toString(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any const candidateData: any = value.toJSON(); candidates.push({ address, @@ -636,6 +638,7 @@ export default function CitizensIssues() { proposalsEntries.forEach(([key, value]) => { const proposalId = key.args[0].toNumber(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any const proposalData: any = value.toJSON(); proposals.push({ id: proposalId, diff --git a/web/src/pages/citizens/GovernmentEntrance.tsx b/web/src/pages/citizens/GovernmentEntrance.tsx index 009c0333..a97f7fe1 100644 --- a/web/src/pages/citizens/GovernmentEntrance.tsx +++ b/web/src/pages/citizens/GovernmentEntrance.tsx @@ -117,7 +117,9 @@ export default function GovernmentEntrance() { useEffect(() => { checkGovernmentAccess(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [nftDetails, dashboardLoading]); + useEffect(() => { if (isApiReady && selectedAccount) { @@ -126,6 +128,7 @@ export default function GovernmentEntrance() { fetchPresidentialCandidates(); fetchUserVotes(); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [isApiReady, selectedAccount]); const checkGovernmentAccess = () => {