Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 4 additions & 5 deletions server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"jsonwebtoken": "^9.0.2",
"mongoose": "^8.5.2",
"nodemailer": "^6.9.14",
"nodemon": "^3.1.4",
"nodemon": "^3.1.10",
"razorpay": "^2.9.4",
"server": "file:"
}
Expand Down
2 changes: 1 addition & 1 deletion src/Component/Auth/Loginform.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const Logingform = () => {
dispatch(signin(email, password, navigate));
} catch (error) {
console.error("Login error:", error);
toast.error("An error occurred during login");
toast.error("Login failed. Please check your credentials and try again.");
}
};

Expand Down
117 changes: 105 additions & 12 deletions src/Component/Auth/Signupform.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,44 @@ const Signupform = () => {
password: "",
});

const handleChange = (e) =>
setFormData({ ...formData, [e.target.name]: e.target.value });
const [passwordValidation, setPasswordValidation] = useState({
minLength: false,
hasUppercase: false,
hasLowercase: false,
hasNumber: false,
hasSpecialChar: false,
});

const [showPassword, setShowPassword] = useState(false);

const validatePassword = (password) => {
const validations = {
minLength: password.length >= 8,
hasUppercase: /[A-Z]/.test(password),
hasLowercase: /[a-z]/.test(password),
hasNumber: /\d/.test(password),
hasSpecialChar: /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(password),
};
setPasswordValidation(validations);
return Object.values(validations).every(Boolean);
};

const handleChange = (e) => {
const { name, value } = e.target;
setFormData({ ...formData, [name]: value });

if (name === "password") {
validatePassword(value);
}
};

const getPasswordStrength = () => {
const validCount = Object.values(passwordValidation).filter(Boolean).length;
if (validCount === 5) return { strength: "Strong", color: "text-green-600", bgColor: "bg-green-100" };
if (validCount >= 3) return { strength: "Medium", color: "text-yellow-600", bgColor: "bg-yellow-100" };
if (validCount >= 1) return { strength: "Weak", color: "text-red-600", bgColor: "bg-red-100" };
return { strength: "Very Weak", color: "text-gray-600", bgColor: "bg-gray-100" };
};

const navigate = useNavigate();
const dispatch = useDispatch();
Expand All @@ -25,14 +61,21 @@ const Signupform = () => {
return toast.error("All fields are required");
}

// Validate password before submission
if (!validatePassword(password)) {
return toast.error("Password does not meet the required criteria.");
}

try {
dispatch(signUp(username, email, password, navigate));
} catch (error) {
console.error("Signup error:", error);
toast.error("An error occurred during signup");
toast.error("Registration failed. Please try again.");
}
};

const passwordStrength = getPasswordStrength();

