You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

173 lines
8.6 KiB

import { useEffect, FormEventHandler, useState } from 'react';
import Checkbox from '@/Components/Checkbox';
import GuestLayout from '@/Layouts/GuestLayout';
import InputError from '@/Components/InputError';
import InputLabel from '@/Components/InputLabel';
import PrimaryButton from '@/Components/PrimaryButton';
import TextInput from '@/Components/TextInput';
import { Head, Link, useForm } from '@inertiajs/react';
import { AtSign, Lock, Eye, EyeOff, LogIn, CheckCircle, XOctagon } from 'react-feather';
import FormGroup from '@/Components/FormGroup';
import ProjectBanner from '@/Components/ProjectBanner';
import Modal from '@/Components/Modal';
import axios from 'axios';
import ModalButton from '@/Components/ModalButton';
export default function Login({ status, canResetPassword }: { status?: string, canResetPassword: boolean }) {
const { data, setData, processing, errors, reset } = useForm({
username: '',
password: '',
remember: false,
});
useEffect(() => {
return () => {
reset('password');
};
}, []);
const [showPassword, setShowPassword] = useState(false);
const toggleShowPassword = () => {
setShowPassword((prevShowPassword) => !prevShowPassword);
};
const [statusTitle, setStatusTitle] = useState('');
const [feedback, setFeedback] = useState('');
const [isSuccessModalOpen, setIsSuccessModalOpen] = useState(false);
const [isErrorModalOpen, setIsErrorModalOpen] = useState(false);
const handleCloseSuccessModal = () => {
setIsSuccessModalOpen(false);
window.location.href = '/login';
};
const submit: FormEventHandler = async (e) => {
e.preventDefault();
try {
const response = await axios.post(route('login'), data);
setStatusTitle('Success')
setFeedback(response.data.message);
setIsSuccessModalOpen(true);
} catch (error) {
setStatusTitle('Error')
if (axios.isAxiosError(error)) {
setFeedback(error.response?.data.message || 'An error occurred');
} else {
setFeedback('An unexpected error occurred');
}
setIsErrorModalOpen(true);
}
};
return (
<GuestLayout>
<Head title="Log in" />
{status && <div className="mb-4 font-medium text-sm text-green-600">{status}</div>}
<div id="Login" className="hero min-h-screen bg-secondary-main">
<div className="hero-content flex-row">
<ProjectBanner />
<div className="card w-104 shrink-0 bg-primary-background">
<div className="card-body justify-center items-center">
<img src="assets/images/img-login.png" alt="An image that represents a login form from StorySet" width="250" height="250" />
<form id="SignInForm" onSubmit={ submit }>
<FormGroup>
<InputLabel htmlFor='username'>
<AtSign className='stroke-neutral-10' />
</InputLabel>
<TextInput
id='username'
name='username'
value={data.username}
autoComplete='off'
placeholder='Username'
required
onChange={(e) => setData('username', e.target.value)}
/>
<InputError message={errors.username} className="mt-2" />
</FormGroup>
<FormGroup>
<InputLabel htmlFor='password'>
<Lock className='stroke-neutral-10' />
</InputLabel>
<TextInput
type={showPassword ? "text" : "password"}
id='password'
name='password'
value={data.password}
autoComplete='off'
placeholder='Password'
required
onChange={(e) => setData('password', e.target.value)}
className='border-r-0'
/>
<label htmlFor="showPassword" className="swap items-center border border-primary-hover border-l-0">
<input type="checkbox" name="showPassword" id="showPassword" onChange={toggleShowPassword} checked={showPassword} className='hidden' />
<Eye className='swap-off px-1 stroke-secondary-main' />
<EyeOff className='swap-on px-1 stroke-secondary-main' />
</label>
<InputError message={errors.password} className="mt-2" />
</FormGroup>
<div className="flex items-center justify-between">
<label className="flex items-center">
<Checkbox
name="remember"
checked={data.remember}
onChange={(e) => setData('remember', e.target.checked)}
/>
<span className="ml-1 text-secondary-main">Remember me</span>
</label>
{canResetPassword && (
<Link
href={route('password.request')}
className="btn btn-link text-secondary-main m-0 p-0"
>
Forgot password...
</Link>
)}
</div>
<div className="flex items-center justify-end mt-4">
<p className="invisible">No account yet? Register instead.</p>
<PrimaryButton type='submit' disabled={processing}>
Log In
<LogIn className='stroke-neutral-10' />
</PrimaryButton>
</div>
</form>
</div>
</div>
</div>
<Modal show={isSuccessModalOpen} onClose={() => setIsSuccessModalOpen(false)} maxWidth="lg" styling='success'>
<div className="p-4 flex flex-col items-center">
<CheckCircle className='stroke-success-main' size={80} />
<h2 className="text-xl font-bold mt-2">{ statusTitle }</h2>
<p className="mt-4">{ feedback }</p>
<ModalButton onClick={handleCloseSuccessModal} className="bg-success-main text-white hover:bg-success-hover active:bg-success-pressed">
Go to Dashboard
</ModalButton>
</div>
</Modal>
<Modal show={isErrorModalOpen} onClose={() => setIsErrorModalOpen(false)} maxWidth="lg" styling='error'>
<div className="p-4 flex flex-col items-center">
<XOctagon className='stroke-error-main' size={80} />
<h2 className="text-xl font-bold mt-2">{ statusTitle }</h2>
<p className="mt-4">{ feedback }</p>
<ModalButton onClick={() => setIsErrorModalOpen(false)} className="bg-error-main text-white hover:bg-error-hover active:bg-error-pressed">
Close
</ModalButton>
</div>
</Modal>
</div>
</GuestLayout>
);
}