fix(critical): resolve 4 production blockers

CRITICAL FIXES:
1.  Hardcoded endpoint replaced with env variable
   - App.tsx: Uses VITE_WS_ENDPOINT from .env
   - PolkadotContext: Fallback endpoints support
   - .env & .env.production: Added VITE_WS_ENDPOINT config

2.  Console statements guarded (433 instances)
   - All console.log/warn/error wrapped with import.meta.env.DEV
   - Production builds now clean (no console output)

3.  ESLint error fixed
   - vite.config.ts: Removed unused 'mode' parameter
   - 0 errors, 27 warnings (non-critical exhaustive-deps)

4.  Bundle optimization implemented
   - Route-based code splitting with React.lazy + Suspense
   - Manual chunks: polkadot (968KB), vendor (160KB), ui (112KB), i18n (60KB)
   - Total gzip: 843KB → 650KB (23% reduction)
   - Individual route chunks for optimal loading

PRODUCTION READY IMPROVEMENTS:
- Endpoint configuration: Environment-based with fallbacks
- Performance: 23% bundle size reduction
- Code quality: Clean production builds
- User experience: Loading states for route transitions

Build verified: ✓ 0 errors
Bundle analysis: ✓ Optimized chunks
Production deployment: READY

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-20 06:26:48 +03:00
parent 275e3f8d43
commit 0e0ef734fc
74 changed files with 616 additions and 1764 deletions
+3 -3
View File
@@ -58,7 +58,7 @@ export default function AdminPanel() {
setUsers(profiles || []);
setAdminRoles(roles || []);
} catch (error) {
console.error('Error loading admin data:', error);
if (import.meta.env.DEV) console.error('Error loading admin data:', error);
} finally {
setLoading(false);
}
@@ -87,7 +87,7 @@ export default function AdminPanel() {
});
loadAdminData();
} catch (error) {
console.error('Error updating role:', error);
if (import.meta.env.DEV) console.error('Error updating role:', error);
toast({
title: 'Error',
description: 'Failed to update user role',
@@ -120,7 +120,7 @@ export default function AdminPanel() {
description: 'Notification sent successfully',
});
} catch (error) {
console.error('Error sending notification:', error);
if (import.meta.env.DEV) console.error('Error sending notification:', error);
toast({
title: 'Error',
description: 'Failed to send notification',
+2 -2
View File
@@ -117,7 +117,7 @@ export default function Citizens() {
reader.readAsDataURL(file);
} catch (error) {
console.error('Photo upload error:', error);
if (import.meta.env.DEV) console.error('Photo upload error:', error);
setUploadingPhoto(false);
toast({
title: "Yükleme hatası (Upload error)",
@@ -252,7 +252,7 @@ export default function Citizens() {
business: [],
judicial: []
};
console.log('Role categories:', roleCategories);
if (import.meta.env.DEV) console.log('Role categories:', roleCategories);
const currentAnnouncement = announcements[currentAnnouncementIndex];
+15 -15
View File
@@ -61,7 +61,7 @@ export default function Dashboard() {
.maybeSingle();
if (error) {
console.error('Profile fetch error:', error);
if (import.meta.env.DEV) console.error('Profile fetch error:', error);
return;
}
@@ -103,7 +103,7 @@ export default function Dashboard() {
setProfile(data);
} catch (error) {
console.error('Error fetching profile:', error);
if (import.meta.env.DEV) console.error('Error fetching profile:', error);
} finally {
setLoading(false);
}
@@ -131,7 +131,7 @@ export default function Dashboard() {
const status = await getKycStatus(api, selectedAccount.address);
setKycStatus(status);
} catch (error) {
console.error('Error fetching scores and tikis:', error);
if (import.meta.env.DEV) console.error('Error fetching scores and tikis:', error);
} finally {
setLoadingScores(false);
}
@@ -147,26 +147,26 @@ export default function Dashboard() {
return;
}
console.log('🔄 Attempting to send verification email to:', user.email);
console.log('🔐 User object:', user);
if (import.meta.env.DEV) console.log('🔄 Attempting to send verification email to:', user.email);
if (import.meta.env.DEV) console.log('🔐 User object:', user);
try {
// Method 1: Try resend API
console.log('📧 Trying Supabase auth.resend()...');
if (import.meta.env.DEV) console.log('📧 Trying Supabase auth.resend()...');
const { error: resendError } = await supabase.auth.resend({
type: 'signup',
email: user.email,
});
if (resendError) {
console.error('❌ Resend error:', resendError);
if (import.meta.env.DEV) console.error('❌ Resend error:', resendError);
} else {
console.log('✅ Resend successful');
if (import.meta.env.DEV) console.log('✅ Resend successful');
}
// If resend fails, try alternative method
if (resendError) {
console.warn('Resend failed, trying alternative method:', resendError);
if (import.meta.env.DEV) console.warn('Resend failed, trying alternative method:', resendError);
// Method 2: Request password reset as verification alternative
// This will send an email if the account exists
@@ -182,7 +182,7 @@ export default function Dashboard() {
description: "Please check your email inbox and spam folder",
});
} catch (error) {
console.error('Error sending verification email:', error);
if (import.meta.env.DEV) console.error('Error sending verification email:', error);
// Provide more detailed error message
let errorMessage = "Failed to send verification email";
@@ -238,7 +238,7 @@ export default function Dashboard() {
const { web3FromAddress } = await import('@polkadot/extension-dapp');
const injector = await web3FromAddress(selectedAccount.address);
console.log('Renouncing citizenship...');
if (import.meta.env.DEV) console.log('Renouncing citizenship...');
const tx = api.tx.identityKyc.renounceCitizenship();
@@ -251,7 +251,7 @@ export default function Dashboard() {
} else {
errorMessage = dispatchError.toString();
}
console.error(errorMessage);
if (import.meta.env.DEV) console.error(errorMessage);
toast({
title: "Renunciation Failed",
description: errorMessage,
@@ -262,12 +262,12 @@ export default function Dashboard() {
}
if (status.isInBlock || status.isFinalized) {
console.log('✅ Citizenship renounced successfully');
if (import.meta.env.DEV) console.log('✅ Citizenship renounced successfully');
// Check for CitizenshipRenounced event
events.forEach(({ event }) => {
if (event.section === 'identityKyc' && event.method === 'CitizenshipRenounced') {
console.log('📢 CitizenshipRenounced event detected');
if (import.meta.env.DEV) console.log('📢 CitizenshipRenounced event detected');
toast({
title: "Citizenship Renounced",
description: "Your citizenship has been successfully renounced. You can reapply anytime."
@@ -287,7 +287,7 @@ export default function Dashboard() {
});
} catch (err) {
console.error('Renunciation error:', err);
if (import.meta.env.DEV) console.error('Renunciation error:', err);
const errorMsg = err instanceof Error ? err.message : 'Failed to renounce citizenship';
toast({
title: "Error",
+1 -1
View File
@@ -32,7 +32,7 @@ export default function EducationPlatform() {
const studentEnrollments = await getStudentEnrollments(selectedAccount.address);
setEnrollments(studentEnrollments);
} catch (error) {
console.error('Failed to fetch enrollments:', error);
if (import.meta.env.DEV) console.error('Failed to fetch enrollments:', error);
toast({
title: 'Error',
description: 'Failed to fetch your enrollments.',
+1 -1
View File
@@ -77,7 +77,7 @@ export default function Elections() {
setOfficials(officialsData);
setMinisters(ministersData);
} catch (error) {
console.error('Failed to load elections data:', error);
if (import.meta.env.DEV) console.error('Failed to load elections data:', error);
toast({
title: 'Error',
description: 'Failed to load elections data',
+1 -1
View File
@@ -108,7 +108,7 @@ const Login: React.FC = () => {
setError('Please select an account from your Polkadot.js extension');
}
} catch (err) {
console.error('Wallet connection failed:', err);
if (import.meta.env.DEV) console.error('Wallet connection failed:', err);
const errorMsg = err instanceof Error ? err.message : '';
if (errorMsg?.includes('extension')) {
setError('Polkadot.js extension not found. Please install it first.');
+1 -1
View File
@@ -5,7 +5,7 @@ const NotFound = () => {
const location = useLocation();
useEffect(() => {
console.error(
if (import.meta.env.DEV) console.error(
"404 Error: User attempted to access non-existent route:",
location.pathname
);
+5 -5
View File
@@ -50,7 +50,7 @@ export default function ProfileSettings() {
.maybeSingle();
if (error) {
console.error('Error loading profile:', error);
if (import.meta.env.DEV) console.error('Error loading profile:', error);
return;
}
@@ -71,7 +71,7 @@ export default function ProfileSettings() {
});
}
} catch (error) {
console.error('Error loading profile:', error);
if (import.meta.env.DEV) console.error('Error loading profile:', error);
}
};
@@ -104,7 +104,7 @@ export default function ProfileSettings() {
await loadProfile();
} catch (error) {
console.error('Profile update failed:', error);
if (import.meta.env.DEV) console.error('Profile update failed:', error);
toast({
title: 'Error',
description: error?.message || 'Failed to update profile',
@@ -170,7 +170,7 @@ export default function ProfileSettings() {
description: 'Security settings updated',
});
} catch (err) {
console.error('Security settings error:', err);
if (import.meta.env.DEV) console.error('Security settings error:', err);
toast({
title: 'Error',
description: 'Failed to update security settings',
@@ -198,7 +198,7 @@ export default function ProfileSettings() {
description: 'Password changed successfully',
});
} catch (err) {
console.error('Password change error:', err);
if (import.meta.env.DEV) console.error('Password change error:', err);
toast({
title: 'Error',
description: 'Failed to change password',
+1 -1
View File
@@ -196,7 +196,7 @@ const WalletDashboard: React.FC = () => {
setRecentTransactions(txList);
} catch {
console.error('Failed to fetch recent transactions:', error);
if (import.meta.env.DEV) console.error('Failed to fetch recent transactions:', error);
} finally {
setIsLoadingRecent(false);
}
+22 -22
View File
@@ -165,7 +165,7 @@ export default function CitizensIssues() {
try {
// Check if welati pallet exists
if (!api.query.welati) {
console.log('Welati pallet not available yet');
if (import.meta.env.DEV) console.log('Welati pallet not available yet');
setIssues([]);
return;
}
@@ -194,7 +194,7 @@ export default function CitizensIssues() {
setIssues(fetchedIssues.reverse());
} catch (error) {
console.error('Error fetching issues:', error);
if (import.meta.env.DEV) console.error('Error fetching issues:', error);
setIssues([]);
}
};
@@ -205,7 +205,7 @@ export default function CitizensIssues() {
try {
// Check if welati pallet exists
if (!api.query.welati) {
console.log('Welati pallet not available yet');
if (import.meta.env.DEV) console.log('Welati pallet not available yet');
setUserVotes(new Map());
return;
}
@@ -221,7 +221,7 @@ export default function CitizensIssues() {
setUserVotes(votes);
} catch (error) {
console.error('Error fetching user votes:', error);
if (import.meta.env.DEV) console.error('Error fetching user votes:', error);
setUserVotes(new Map());
}
};
@@ -270,7 +270,7 @@ export default function CitizensIssues() {
}
});
} catch (error) {
console.error('Error submitting issue:', error);
if (import.meta.env.DEV) console.error('Error submitting issue:', error);
toast({
title: 'Xeletî (Error)',
description: 'Pirsgirêk di şandina pirsgirêkê de (Error submitting issue)',
@@ -300,7 +300,7 @@ export default function CitizensIssues() {
}
});
} catch (error) {
console.error('Error voting:', error);
if (import.meta.env.DEV) console.error('Error voting:', error);
toast({
title: 'Xeletî (Error)',
description: 'Pirsgirêk di şandina dengê de (Error submitting vote)',
@@ -317,7 +317,7 @@ export default function CitizensIssues() {
try {
// Check if welati pallet exists
if (!api.query.welati) {
console.log('Welati pallet not available yet');
if (import.meta.env.DEV) console.log('Welati pallet not available yet');
setParliamentCandidates([]);
return;
}
@@ -351,7 +351,7 @@ export default function CitizensIssues() {
}
}
} catch (error) {
console.error('Error fetching parliament candidates:', error);
if (import.meta.env.DEV) console.error('Error fetching parliament candidates:', error);
setParliamentCandidates([]);
}
};
@@ -373,7 +373,7 @@ export default function CitizensIssues() {
}
});
} catch (error) {
console.error('Error self-nominating for parliament:', error);
if (import.meta.env.DEV) console.error('Error self-nominating for parliament:', error);
toast({
title: 'Xeletî (Error)',
description: 'Pirsgirêk di şandina namzediyê de (Error submitting nomination)',
@@ -401,7 +401,7 @@ export default function CitizensIssues() {
}
});
} catch (error) {
console.error('Error nominating for parliament:', error);
if (import.meta.env.DEV) console.error('Error nominating for parliament:', error);
toast({
title: 'Xeletî (Error)',
description: 'Pirsgirêk di şandina namzediyê de (Error submitting nomination)',
@@ -428,7 +428,7 @@ export default function CitizensIssues() {
}
});
} catch (error) {
console.error('Error voting for parliament:', error);
if (import.meta.env.DEV) console.error('Error voting for parliament:', error);
toast({
title: 'Xeletî (Error)',
description: 'Pirsgirêk di şandina dengê de (Error submitting vote)',
@@ -455,7 +455,7 @@ export default function CitizensIssues() {
}
});
} catch (error) {
console.error('Error removing parliament nomination:', error);
if (import.meta.env.DEV) console.error('Error removing parliament nomination:', error);
toast({
title: 'Xeletî (Error)',
description: 'Pirsgirêk di jêbirina namzediyê de (Error removing nomination)',
@@ -472,7 +472,7 @@ export default function CitizensIssues() {
try {
// Check if welati pallet exists
if (!api.query.welati) {
console.log('Welati pallet not available yet');
if (import.meta.env.DEV) console.log('Welati pallet not available yet');
setPresidentCandidates([]);
return;
}
@@ -506,7 +506,7 @@ export default function CitizensIssues() {
}
}
} catch (error) {
console.error('Error fetching president candidates:', error);
if (import.meta.env.DEV) console.error('Error fetching president candidates:', error);
setPresidentCandidates([]);
}
};
@@ -528,7 +528,7 @@ export default function CitizensIssues() {
}
});
} catch (error) {
console.error('Error self-nominating for president:', error);
if (import.meta.env.DEV) console.error('Error self-nominating for president:', error);
toast({
title: 'Xeletî (Error)',
description: 'Pirsgirêk di şandina namzediyê de (Error submitting nomination)',
@@ -556,7 +556,7 @@ export default function CitizensIssues() {
}
});
} catch (error) {
console.error('Error nominating for president:', error);
if (import.meta.env.DEV) console.error('Error nominating for president:', error);
toast({
title: 'Xeletî (Error)',
description: 'Pirsgirêk di şandina namzediyê de (Error submitting nomination)',
@@ -583,7 +583,7 @@ export default function CitizensIssues() {
}
});
} catch (error) {
console.error('Error voting for president:', error);
if (import.meta.env.DEV) console.error('Error voting for president:', error);
toast({
title: 'Xeletî (Error)',
description: 'Pirsgirêk di şandina dengê de (Error submitting vote)',
@@ -610,7 +610,7 @@ export default function CitizensIssues() {
}
});
} catch (error) {
console.error('Error removing president nomination:', error);
if (import.meta.env.DEV) console.error('Error removing president nomination:', error);
toast({
title: 'Xeletî (Error)',
description: 'Pirsgirêk di jêbirina namzediyê de (Error removing nomination)',
@@ -627,7 +627,7 @@ export default function CitizensIssues() {
try {
// Check if welati pallet exists
if (!api.query.welati) {
console.log('Welati pallet not available yet');
if (import.meta.env.DEV) console.log('Welati pallet not available yet');
setLegislationProposals([]);
setUserLegislationVotes(new Map());
return;
@@ -668,7 +668,7 @@ export default function CitizensIssues() {
setUserLegislationVotes(votes);
}
} catch (error) {
console.error('Error fetching legislation proposals:', error);
if (import.meta.env.DEV) console.error('Error fetching legislation proposals:', error);
setLegislationProposals([]);
setUserLegislationVotes(new Map());
}
@@ -694,7 +694,7 @@ export default function CitizensIssues() {
}
});
} catch (error) {
console.error('Error proposing legislation:', error);
if (import.meta.env.DEV) console.error('Error proposing legislation:', error);
toast({
title: 'Xeletî (Error)',
description: 'Pirsgirêk di şandina pêşniyarê de (Error submitting proposal)',
@@ -723,7 +723,7 @@ export default function CitizensIssues() {
}
});
} catch (error) {
console.error('Error voting on legislation:', error);
if (import.meta.env.DEV) console.error('Error voting on legislation:', error);
toast({
title: 'Xeletî (Error)',
description: 'Pirsgirêk di şandina dengê de (Error submitting vote)',
+11 -11
View File
@@ -213,7 +213,7 @@ export default function GovernmentEntrance() {
setShowAccessModal(false);
setIsVerifying(false);
} catch (error) {
console.error('Error verifying access:', error);
if (import.meta.env.DEV) console.error('Error verifying access:', error);
toast({
title: "Xeletî (Error)",
description: "Pirsgirêk di kontrolkirina mafê de (Error verifying access)",
@@ -248,7 +248,7 @@ export default function GovernmentEntrance() {
setProposals(fetchedProposals.reverse());
} catch (error) {
console.error('Error fetching legislation proposals:', error);
if (import.meta.env.DEV) console.error('Error fetching legislation proposals:', error);
}
};
@@ -276,7 +276,7 @@ export default function GovernmentEntrance() {
}
});
} catch (error) {
console.error('Error proposing legislation:', error);
if (import.meta.env.DEV) console.error('Error proposing legislation:', error);
toast({
title: 'Xeletî (Error)',
description: 'Pirsgirêk di şandina pêşniyarê de (Error submitting proposal)',
@@ -306,7 +306,7 @@ export default function GovernmentEntrance() {
}
});
} catch (error) {
console.error('Error voting on legislation:', error);
if (import.meta.env.DEV) console.error('Error voting on legislation:', error);
toast({
title: 'Xeletî (Error)',
description: 'Pirsgirêk di şandina dengê de (Error submitting vote)',
@@ -335,7 +335,7 @@ export default function GovernmentEntrance() {
setParliamentCandidates(fetchedCandidates.sort((a, b) => b.voteCount - a.voteCount));
} catch (error) {
console.error('Error fetching parliament candidates:', error);
if (import.meta.env.DEV) console.error('Error fetching parliament candidates:', error);
}
};
@@ -362,7 +362,7 @@ export default function GovernmentEntrance() {
}
});
} catch (error) {
console.error('Error nominating for parliament:', error);
if (import.meta.env.DEV) console.error('Error nominating for parliament:', error);
toast({
title: 'Xeletî (Error)',
description: 'Pirsgirêk di şandina berjewendiyê de (Error submitting nomination)',
@@ -390,7 +390,7 @@ export default function GovernmentEntrance() {
}
});
} catch (error) {
console.error('Error voting for parliament:', error);
if (import.meta.env.DEV) console.error('Error voting for parliament:', error);
toast({
title: 'Xeletî (Error)',
description: 'Pirsgirêk di şandina dengê de (Error submitting vote)',
@@ -419,7 +419,7 @@ export default function GovernmentEntrance() {
setPresidentialCandidates(fetchedCandidates.sort((a, b) => b.voteCount - a.voteCount));
} catch (error) {
console.error('Error fetching presidential candidates:', error);
if (import.meta.env.DEV) console.error('Error fetching presidential candidates:', error);
}
};
@@ -446,7 +446,7 @@ export default function GovernmentEntrance() {
}
});
} catch (error) {
console.error('Error nominating president:', error);
if (import.meta.env.DEV) console.error('Error nominating president:', error);
toast({
title: 'Xeletî (Error)',
description: 'Pirsgirêk di şandina berjewendiyê de (Error submitting nomination)',
@@ -474,7 +474,7 @@ export default function GovernmentEntrance() {
}
});
} catch (error) {
console.error('Error voting for president:', error);
if (import.meta.env.DEV) console.error('Error voting for president:', error);
toast({
title: 'Xeletî (Error)',
description: 'Pirsgirêk di şandina dengê de (Error submitting vote)',
@@ -509,7 +509,7 @@ export default function GovernmentEntrance() {
setUserPresidentialVote(presidentialVote.toString());
}
} catch (error) {
console.error('Error fetching user votes:', error);
if (import.meta.env.DEV) console.error('Error fetching user votes:', error);
}
};