init commit
This commit is contained in:
102
frontend/resume-builder/src/pages/Auth/Login.jsx
Normal file
102
frontend/resume-builder/src/pages/Auth/Login.jsx
Normal file
@ -0,0 +1,102 @@
|
||||
import React, { useContext, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import Input from "../../components/Inputs/Input";
|
||||
import { validateEmail } from "../../utils/helper";
|
||||
import { UserContext } from "../../context/userContext";
|
||||
import axiosInstance from "../../utils/axiosInstance";
|
||||
import { API_PATHS } from "../../utils/apiPaths";
|
||||
|
||||
const Login = ({ setCurrentPage }) => {
|
||||
const [email, setEmail] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
const { updateUser } = useContext(UserContext);
|
||||
const navigate = useNavigate();
|
||||
|
||||
// Handle Login Form Submit
|
||||
const handleLogin = async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!validateEmail(email)) {
|
||||
setError("Please enter a valid email address.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!password) {
|
||||
setError("Please enter the password");
|
||||
return;
|
||||
}
|
||||
|
||||
setError("");
|
||||
|
||||
//Login API Call
|
||||
try {
|
||||
const response = await axiosInstance.post(API_PATHS.AUTH.LOGIN, {
|
||||
email,
|
||||
password,
|
||||
});
|
||||
|
||||
const { token } = response.data;
|
||||
|
||||
if (token) {
|
||||
localStorage.setItem("token", token);
|
||||
updateUser(response.data);
|
||||
navigate("/dashboard");
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data.message) {
|
||||
setError(error.response.data.message);
|
||||
} else {
|
||||
setError("Something went wrong. Please try again.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-[90vw] md:w-[33vw] p-7 flex flex-col justify-center">
|
||||
<h3 className="text-lg font-semibold text-black">Welcome Back</h3>
|
||||
<p className="text-xs text-slate-700 mt-[5px] mb-6">
|
||||
Please enter your details to log in
|
||||
</p>
|
||||
|
||||
<form onSubmit={handleLogin}>
|
||||
<Input
|
||||
value={email}
|
||||
onChange={({ target }) => setEmail(target.value)}
|
||||
label="Email Address"
|
||||
placeholder="john@example.com"
|
||||
type="text"
|
||||
/>
|
||||
|
||||
<Input
|
||||
value={password}
|
||||
onChange={({ target }) => setPassword(target.value)}
|
||||
label="Password"
|
||||
placeholder="Min 8 Characters"
|
||||
type="password"
|
||||
/>
|
||||
|
||||
{error && <p className="text-red-500 text-xs pb-2.5">{error}</p>}
|
||||
|
||||
<button type="submit" className="btn-primary">
|
||||
LOGIN
|
||||
</button>
|
||||
|
||||
<p className="text-[13px] text-slate-800 mt-3">
|
||||
Don’t have an account?{" "}
|
||||
<button
|
||||
className="font-medium text-primary underline cursor-pointer"
|
||||
onClick={() => {
|
||||
setCurrentPage("signup");
|
||||
}}
|
||||
>
|
||||
SignUp
|
||||
</button>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Login;
|
||||
135
frontend/resume-builder/src/pages/Auth/SignUp.jsx
Normal file
135
frontend/resume-builder/src/pages/Auth/SignUp.jsx
Normal file
@ -0,0 +1,135 @@
|
||||
import React, { useContext, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import Input from "../../components/Inputs/Input";
|
||||
import { validateEmail } from "../../utils/helper";
|
||||
import ProfilePhotoSelector from "../../components/Inputs/ProfilePhotoSelector";
|
||||
import axiosInstance from "../../utils/axiosInstance";
|
||||
import { API_PATHS } from "../../utils/apiPaths";
|
||||
import { UserContext } from "../../context/userContext";
|
||||
import uploadImage from "../../utils/uploadImage";
|
||||
|
||||
const SignUp = ({setCurrentPage}) => {
|
||||
const [profilePic, setProfilePic] = useState(null);
|
||||
const [fullName, setFullName] = useState("");
|
||||
const [email, setEmail] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
const { updateUser } = useContext(UserContext);
|
||||
const navigate = useNavigate();
|
||||
|
||||
// Handle SignUp Form Submit
|
||||
const handleSignUp = async (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
let profileImageUrl = "";
|
||||
|
||||
if (!fullName) {
|
||||
setError("Please enter full name.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!validateEmail(email)) {
|
||||
setError("Please enter a valid email address.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!password) {
|
||||
setError("Please enter the password");
|
||||
return;
|
||||
}
|
||||
|
||||
setError("");
|
||||
|
||||
//SignUp API Call
|
||||
try {
|
||||
// Upload image if present
|
||||
if (profilePic) {
|
||||
const imgUploadRes = await uploadImage(profilePic);
|
||||
profileImageUrl = imgUploadRes.imageUrl || "";
|
||||
}
|
||||
|
||||
const response = await axiosInstance.post(API_PATHS.AUTH.REGISTER, {
|
||||
name: fullName,
|
||||
email,
|
||||
password,
|
||||
profileImageUrl,
|
||||
});
|
||||
|
||||
const { token } = response.data;
|
||||
|
||||
if (token) {
|
||||
localStorage.setItem("token", token);
|
||||
updateUser(response.data);
|
||||
navigate("/dashboard");
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data.message) {
|
||||
setError(error.response.data.message);
|
||||
} else {
|
||||
setError("Something went wrong. Please try again.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-[90vw] md:w-[33vw] p-7 flex flex-col justify-center">
|
||||
<h3 className="text-lg font-semibold text-black">Create an Account</h3>
|
||||
<p className="text-xs text-slate-700 mt-[5px] mb-6">
|
||||
Join us today by entering your details below.
|
||||
</p>
|
||||
|
||||
<form onSubmit={handleSignUp}>
|
||||
|
||||
<ProfilePhotoSelector image={profilePic} setImage={setProfilePic} />
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-1 gap-2">
|
||||
<Input
|
||||
value={fullName}
|
||||
onChange={({ target }) => setFullName(target.value)}
|
||||
label="Full Name"
|
||||
placeholder="John"
|
||||
type="text"
|
||||
/>
|
||||
|
||||
<Input
|
||||
value={email}
|
||||
onChange={({ target }) => setEmail(target.value)}
|
||||
label="Email Address"
|
||||
placeholder="john@example.com"
|
||||
type="text"
|
||||
/>
|
||||
|
||||
<Input
|
||||
value={password}
|
||||
onChange={({ target }) => setPassword(target.value)}
|
||||
label="Password"
|
||||
placeholder="Min 8 Characters"
|
||||
type="password"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{error && <p className="text-red-500 text-xs pb-2.5">{error}</p>}
|
||||
|
||||
<button type="submit" className="btn-primary">
|
||||
SIGN UP
|
||||
</button>
|
||||
|
||||
<p className="text-[13px] text-slate-800 mt-3">
|
||||
Already an account?{" "}
|
||||
<button
|
||||
className="font-medium text-primary underline cursor-pointer"
|
||||
onClick={() => {
|
||||
setCurrentPage("login");
|
||||
}}
|
||||
>
|
||||
Login
|
||||
</button>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default SignUp
|
||||
Reference in New Issue
Block a user