Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

21 implementing api endpoints in the frontend #29

Merged
merged 28 commits into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
114800a
feat: add API for create course
reesedychiao Mar 12, 2024
a2e36c6
feat(next): add @sanity/icons
Mar 13, 2024
8a3992b
feat(next): create AddButton component
Mar 13, 2024
d397ac4
feat(next): add onClick event to add button
Mar 13, 2024
b04c14f
refactor(next): add response type
Mar 13, 2024
abfbb94
feat(next): add CloseIcon to CreateCourse
Mar 13, 2024
b54bc87
refactor(next): move course files to course dir
Mar 13, 2024
8f2819c
Merge pull request #24 from n30w/minor-ui-edits-1
reesedychiao Mar 14, 2024
2cfa7f8
feat: add API create to the frontend
reesedychiao Mar 17, 2024
af36272
feat: add API read to the frontend
reesedychiao Mar 17, 2024
812c4f7
feat: add navbar
reesedychiao Mar 17, 2024
fe7446d
feat: add POST request for authentication
reesedychiao Mar 18, 2024
65d6e49
Update .gitignore
Mar 18, 2024
61f0a23
Update .gitignore
Mar 18, 2024
c60d9a1
Create apiPath.ts
Mar 18, 2024
288c80f
Update settings.json
Mar 18, 2024
ac90478
Create .env.example
Mar 18, 2024
5f18c29
feat+refactor: add helpers folder
Mar 18, 2024
b5491b0
Create types.ts
Mar 18, 2024
386e1d6
refactor: reorganize components
Mar 18, 2024
c070900
Create Navbar.tsx
Mar 18, 2024
900a94b
refactor: add interface to Announcements.tsx
Mar 18, 2024
5ae22a9
refactor: add interface to Assignments.tsx
Mar 18, 2024
d39b79f
refactor: formatDate into helpers
Mar 18, 2024
6926983
refactor: remove CourseDisplay component
Mar 18, 2024
a94fc4d
refactor: amend validatePassword import
Mar 18, 2024
52f214c
refactor: add getData async func
Mar 18, 2024
a9eb749
Merge branch 'main' into 21-implementing-api-endpoints-in-the-frontend
Mar 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# env
.env
.env.local

# dependencies
frontend/node_modules
frontend/.pnp.cjs
Expand Down Expand Up @@ -27,6 +31,9 @@ frontend/build
.DS_Store
*.pem

# fonts
.woff2

