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.

233 lines
12 KiB

  1. import { useEffect, FormEventHandler, useState } from 'react';
  2. import { Head, Link, useForm } from '@inertiajs/react';
  3. import GuestLayout from '@/Layouts/GuestLayout';
  4. import ProjectBanner from '@/Components/ProjectBanner';
  5. import FormGroup from '@/Components/FormGroup';
  6. import InputError from '@/Components/InputError';
  7. import InputLabel from '@/Components/InputLabel';
  8. import TextInput from '@/Components/TextInput';
  9. import PrimaryButton from '@/Components/PrimaryButton';
  10. import { Grid, User, Mail, AtSign, Lock, Eye, EyeOff, LogIn, Unlock, CheckCircle, XOctagon } from 'react-feather';
  11. import axios from 'axios';
  12. import Modal from '@/Components/Modal';
  13. export default function Register() {
  14. const { data, setData, post, processing, errors, reset } = useForm({
  15. emp_id: '',
  16. name: '',
  17. email: '',
  18. username: '',
  19. password: '',
  20. password_confirmation: '',
  21. role_id: ''
  22. });
  23. useEffect(() => {
  24. return () => {
  25. reset('password', 'password_confirmation');
  26. };
  27. }, []);
  28. const [showPassword, setShowPassword] = useState(false);
  29. const toggleShowPassword = () => {
  30. setShowPassword((prevShowPassword) => !prevShowPassword);
  31. };
  32. const [status, setStatus] = useState('');
  33. const [feedback, setFeedback] = useState('');
  34. const [isSuccessModalOpen, setIsSuccessModalOpen] = useState(false);
  35. const [isErrorModalOpen, setIsErrorModalOpen] = useState(false);
  36. const handleCloseSuccessModal = () => {
  37. setIsSuccessModalOpen(false);
  38. window.location.href = '/login';
  39. };
  40. const submit: FormEventHandler = async (e) => {
  41. e.preventDefault();
  42. try {
  43. const response = await axios.post(route('register'), data);
  44. setStatus('Success')
  45. setFeedback(response.data.message);
  46. setIsSuccessModalOpen(true);
  47. } catch (error) {
  48. setStatus('Error')
  49. if (axios.isAxiosError(error)) {
  50. setFeedback(error.response?.data.message || 'An error occurred');
  51. } else {
  52. setFeedback('An unexpected error occurred');
  53. }
  54. setIsErrorModalOpen(true);
  55. }
  56. };
  57. return (
  58. <GuestLayout>
  59. <Head title="Register" />
  60. <div id="Register" className="hero min-h-screen bg-secondary-main">
  61. <div className="hero-content flex-row-reverse">
  62. <ProjectBanner />
  63. <div className="custom-font card w-104 shrink-0 bg-primary-background">
  64. <div className="card-body justify-center items-center">
  65. <img src="assets/images/img-signup.png" alt="An image that represents a sign up form from StorySet" width="250" height="250" />
  66. <form id="SignUpForm" onSubmit={submit}>
  67. <FormGroup>
  68. <InputLabel htmlFor='emp_id'>
  69. <Grid stroke="#FFFFFF" />
  70. </InputLabel>
  71. <TextInput
  72. id='emp_id'
  73. name='emp_id'
  74. value={data.emp_id}
  75. autoComplete='off'
  76. placeholder='Employee ID'
  77. required
  78. onChange={(e) => setData('emp_id', e.target.value)}
  79. className='border-r-0'
  80. />
  81. <InputError message={errors.emp_id} className="mt-2" />
  82. <select name="role_id" id="role_id" value={data.role_id} onChange={(e) => setData('role_id', e.target.value)}
  83. className='px-2 py-0 flex-grow w-full h-[30px] box-border bg-primary-background border border-primary-hover focus:outline-none focus:bg-neutral-10 focus:border focus:border-primary-hover'>
  84. <option value="" selected disabled>Select your role</option>
  85. <option value="1">Admin</option>
  86. <option value="2">Team Leader</option>
  87. <option value="3">Team Member</option>
  88. </select>
  89. </FormGroup>
  90. <FormGroup>
  91. <InputLabel htmlFor='name'>
  92. <User stroke="#FFFFFF" />
  93. </InputLabel>
  94. <TextInput
  95. id='name'
  96. name='name'
  97. value={data.name}
  98. autoComplete='off'
  99. placeholder='Full Name'
  100. required
  101. onChange={(e) => setData('name', e.target.value)}
  102. />
  103. <InputError message={errors.name} className="mt-2" />
  104. </FormGroup>
  105. <FormGroup>
  106. <InputLabel htmlFor='email'>
  107. <Mail stroke="#FFFFFF" />
  108. </InputLabel>
  109. <TextInput
  110. type='email'
  111. id='email'
  112. name='email'
  113. value={data.email}
  114. autoComplete='off'
  115. placeholder='Email Address'
  116. required
  117. onChange={(e) => setData('email', e.target.value)}
  118. />
  119. <InputError message={errors.email} className="mt-2" />
  120. </FormGroup>
  121. <FormGroup>
  122. <InputLabel htmlFor='username'>
  123. <AtSign stroke="#FFFFFF" />
  124. </InputLabel>
  125. <TextInput
  126. id='username'
  127. name='username'
  128. value={data.username}
  129. autoComplete='off'
  130. placeholder='Username'
  131. required
  132. onChange={(e) => setData('username', e.target.value)}
  133. />
  134. <InputError message={errors.username} className="mt-2" />
  135. </FormGroup>
  136. <FormGroup>
  137. <InputLabel htmlFor='password'>
  138. <Lock stroke="#FFFFFF" />
  139. </InputLabel>
  140. <TextInput
  141. type={showPassword ? "text" : "password"}
  142. id='password'
  143. name='password'
  144. value={data.password}
  145. autoComplete='off'
  146. placeholder='Password'
  147. required
  148. onChange={(e) => setData('password', e.target.value)}
  149. className='border-r-0'
  150. />
  151. <label htmlFor="showPassword" className="swap items-center border border-primary-hover border-l-0">
  152. <input type="checkbox" name="showPassword" id="showPassword" onChange={toggleShowPassword} checked={showPassword} className='hidden' />
  153. <Eye stroke='#002F42' className='swap-off px-1' />
  154. <EyeOff stroke='#002F42' className='swap-on px-1' />
  155. </label>
  156. <InputError message={errors.password} className="mt-2" />
  157. </FormGroup>
  158. <FormGroup>
  159. <InputLabel htmlFor='password_confirmation'>
  160. <Unlock stroke="#FFFFFF" />
  161. </InputLabel>
  162. <TextInput
  163. type={"password"}
  164. id='password_confirmation'
  165. name='password_confirmation'
  166. value={data.password_confirmation}
  167. autoComplete='off'
  168. placeholder='Confirm Password'
  169. required
  170. onChange={(e) => setData('password_confirmation', e.target.value)}
  171. />
  172. </FormGroup>
  173. <div className="flex items-center justify-end mt-4">
  174. <Link
  175. href={route('login')}
  176. className="btn btn-link text-secondary-main"
  177. >
  178. Already registered?
  179. </Link>
  180. <PrimaryButton type='submit' disabled={processing}>
  181. Sign Up
  182. <LogIn stroke='#FFFFFF' />
  183. </PrimaryButton>
  184. </div>
  185. </form>
  186. </div>
  187. </div>
  188. </div>
  189. <Modal show={isSuccessModalOpen} onClose={() => setIsSuccessModalOpen(false)} maxWidth="lg" styling='success'>
  190. <div className="p-4 flex flex-col items-center">
  191. <CheckCircle stroke='#007505' size={80} />
  192. <h2 className="text-xl font-bold mt-2">{ status }</h2>
  193. <p className="mt-4">{ feedback }</p>
  194. <button onClick={handleCloseSuccessModal} className="mt-4 w-full btn bg-success-main text-lg text-white hover:bg-success-hover active:bg-success-pressed">
  195. Login Now
  196. </button>
  197. </div>
  198. </Modal>
  199. <Modal show={isErrorModalOpen} onClose={() => setIsErrorModalOpen(false)} maxWidth="lg" styling='error'>
  200. <div className="p-4 flex flex-col items-center">
  201. <XOctagon stroke='#B20000' size={80} />
  202. <h2 className="text-xl font-bold mt-2">{ status }</h2>
  203. <p className="mt-4">{ feedback }</p>
  204. <button onClick={() => setIsErrorModalOpen(false)} className="mt-4 w-full btn bg-error-main text-lg text-white hover:bg-error-hover active:bg-error-pressed">
  205. Close
  206. </button>
  207. </div>
  208. </Modal>
  209. </div>
  210. </GuestLayout>
  211. );
  212. }