|
|
import { FormEventHandler, Fragment, PropsWithChildren, useEffect, useState } from 'react'; import { Dialog, Transition } from '@headlessui/react'; import { FileText, Box, Info, XCircle, ArrowRightCircle, CheckCircle, XOctagon } from 'react-feather'; import { useForm } from '@inertiajs/react'; import FormGroup from '@/Components/FormGroup'; import InputLabel from '@/Components/InputLabel'; import TextInput from '@/Components/TextInput'; import InputError from '@/Components/InputError'; import ErrorButton from '@/Components/ErrorButton'; import PrimaryButton from '@/Components/PrimaryButton'; import axios from 'axios'; import Modal from '@/Components/Modal'; import ModalButton from '@/Components/ModalButton';
export default function AddCategoryModal({ show = false, maxWidth = '2xl', closeable = true, onClose = () => {}, onCategoryAdded = () => {}, className = '', }: PropsWithChildren<{ show: boolean; maxWidth?: 'sm' | 'md' | 'lg' | 'xl' | '2xl'; closeable?: boolean; onClose: CallableFunction; onCategoryAdded: CallableFunction; className?: string; }>) { const close = () => { if (closeable) { onClose(); } };
const maxWidthClass = { sm: 'sm:max-w-sm', md: 'sm:max-w-md', lg: 'sm:max-w-lg', xl: 'sm:max-w-xl', '2xl': 'sm:max-w-2xl', }[maxWidth];
const { data, setData, errors, reset } = useForm({ subjectTitle: '', description:'', });
useEffect(() => { return () => { reset('subjectTitle'); reset('description'); }; }, []);
const [status, setStatus] = useState(''); const [feedback, setFeedback] = useState(''); const [isSuccessModalOpen, setIsSuccessModalOpen] = useState(false); const [isErrorModalOpen, setIsErrorModalOpen] = useState(false);
const handleCloseSuccessModal = () => { setIsSuccessModalOpen(false); onCategoryAdded(); close(); }
const submit: FormEventHandler = async (e) => { e.preventDefault();
try { const response = await axios.post(route('category.add'), data); setStatus('Success') setFeedback(response.data.message); setIsSuccessModalOpen(true); } catch (error) { setStatus('Error') if (axios.isAxiosError(error)) { setFeedback(error.response?.data.message || 'An error occurred'); } else { setFeedback('An unexpected error occurred'); } setIsErrorModalOpen(true); } };
return ( <Transition show={show} as={Fragment} leave="duration-200"> <Dialog as="div" id="modal" className="fixed inset-0 flex overflow-y-auto px-4 py-6 sm:px-0 items-center z-50 transform transition-all" onClose={close} > <Transition.Child as={Fragment} enter="ease-out duration-300" enterFrom="opacity-0" enterTo="opacity-100" leave="ease-in duration-200" leaveFrom="opacity-100" leaveTo="opacity-0" > <div className="absolute inset-0 bg-neutral-0 opacity-50" /> </Transition.Child>
<Transition.Child as={Fragment} enter="ease-out duration-300" enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" enterTo="opacity-100 translate-y-0 sm:scale-100" leave="ease-in duration-200" leaveFrom="opacity-100 translate-y-0 sm:scale-100" leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" > <Dialog.Panel className={`mb-6 bg-white border-4 rounded-lg overflow-hidden shadow-xl items-center transform transition-all sm:w-full sm:mx-auto bg-neutral-white ${maxWidthClass} ${className}`} > <div className="p-4 flex flex-col"> <h1 className="font-bold text-xl text-primary-main flex items-center my-2"><FileText className="stroke-primary-main mr-2" />Add New Category</h1> <div className="divider"></div>
<form id="AddCategoryForm"> <div> <FormGroup> <InputLabel htmlFor="subjectTitle"><Box className='stroke-neutral-10' /></InputLabel> <label htmlFor="subjectTitle" className="mx-2 font-semibold">Subject Category Title:</label> </FormGroup> <TextInput id='subjectTitle' name='subjectTitle' value={data.subjectTitle} autoComplete='off' required onChange={(e) => setData('subjectTitle', e.target.value)} /> <InputError message={errors.subjectTitle} className="mt-2" /> </div>
<div> <FormGroup> <InputLabel htmlFor="category"><Info className='stroke-neutral-10' /></InputLabel> <label htmlFor="category" className="mx-2 font-semibold">Description:</label> </FormGroup> <textarea className="px-2 flex-grow w-full bg-primary-background border border-primary-hover focus:outline-none focus:bg-neutral-10 focus:border-2 focus:border-primary-hover" onChange={(e) => setData('description', e.target.value)}> </textarea> </div>
<div className='flex items-center justify-center mt-3 w-full'> <ErrorButton type="button" className='w-1/2' onClick={close}> <XCircle className='stroke-neutral-10' /> Cancel </ErrorButton> <PrimaryButton type="button" onClick={submit} className='w-1/2'> <ArrowRightCircle className='stroke-neutral-10' /> Save </PrimaryButton> </div> </form> </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">{ status }</h2> <p className="mt-4">{ feedback }</p> <ModalButton onClick={handleCloseSuccessModal} className="bg-success-main text-white hover:bg-success-hover active:bg-success-pressed"> Close </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">{ status }</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> </Dialog.Panel> </Transition.Child> </Dialog> </Transition> ); }
|