diff --git a/frontend-issues.md b/frontend-issues.md new file mode 100644 index 0000000..90aa809 --- /dev/null +++ b/frontend-issues.md @@ -0,0 +1,365 @@ +# 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({ + 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({ + queryKey: ["/api/auctions"], +}); + +// Add error rendering +if (isError) { + return ( +
+ +

Failed to Load Auctions

+

+ {error?.message || "An error occurred while fetching data"} +

+ +
+ ); +} +``` + +**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 + 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 ? ( +
Loading...
// Inconsistent! +) : ( + +)} +``` + +**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)