Files
sapiens-web3/frontend-issues.md
kimjaehyeon0101 e4a776f67e Fix critical issues to ensure platform stability and user functionality
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
2025-10-12 08:24:44 +00:00

366 lines
8.9 KiB
Markdown

# 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.tsx`
- `client/src/pages/Landing.tsx`
- `client/src/pages/Auctions.tsx`
- `client/src/pages/MediaOutlet.tsx`
**Problem:**
Multiple pages initialize React state directly from `localStorage` without checking if `window` is defined:
```typescript
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:**
1. Run unit tests that mount these components
2. Try server-side rendering
3. Access `localStorage` before window is available
**Fix Solution:**
```typescript
// ❌ 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:
```typescript
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:**
1. Navigate to an article with prediction market
2. Enter any bet amount (e.g., 500)
3. Click place bet
4. Backend receives 10,000 instead of 500
**Fix Solution:**
```typescript
// ❌ 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.tsx`
- `client/src/pages/Landing.tsx`
- `client/src/pages/Auctions.tsx`
- `client/src/pages/MediaOutlet.tsx`
**Problem:**
Direct access to `document.documentElement` in useEffect without browser check:
```typescript
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:**
```typescript
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.tsx`
- `client/src/pages/MediaOutlet.tsx`
- `client/src/pages/Article.tsx`
- `client/src/pages/AdminDashboard.tsx`
**Problem:**
Queries fetch data but don't handle error states:
```typescript
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:**
```typescript
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:
```typescript
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:**
```typescript
// 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:
```typescript
<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:**
```typescript
// 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:
```typescript
{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:**
1. Fix localStorage/document browser checks (affects all environments)
2. Fix betting input bug (core functionality)
3. Add error state rendering (user experience)
4. Add form validation (UX improvement)
5. Address memory leaks (stability)
6. Polish loading states and accessibility (enhancement)