Skip to content

Commit 5e259ab

Browse files
Merge pull request #68 from Treevyy/frontend/fixes
Frontend/fixes
2 parents 1526354 + 221b2bf commit 5e259ab

File tree

13 files changed

+2126
-408
lines changed

13 files changed

+2126
-408
lines changed

client/minions/codezilla3.png

8.87 MB
Loading

client/minions/pie-thon3.png

2.73 MB
Loading

client/package-lock.json

Lines changed: 1940 additions & 342 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/public/codezilla_intro.mp4

496 KB
Binary file not shown.

client/src/App.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
import React from 'react';
22
import { BrowserRouter as Router, Routes, Route, useNavigate } from 'react-router-dom';
3+
import IntroPage from './components/screens/IntroPage';
34
import { Login } from './components/screens/Login';
45
import GameMap from './components/screens/GameMap';
56
import GameOver from './components/screens/GameOver';
67
import Victory from './components/screens/Victory';
78
import Signup from './components/screens/Signup';
89
import Questions from './components/screens/Questions';
9-
1010
import './styles/codezilla.css';
1111

12+
1213
const LogoutButton: React.FC = () => {
1314
const navigate = useNavigate();
1415

1516
const handleLogout = () => {
1617
localStorage.clear();
17-
navigate('/signup');
18+
navigate('/login');
1819
};
1920

2021
return (
@@ -28,14 +29,14 @@ const App: React.FC = () => {
2829
return (
2930
<Router>
3031
<div className="app-wrapper">
31-
{/* Background Image */}
32+
{/* Background Image
3233
<img
3334
src="/background/codezilla_bkgd.png"
3435
alt="Dark rainy cityscape"
3536
className="background-image"
36-
/>
37+
/> */}
3738

38-
{/* Logo */}
39+
3940
<img
4041
src="/codezilla_logo.png"
4142
alt="Codezilla Logo"
@@ -47,7 +48,8 @@ const App: React.FC = () => {
4748

4849
{/* Routes */}
4950
<Routes>
50-
<Route path="/" element={<Login />} />
51+
<Route path="/" element={<IntroPage />} />
52+
<Route path="/login" element={<Login />} />
5153
<Route path="/map" element={<GameMap />} />
5254
<Route path="/gameover" element={<GameOver />} />
5355
<Route path="/signup" element={<Signup />} />

client/src/Utils/useBodyClass.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// src/Utils/useBodyClass.ts
2+
import { useEffect } from 'react';
3+
4+
export const useBodyClass = (className: string) => {
5+
useEffect(() => {
6+
console.log(`✅applying body class: ${className}`);
7+
8+
document.body.classList.add(className);
9+
return () => {
10+
document.body.classList.remove(className);
11+
};
12+
}, [className]);
13+
};

client/src/components/screens/GameMap.tsx

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
// src/components/screens/GameMap.tsx
2-
3-
// IMPORT LIBRARIES
41
import React, { useState, useEffect } from 'react';
52
import { useNavigate } from 'react-router-dom';
63
import Minion from './Minions';
4+
import { useBodyClass } from '../../Utils/useBodyClass';
75
import { preloadSounds } from '../../utils/preloadSounds';
8-
import '../../styles/codezilla.css';
6+
import "../../styles/codezilla.css";
97
import drDanImg from '../../../avatars/drdan2.png';
108
import flameImg from '../../assets/flame.png';
119

@@ -14,9 +12,11 @@ const username = localStorage.getItem('username') || 'Player';
1412

1513
const GameMap: React.FC = () => {
1614
const navigate = useNavigate();
15+
useBodyClass('login-background');
16+
1717
const [completedPaths, setCompletedPaths] = useState<string[]>([]);
18+
const [selectedMinionId, setSelectedMinionId] = useState<string | null>(null);
1819

19-
// ✅ Preload Dr. Dan audio files on mount
2020
useEffect(() => {
2121
preloadSounds([
2222
'/audio/Dan_correct/Dan-correct-1.wav',
@@ -31,7 +31,6 @@ const GameMap: React.FC = () => {
3131
'/audio/5inarow.wav'
3232
]);
3333
}, []);
34-
const [selectedMinionId, setSelectedMinionId] = useState<string | null>(null);
3534

3635
const minions = [
3736
{
@@ -105,15 +104,12 @@ const GameMap: React.FC = () => {
105104

106105
const goToQuestion = (questionId: string) => {
107106
const currentIndex = minions.findIndex(m => m.questionId === questionId);
108-
109107
if (currentIndex < nodes.length - 1) {
110108
const pathId = `${nodes[currentIndex].id}-${nodes[currentIndex + 1].id}`;
111109
setCompletedPaths(prev => [...prev, pathId]);
112110
}
113111
const minion = minions.find(m => m.questionId === questionId);
114-
if (minion) {
115-
setSelectedMinionId(minion.id);
116-
}
112+
if (minion) setSelectedMinionId(minion.id);
117113
navigate(`/question/${questionId}`);
118114
};
119115

@@ -123,7 +119,6 @@ const GameMap: React.FC = () => {
123119
{nodes.map((node, index) => {
124120
const nextNode = nodes[index + 1];
125121
if (!nextNode) return null;
126-
127122
return (
128123
<line
129124
key={`line-${node.id}-${nextNode.id}`}
@@ -136,10 +131,8 @@ const GameMap: React.FC = () => {
136131
);
137132
})}
138133

139-
{/* GLOWING OUTER CIRCLE + DARKER INNER CIRCLE */}
140134
{nodes.map((node, index) => {
141135
const isCompleted = index < completedPaths.length;
142-
143136
return (
144137
<g key={`node-${node.id}`}>
145138
<circle
@@ -158,6 +151,7 @@ const GameMap: React.FC = () => {
158151
);
159152
})}
160153
</svg>
154+
161155
<div className="dr-dan-wrapper">
162156
<div className="glow-circle"></div>
163157
<img src={drDanImg} alt="Dr. Dan" className="dr-dan-image" />
@@ -167,22 +161,19 @@ const GameMap: React.FC = () => {
167161
<div className="player-avatar-wrapper">
168162
<div className="player-glow-circle"></div>
169163
<img src={selectedAvatar} alt="Your Avatar" className="player-avatar" />
170-
171164
<div className="player-info-wrapper">
172165
<div className="player-info-box">
173166
<p className="player-name">{username}</p>
174167
<p className="player-level">Level 1</p>
175168
</div>
176-
177169
<div className="learning-info-box">
178-
<p className='learning-title'> Studying</p>
170+
<p className='learning-title'>Studying</p>
179171
<p className="learning-text">Coding Bootcamp</p>
180172
</div>
181-
{/* Lifeline Box */}
182173
<div className='flames'>
183174
<div className="lifeline-info-box">
184175
<div className="lifeline-flames">
185-
<p className='learning-title'> Life Lines</p>
176+
<p className='learning-title'>Life Lines</p>
186177
<img src={flameImg} alt="Flame 1" />
187178
<img src={flameImg} alt="Flame 2" />
188179
<img src={flameImg} alt="Flame 3" />

client/src/components/screens/GameOver.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { useNavigate } from 'react-router-dom';
22
import "../../styles/codezilla.css";
33

4+
45
const GameOverPage = ({
5-
backgroundUrl = 'client/background/codezilla_bkgd.png',
6+
// backgroundUrl = 'client/background/codezilla_bkgd.png',
67
avatarUrl = 'client/avatars/avatar4.png',
78
codezillaUrl = 'client/minions/codezilla2.png',
89
}) => {
@@ -21,7 +22,7 @@ const GameOverPage = ({
2122
return (
2223
<div
2324
className="game-over-page"
24-
style={{ backgroundImage: `url(${backgroundUrl})` }}
25+
// style={{ backgroundImage: `url(${backgroundUrl})` }}
2526
>
2627
<div className="game-over-container">
2728
<h1 className="game-over-title">Game Over!</h1>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import React, { useState, useEffect, useRef } from 'react';
2+
import { useNavigate } from 'react-router-dom';
3+
import { useBodyClass } from '../../Utils/useBodyClass';
4+
import "../../styles/codezilla.css";
5+
6+
const IntroPage: React.FC = () => {
7+
const navigate = useNavigate();
8+
const videoRef = useRef<HTMLVideoElement | null>(null);
9+
const [hasClicked, setHasClicked] = useState(false);
10+
useBodyClass('intro-background');
11+
12+
const handleVideoEnd = () => {
13+
navigate('/login');
14+
};
15+
16+
const handleUserClick = () => {
17+
if (videoRef.current && !hasClicked) {
18+
videoRef.current.muted = false;
19+
videoRef.current.play();
20+
setHasClicked(true);
21+
}
22+
};
23+
24+
useEffect(() => {
25+
document.addEventListener('click', handleUserClick);
26+
return () => document.removeEventListener('click', handleUserClick);
27+
}, [hasClicked]);
28+
29+
return (
30+
<div className="intro-overlay">
31+
<video
32+
ref={videoRef}
33+
className="intro-video"
34+
autoPlay
35+
muted
36+
playsInline
37+
onEnded={handleVideoEnd}
38+
>
39+
<source src="/codezilla_intro.mp4" type="video/mp4" />
40+
Your browser does not support the video tag.
41+
</video>
42+
</div>
43+
);
44+
};
45+
46+
export default IntroPage;

client/src/components/screens/Login.tsx

Lines changed: 24 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,47 @@
1-
// src/components/Login.tsx
2-
import React from "react";
1+
// src/components/screens/Login.tsx
2+
import React, { useState, } from "react";
33
import "../../styles/codezilla.css";
44
import { useNavigate } from "react-router-dom";
55
import { useMutation } from "@apollo/client";
66
import { LOGIN } from "../../graphql/mutations";
7-
import { useState } from "react";
7+
import { useBodyClass } from "../../Utils/useBodyClass";
88

99
export const Login: React.FC = () => {
1010
const navigate = useNavigate();
11+
useBodyClass('login-background'); // ✅ YOUR background image class
1112
const [username, setUsername] = useState('');
1213
const [password, setPassword] = useState('');
1314

14-
// create a function to handle the mutation
1515
const [login] = useMutation(LOGIN);
1616

17-
const handleLogin = async (e:any) => {
18-
e.preventDefault();
17+
const handleLogin = async (e: React.FormEvent<HTMLFormElement>) => {
18+
e.preventDefault();
1919

20-
console.log(username)
21-
console.log(password)
20+
try {
21+
const response = await login({
22+
variables: { username, password }
23+
});
2224

23-
try {
24-
const response = await login({
25-
variables: {
26-
username: username,
27-
password: password,
28-
},
29-
});
25+
const token = response.data.login.token;
26+
localStorage.setItem('token', token);
3027

31-
const token = response.data.login.token;
32-
33-
34-
localStorage.setItem('token', token);
35-
console.log(token)
36-
37-
if(token) {
38-
navigate('/map');
28+
if (token) {
29+
navigate('/map');
30+
}
31+
} catch (err) {
32+
console.error("Login failed", err);
33+
alert("Login failed. Please check your username and password.");
3934
}
40-
} catch(err) {
41-
console.error("Login failed", err);
42-
alert("Login failed. Please check your username and password.");
43-
}
44-
4535
};
4636

37+
const goToSignup = () => navigate('/signup');
38+
4739
return (
4840
<div className="login-wrapper">
4941
<div className="login-content">
5042
<form className="question-box" onSubmit={handleLogin}>
5143
<h1>Login</h1>
52-
44+
5345
<input
5446
type="text"
5547
placeholder="username"
@@ -66,11 +58,10 @@ export const Login: React.FC = () => {
6658
/>
6759
<button type="submit">Login</button>
6860

69-
7061
<p>Not a player yet?</p>
71-
<a href="/signup" className="signup-link">
72-
<button type="button" className="signup-button">Sign Up</button>
73-
</a>
62+
<button type="button" className="signup-button" onClick={goToSignup}>
63+
Sign Up!
64+
</button>
7465
</form>
7566
</div>
7667
</div>

0 commit comments

Comments
 (0)