return (
<form className="space-y-5 w-full" onSubmit={onSubmithandle}>
<div>
Expand All @@ -46,6 +89,7 @@ const Signupform = () => {
placeholder="[email protected]"
value={formData.email}
onChange={handleChange}
required
/>
</div>

Expand All @@ -60,26 +104,75 @@ const Signupform = () => {
placeholder="your_username"
value={formData.username}
onChange={handleChange}
required
/>
</div>

<div>
<label className="block text-sm font-medium text-green-800 mb-1">
Password
</label>
<input
className="w-full rounded-md p-2 bg-white border border-green-300 input-shadow focus:outline-none focus:ring-2 focus:ring-green-400"
type="password"
name="password"
placeholder="••••••••"
value={formData.password}
onChange={handleChange}
/>
<div className="relative">
<input
className="w-full rounded-md p-2 bg-white border border-green-300 input-shadow focus:outline-none focus:ring-2 focus:ring-green-400 pr-10"
type={showPassword ? "text" : "password"}
name="password"
placeholder="••••••••"
value={formData.password}
onChange={handleChange}
required
/>
<button
type="button"
className="absolute right-2 top-1/2 transform -translate-y-1/2 text-gray-500 hover:text-gray-700"
onClick={() => setShowPassword(!showPassword)}
>
{showPassword ? "🙈" : "👁️"}
</button>
</div>

{/* Password Strength Indicator */}
{formData.password && (
<div className="mt-2">
<div className="flex items-center gap-2 mb-2">
<span className="text-sm font-medium">Password Strength:</span>
<span className={`text-sm font-semibold ${passwordStrength.color}`}>
{passwordStrength.strength}
</span>
</div>
<div className={`p-3 rounded-md ${passwordStrength.bgColor} border`}>
<h4 className="text-sm font-medium mb-2">Password Requirements:</h4>
<ul className="space-y-1 text-sm">
<li className={`flex items-center gap-2 ${passwordValidation.minLength ? 'text-green-600' : 'text-red-600'}`}>
<span>{passwordValidation.minLength ? '✅' : '❌'}</span>
At least 8 characters
</li>
<li className={`flex items-center gap-2 ${passwordValidation.hasUppercase ? 'text-green-600' : 'text-red-600'}`}>
<span>{passwordValidation.hasUppercase ? '✅' : '❌'}</span>
At least 1 uppercase letter (A-Z)
</li>
<li className={`flex items-center gap-2 ${passwordValidation.hasLowercase ? 'text-green-600' : 'text-red-600'}`}>
<span>{passwordValidation.hasLowercase ? '✅' : '❌'}</span>
At least 1 lowercase letter (a-z)
</li>
<li className={`flex items-center gap-2 ${passwordValidation.hasNumber ? 'text-green-600' : 'text-red-600'}`}>
<span>{passwordValidation.hasNumber ? '✅' : '❌'}</span>
At least 1 number (0-9)
</li>
<li className={`flex items-center gap-2 ${passwordValidation.hasSpecialChar ? 'text-green-600' : 'text-red-600'}`}>
<span>{passwordValidation.hasSpecialChar ? '✅' : '❌'}</span>
At least 1 special character (!@#$%^&*)
</li>
</ul>
</div>
</div>
)}
</div>

<button
type="submit"
className="w-full bg-green-300 text-green-900 font-semibold p-2 rounded-md input-shadow hover:bg-green-400 transition"
className="w-full bg-green-300 text-green-900 font-semibold p-2 rounded-md input-shadow hover:bg-green-400 transition disabled:opacity-50 disabled:cursor-not-allowed"
disabled={!Object.values(passwordValidation).every(Boolean) || !formData.email || !formData.username}
>
Signup
</button>
Expand Down
16 changes: 16 additions & 0 deletions src/service/apiConnector.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,32 @@ export const axiosInstance = axios.create({});

export const apiConnector = async (method, url, bodyData, headers, params) => {
try {
console.log("Making API request:", {
method,
url,
bodyData,
headers,
params
});

const response = await axiosInstance({
method: `${method}`,
url: `${url}`,
data: bodyData ? bodyData : null,
headers: headers ? headers : null,
params: params ? params : null,
});

console.log("API response:", response);
return response;
} catch (error) {
console.error("API Connector Error:", error);
console.error("Error details:", {
message: error.message,
code: error.code,
response: error.response,
request: error.request
});
throw error;
}
};
29 changes: 17 additions & 12 deletions src/service/apis.jsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,33 @@
const BASE_URL = import.meta.env.VITE_BASE_URL;

console.log("Environment variables:", {
VITE_BASE_URL: import.meta.env.VITE_BASE_URL,
BASE_URL: BASE_URL
});

export const authEndpoits = {
SIGNUP_API: `${BASE_URL}/user/signup`,
SIGNIN_API: `${BASE_URL}/user/signin`,
SIGNUP_API: `${BASE_URL}/api/user/signup`,
SIGNIN_API: `${BASE_URL}/api/user/signin`,
};

export const BlogEndpoints = {
GET_BLOGS: `${BASE_URL}/blog/blogs`,
CREATE_BLOG: `${BASE_URL}/blog/create`,
GET_BLOG: `${BASE_URL}/blog/blogdel:id`,
GET_BLOGS: `${BASE_URL}/api/blog/blogs`,
CREATE_BLOG: `${BASE_URL}/api/blog/create`,
GET_BLOG: `${BASE_URL}/api/blog/blogdel:id`,
};

export const OrderEndpoints = {
CREATE_ORDER: `${BASE_URL}/order/createOrder`,
CANCEL_ORDER: `${BASE_URL}/order/cancel:id`,
CREATE_ORDER: `${BASE_URL}/api/order/createOrder`,
CANCEL_ORDER: `${BASE_URL}/api/order/cancel:id`,
};

export const PaymentEndpoints = {
CREATE_PAYMENT: `${BASE_URL}/payment/createPayment`,
VERIFY_PAYMENT: `${BASE_URL}/payment/verifyPayment`,
CREATE_PAYMENT: `${BASE_URL}/api/payment/createPayment`,
VERIFY_PAYMENT: `${BASE_URL}/api/payment/verifyPayment`,
};

export const PlantsEndpoints = {
GET_PLANTS: `${BASE_URL}/plants/getAllplants`,
ADD_PLANT: `${BASE_URL}/plants/addPlant`,
GET_PLANT: `${BASE_URL}/plants/getplant`,
GET_PLANTS: `${BASE_URL}/api/plants/getAllplants`,
ADD_PLANT: `${BASE_URL}/api/plants/addPlant`,
GET_PLANT: `${BASE_URL}/api/plants/getplant`,
};
12 changes: 6 additions & 6 deletions src/service/oprations/authApi.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ export function signUp(username, email, password, navigate) {
}
);

toast.success("Signup Successfully");
toast.success("Registration complete! You can now log in.");

navigate("/signin");
} catch (error) {
console.log(error);

toast.error(error.response?.data?.error || "An error occurred");
toast.error(error.response?.data?.error || error.response?.data?.message || "Registration failed. Please try again.");
} finally {
dispatch(setLoading(false));
}
Expand All @@ -54,11 +54,11 @@ export function signin(email, password, navigate) {
dispatch(setToken(response.data.token));
localStorage.setItem("token", response.data.token);
dispatch(setIslogin(true));
toast.success("Logged In");
toast.success("Login successful! Welcome🎉");
navigate("/");
} catch (error) {
console.log(error);
toast.error(error.response?.data?.message || "An error occurred");
toast.error(error.response?.data?.message || "Login failed. Please check your credentials and try again.");
} finally {
dispatch(setLoading(false));
}
Expand All @@ -70,8 +70,8 @@ export function logout() {
try {
dispatch(setToken(null));
dispatch(setIslogin(null));
localStorage.getItem("token", "");
toast.success("Log Out");
localStorage.removeItem("token");
toast.success("You've been logged out successfully.");
} catch (error) {
console.log(error);
toast.error("Internal Server Error While Log out");
Expand Down