diff --git a/client/src/Utils/apolloClient.ts b/client/src/Utils/apolloClient.ts index dabe3ae..618014c 100644 --- a/client/src/Utils/apolloClient.ts +++ b/client/src/Utils/apolloClient.ts @@ -6,6 +6,9 @@ const client = new ApolloClient({ ? `${import.meta.env.VITE_API_URL}/graphql` : '/graphql', credentials: 'include', // 🔐 Send cookies with each request + headers: { + 'Authorization': `Bearer ${localStorage.getItem('token') || ''}`, + } }), cache: new InMemoryCache(), }); diff --git a/client/src/components/LeaderBoard.tsx b/client/src/components/LeaderBoard.tsx new file mode 100644 index 0000000..be91342 --- /dev/null +++ b/client/src/components/LeaderBoard.tsx @@ -0,0 +1,58 @@ +import React, { useState } from 'react'; +import { useQuery } from '@apollo/client'; +import { GET_USERS } from '../graphql/queries'; // Adjust the import path as necessary + +function LeaderBoard() { + + interface IUser { + _id: string; + username: string; + correctAnswers: number; + avatar: string; // Assuming you have an avatar property + } + + // Data for leaderboard + /* const [leaderboardData, setLeaderboardData] = useState([ + { _id: 'kjhd63r9bhsef', username: 'Player1', correctAnswers: 100 }, + { username: 'Player2', score: 90 }, + { username: 'Player3', score: 80 }, + { username: 'Player4', score: 70 }, + { username: 'Player5', score: 60 }, + ]); + */ + // Fetch leaderboard data from the server (mocked for now) + const [leaderboardData, setLeaderboardData] = useState([]); + + // How do we get the data from the server? + + const { loading, data, error } = useQuery(GET_USERS); + + if (loading) return

Loading...

; + if (error) return

Error: {error.message}

; + // const { loading, data, errer } = useQuery(GET_LEADERBOARD_DATA, { + // variables: { difficulty_lvl: 'easy' }, // Example variable + // ); + const users = data?.users || []; + + // Sort the leaderboard data by score in descending order - by what measurement (?) + const sortedLeaderboard = users.sort((a: number, b: number) => b.correctAnswers - a.correctAnswers); + + + return ( +
+ { sortedLeaderboard.length > 0 ? sortedLeaderboard.map(user: IUser => ( +
+
+ Avatar {/* Assuming you have an avatar property */} + {user.username} + {user.correctAnswers} +
+ )) +
+ } +
+ + ) +} + +export default LeaderBoard diff --git a/client/src/components/screens/Questions.tsx b/client/src/components/screens/Questions.tsx index 12d67cf..4dbb5d5 100644 --- a/client/src/components/screens/Questions.tsx +++ b/client/src/components/screens/Questions.tsx @@ -5,6 +5,8 @@ import ReactMarkdown from 'react-markdown'; import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism'; import { preloadSounds } from '../../utils/preloadSounds'; +import { UPDATE_STATS } from '@/graphql/mutations'; +import { useMutation } from '@apollo/client'; interface Question { snippet?: string; @@ -14,6 +16,7 @@ interface Question { } const Questions: React.FC = () => { + const [updateStats] = useMutation(UPDATE_STATS); const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); @@ -23,6 +26,8 @@ const Questions: React.FC = () => { const [userWasCorrect, setUserWasCorrect] = useState(false); const [audioUrl, setAudioUrl] = useState(''); + const [score, setScore] = useState(0); + useEffect(() => { preloadSounds([ '/audio/Dan_correct/Dan-correct-1.wav', @@ -117,6 +122,10 @@ const Questions: React.FC = () => { if (!question || !selectedAnswer) return; const isCorrect = selectedAnswer === question.correctAnswer; + updateStats({ variables: { isCorrect } }) + if(isCorrect) { + setScore((prevScore) => prevScore + 1); + } setUserWasCorrect(isCorrect); setAudioUrl(getRandomAudio(isCorrect)); setShowResult(true); @@ -127,7 +136,7 @@ const Questions: React.FC = () => { return (

Question {id?.replace('q', '') || ''}

- +

Score: {score}

{!question ? (

Loading question...

) : ( diff --git a/client/tsconfig.node.json b/client/tsconfig.node.json index db0becc..1adfa09 100644 --- a/client/tsconfig.node.json +++ b/client/tsconfig.node.json @@ -18,7 +18,41 @@ "noUnusedLocals": true, "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, - "noUncheckedSideEffectImports": true + "noUncheckedSideEffectImports": true, + + /* ← ADD THESE TWO LINES: */ + "baseUrl": "src", + "paths": { + "@/*": ["*"] + } }, - "include": ["vite.config.ts"] + "include": [ + "vite.config.ts", + "src" /* ← ADD THIS LINE so your utils/ folder is picked up */ + ] } + +// { +// "compilerOptions": { +// "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", +// "target": "ES2022", +// "lib": ["ES2023"], +// "module": "ESNext", +// "skipLibCheck": true, + +// /* Bundler mode */ +// "moduleResolution": "bundler", +// "allowImportingTsExtensions": true, +// "isolatedModules": true, +// "moduleDetection": "force", +// "noEmit": true, + +// /* Linting */ +// "strict": true, +// "noUnusedLocals": true, +// "noUnusedParameters": true, +// "noFallthroughCasesInSwitch": true, +// "noUncheckedSideEffectImports": true +// }, +// "include": ["vite.config.ts"] +// } \ No newline at end of file diff --git a/server/src/server.ts b/server/src/server.ts index f9a2aaf..47ecb30 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -37,9 +37,10 @@ const getContext = async ({ req }: { req: Request }) => { if (!token) return { user: null }; try { - const user = jwt.verify(token, process.env.JWT_SECRET as string); + const user = jwt.verify(token, process.env.JWT_SECRET_KEY as string); return { user }; } catch (err) { + console.log(err) console.warn('❌ Invalid JWT'); return { user: null }; }