From 228e2dcb1ad353043e8dfbeffea5915365afc3b9 Mon Sep 17 00:00:00 2001 From: sumitmodanwal962 Date: Sun, 27 Jul 2025 18:18:22 +0530 Subject: [PATCH 1/2] fix: resolve eslint and user page type errors --- frontend/package.json | 65 +++++++++++++++++++++-------------------- frontend/pnpm-lock.yaml | 3 ++ 2 files changed, 36 insertions(+), 32 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index bc73dd3..cdd9ed8 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,32 +1,33 @@ -{ - "name": "flagged-ctfd", - "version": "0.1.0", - "private": true, - "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "lint": "next lint" - }, - "dependencies": { - "@tsparticles/engine": "^3.8.1", - "@tsparticles/react": "^3.0.0", - "@vscode/codicons": "^0.0.36", - "lucide-react": "^0.525.0", - "next": "15.3.3", - "react": "^19.0.0", - "react-dom": "^19.0.0", - "tsparticles": "^3.8.1" - }, - "devDependencies": { - "@types/node": "^20.17.5", - "@types/react": "^19.0.0", - "@types/react-dom": "^19.0.0", - "autoprefixer": "^10.4.21", - "eslint": "^9", - "eslint-config-next": "15.3.3", - "postcss": "^8.5.4", - "tailwindcss": "^3.4.14", - "typescript": "^5.6.3" - } -} +{ + "name": "flagged-ctfd", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "@tsparticles/engine": "^3.8.1", + "@tsparticles/react": "^3.0.0", + "@vscode/codicons": "^0.0.36", + "lucide-react": "^0.525.0", + "next": "15.3.3", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "tsparticles": "^3.8.1" + }, + "devDependencies": { + "@eslint/eslintrc": "^3.3.1", + "@types/node": "^20.17.5", + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", + "autoprefixer": "^10.4.21", + "eslint": "^9", + "eslint-config-next": "15.3.3", + "postcss": "^8.5.4", + "tailwindcss": "^3.4.14", + "typescript": "^5.6.3" + } +} diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 9b038b1..fd96dc1 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -33,6 +33,9 @@ importers: specifier: ^3.8.1 version: 3.8.1 devDependencies: + '@eslint/eslintrc': + specifier: ^3.3.1 + version: 3.3.1 '@types/node': specifier: ^20.17.5 version: 20.19.0 From 43721c9d907434bfb584c2848979836041ee92d5 Mon Sep 17 00:00:00 2001 From: sumitmodanwal962 Date: Sun, 27 Jul 2025 18:30:48 +0530 Subject: [PATCH 2/2] fix: resolve all ESLint errors in both user pages --- frontend/app/users/[userId]/page.tsx | 88 ++++++++++++++++------------ frontend/app/users/page.tsx | 32 +++++----- 2 files changed, 67 insertions(+), 53 deletions(-) diff --git a/frontend/app/users/[userId]/page.tsx b/frontend/app/users/[userId]/page.tsx index afa28a7..735a687 100644 --- a/frontend/app/users/[userId]/page.tsx +++ b/frontend/app/users/[userId]/page.tsx @@ -4,32 +4,46 @@ import React, { useEffect, useState } from "react"; -export default function PublicUserProfilePage({ params }: { params: { userId: string } }) { - const { userId } = params; +// --- FIX: Define specific types for the data --- +interface Solve { + id: number; + name: string; + points: number; +} + +interface User { + id: number; + name: string; + team_name?: string; + points: number; + team_id?: number; + solves: Solve[]; +} + +interface Team { + id: number; + name: string; + points: number; +} +export default function PublicUserProfilePage({ params }: { params: { userId: string } }) { + const { userId } = params; - const [user, setUser] = useState(null); - const [team, setTeam] = useState(null); + // --- FIX: Use the new types instead of 'any' --- + const [user, setUser] = useState(null); + const [team, setTeam] = useState(null); const [teamRank, setTeamRank] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const API_BASE = "http://127.0.0.1:8000"; - // ✅ UPDATED FUNCTION function getAuthHeaders(): Record { - const headers: Record = { - "Content-Type": "application/json", - }; - + const headers: Record = { "Content-Type": "application/json" }; const token = localStorage.getItem("token"); - if (token) { headers["Authorization"] = `Bearer ${token}`; - } else { - console.warn("No auth token found. Continuing without authentication."); } - return headers; } @@ -40,36 +54,36 @@ export default function PublicUserProfilePage({ params }: { params: { userId: st try { setLoading(true); - const userRes = await fetch(`${API_BASE}/users/${userId}`, { - headers: getAuthHeaders(), - }); - if (!userRes.ok) { - throw new Error("User not found or failed to fetch data"); - } - const userData = await userRes.json(); + const userRes = await fetch(`${API_BASE}/users/${userId}`, { headers: getAuthHeaders() }); + if (!userRes.ok) throw new Error("User not found or failed to fetch data"); + + // --- FIX: Tell TypeScript the shape of the incoming data --- + const userData: User = await userRes.json(); setUser(userData); if (userData.team_id) { - const teamRes = await fetch(`${API_BASE}/teams/${userData.team_id}`, { - headers: getAuthHeaders(), - }); + const teamRes = await fetch(`${API_BASE}/teams/${userData.team_id}`, { headers: getAuthHeaders() }); if (teamRes.ok) { setTeam(await teamRes.json()); } - const allTeamsRes = await fetch(`${API_BASE}/teams`, { - headers: getAuthHeaders(), - }); + const allTeamsRes = await fetch(`${API_BASE}/teams`, { headers: getAuthHeaders() }); if (allTeamsRes.ok) { const allTeamsData = await allTeamsRes.json(); - const teamsList = allTeamsData.teams || []; - const sortedTeams = teamsList.sort((a: any, b: any) => b.points - a.points); - const rank = sortedTeams.findIndex((t: any) => t.id === userData.team_id) + 1; + // --- FIX: Type the list of teams --- + const teamsList: Team[] = allTeamsData.teams || []; + const sortedTeams = teamsList.sort((a, b) => b.points - a.points); + const rank = sortedTeams.findIndex((t) => t.id === userData.team_id) + 1; setTeamRank(rank > 0 ? rank : null); } } - } catch (err: any) { - setError(err.message); + } catch (err) { + // --- FIX: Type the error properly --- + if (err instanceof Error) { + setError(err.message); + } else { + setError("An unknown error occurred"); + } } finally { setLoading(false); } @@ -85,14 +99,13 @@ export default function PublicUserProfilePage({ params }: { params: { userId: st if (error) { return
Error: {error}
; } - + if (!user) { return
User not found.
; } return ( -
- {/* Header */} +

{user.team_name || "No Team"} @@ -105,7 +118,6 @@ export default function PublicUserProfilePage({ params }: { params: { userId: st )}

- {/* User Info */}

Username: {user.name} @@ -113,7 +125,6 @@ export default function PublicUserProfilePage({ params }: { params: { userId: st

Individual Points: {user.points}

- {/* Solves Table */}

Solves @@ -128,7 +139,8 @@ export default function PublicUserProfilePage({ params }: { params: { userId: st {user.solves && user.solves.length > 0 ? ( - user.solves.map((solve: any) => ( + // --- FIX: Use the 'Solve' type for each item in the map function --- + user.solves.map((solve: Solve) => (

); -} +} \ No newline at end of file diff --git a/frontend/app/users/page.tsx b/frontend/app/users/page.tsx index 9a66909..623134b 100644 --- a/frontend/app/users/page.tsx +++ b/frontend/app/users/page.tsx @@ -1,11 +1,13 @@ +// File: app/users/page.tsx + "use client"; import React, { useEffect, useState } from "react"; -import { useRouter } from 'next/navigation'; // ✅ 1. Import the useRouter hook -import { Jersey_10, Jaini_Purva, Outfit } from "next/font/google"; +import { useRouter } from 'next/navigation'; +// --- FIX: Removed 'Jaini_Purva' as it was unused --- +import { Jersey_10, Outfit } from "next/font/google"; const jersey = Jersey_10({ subsets: ["latin"], weight: "400", variable: "--font-jersey-10" }); -const jainiPurva = Jaini_Purva({ subsets: ["latin"], weight: "400", variable: "--font-jaini-purva" }); const outfit = Outfit({ subsets: ["latin"], variable: "--font-outfit" }); interface User { @@ -18,25 +20,29 @@ interface User { } export default function UsersPage() { - const router = useRouter(); // ✅ 2. Initialize the router + const router = useRouter(); const [users, setUsers] = useState([]); const [searchTerm, setSearchTerm] = useState(""); const [filterBy, setFilterBy] = useState<"name" | "affiliation" | "country">("name"); const [loading, setLoading] = useState(true); const [error, setError] = useState(""); - + const API_BASE = "http://127.0.0.1:8000"; useEffect(() => { const fetchUsers = async () => { try { - // Using your backend endpoint to get the list of all users const res = await fetch(`${API_BASE}/users`); if (!res.ok) throw new Error("Failed to fetch users"); const data = await res.json(); setUsers(data.users || []); - } catch (err: any) { - setError(err.message || "Error fetching users"); + } catch (err) { + // --- FIX: Typed the error properly instead of using 'any' --- + if (err instanceof Error) { + setError(err.message); + } else { + setError("An unknown error occurred while fetching users"); + } } finally { setLoading(false); } @@ -48,12 +54,11 @@ export default function UsersPage() { const filteredUsers = users.filter((user) => { const field = filterBy === "name" ? user.name : - filterBy === "affiliation" ? user?.affiliation ?? "" : - user?.country ?? ""; + filterBy === "affiliation" ? user?.affiliation ?? "" : + user?.country ?? ""; return field.toLowerCase().includes(searchTerm.toLowerCase()); }); - // Function to handle navigation when a row is clicked const handleRowClick = (userId: number) => { router.push(`/users/${userId}`); }; @@ -66,7 +71,6 @@ export default function UsersPage() {
- {/* Search and Filter */}