text changes, error styling, navbar menu styling
This commit is contained in:
@@ -81,7 +81,7 @@ const validateRegistration = [
|
|||||||
.withMessage("Password must be between 8 and 128 characters")
|
.withMessage("Password must be between 8 and 128 characters")
|
||||||
.matches(passwordStrengthRegex)
|
.matches(passwordStrengthRegex)
|
||||||
.withMessage(
|
.withMessage(
|
||||||
"Password must contain at least one uppercase letter, one lowercase letter, one number, and one special character"
|
"Password does not meet requirements"
|
||||||
)
|
)
|
||||||
.custom((value) => {
|
.custom((value) => {
|
||||||
if (commonPasswords.includes(value.toLowerCase())) {
|
if (commonPasswords.includes(value.toLowerCase())) {
|
||||||
@@ -275,7 +275,7 @@ const validateResetPassword = [
|
|||||||
.withMessage("Password must be between 8 and 128 characters")
|
.withMessage("Password must be between 8 and 128 characters")
|
||||||
.matches(passwordStrengthRegex)
|
.matches(passwordStrengthRegex)
|
||||||
.withMessage(
|
.withMessage(
|
||||||
"Password must contain at least one uppercase letter, one lowercase letter, one number, and one special character"
|
"Password does not meet requirements"
|
||||||
)
|
)
|
||||||
.custom((value) => {
|
.custom((value) => {
|
||||||
if (commonPasswords.includes(value.toLowerCase())) {
|
if (commonPasswords.includes(value.toLowerCase())) {
|
||||||
|
|||||||
@@ -206,8 +206,7 @@ router.post(
|
|||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return res.status(401).json({
|
return res.status(401).json({
|
||||||
error:
|
error: "Please check your email and password, or create an account.",
|
||||||
"Unable to log in. Please check your email and password, or create an account.",
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,8 +225,7 @@ router.post(
|
|||||||
// Increment login attempts
|
// Increment login attempts
|
||||||
await user.incLoginAttempts();
|
await user.incLoginAttempts();
|
||||||
return res.status(401).json({
|
return res.status(401).json({
|
||||||
error:
|
error: "Please check your email and password, or create an account.",
|
||||||
"Unable to log in. Please check your email and password, or create an account.",
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
content="Village Share - Life is too expensive. Rent or borrow from your neighbors"
|
content="Village Share - Life is too expensive. Rent or borrow from your neighbors"
|
||||||
/>
|
/>
|
||||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||||
<title>Village Share - Community Rental Marketplace</title>
|
<title>Village Share</title>
|
||||||
<link
|
<link
|
||||||
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"
|
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
|
|||||||
@@ -112,9 +112,32 @@ const AuthModal: React.FC<AuthModalProps> = ({
|
|||||||
|
|
||||||
const handleEmailSubmit = async (e: React.FormEvent) => {
|
const handleEmailSubmit = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setLoading(true);
|
|
||||||
setError("");
|
setError("");
|
||||||
|
|
||||||
|
// Custom validation to match app's error styling
|
||||||
|
if (mode === "signup") {
|
||||||
|
if (!firstName.trim()) {
|
||||||
|
setError("Please enter your first name");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!lastName.trim()) {
|
||||||
|
setError("Please enter your last name");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
if (!email.trim()) {
|
||||||
|
setError("Please enter your email address");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!emailRegex.test(email)) {
|
||||||
|
setError("Please enter a valid email address");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (mode === "login") {
|
if (mode === "login") {
|
||||||
await login(email, password);
|
await login(email, password);
|
||||||
@@ -132,7 +155,10 @@ const AuthModal: React.FC<AuthModalProps> = ({
|
|||||||
// Don't call onHide() - keep modal context for verification
|
// Don't call onHide() - keep modal context for verification
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
setError(err.response?.data?.error || "An error occurred");
|
// Show first specific validation error if available, otherwise generic error
|
||||||
|
const details = err.response?.data?.details;
|
||||||
|
const specificError = details?.[0]?.message;
|
||||||
|
setError(specificError || err.response?.data?.error || "An error occurred");
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
@@ -202,7 +228,6 @@ const AuthModal: React.FC<AuthModalProps> = ({
|
|||||||
className="form-control"
|
className="form-control"
|
||||||
value={firstName}
|
value={firstName}
|
||||||
onChange={(e) => setFirstName(e.target.value)}
|
onChange={(e) => setFirstName(e.target.value)}
|
||||||
required
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="col">
|
<div className="col">
|
||||||
@@ -212,7 +237,6 @@ const AuthModal: React.FC<AuthModalProps> = ({
|
|||||||
className="form-control"
|
className="form-control"
|
||||||
value={lastName}
|
value={lastName}
|
||||||
onChange={(e) => setLastName(e.target.value)}
|
onChange={(e) => setLastName(e.target.value)}
|
||||||
required
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -222,11 +246,12 @@ const AuthModal: React.FC<AuthModalProps> = ({
|
|||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label className="form-label">Email</label>
|
<label className="form-label">Email</label>
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="text"
|
||||||
className="form-control"
|
className="form-control"
|
||||||
value={email}
|
value={email}
|
||||||
onChange={(e) => setEmail(e.target.value)}
|
onChange={(e) => setEmail(e.target.value)}
|
||||||
required
|
placeholder="name@example.com"
|
||||||
|
autoComplete="email"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -298,6 +323,7 @@ const AuthModal: React.FC<AuthModalProps> = ({
|
|||||||
className="text-primary text-decoration-none"
|
className="text-primary text-decoration-none"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
setError("");
|
||||||
setMode(mode === "login" ? "signup" : "login");
|
setMode(mode === "login" ? "signup" : "login");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -25,9 +25,21 @@ const ForgotPasswordModal: React.FC<ForgotPasswordModalProps> = ({
|
|||||||
|
|
||||||
const handleSubmit = async (e: React.FormEvent) => {
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setLoading(true);
|
|
||||||
setError("");
|
setError("");
|
||||||
|
|
||||||
|
// Custom email validation to match app's error styling
|
||||||
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
if (!email.trim()) {
|
||||||
|
setError("Please enter your email address");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!emailRegex.test(email)) {
|
||||||
|
setError("Please enter a valid email address");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await authAPI.forgotPassword(email);
|
await authAPI.forgotPassword(email);
|
||||||
setSuccess(true);
|
setSuccess(true);
|
||||||
@@ -124,12 +136,12 @@ const ForgotPasswordModal: React.FC<ForgotPasswordModalProps> = ({
|
|||||||
<div className="mb-3">
|
<div className="mb-3">
|
||||||
<label className="form-label">Email Address</label>
|
<label className="form-label">Email Address</label>
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="text"
|
||||||
className="form-control"
|
className="form-control"
|
||||||
value={email}
|
value={email}
|
||||||
onChange={(e) => setEmail(e.target.value)}
|
onChange={(e) => setEmail(e.target.value)}
|
||||||
placeholder="your@email.com"
|
placeholder="your@email.com"
|
||||||
required
|
autoComplete="email"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user