-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit dc6cc18
Showing
23 changed files
with
7,216 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,172 @@ | ||
import { useState, useEffect } from 'react'; | ||
import { useRouter } from 'next/navigation'; | ||
import Link from 'next/link'; | ||
import { FiEye, FiEyeOff } from 'react-icons/fi'; | ||
|
||
export default function Login() { | ||
const router = useRouter(); | ||
const [formData, setFormData] = useState({ | ||
email: '', | ||
password: '' | ||
}); | ||
const [error, setError] = useState(''); | ||
const [loading, setLoading] = useState(false); | ||
const [showPassword, setShowPassword] = useState(false); | ||
const [isClient, setIsClient] = useState(false); // State to track client-side rendering | ||
|
||
const handleSubmit = async (e) => { | ||
e.preventDefault(); | ||
setLoading(true); | ||
setError(''); | ||
|
||
try { | ||
const res = await fetch('/api/login', { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify(formData), | ||
}); | ||
|
||
const data = await res.json(); | ||
|
||
if (!res.ok) { | ||
throw new Error(data.message || 'Login failed'); | ||
} | ||
|
||
// Store user data in localStorage or state management solution | ||
localStorage.setItem('user', JSON.stringify(data.user)); | ||
|
||
// Redirect to dashboard or home page | ||
router.push('/layout'); | ||
} catch (error) { | ||
setError(error.message); | ||
} finally { | ||
setLoading(false); | ||
} | ||
}; | ||
|
||
const handleChange = (e) => { | ||
const { name, value } = e.target; | ||
setFormData(prev => ({ | ||
...prev, | ||
[name]: value | ||
})); | ||
}; | ||
|
||
const togglePasswordVisibility = () => { | ||
setShowPassword((prev) => !prev); | ||
}; | ||
|
||
// Set client-side flag after component mounts | ||
useEffect(() => { | ||
setIsClient(true); | ||
}, []); | ||
|
||
return ( | ||
<div className="min-h-screen relative flex items-center justify-center"> | ||
{/* Conditionally render the video only on the client */} | ||
{isClient && ( | ||
<video | ||
autoPlay | ||
loop | ||
muted | ||
playsInline | ||
className="absolute top-0 left-0 w-full h-full object-cover z-0" | ||
> | ||
<source src="/login.mp4" type="video/mp4" /> | ||
Your browser does not support the video tag. | ||
</video> | ||
)} | ||
|
||
{/* Overlay */} | ||
<div className="absolute top-0 left-0 w-full h-full bg-black bg-opacity-50 z-10" /> | ||
|
||
{/* Login Form */} | ||
<div className="relative z-20 w-full max-w-md p-8 bg-white bg-opacity-90 rounded-xl shadow-2xl"> | ||
<h2 className="text-3xl font-bold text-center text-gray-800 mb-8"> | ||
Welcome Back | ||
</h2> | ||
|
||
{error && ( | ||
<div className="mb-4 p-3 bg-red-100 border border-red-400 text-red-700 rounded"> | ||
{error} | ||
</div> | ||
)} | ||
|
||
<form onSubmit={handleSubmit} className="space-y-6"> | ||
<div> | ||
<label htmlFor="email" className="block text-gray-700 text-sm font-bold mb-2"> | ||
Email Address | ||
</label> | ||
<input | ||
type="email" | ||
id="email" | ||
name="email" | ||
value={formData.email} | ||
onChange={handleChange} | ||
className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 text-black" | ||
placeholder="Enter your email" | ||
required | ||
/> | ||
</div> | ||
|
||
<div className="relative"> | ||
<label htmlFor="password" className="block text-gray-700 text-sm font-bold mb-2"> | ||
Password | ||
</label> | ||
<input | ||
type={showPassword ? "text" : "password"} | ||
id="password" | ||
name="password" | ||
value={formData.password} | ||
onChange={handleChange} | ||
className="w-full px-4 py-3 border rounded-lg focus:ring-2 focus:ring-blue-500 outline-none text-black transition" | ||
placeholder="Enter your password" | ||
required | ||
/> | ||
<button | ||
type="button" | ||
onClick={togglePasswordVisibility} | ||
className="absolute inset-y-0 right-4 flex items-center text-gray-500 hover:text-blue-500" | ||
> | ||
{showPassword ? <FiEyeOff /> : <FiEye />} | ||
</button> | ||
|
||
</div> | ||
|
||
<button | ||
type="submit" | ||
disabled={loading} | ||
className={`w-full py-3 px-4 bg-blue-600 text-white rounded-lg font-semibold transition duration-200 | ||
${loading ? 'opacity-50 cursor-not-allowed' : 'hover:bg-blue-700'}`} | ||
> | ||
{loading ? 'Signing In...' : 'Sign In'} | ||
</button> | ||
</form> | ||
|
||
<div className="mt-6 text-center"> | ||
<p className="text-gray-600"> | ||
Don't have an account?{' '} | ||
<Link | ||
href="/register" | ||
className="text-blue-600 hover:text-blue-700 font-semibold" | ||
> | ||
Register here | ||
</Link> | ||
</p> | ||
</div> | ||
|
||
{/* Optional: Forgot Password Link */} | ||
<div className="mt-4 text-center"> | ||
<Link | ||
href="/forgot-password" | ||
className="text-sm text-gray-600 hover:text-gray-800" | ||
> | ||
Forgot your password? | ||
</Link> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import { useState } from 'react'; | ||
import { useRouter } from 'next/router'; | ||
|
||
export default function Register() { | ||
const router = useRouter(); | ||
const [formData, setFormData] = useState({ name: '', email: '', password: '' }); | ||
const [loading, setLoading] = useState(false); | ||
const [error, setError] = useState(null); | ||
|
||
const handleChange = (e) => { | ||
const { name, value } = e.target; | ||
setFormData((prev) => ({ ...prev, [name]: value })); | ||
}; | ||
|
||
const handleSubmit = async (e) => { | ||
e.preventDefault(); | ||
setLoading(true); | ||
setError(null); | ||
|
||
try { | ||
const response = await fetch('/api/register', { | ||
method: 'POST', | ||
headers: { 'Content-Type': 'application/json' }, | ||
body: JSON.stringify(formData), | ||
}); | ||
|
||
if (!response.ok) { | ||
const data = await response.json(); | ||
throw new Error(data.message || 'Registration failed'); | ||
} | ||
|
||
// On successful registration, redirect to the layout page | ||
router.push('/layout'); | ||
} catch (err) { | ||
setError(err.message); | ||
} finally { | ||
setLoading(false); | ||
} | ||
}; | ||
|
||
return ( | ||
<div className="min-h-screen flex items-center justify-center bg-gray-50 dark:bg-gray-900"> | ||
<form onSubmit={handleSubmit} className="bg-white dark:bg-gray-800 p-6 rounded shadow-md w-full max-w-md"> | ||
<h1 className="text-2xl font-bold mb-4">Register</h1> | ||
|
||
{error && <p className="text-red-500 text-sm mb-4">{error}</p>} | ||
|
||
<div className="mb-4"> | ||
<label className="block text-sm font-medium mb-1">Name</label> | ||
<input | ||
type="text" | ||
name="name" | ||
value={formData.name} | ||
onChange={handleChange} | ||
required | ||
className="w-full px-3 py-2 border rounded" | ||
/> | ||
</div> | ||
|
||
<div className="mb-4"> | ||
<label className="block text-sm font-medium mb-1">Email</label> | ||
<input | ||
type="email" | ||
name="email" | ||
value={formData.email} | ||
onChange={handleChange} | ||
required | ||
className="w-full px-3 py-2 border rounded" | ||
/> | ||
</div> | ||
|
||
<div className="mb-4"> | ||
<label className="block text-sm font-medium mb-1">Password</label> | ||
<input | ||
type="password" | ||
name="password" | ||
value={formData.password} | ||
onChange={handleChange} | ||
required | ||
className="w-full px-3 py-2 border rounded" | ||
/> | ||
</div> | ||
|
||
<button | ||
type="submit" | ||
disabled={loading} | ||
className="w-full bg-blue-600 text-white py-2 rounded hover:bg-blue-700" | ||
> | ||
{loading ? 'Registering...' : 'Register'} | ||
</button> | ||
</form> | ||
</div> | ||
); | ||
} |
Oops, something went wrong.