- Created `/frontend/app/api/votes/check/route.ts` to handle GET requests for checking if a user has voted in a specific election. - Added error handling for unauthorized access and missing election ID. - Forwarded requests to the backend API and returned appropriate responses. - Updated `/frontend/app/api/votes/history/route.ts` to fetch user's voting history with error handling. - Ensured both endpoints utilize the authorization token for secure access.
9.8 KiB
9.8 KiB
✅ LOGGING ENHANCEMENTS - DEPLOYMENT READY
Date: November 10, 2025
Status: All logging code added and verified
Purpose: Comprehensive diagnosis of truncateHash undefined error
📝 Summary of Changes
Files Modified with Enhanced Logging
-
✅
/frontend/components/blockchain-visualizer.tsx- Added component mount/update logging
- Added data structure inspection logging
- Enhanced truncateHash with detailed parameter logging
- All blocks logged with field inspection
-
✅
/frontend/components/blockchain-viewer.tsx- Added useEffect import
- Added component mount/update logging
- Enhanced truncateHash with warning logging
-
✅
/frontend/app/dashboard/blockchain/page.tsx- Added fetch logging
- Added data received logging with structure inspection
- Added error logging
- Added mock data logging
🎯 What the Logging Will Show
Scenario 1: Data Loads Successfully
[BlockchainPage] Fetching blockchain for election: 1
[BlockchainPage] Fetch response status: 200
[BlockchainPage] Received blockchain data: { blocksCount: 5, hasVerification: true, ... }
[BlockchainVisualizer] Component mounted/updated { dataExists: true, blocksCount: 5, ... }
[BlockchainVisualizer] First block structure: { index: 0, transaction_id: "genesis", encrypted_vote: "", signature: "" }
Block 0: { transaction_id: "genesis", encrypted_vote_empty: true, signature_empty: true }
[truncateHash] Called with: { hash: "genesis", type: "string", ... }
[truncateHash] Result: genesis
[truncateHash] Called with: { hash: "", type: "string", isEmpty: true, ... }
[truncateHash] Empty string received
[truncateHash] Result: N/A
Scenario 2: Data Has Undefined Fields
[BlockchainPage] Received blockchain data: { blocksCount: 5, firstBlockStructure: { index: 0, transaction_id: undefined, ... } }
[truncateHash] Called with: { hash: undefined, type: "undefined", isUndefined: true, ... }
[truncateHash] Received undefined
🚀 How to Test
Step 1: Restart Frontend
cd /home/paul/CIA/e-voting-system
docker compose restart frontend
sleep 5
Step 2: Open Browser Console
Press F12 → Console tab
Step 3: Navigate to Blockchain Dashboard
URL: http://localhost:3000/dashboard/blockchain
Step 4: Select an Election
Click dropdown → Select first election
Watch for console logs
Step 5: Check Console Output
Look for logs starting with:
- [BlockchainPage]
- [BlockchainVisualizer]
- [truncateHash]
Step 6: Share the Logs
If you see any [truncateHash] calls with:
- hash: undefined
- type: "undefined"
- isUndefined: true
Then we found the problem!
📊 Log Levels
Info Level (ℹ️)
console.log("[Component] Information message")
Used for: Normal flow, data received, function calls
Warning Level (⚠️)
console.warn("[Component] Warning message")
Used for: Unexpected but handled cases (like undefined hash)
Error Level (❌)
console.error("[Component] Error message")
Used for: Actual errors that need attention
🔍 Key Logging Points
| Location | Purpose | Log Output |
|---|---|---|
| BlockchainPage fetch | Track API call | [BlockchainPage] Fetching blockchain for election: X |
| BlockchainPage response | Track data received | [BlockchainPage] Fetch response status: 200 |
| BlockchainPage data | Inspect structure | [BlockchainPage] Received blockchain data: {...} |
| Visualizer mount | Track component | [BlockchainVisualizer] Component mounted/updated {...} |
| Visualizer data | Inspect blocks | [BlockchainVisualizer] First block structure: {...} |
| truncateHash call | Log each call | [truncateHash] Called with: {...} |
| truncateHash result | Track output | [truncateHash] Result: value |
🎓 Reading the Logs
For [truncateHash] Called with: logs, check these fields:
| Field | What It Means |
|---|---|
hash |
The actual value passed |
type |
JavaScript type (string, undefined, object, etc.) |
isNull |
true if value is null |
isUndefined |
true if value is undefined |
isEmpty |
true if value is empty string "" |
length |
Actual string length or 0 |
requestedLength |
How many chars to show |
Example Good Call:
[truncateHash] Called with: {
hash: "abc123def456",
type: "string",
isNull: false,
isUndefined: false,
isEmpty: false,
length: 12,
requestedLength: 8
}
[truncateHash] Result: abc123de...
Example Problem Call:
[truncateHash] Called with: {
hash: undefined,
type: "undefined",
isNull: false,
isUndefined: true,
isEmpty: false,
length: 0,
requestedLength: 16
}
[truncateHash] Received undefined
💾 Code Added
blockchain-visualizer.tsx
// Debug logging - log all received data
useEffect(() => {
console.log("[BlockchainVisualizer] Component mounted/updated", { ... })
if (data?.blocks && data.blocks.length > 0) {
console.log("[BlockchainVisualizer] First block structure:", { ... })
data.blocks.forEach((block, idx) => {
console.log(`Block ${idx}:`, { ... })
})
}
}, [data, isValidData])
// Enhanced truncateHash
const truncateHash = (hash: string | undefined | null, length: number = 16) => {
console.log(`[truncateHash] Called with:`, { ... })
if (hash === null || hash === undefined) {
console.warn(`[truncateHash] Received ${hash === null ? "null" : "undefined"}`)
return "N/A"
}
if (typeof hash !== "string") {
console.error(`[truncateHash] Invalid type: ${typeof hash}, value: ${hash}`)
return "N/A"
}
if (hash.length === 0) {
console.log(`[truncateHash] Empty string received`)
return "N/A"
}
const result = hash.length > length ? `${hash.slice(0, length)}...` : hash
console.log(`[truncateHash] Result:`, result)
return result
}
blockchain-viewer.tsx
// Added useEffect import
import { useState, useEffect } from "react"
// Debug logging
useEffect(() => {
console.log("[BlockchainViewer] Component mounted/updated", { ... })
}, [data, isLoading, isVerifying])
// Enhanced truncateHash
const truncateHash = (hash: string | undefined | null, length: number = 16) => {
if (!hash || typeof hash !== "string") {
console.warn("[BlockchainViewer] truncateHash received invalid value:", { hash, type: typeof hash })
return "N/A"
}
return hash.length > length ? `${hash.slice(0, length)}...` : hash
}
page.tsx (BlockchainPage)
// Fetch logging
console.log("[BlockchainPage] Fetching blockchain for election:", selectedElection)
console.log("[BlockchainPage] Fetch response status:", response.status)
// Data logging
console.log("[BlockchainPage] Received blockchain data:", {
blocksCount: data?.blocks?.length || 0,
hasVerification: !!data?.verification,
firstBlockStructure: { ... }
})
// Error logging
console.error("[BlockchainPage] Error fetching blockchain:", errorMessage)
// Mock data logging
console.log("[BlockchainPage] Using mock data")
🎯 Expected Output Examples
✅ Good Output
[BlockchainPage] Fetching blockchain for election: 1
[BlockchainPage] Fetch response status: 200
[BlockchainPage] Received blockchain data: {blocksCount: 3, hasVerification: true, firstBlockStructure: {index: 0, transaction_id: 'genesis', encrypted_vote: '', signature: ''}}
[BlockchainVisualizer] Component mounted/updated {dataExists: true, isValidData: true, blocksCount: 3, isLoading: false, isVerifying: false}
[BlockchainVisualizer] First block structure: {index: 0, transaction_id: 'genesis', prev_hash: '00000000...', block_hash: 'e3b0c442...', encrypted_vote: '', signature: '', timestamp: 1731219600}
Block 0: {transaction_id: 'genesis', encrypted_vote_empty: true, signature_empty: true}
[truncateHash] Called with: {hash: 'genesis', type: 'string', isNull: false, isUndefined: false, isEmpty: false, length: 7, requestedLength: 20}
[truncateHash] Result: genesis
[truncateHash] Called with: {hash: '', type: 'string', isNull: false, isUndefined: false, isEmpty: true, length: 0, requestedLength: 60}
[truncateHash] Empty string received
[truncateHash] Result: N/A
❌ Problem Output (what we're looking for)
[BlockchainPage] Received blockchain data: {blocksCount: 1, hasVerification: true, firstBlockStructure: {index: 0, transaction_id: undefined, encrypted_vote: undefined, signature: undefined}}
...
[truncateHash] Called with: {hash: undefined, type: 'undefined', isNull: false, isUndefined: true, isEmpty: false, length: 0, requestedLength: 16}
[truncateHash] Received undefined
✨ Benefits of This Logging
- Visibility: See exactly what data is being passed through the system
- Diagnostics: Identify where undefined values come from
- Debugging: Trace the flow from fetch → component → rendering
- Performance: Identify performance issues with repeated logs
- Testing: Verify components work as expected during tests
📋 Deployment Checklist
- Logging code added to blockchain-visualizer.tsx
- Logging code added to blockchain-viewer.tsx
- Logging code added to page.tsx
- useEffect import added where needed
- No breaking changes introduced
- All logging is non-intrusive (just console.log)
- Ready to test in browser
- Comprehensive logging guide created
🚀 Next Steps
-
Rebuild frontend:
docker compose restart frontend sleep 5 -
Open browser console: F12 → Console
-
Navigate to dashboard/blockchain
-
Select an election
-
Look for logs with
[truncateHash]andundefined -
If found, report back with the exact console output
Status: ✅ READY FOR TESTING
Changes: Non-breaking logging enhancements
Safe to Deploy: YES ✅