va-tracker/src/ui/pages/Login.tsx

211 lines
7.1 KiB
TypeScript

import React, { useState, useEffect, useRef, FormEvent, ChangeEvent } from 'react'
import { useDispatch } from 'react-redux';
import { useNavigate } from 'react-router-dom'
import { setUserSlice } from '../store/userSlice';
import DocVaLogoLight from '../../assets/logo-colored-vertical.svg'
import DocVaLogoDark from '../../assets/logo-white-vertical.svg'
import { useTheme } from '../helper/ThemeToggle';
import { Eye, EyeOff, KeyRound, Mail } from 'lucide-react';
const Login = () => {
const { theme, setTheme } = useTheme();
const inputRef = useRef<HTMLFormElement | null>(null)
const navigate = useNavigate()
const dispatch = useDispatch();
const [errorMessage, setErrorMessage] = useState("")
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [isForgotMode, setIsForgotMode] = useState(false);
const [loading, setLoading] = useState(false);
const [showPassword, setShowPassword] = useState(false);
useEffect(() => {
document.documentElement.setAttribute("data-theme", theme);
}, [theme]);
const logo = theme === "dark" ? DocVaLogoDark : DocVaLogoLight;
const handleLogin = async (e: FormEvent<HTMLFormElement> | KeyboardEvent) => {
e.preventDefault()
if (email === "" || password === "") return
setLoading(true);
try {
const response = await window.electron.login({ email, password });
console.log(response)
if (response.success) {
// setUser(response.user);
dispatch(setUserSlice({
id: response.user.id,
name: response.user.name,
email: response.user.email,
}));
navigate("/")
}
else if (response.success == false) {
console.log(response.error.message)
setErrorMessage(response.error.message)
}
} catch (error) {
console.log(error)
} finally {
setLoading(false);
}
}
const handleForgotPassword = async (e: FormEvent<HTMLFormElement> | KeyboardEvent) => {
e.preventDefault();
setLoading(true);
try {
const res = await window.electron.forgotPassword(email);
console.log("Forgot password response:", res);
alert("Password reset link sent to your email");
setIsForgotMode(false);
} catch (error) {
console.error("Forgot password error:", error);
} finally {
setLoading(false);
}
};
// Detect Enter key press
useEffect(() => {
const handleEnter = (e: KeyboardEvent) => {
if (e.key === 'Enter') {
if (!isForgotMode) {
handleLogin(e)
} else {
handleForgotPassword(e)
}
}
}
const inputElement = inputRef.current
inputElement?.addEventListener('keydown', handleEnter)
return () => inputElement?.removeEventListener('keydown', handleEnter)
}, [email, password])
return (
<>
<div className="min-h-screen flex items-center justify-center bg-linear-to-br from-primary/10 via-base-200 to-secondary/10 p-4">
<div className="card w-full max-w-md shadow-2xl bg-base-100 backdrop-blur-sm">
<div className="card-body">
<div className="flex justify-center items-center mb-4">
<div className="avatar placeholder">
{/* <div className="bg-primary text-primary-content rounded-full w-20 h-20 flex items-center justify-center"> */}
<img src={logo} className='w-35 h-23' />
{/* </div> */}
</div>
</div>
<h2 className="text-center text-3xl font-bold mb-2">Welcome Back</h2>
<p className="text-center text-base-content/60 mb-6">Sign in to Employee Tracker</p>
<form
ref={inputRef}
className="flex flex-col items-center justify-center w-full"
onSubmit={isForgotMode ? handleForgotPassword : handleLogin}
>
<div className="form-control w-90 px-5">
<label className="label">
<span className="label-text font-medium">Email Address</span>
</label>
<label className="input input-bordered flex items-center gap-2" tabIndex={0}>
{/* <Mail size={18} /> */}
<input
type="email"
name="email"
placeholder="you@example.com"
className="grow"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
</label>
</div>
{!isForgotMode && (
<div className="form-control w-90 px-5 mt-3">
<label className="label">
<span className="label-text font-medium">Password</span>
</label>
<label className="input input-bordered flex items-center gap-2" tabIndex={0}>
{/* <KeyRound size={18} /> */}
<input
type={showPassword ? "text" : "password"}
name="password"
placeholder="Enter your password"
className="grow"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
{/* Toggle Icon */}
<button
type="button"
className="cursor-pointer"
onClick={() => setShowPassword((prev) => !prev)}
>
{showPassword ? (
<EyeOff size={18} className="opacity-70" />
) : (
<Eye size={18} className="opacity-70" />
)}
</button>
</label>
</div>
)}
<div className="form-control w-90 px-5 mt-4">
<button
type="submit"
disabled={loading}
className="btn btn-primary w-full"
>
{loading
? "Please wait..."
: isForgotMode
? "Send Reset Link"
: "Login"}
</button>
</div>
<div className="text-center mt-4">
{isForgotMode ? (
<button
type="button"
onClick={() => setIsForgotMode(false)}
className="link link-primary text-sm"
>
Back to Login
</button>
) : (
<button
type="button"
onClick={() => setIsForgotMode(true)}
className="link link-primary text-sm"
>
Forgot Password?
</button>
)}
</div>
{errorMessage && <span className='text-red-500 font-semibold mt-2'>{errorMessage}...!</span>}
</form>
</div>
</div>
</div>
</>
)
}
export default Login