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.
 
 
 
 

196 lines
8.9 KiB

import { FormEventHandler, Fragment, PropsWithChildren, useEffect, useState } from 'react';
import { Dialog, Transition } from '@headlessui/react';
import { FileText, Box, XCircle, ArrowRightCircle, CheckCircle, XOctagon, Code } 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 AddFrameworkModal({
show = false,
maxWidth = '2xl',
closeable = true,
onClose = () => {},
onFrameworkAdded = () => {},
className = '',
}: PropsWithChildren<{
show: boolean;
maxWidth?: 'sm' | 'md' | 'lg' | 'xl' | '2xl';
closeable?: boolean;
onClose: CallableFunction;
onFrameworkAdded: 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, reset, errors } = useForm({
frameworkName: '',
version:'',
});
useEffect(() => {
return () => {
reset('frameworkName');
reset('version');
};
}, []);
const [status, setStatus] = useState('');
const [feedback, setFeedback] = useState('');
const [isSuccessModalOpen, setIsSuccessModalOpen] = useState(false);
const [isErrorModalOpen, setIsErrorModalOpen] = useState(false);
const handleCloseSuccessModal = () => {
setIsSuccessModalOpen(false);
onFrameworkAdded();
close();
}
const submit: FormEventHandler = async (e) => {
e.preventDefault();
try {
const response = await axios.post(route('framework.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 Framework</h1>
<div className="divider"></div>
<form id="AddFrameworkForm">
<div>
<FormGroup>
<InputLabel htmlFor="frameworkName"><Box className='stroke-neutral-10' /></InputLabel>
<label htmlFor="frameworkName" className="mx-2 font-semibold">App Framework Name:</label>
</FormGroup>
<TextInput
id='frameworkName'
name='frameworkName'
value={data.frameworkName}
autoComplete='off'
required
onChange={(e) => setData('frameworkName', e.target.value)}
/>
<InputError message={errors.frameworkName} className="mt-2" />
</div>
<div>
<FormGroup>
<InputLabel htmlFor="version"><Code className='stroke-neutral-10' /></InputLabel>
<label htmlFor="version" className="mx-2 font-semibold">Version:</label>
</FormGroup>
<TextInput
id='version'
name='version'
value={data.version}
autoComplete='off'
required
onChange={(e) => setData('version', e.target.value)}
/>
<InputError message={errors.version} className="mt-2" />
</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" className='w-1/2' onClick={submit}>
<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>
);
}