import React from 'react';
import styled from 'styled-components';
import { motion } from 'framer-motion';
import { useNavigate } from 'react-router-dom';
import { useAuth } from '@/contexts/AuthContext';
import { useForm } from 'react-hook-form';
import toast from 'react-hot-toast';
import { InputGroup } from './Dashboard/CreateAccountStyles';
import { FaSpinner } from 'react-icons/fa';
// Design tokens
const colors = {
primary: '#667eea',
primaryDark: '#5a67d8',
secondary: '#764ba2',
success: '#48bb78',
error: '#ff6b6b',
warning: '#f6ad55',
text: '#1a202c',
textSecondary: '#4a5568',
textMuted: '#a0aec0',
background: 'rgba(255, 255, 255, 0.95)',
border: 'rgba(102, 126, 234, 0.2)',
borderHover: '#667eea',
glass: 'rgba(255, 255, 255, 0.95)',
glassLight: 'rgba(255, 255, 255, 0.8)',
shadow: 'rgba(0, 0, 0, 0.1)',
shadowHover: 'rgba(102, 126, 234, 0.1)'
};
const gradients = {
primary: `linear-gradient(135deg, ${colors.primary}, ${colors.secondary})`,
success: `linear-gradient(135deg, ${colors.success}, #38b2ac)`,
error: `linear-gradient(135deg, ${colors.error}, #ee5a52)`,
warning: `linear-gradient(135deg, ${colors.warning}, #ff8c00)`
};
const spacing = {
xs: '4px',
sm: '8px',
md: '12px',
lg: '16px',
xl: '20px',
xxl: '24px',
xxxl: '32px'
};
// Styled Components
const Container = styled.div`
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: ${spacing.xl};
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
position: relative;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background:
radial-gradient(circle at 20% 80%, rgba(120, 119, 198, 0.3) 0%, transparent 50%),
radial-gradient(circle at 80% 20%, rgba(255, 255, 255, 0.1) 0%, transparent 50%),
radial-gradient(circle at 40% 40%, rgba(120, 119, 198, 0.2) 0%, transparent 50%);
}
`;
const FormWrapper = styled(motion.div)`
background: ${colors.glass};
backdrop-filter: blur(20px);
border-radius: 20px;
padding: ${spacing.xxxl};
box-shadow: 0 8px 32px ${colors.shadow};
border: 1px solid rgba(255, 255, 255, 0.2);
position: relative;
overflow: hidden;
width: 100%;
max-width: 420px;
z-index: 1;
&::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: ${gradients.primary};
}
@media (max-width: 768px) {
padding: ${spacing.xxl};
max-width: 100%;
}
`;
const Title = styled.h1`
font-size: 32px;
font-weight: 800;
color: ${colors.text};
margin-bottom: ${spacing.sm};
background: ${gradients.primary};
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
text-align: center;
line-height: 1.2;
@media (max-width: 768px) {
font-size: 28px;
}
`;
const Subtitle = styled.p`
font-size: 16px;
color: ${colors.textSecondary};
text-align: center;
margin-bottom: ${spacing.xxxl};
font-weight: 500;
line-height: 1.4;
`;
const Form = styled.form`
display: flex;
flex-direction: column;
gap: ${spacing.xl};
`;
const StyledInputGroup = styled.div`
display: flex;
flex-direction: column;
gap: ${spacing.xs};
`;
const Input = styled.input`
width: 100%;
padding: ${spacing.lg} ${spacing.xl};
border: 2px solid ${props => props.errors ? colors.error : colors.border};
border-radius: 12px;
font-size: 16px;
font-weight: 500;
color: ${colors.text};
background: ${colors.glassLight};
backdrop-filter: blur(10px);
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-sizing: border-box;
&:focus {
outline: none;
border-color: ${props => props.errors ? colors.error : colors.borderHover};
box-shadow: 0 0 0 4px ${props => props.errors ? 'rgba(255, 107, 107, 0.1)' : colors.shadowHover};
background: ${colors.background};
}
&::placeholder {
color: ${colors.textMuted};
}
&:-webkit-autofill {
-webkit-box-shadow: 0 0 0 30px ${colors.background} inset;
-webkit-text-fill-color: ${colors.text};
}
`;
const ErrorMessage = styled.p`
color: ${colors.error};
font-size: 14px;
margin: 0;
font-weight: 500;
margin-top: ${spacing.xs};
`;
const Button = styled(motion.button)`
width: 100%;
padding: ${spacing.lg} ${spacing.xl};
border-radius: 12px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
border: none;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
background: ${gradients.primary};
color: white;
box-shadow: 0 4px 16px rgba(102, 126, 234, 0.4);
display: flex;
align-items: center;
justify-content: center;
gap: ${spacing.sm};
margin-top: ${spacing.md};
&:hover:not(:disabled) {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.5);
}
&:active {
transform: translateY(0);
}
&:disabled {
opacity: 0.6;
cursor: not-allowed;
}
svg {
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
`;
const SignupText = styled.p`
text-align: center;
margin-top: ${spacing.xxxl};
color: ${colors.textSecondary};
font-size: 14px;
font-weight: 500;
`;
const SignupLink = styled.a`
color: ${colors.primary};
text-decoration: none;
font-weight: 600;
margin-left: ${spacing.xs};
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
&:hover {
color: ${colors.primaryDark};
text-decoration: underline;
}
`;
function Login() {
const navigate = useNavigate();
const { login } = useAuth();
const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm();
const onSubmit = async (data) => {
try {
const userData = await login({
email: data.email,
password: data.password
});
toast.success("Logged in successfully!");
setTimeout(() => {
navigate("/dashboard/profile");
}, 1000);
} catch (error) {
console.error("Login Error ", error);
toast.error(error.response?.data?.message || error.message || "Login Failed. Please try again!");
}
};
return (
<Container>
<FormWrapper
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, ease: 'easeOut' }}
aria-label="Login form"
>
<Title>Banking Application</Title>
<Subtitle>Secure Login to Your Account</Subtitle>
<Form onSubmit={handleSubmit(onSubmit)}>
<StyledInputGroup>
<Input
id="email"
type="text"
placeholder="Email"
errors={errors.email}
{...register('email')}
/>
{errors.email && (
<ErrorMessage>
{errors.email.message}
</ErrorMessage>
)}
</StyledInputGroup>
<StyledInputGroup>
<Input
id="password"
type="password"
placeholder="Password"
errors={errors.password}
{...register('password')}
/>
{errors.password && (
<ErrorMessage>
{errors.password.message}
</ErrorMessage>
)}
</StyledInputGroup>
<Button
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
type="submit"
aria-label="Log In"
disabled={isSubmitting}
>
{isSubmitting ? <FaSpinner /> : "Login"}
</Button>
</Form>
<SignupText>
New here?
<SignupLink href="/signup"> Sign up</SignupLink>
</SignupText>
</FormWrapper>
</Container>
);
}
export default Login;
For further actions, you may consider blocking this person and/or reporting abuse
Top comments (0)