# debug
frontend/npm-debug.log*
frontend/yarn-debug.log*
Expand Down
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"cSpell.words": [
"cmds",
"coursepage",
"corepack",
"Darkspace",
"healthcheck",
Expand Down
14 changes: 14 additions & 0 deletions frontend/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# INSTRUCTIONS:
# 1. Make a copy of this in the root of the frontend directory.
# 2. Rename that copy to .env.local
#
# Quotation marks for the key values are optional.

# Name of the API server. This would be "localhost" in a development environment.
API_HOSTNAME=

# Port of the server. The backend's default is 6789.
API_PORT=

# Small note about environment variables...
# According to this link https://nextjs.org/docs/app/building-your-application/configuring/environment-variables#loading-environment-variables: "If you are using a /src folder, please note that Next.js will load the .env files only from the parent folder and not from the /src folder."
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"format:fix": "prettier --write --list-different ./src"
},
"dependencies": {
"@sanity/icons": "^2.11.2",
"next": "14.1.0",
"react": "^18",
"react-dom": "^18"
Expand Down
Binary file added frontend/public/backgrounds/profile-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
58 changes: 58 additions & 0 deletions frontend/src/app/(auth)/login/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
"use client";

import React, { useState } from "react";
import { useRouter } from "next/navigation";
import Image from "next/image";
import Link from "next/link";
import { userAgentFromString } from "next/server";

export default function Page() {
// const [isBlurred, setIsBlurred] = useState(false);
Expand All @@ -11,6 +13,58 @@ export default function Page() {
// setIsBlurred(true);
// };

const [userLogin, setUserLogin] = useState({
email: "",
password: "",
});
const [loginError, setLoginError] = useState<string>("");
const route = useRouter();

const fetchUserInfo = async () => {
try {
const res: Response = await fetch("/v1/user/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(userLogin),
});
if (res.ok) {
const userInfo = await res.json();
return userInfo;
} else {
console.error("Failed to fetch user info:", res.statusText);
return [];
}
} catch (error) {
console.error("Error fetching user info:", error);
return [];
}
};

const handleChange = (e: { target: { name: any; value: any } }) => {
const { name, value } = e.target;
setUserLogin({
...userLogin,
[name]: value,
});
};

const handleSubmit = async (e: { preventDefault: () => void }) => {
e.preventDefault();
const info = await fetchUserInfo();
for (let i = 0; i < info.length; i++) {
if (info[i].email === userLogin.email) {
if (info[i].password === userLogin.password) {
route.push("");
} else {
setLoginError("Wrong password entered");
}
}
}
setLoginError("Wrong email entered");
};

return (
<div className="flex h-screen">
<div className="h-screen bg-black py-8 px-32 w-1/2">
Expand All @@ -37,6 +91,7 @@ export default function Page() {
method="post"
className="flex flex-col"
// onClick={handleFormClick}
onSubmit={handleSubmit}
>
<label htmlFor="email" className="text-white font-light py-2">
Email<span className="text-red-500">*</span>
Expand All @@ -48,6 +103,7 @@ export default function Page() {
placeholder="[email protected]"
required
className="w-80 h-10 px-4 mb-8"
onChange={handleChange}
/>
<label htmlFor="password" className="text-white font-light py-2">
Password<span className="text-red-500">*</span>
Expand All @@ -59,7 +115,9 @@ export default function Page() {
placeholder="••••••••••"
required
className="w-80 h-10 px-4 mb-8"
onChange={handleChange}
/>
{loginError && <p className="text-red-500 pb-2">{loginError}</p>}
<input
type="submit"
value="LOG IN"
Expand Down
98 changes: 76 additions & 22 deletions frontend/src/app/(auth)/signup/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import React, { useState } from "react";
import Image from "next/image";
import Link from "next/link";
import validatePassword from "@/lib/passwordValidator";
import validatePassword from "@/lib/helpers/passwordValidator";

export default function Page() {
// const [isBlurred, setIsBlurred] = useState(false);
Expand All @@ -12,34 +12,61 @@ export default function Page() {
// setIsBlurred(true);
// };

const [password, setPassword] = useState<string>("");
// const [password, setPassword] = useState<string>("");
const [reenteredPassword, setReenteredPassword] = useState<string>("");
const [passwordError, setPasswordError] = useState<string>("");
const [reenteredPasswordError, setReenteredPasswordError] =
useState<string>("");
const [userData, setUserData] = useState({
email: "",
password: "",
netid: "",
});

const handlePasswordChange = (
e: React.ChangeEvent<HTMLInputElement>
): void => {
const newPassword = e.target.value;
setPassword(newPassword);
setPasswordError("");
if (passwordError) setPasswordError("");
};
// const handlePasswordChange = (
// e: React.ChangeEvent<HTMLInputElement>
// ): void => {
// const newPassword = e.target.value;
// setPassword(newPassword);
// setPasswordError("");
// if (passwordError) setPasswordError("");
// };

const handleReenteredPasswordChange = (
e: React.ChangeEvent<HTMLInputElement>
): void => {
const newReenteredPassword = e.target.value;
setReenteredPassword(newReenteredPassword);
setReenteredPasswordError("");
if (reenteredPasswordError) setReenteredPasswordError("");
// const handleReenteredPasswordChange = (
// e: React.ChangeEvent<HTMLInputElement>
// ): void => {
// const newReenteredPassword = e.target.value;
// setReenteredPassword(newReenteredPassword);
// setReenteredPasswordError("");
// if (reenteredPasswordError) setReenteredPasswordError("");
// };

const postNewUser = async (userData: any) => {
try {
const res: Response = await fetch("/v1/user/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(userData),
});
if (res.ok) {
const newUser = await res.json();
newUser.email = userData.email;
newUser.password = userData.password;
newUser.netid = userData.netid;
} else {
console.error("Failed to create user:", res.statusText);
}
} catch (error) {
console.error("Error creating user:", error);
}
};

const handleSubmit = (e: React.FormEvent<HTMLFormElement>): void => {
e.preventDefault();
const isValidPassword = validatePassword(password);
const doPasswordsMatch = password === reenteredPassword;
const isValidPassword = validatePassword(userData.password);
const doPasswordsMatch = userData.password === reenteredPassword;

if (!isValidPassword) {
setPasswordError(
Expand All @@ -52,10 +79,21 @@ export default function Page() {
setReenteredPasswordError("Passwords do not match.");
return;
}

postNewUser(userData);
console.log("Form submitted");
};

const handleChange = (e: { target: { name: any; value: any } }) => {
const { name, value } = e.target;
setUserData({
...userData,
[name]: value,
});
setPasswordError("");
setReenteredPassword(value);
setReenteredPasswordError("");
};

return (
<div className="flex h-screen">
<div className="h-screen bg-black py-8 px-32 w-1/2">
Expand Down Expand Up @@ -84,6 +122,19 @@ export default function Page() {
// onClick={handleFormClick}
onSubmit={handleSubmit}
>
<label htmlFor="email" className="text-white font-light py-2">
NetId<span className="text-red-500">*</span>
</label>
<input
type="text"
id="netid"
name="netid"
placeholder="abc123"
required
className="w-80 h-10 px-4 mb-8"
value={userData.netid}
onChange={handleChange}
/>
<label htmlFor="email" className="text-white font-light py-2">
Email<span className="text-red-500">*</span>
</label>
Expand All @@ -94,6 +145,8 @@ export default function Page() {
placeholder="[email protected]"
required
className="w-80 h-10 px-4 mb-8"
value={userData.email}
onChange={handleChange}
/>
<label htmlFor="password" className="text-white font-light py-2">
Password<span className="text-red-500">*</span>
Expand All @@ -104,8 +157,8 @@ export default function Page() {
name="password"
placeholder="••••••••••"
required
value={password}
onChange={handlePasswordChange}
value={userData.password}
onChange={handleChange}
className={`w-80 h-10 px-4 mb-8 ${
passwordError && "border-red-500"
}`}
Expand All @@ -128,6 +181,7 @@ export default function Page() {
className={`w-80 h-10 px-4 mb-8 ${
reenteredPasswordError && "border-red-500"
}`}
onChange={handleChange}
/>
{reenteredPasswordError && (
<p className="text-red-500 pb-2">{reenteredPasswordError}</p>
Expand Down
Loading
Loading