diff --git a/frontend/app/auth/signin/forgot-password-modal.tsx b/frontend/app/auth/signin/forgot-password-modal.tsx index c2eb19c..14f0901 100644 --- a/frontend/app/auth/signin/forgot-password-modal.tsx +++ b/frontend/app/auth/signin/forgot-password-modal.tsx @@ -18,21 +18,21 @@ export default function ForgotPasswordModal() {
- - + What's your email? - Please verify your email for us. Once you do, we'll send instructions to reset your password + Please verify your email for us. Once you do, we'll send instructions to reset your password.
diff --git a/frontend/app/auth/signin/google-oauth.tsx b/frontend/app/auth/signin/google-oauth.tsx index 7b1f2cb..8d5f1da 100644 --- a/frontend/app/auth/signin/google-oauth.tsx +++ b/frontend/app/auth/signin/google-oauth.tsx @@ -2,8 +2,9 @@ import Image from "next/image"; export function GoogleSigninButton() { return ( -
+
Google Logo + Sign in with Google
); } diff --git a/frontend/app/auth/signin/page.tsx b/frontend/app/auth/signin/page.tsx index c49235e..450ae1e 100644 --- a/frontend/app/auth/signin/page.tsx +++ b/frontend/app/auth/signin/page.tsx @@ -2,35 +2,35 @@ import { zodResolver } from "@hookform/resolvers/zod"; import { useForm } from "react-hook-form"; - import { signInSchema } from "@/schemas/auth.schema"; - import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Checkbox } from "@/components/ui/checkbox"; import { Button } from "@/components/ui/button"; import ForgotPasswordModal from "./forgot-password-modal"; - import Link from "next/link"; import Image from "next/image"; import { GoogleSigninButton } from "./google-oauth"; -import { z } from "zod"; +import type { z } from "zod"; import { useContext, useState } from "react"; import { useRouter } from "next/navigation"; - import { loginUser } from "@/api/authentication"; import { SessionContext } from "@/context/SessionContext"; +import { Eye, EyeOff, Leaf, ArrowRight, AlertCircle, Loader2 } from "lucide-react"; +import { Alert, AlertDescription } from "@/components/ui/alert"; +import { ThemeToggle } from "@/components/theme-toggle"; export default function SigninPage() { const [serverError, setServerError] = useState(null); const [isLoading, setIsLoading] = useState(false); + const [showPassword, setShowPassword] = useState(false); const router = useRouter(); const session = useContext(SessionContext); const { register, handleSubmit, - formState: { errors }, + formState: { errors, isSubmitting }, } = useForm({ resolver: zodResolver(signInSchema), defaultValues: { @@ -56,68 +56,188 @@ export default function SigninPage() { router.push("/setup"); } catch (error: any) { console.error("Error logging in:", error); - setServerError(error.message); + setServerError(error.message || "Invalid email or password. Please try again."); } finally { setIsLoading(false); } }; return ( -
-
-
+
+
+ {/* Left side - Image */} +
+
+
+
+ + + ForFarm + +
-
-
-
- - Forfarm - -

Welcome back.

-
- New to Forfarm? - - - Sign up - - +
+

Grow smarter with ForFarm

+

+ Join thousands of farmers using our platform to optimize their agricultural operations and increase + yields. +

+
+
+ {[1, 2, 3].map((i) => ( +
+ User +
+ ))} +
+
+ 500+ farmers already using ForFarm +
+
+
+
+ + {/* Right side - Form */} +
+
+
+ + Forfarm + +
+ +
+

Welcome back

+

+ New to Forfarm?{" "} + + Sign up + +

+
+ + {serverError && ( + + + {serverError} + + )} {/* Sign in form */} -
-
- - - {errors.email &&

{errors.email.message}

} -
-
- - - {errors.password &&

{errors.password.message}

} + +
+ +
+ +
+ {errors.email && ( +

+ + {errors.email.message} +

+ )}
- +
+ {errors.password && ( +

+ + {errors.password.message} +

+ )} +
+ +
+ + +
+ + - diff --git a/frontend/app/auth/signin/waterdrop.tsx b/frontend/app/auth/signin/waterdrop.tsx deleted file mode 100644 index b06bb2f..0000000 --- a/frontend/app/auth/signin/waterdrop.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import React from "react"; - -const WaterDrop = () => { - return ( -
- {/* Water Drop animation */} -
-
- ); -}; - -export default WaterDrop; diff --git a/frontend/app/auth/signup/page.tsx b/frontend/app/auth/signup/page.tsx index 4600e86..ed0cb02 100644 --- a/frontend/app/auth/signup/page.tsx +++ b/frontend/app/auth/signup/page.tsx @@ -1,28 +1,30 @@ "use client"; +import type React from "react"; import { zodResolver } from "@hookform/resolvers/zod"; import { useForm } from "react-hook-form"; - import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Button } from "@/components/ui/button"; - import { signUpSchema } from "@/schemas/auth.schema"; - import Link from "next/link"; import Image from "next/image"; import { useContext, useState } from "react"; -import { z } from "zod"; - +import type { z } from "zod"; import { useRouter } from "next/navigation"; - import { registerUser } from "@/api/authentication"; import { SessionContext } from "@/context/SessionContext"; +import { Eye, EyeOff, Leaf, ArrowRight, AlertCircle, Loader2, Check } from "lucide-react"; +import { Alert, AlertDescription } from "@/components/ui/alert"; +import { Progress } from "@/components/ui/progress"; export default function SignupPage() { const [serverError, setServerError] = useState(null); const [successMessage, setSuccessMessage] = useState(null); const [isLoading, setIsLoading] = useState(false); + const [showPassword, setShowPassword] = useState(false); + const [showConfirmPassword, setShowConfirmPassword] = useState(false); + const [passwordStrength, setPasswordStrength] = useState(0); const router = useRouter(); const session = useContext(SessionContext); @@ -30,7 +32,8 @@ export default function SignupPage() { const { register, handleSubmit, - formState: { errors }, + watch, + formState: { errors, isSubmitting }, } = useForm>({ resolver: zodResolver(signUpSchema), defaultValues: { @@ -40,6 +43,29 @@ export default function SignupPage() { }, }); + const password = watch("password"); + + // Calculate password strength based on several criteria + const calculatePasswordStrength = (password: string) => { + if (!password) return 0; + let strength = 0; + + // Length check + if (password.length >= 8) strength += 25; + // Contains lowercase + if (/[a-z]/.test(password)) strength += 25; + // Contains uppercase + if (/[A-Z]/.test(password)) strength += 25; + // Contains number or special char + if (/[0-9!@#$%^&*(),.?":{}|<>]/.test(password)) strength += 25; + return strength; + }; + + const onPasswordChange = (e: React.ChangeEvent) => { + const newStrength = calculatePasswordStrength(e.target.value); + setPasswordStrength(newStrength); + }; + const onSubmit = async (values: z.infer) => { setServerError(null); setSuccessMessage(null); @@ -52,83 +78,265 @@ export default function SignupPage() { setServerError("An error occurred while registering. Please try again."); throw new Error("No data received from the server."); } + session!.setToken(data.token); session!.setUser(values.email); - setSuccessMessage("Registration successful! You can now sign in."); router.push("/setup"); } catch (error: any) { console.error("Error during registration:", error); - setServerError(error.message); + setServerError(error.message || "Registration failed. Please try again."); } finally { setIsLoading(false); } }; + const getPasswordStrengthText = () => { + if (passwordStrength === 0) return ""; + if (passwordStrength <= 25) return "Weak"; + if (passwordStrength <= 50) return "Fair"; + if (passwordStrength <= 75) return "Good"; + return "Strong"; + }; + + const getPasswordStrengthColor = () => { + if (passwordStrength <= 25) return "bg-red-500"; + if (passwordStrength <= 50) return "bg-yellow-500"; + if (passwordStrength <= 75) return "bg-blue-500"; + return "bg-green-500"; + }; + return ( -
-
-
- -
-
-
- - Forfarm - -

Hi! Welcome

-
- Already have an account? - - - Sign in - - -
-
- - {/* Signup form */} -
+
+
+ {/* Left Side - Image */} +
+
+
- - - {errors.email &&

{errors.email.message}

} + + + ForFarm +
-
- - - {errors.password &&

{errors.password.message}

} -
-
- - - {errors.confirmPassword &&

{errors.confirmPassword.message}

} -
- - {serverError &&

{serverError}

} - {successMessage &&

{successMessage}

} - - - - -
-

Or sign up with

-
- {/* Google OAuth button or additional providers */} -
- Google Logo +
+

Join the farming revolution

+

+ Create your account today and discover how ForFarm can help you optimize your agricultural operations. +

+
+ {[ + "Real-time monitoring of your crops", + "Smart resource management", + "Data-driven insights for better yields", + "Connect with other farmers in your area", + ].map((feature, index) => ( +
+
+ +
+ {feature} +
+ ))}
+ + {/* Right Side - Form */} +
+
+ {/* Theme Selector Placeholder */} +
Theme Selector Placeholder
+ +
+ + Forfarm + +
+ +
+

Create your account

+

+ Already have an account?{" "} + + Sign in + +

+
+ + {serverError && ( + + + {serverError} + + )} + + {successMessage && ( + + + {successMessage} + + )} + + {/* Sign Up Form */} +
+ {/* Email */} +
+ +
+ +
+ {errors.email && ( +

+ + {errors.email.message} +

+ )} +
+ + {/* Password */} +
+ +
+ + +
+ + {/* Password Strength Indicator */} + {password && ( +
+
+ Password strength + + {getPasswordStrengthText()} + +
+ +
+ )} + + {errors.password && ( +

+ + {errors.password.message} +

+ )} +
+ + {/* Confirm Password */} +
+ +
+ + +
+ {errors.confirmPassword && ( +

+ + {errors.confirmPassword.message} +

+ )} +
+ + +
+ +
+
+
+
+
+
+ + Or sign up with + +
+
+ +
+ +
+
+ +

+ By signing up, you agree to our{" "} + + Terms of Service + {" "} + and{" "} + + Privacy Policy + +

+
+
); diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx index e574d77..de17932 100644 --- a/frontend/app/page.tsx +++ b/frontend/app/page.tsx @@ -93,7 +93,7 @@ export default function Home() {