Addresses critical issues including SSR crashes due to improper localStorage/document access and a broken betting feature in Article.tsx. Replit-Commit-Author: Agent Replit-Commit-Session-Id: aabe2db1-f078-4501-aab5-be145ebc6b9a Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3df548ff-50ae-432f-9be4-25d34eccc983/aabe2db1-f078-4501-aab5-be145ebc6b9a/TqVS1Ec
8.9 KiB
Frontend Issues - Code Review Report
🔴 Critical Issues (Immediate Fix Required)
1. localStorage Access Without Browser Check - SSR Crash Risk
Severity: CRITICAL
Files Affected:
client/src/pages/Home.tsxclient/src/pages/Landing.tsxclient/src/pages/Auctions.tsxclient/src/pages/MediaOutlet.tsx
Problem:
Multiple pages initialize React state directly from localStorage without checking if window is defined:
const [theme, setTheme] = useState(() => localStorage.getItem('theme') || 'light');
Impact:
- ReferenceError in SSR/non-browser environments (tests, server-side rendering)
- Application crashes immediately on page load
- Breaks testing infrastructure
- Prevents server-side rendering if needed in future
Reproduction:
- Run unit tests that mount these components
- Try server-side rendering
- Access
localStoragebefore window is available
Fix Solution:
// ❌ Current (BROKEN)
const [theme, setTheme] = useState(() => localStorage.getItem('theme') || 'light');
// ✅ Fixed
const [theme, setTheme] = useState(() => {
if (typeof window !== 'undefined') {
return localStorage.getItem('theme') || 'light';
}
return 'light';
});
// Alternative: Move to useEffect
const [theme, setTheme] = useState('light');
useEffect(() => {
if (typeof window !== 'undefined') {
const savedTheme = localStorage.getItem('theme');
if (savedTheme) setTheme(savedTheme);
}
}, []);
Priority: P0 - Fix immediately
2. Betting Feature Completely Broken - Ignores User Input
Severity: CRITICAL
File: client/src/pages/Article.tsx
Problem:
The handlePlaceBet function ignores user input and always submits hardcoded value:
const handlePlaceBet = (marketId: string, option: "yes" | "no") => {
// User input stored in betAmounts[marketId] is IGNORED
const amount = 10000; // ❌ HARDCODED!
placeBetMutation.mutate({ marketId, option, amount });
};
Impact:
- Users cannot place custom bets
- All bets are forced to 10,000 regardless of input
- Primary feature of the page is non-functional
- Poor user experience
Reproduction:
- Navigate to an article with prediction market
- Enter any bet amount (e.g., 500)
- Click place bet
- Backend receives 10,000 instead of 500
Fix Solution:
// ❌ Current (BROKEN)
const handlePlaceBet = (marketId: string, option: "yes" | "no") => {
const amount = 10000; // Hardcoded!
placeBetMutation.mutate({ marketId, option, amount });
};
// ✅ Fixed
const handlePlaceBet = (marketId: string, option: "yes" | "no") => {
const inputAmount = betAmounts[marketId];
// Validate input
if (!inputAmount || parseFloat(inputAmount) <= 0) {
toast({
title: "Invalid Amount",
description: "Please enter a valid bet amount greater than 0",
variant: "destructive"
});
return;
}
const amount = parseFloat(inputAmount);
placeBetMutation.mutate({ marketId, option, amount });
};
Priority: P0 - Fix immediately
🟠 High Priority Issues
3. document.documentElement Access Without Browser Check
Severity: HIGH
Files Affected:
client/src/pages/Home.tsxclient/src/pages/Landing.tsxclient/src/pages/Auctions.tsxclient/src/pages/MediaOutlet.tsx
Problem:
Direct access to document.documentElement in useEffect without browser check:
useEffect(() => {
if (theme === 'dark') {
document.documentElement.classList.add('dark'); // No browser check!
}
}, [theme]);
Impact:
- Crashes in SSR environments
- Breaks in test environments without DOM
- Prevents future SSR implementation
Fix Solution:
useEffect(() => {
if (typeof window === 'undefined') return;
if (theme === 'dark') {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
localStorage.setItem('theme', theme);
}, [theme]);
Priority: P1 - Fix soon
4. Missing Error State Rendering
Severity: HIGH
Files Affected:
client/src/pages/Auctions.tsxclient/src/pages/MediaOutlet.tsxclient/src/pages/Article.tsxclient/src/pages/AdminDashboard.tsx
Problem: Queries fetch data but don't handle error states:
const { data: auctions = [], isLoading } = useQuery<Auction[]>({
queryKey: ["/api/auctions"],
});
// No error handling! 😱
Impact:
- Users see blank screen on API failures
- No feedback when network is down
- Poor user experience
- Difficult debugging
Fix Solution:
const { data: auctions = [], isLoading, error, isError } = useQuery<Auction[]>({
queryKey: ["/api/auctions"],
});
// Add error rendering
if (isError) {
return (
<div className="flex flex-col items-center justify-center min-h-[400px] p-8">
<AlertCircle className="h-12 w-12 text-destructive mb-4" />
<h3 className="text-xl font-semibold mb-2">Failed to Load Auctions</h3>
<p className="text-muted-foreground mb-4">
{error?.message || "An error occurred while fetching data"}
</p>
<Button onClick={() => queryClient.invalidateQueries({ queryKey: ["/api/auctions"] })}>
Try Again
</Button>
</div>
);
}
Priority: P1 - Add error boundaries
🟡 Medium Priority Issues
5. Potential Memory Leak - Missing Cleanup in Mutations
Severity: MEDIUM
Files Affected: Multiple pages with mutations
Problem: Mutations don't cancel on component unmount:
const placeBetMutation = useMutation({
mutationFn: async (data) => { /* ... */ },
onSuccess: () => { /* ... */ }
});
// No cleanup when component unmounts!
Impact:
- State updates after unmount warnings
- Memory leaks in SPA navigation
- React warnings in console
Fix Solution:
// Use React Query's built-in cleanup or add manual abort
const placeBetMutation = useMutation({
mutationFn: async (data, { signal }) => {
return await apiRequest("POST", `/api/endpoint`, data, { signal });
},
// React Query handles cleanup automatically
});
Priority: P2 - Improve stability
6. Form Validation Missing on Frontend
Severity: MEDIUM
Files Affected:
client/src/pages/Auctions.tsx(bid form)client/src/pages/Article.tsx(bet form)client/src/components/LoginModal.tsx
Problem: Forms rely only on backend validation:
<Input
type="number"
value={bidForm.amount}
onChange={(e) => setBidForm(prev => ({ ...prev, amount: e.target.value }))}
required
/>
Impact:
- Poor UX - errors shown only after submission
- Unnecessary API calls with invalid data
- Backend load from validation
Fix Solution:
// Add react-hook-form with zod validation
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
const bidSchema = z.object({
amount: z.number()
.min(0.01, "Amount must be greater than 0")
.max(1000000, "Amount too large"),
qualityScore: z.number()
.int("Must be a whole number")
.min(1, "Score must be at least 1")
.max(100, "Score cannot exceed 100")
});
const form = useForm({
resolver: zodResolver(bidSchema),
defaultValues: { amount: "", qualityScore: "" }
});
Priority: P2 - Enhance UX
🟢 Low Priority Issues
7. Inconsistent Loading States
Severity: LOW
Files Affected: Multiple pages
Problem: Some pages show skeleton loaders, others show nothing:
{isLoading ? (
<div>Loading...</div> // Inconsistent!
) : (
<Content />
)}
Impact:
- Inconsistent user experience
- Some pages feel slower than others
Fix Solution: Create reusable skeleton components and use consistently.
Priority: P3 - Polish
8. Accessibility Issues
Severity: LOW
Files Affected: Multiple components
Issues Found:
- Missing ARIA labels on icon buttons
- Color contrast issues in dark mode
- Keyboard navigation not fully tested
- Focus management in modals could be improved
Fix Solution:
- Add aria-label to icon-only buttons
- Test with screen readers
- Implement focus traps in modals
- Add skip navigation links
Priority: P3 - Accessibility enhancement
Summary
| Severity | Count | Must Fix Before Production |
|---|---|---|
| 🔴 Critical | 2 | ✅ Yes |
| 🟠 High | 2 | ✅ Yes |
| 🟡 Medium | 2 | ⚠️ Recommended |
| 🟢 Low | 2 | ❌ Nice to have |
Total Issues: 8
Estimated Fix Time:
- Critical issues: 2-4 hours
- High priority: 4-6 hours
- Medium priority: 4-8 hours
- Low priority: 8-12 hours
Recommended Fix Order:
- Fix localStorage/document browser checks (affects all environments)
- Fix betting input bug (core functionality)
- Add error state rendering (user experience)
- Add form validation (UX improvement)
- Address memory leaks (stability)
- Polish loading states and accessibility (enhancement)