Skip to content

Commit 02281c4

Browse files
authored
Merge pull request #66 from Treevyy/feature/UserRegistration
Feature/user registration
2 parents 1faeae2 + 0ca377e commit 02281c4

File tree

8 files changed

+200
-80
lines changed

8 files changed

+200
-80
lines changed

client/src/components/screens/Login.tsx

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,77 @@
11
// src/components/Login.tsx
2-
import React from 'react';
2+
import React from "react";
33
import "../../styles/codezilla.css";
4-
import { useNavigate } from 'react-router-dom';
4+
import { useNavigate } from "react-router-dom";
5+
import { useMutation } from "@apollo/client";
6+
import { LOGIN } from "../../graphql/mutations";
7+
import { useState } from "react";
58

69
export const Login: React.FC = () => {
710
const navigate = useNavigate();
11+
const [username, setUsername] = useState('');
12+
const [password, setPassword] = useState('');
13+
14+
// create a function to handle the mutation
15+
const [login] = useMutation(LOGIN);
16+
17+
const handleLogin = async (e:any) => {
18+
e.preventDefault();
19+
20+
console.log(username)
21+
console.log(password)
22+
23+
try {
24+
const response = await login({
25+
variables: {
26+
username: username,
27+
password: password,
28+
},
29+
});
30+
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');
39+
}
40+
} catch(err) {
41+
console.error("Login failed", err);
42+
alert("Login failed. Please check your username and password.");
43+
}
844

9-
const handleLogin = () => {
10-
navigate('/signup');
1145
};
1246

1347
return (
1448
<div className="login-wrapper">
1549
<div className="login-content">
16-
<div className="question-box">
50+
<form className="question-box" onSubmit={handleLogin}>
1751
<h1>Login</h1>
18-
<input type="text" placeholder="username" className="login-input" />
19-
<input type="password" placeholder="password" className="login-input" />
52+
53+
<input
54+
type="text"
55+
placeholder="username"
56+
className="login-input"
57+
value={username}
58+
onChange={(e) => setUsername(e.target.value)}
59+
/>
60+
<input
61+
type="password"
62+
placeholder="password"
63+
className="login-input"
64+
value={password}
65+
onChange={(e) => setPassword(e.target.value)}
66+
/>
67+
<button type="submit">Login</button>
68+
69+
2070
<p>Not a player yet?</p>
21-
<button className="signup-button" onClick={handleLogin}>Sign Up!</button>
22-
</div>
71+
<a href="/signup" className="signup-link">
72+
<button type="button" className="signup-button">Sign Up</button>
73+
</a>
74+
</form>
2375
</div>
2476
</div>
2577
);

client/src/components/screens/Signup.tsx

Lines changed: 76 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,62 @@
11
/*CREATE IMPORTS */
2-
import React, { useState } from 'react';
3-
import { useNavigate } from 'react-router-dom';
2+
import React, { useState } from "react";
3+
import { useNavigate } from "react-router-dom";
44
import "../../styles/codezilla.css";
5+
import { useMutation } from "@apollo/client";
6+
import { ADD_USER } from "../../graphql/mutations";
57

68
const avatarList = [
7-
'/avatars/carmen.png',
8-
'/avatars/jacquilyn.png',
9-
'/avatars/trevor.png',
10-
'/avatars/michael.png',
11-
'/avatars/shawna.png',
9+
"/avatars/carmen.png",
10+
"/avatars/jacquilyn.png",
11+
"/avatars/trevor.png",
12+
"/avatars/michael.png",
13+
"/avatars/shawna.png",
1214
];
1315

1416
const SignUp: React.FC = () => {
1517
const navigate = useNavigate();
16-
const [selectedAvatar, setSelectedAvatar] = useState('');
17-
const [username, setUsername] = useState('');
18-
const [password, setPassword] = useState('');
18+
const [selectedAvatar, setSelectedAvatar] = useState("");
19+
const [username, setUsername] = useState("");
20+
const [password, setPassword] = useState("");
1921

20-
const handleSubmit = (e: React.FormEvent) => {
22+
// create a function to handle the mutation
23+
const [addUser] = useMutation(ADD_USER);
24+
25+
const handleSubmit = async (e: React.FormEvent) => {
2126
e.preventDefault();
22-
27+
2328
if (!username.trim() || !selectedAvatar) {
24-
alert('Please enter a username and select an avatar before proceeding.');
29+
alert("Please enter a username and select an avatar before proceeding.");
2530
return;
2631
}
27-
28-
localStorage.setItem('selectedAvatar', selectedAvatar);
29-
localStorage.setItem('username', username);
30-
32+
33+
// localStorage.setItem('selectedAvatar', selectedAvatar);
34+
// localStorage.setItem('username', username);
35+
3136
console.log({ username, password, selectedAvatar });
32-
navigate('/map');
37+
38+
try {
39+
const response = await addUser({
40+
variables: {
41+
input: {
42+
password: password,
43+
selectedAvatar: selectedAvatar,
44+
username: username,
45+
},
46+
},
47+
});
48+
49+
const token = response.data.addUser.token;
50+
51+
localStorage.setItem("token", token);
52+
53+
console.log(response);
54+
navigate('/map');
55+
} catch (err) {
56+
console.error("Signup failed", err);
57+
alert("Signup failed");
58+
}
3359
};
34-
35-
3660

3761
return (
3862
<div className="login-wrapper">
@@ -53,34 +77,39 @@ const SignUp: React.FC = () => {
5377
onChange={(e) => setPassword(e.target.value)}
5478
/>
5579

56-
<p>Select Your Avatar</p>
57-
<div className="avatar-grid">
58-
<div className="avatar-row">
59-
{avatarList.slice(0, 3).map((avatar, index) => (
60-
<img
61-
key={index}
62-
src={avatar}
63-
alt={`Avatar ${index}`}
64-
className={`avatar-option ${selectedAvatar === avatar ? 'selected' : ''}`}
65-
onClick={() => setSelectedAvatar(avatar)}
66-
/>
67-
))}
68-
</div>
69-
<div className="avatar-row">
70-
{avatarList.slice(3).map((avatar, index) => (
71-
<img
72-
key={index + 3}
73-
src={avatar}
74-
alt={`Avatar ${index + 3}`}
75-
className={`avatar-option ${selectedAvatar === avatar ? 'selected' : ''}`}
76-
onClick={() => setSelectedAvatar(avatar)}
77-
/>
78-
))}
79-
</div>
80-
</div>
81-
80+
<p>Select Your Avatar</p>
81+
<div className="avatar-grid">
82+
<div className="avatar-row">
83+
{avatarList.slice(0, 3).map((avatar, index) => (
84+
<img
85+
key={index}
86+
src={avatar}
87+
alt={`Avatar ${index}`}
88+
className={`avatar-option ${
89+
selectedAvatar === avatar ? "selected" : ""
90+
}`}
91+
onClick={() => setSelectedAvatar(avatar)}
92+
/>
93+
))}
94+
</div>
95+
<div className="avatar-row">
96+
{avatarList.slice(3).map((avatar, index) => (
97+
<img
98+
key={index + 3}
99+
src={avatar}
100+
alt={`Avatar ${index + 3}`}
101+
className={`avatar-option ${
102+
selectedAvatar === avatar ? "selected" : ""
103+
}`}
104+
onClick={() => setSelectedAvatar(avatar)}
105+
/>
106+
))}
107+
</div>
108+
</div>
82109

83-
<button className="signup-button" type="submit">Enter the Game</button>
110+
<button className="signup-button" type="submit">
111+
Enter the Game
112+
</button>
84113
</form>
85114
</div>
86115
);

client/src/graphql/mutations.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ export const UPDATE_STATS = gql`
1212

1313
// Mutation to login
1414
export const LOGIN = gql`
15-
mutation Login($email: String!, $password: String!) {
16-
login(email: $email, password: $password) {
17-
token
18-
user {
19-
_id
20-
username
21-
}
15+
mutation Login($username: String!, $password: String!) {
16+
login(username: $username, password: $password) {
17+
token
18+
user {
19+
_id
20+
username
2221
}
2322
}
23+
}
2424
`;
2525

2626
// Mutation to add a new user

server/package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@
99
"build": "tsc",
1010
"test": "echo \"Error: no test specified\" && exit 1",
1111
"dev": "nodemon src/server.ts",
12-
"watch": "nodemon dist/server.js"
12+
"watch": "nodemon"
13+
},
14+
"nodemonConfig": {
15+
"watch": ["src"],
16+
"ext": "ts,json,js",
17+
"exec": "npx tsc && node dist/server.js"
1318
},
1419
"keywords": [],
1520
"author": "",

server/src/models/User.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import bcrypt from 'bcrypt';
44
// Define an interface for the User document
55
interface IUser extends Document {
66
username: string;
7-
email: string;
7+
// email: string;
8+
selectedAvatar: string;
89
password: string;
910
correctAnswers: number;
1011
wrongAnswers: number;
@@ -20,16 +21,21 @@ const userSchema = new Schema<IUser>(
2021
unique: true,
2122
trim: true,
2223
},
23-
email: {
24+
// email: {
25+
// type: String,
26+
// required: true,
27+
// unique: true,
28+
// match: [/.+@.+\..+/, 'Must match an email address!'],
29+
// },
30+
password: {
2431
type: String,
2532
required: true,
26-
unique: true,
27-
match: [/.+@.+\..+/, 'Must match an email address!'],
33+
minlength: 5,
2834
},
29-
password: {
35+
36+
selectedAvatar: {
3037
type: String,
3138
required: true,
32-
minlength: 5,
3339
},
3440
correctAnswers: {
3541
type: Number,

server/src/schemas/resolvers.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@ const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
1313
interface AddUserArgs {
1414
input: {
1515
username: string;
16-
email: string;
16+
// email: string;
17+
selectedAvatar: string;
1718
password: string;
1819
};
1920
}
2021

2122
interface LoginUserArgs {
22-
email: string;
23+
// email: string;
24+
username: string;
2325
password: string;
2426
}
2527

@@ -64,11 +66,17 @@ const resolvers = {
6466
Mutation: {
6567
addUser: async (_parent: any, { input }: AddUserArgs) => {
6668
const user = await User.create(input);
67-
const token = signToken(user.username, user.email, user._id);
69+
const token = signToken(
70+
user.username,
71+
// user.email,
72+
user._id
73+
);
6874
return { token, user };
6975
},
70-
login: async (_parent: any, { email, password }: LoginUserArgs) => {
71-
const user = await User.findOne({ email });
76+
// login: async (_parent: any, { email, password }: LoginUserArgs) => {
77+
// const user = await User.findOne({ email });
78+
login: async (_parent: any, { username, password }: LoginUserArgs) => {
79+
const user = await User.findOne({ username });
7280

7381
if (!user) {
7482
throw new AuthenticationError('Invalid credentials');
@@ -80,7 +88,12 @@ const resolvers = {
8088
throw new AuthenticationError('Invalid credentials');
8189
}
8290

83-
const token = signToken(user.username, user.email, user._id);
91+
const token = signToken(
92+
user.username,
93+
// user.email,
94+
user._id
95+
);
96+
8497
return { token, user };
8598
},
8699
createCharacter: async (_: any, { name, picture, voice }: { name: string, picture: string, voice: string }) => {

server/src/schemas/typeDefs.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const typeDefs = gql`
1212
1313
input UserInput {
1414
username: String!
15-
email: String!
15+
selectedAvatar: String!
1616
password: String!
1717
}
1818
@@ -44,11 +44,18 @@ const typeDefs = gql`
4444
4545
type Mutation {
4646
addUser(input: UserInput!): Auth
47-
login(email: String!, password: String!): Auth
47+
login(username: String!, password: String!): Auth
4848
createCharacter(name: String!, picture: String!, voice: String!): Character
4949
deleteCharacter(id: ID!): Character
5050
updateStats(isCorrect: Boolean!): User
5151
}
5252
`;
5353

5454
export default typeDefs;
55+
56+
57+
// input UserInput {
58+
// username: String!
59+
// email: String!
60+
// password: String!
61+
// }

0 commit comments

Comments
 (0)