forked from CSI-KJSCE/appointment_to_examiner
Fixes for Admin Login, @somaiya.edu validation, and Password Visibility
This commit is contained in:
@@ -40,6 +40,9 @@ const CourseForm = () => {
|
||||
|
||||
const [errors, setErrors] = useState({});
|
||||
|
||||
// State to check if the form is currently submitting
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchOptionsAndFaculties = async () => {
|
||||
try {
|
||||
@@ -72,11 +75,11 @@ const CourseForm = () => {
|
||||
|
||||
const handleAddFaculty = (field) => {
|
||||
if (!formData[field]) return;
|
||||
|
||||
|
||||
const selectedFaculty = options.faculties.find(
|
||||
(faculty) => faculty.name === formData[field]
|
||||
);
|
||||
|
||||
|
||||
if (selectedFaculty) {
|
||||
setTempAssignments((prev) => ({
|
||||
...prev,
|
||||
@@ -85,7 +88,6 @@ const CourseForm = () => {
|
||||
setFormData({ ...formData, [field]: "" });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const handleRemoveFaculty = (field, index) => {
|
||||
setTempAssignments((prev) => {
|
||||
@@ -139,6 +141,10 @@ const CourseForm = () => {
|
||||
});
|
||||
|
||||
const payload = Object.values(groupedTasks);
|
||||
|
||||
// Start loading so user knows it is saving
|
||||
setLoading(true);
|
||||
|
||||
await saveAppointment(payload);
|
||||
// await updateCourseStatus(course?.courseId || id);
|
||||
|
||||
@@ -152,6 +158,8 @@ const CourseForm = () => {
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Failed to save appointment:", error);
|
||||
// If error comes, stop the loading
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -343,13 +351,15 @@ const CourseForm = () => {
|
||||
type="submit"
|
||||
className="courseFormButton"
|
||||
style={{ gridColumn: "1 / -1" }}
|
||||
disabled={loading} // Disable button when loading
|
||||
>
|
||||
Submit
|
||||
{/* Change text based on loading state */}
|
||||
{loading ? "Saving..." : "Submit"}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<Footer/>
|
||||
<Footer />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Container, Col, Row } from "react-bootstrap";
|
||||
import { FcGoogle } from "react-icons/fc";
|
||||
import { FaEye, FaEyeSlash } from "react-icons/fa";
|
||||
import axios from "axios";
|
||||
import md5 from "md5";
|
||||
|
||||
@@ -39,18 +40,26 @@ function AuthPage() {
|
||||
|
||||
async function handleSubmit(event) {
|
||||
event.preventDefault();
|
||||
// check if username is there
|
||||
if (!formData.username.trim() && signin) {
|
||||
notifyError("Username cannot be empty");
|
||||
return;
|
||||
}
|
||||
|
||||
// check email format
|
||||
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
||||
if (!emailRegex.test(formData.email)) {
|
||||
notifyError("Enter a valid email address");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check password length
|
||||
// restrict to somaiya emails
|
||||
if (formData.email.endsWith("@somaiya.edu") === false) {
|
||||
notifyError("Only @somaiya.edu emails are allowed");
|
||||
return;
|
||||
}
|
||||
|
||||
// password validation
|
||||
if (formData.password.length < 8) {
|
||||
notifyError("Password must be at least 8 characters long");
|
||||
return;
|
||||
@@ -164,12 +173,17 @@ function TogglerContainer(props) {
|
||||
}
|
||||
|
||||
function SignUpForm(props) {
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
return (
|
||||
<>
|
||||
<form>
|
||||
<form onSubmit={props.handleSubmit}>
|
||||
<h1>Create Account</h1>
|
||||
<div className="Googlediv">
|
||||
<button className="GoogleBtn" onClick={props.handleGoogleLogin}>
|
||||
<button
|
||||
type="button"
|
||||
className="GoogleBtn"
|
||||
onClick={props.handleGoogleLogin}
|
||||
>
|
||||
<FcGoogle className="icon" /> Sign up with Google
|
||||
</button>
|
||||
</div>
|
||||
@@ -190,27 +204,48 @@ function SignUpForm(props) {
|
||||
placeholder="Email"
|
||||
required
|
||||
/>
|
||||
<input
|
||||
type="password"
|
||||
name="password"
|
||||
value={props.formData.password}
|
||||
onChange={props.handleInputChange}
|
||||
placeholder="Password"
|
||||
required
|
||||
/>
|
||||
<button onClick={props.handleSubmit}>Sign Up</button>
|
||||
<div style={{ position: "relative", width: "100%" }}>
|
||||
<input
|
||||
type={showPassword ? "text" : "password"}
|
||||
name="password"
|
||||
value={props.formData.password}
|
||||
onChange={props.handleInputChange}
|
||||
placeholder="Password"
|
||||
required
|
||||
style={{ paddingRight: "40px" }}
|
||||
/>
|
||||
<span
|
||||
onClick={() => setShowPassword(!showPassword)}
|
||||
style={{
|
||||
position: "absolute",
|
||||
right: "10px",
|
||||
top: "50%",
|
||||
transform: "translateY(-50%)",
|
||||
cursor: "pointer",
|
||||
color: "#666",
|
||||
}}
|
||||
>
|
||||
{showPassword ? <FaEyeSlash /> : <FaEye />}
|
||||
</span>
|
||||
</div>
|
||||
<button type="submit">Sign Up</button>
|
||||
</form>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function SignInForm(props) {
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
return (
|
||||
<>
|
||||
<form>
|
||||
<form onSubmit={props.handleSubmit}>
|
||||
<h1>Sign In</h1>
|
||||
<div>
|
||||
<button className="GoogleBtn" onClick={props.handleGoogleLogin}>
|
||||
<button
|
||||
type="button"
|
||||
className="GoogleBtn"
|
||||
onClick={props.handleGoogleLogin}
|
||||
>
|
||||
<FcGoogle className="icon" /> Sign in with Google
|
||||
</button>
|
||||
</div>
|
||||
@@ -223,19 +258,35 @@ function SignInForm(props) {
|
||||
placeholder="Email"
|
||||
required
|
||||
/>
|
||||
<input
|
||||
type="password"
|
||||
name="password"
|
||||
value={props.formData.password}
|
||||
onChange={props.handleInputChange}
|
||||
placeholder="Password"
|
||||
required
|
||||
/>
|
||||
<div style={{ position: "relative", width: "100%" }}>
|
||||
<input
|
||||
type={showPassword ? "text" : "password"}
|
||||
name="password"
|
||||
value={props.formData.password}
|
||||
onChange={props.handleInputChange}
|
||||
placeholder="Password"
|
||||
required
|
||||
style={{ paddingRight: "40px" }}
|
||||
/>
|
||||
<span
|
||||
onClick={() => setShowPassword(!showPassword)}
|
||||
style={{
|
||||
position: "absolute",
|
||||
right: "10px",
|
||||
top: "50%",
|
||||
transform: "translateY(-50%)",
|
||||
cursor: "pointer",
|
||||
color: "#666",
|
||||
}}
|
||||
>
|
||||
{showPassword ? <FaEyeSlash /> : <FaEye />}
|
||||
</span>
|
||||
</div>
|
||||
<a href="/ForgetPw">Forget Your Password?</a>
|
||||
<button onClick={props.handleSubmit}>Sign In</button>
|
||||
<button type="submit">Sign In</button>
|
||||
</form>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default AuthPage;
|
||||
export default AuthPage;
|
||||
|
||||
@@ -28,7 +28,7 @@ const WelcomeWithFilter = () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Footer/>
|
||||
<Footer />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
BIN
client/src/assets/Somaiya.jpg
Normal file
BIN
client/src/assets/Somaiya.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 317 KiB |
Reference in New Issue
Block a user