diff --git a/web/src/pages/ansible/nginx/components/hosts-field.tsx b/web/src/pages/ansible/nginx/components/hosts-field.tsx new file mode 100644 index 00000000..33e1f399 --- /dev/null +++ b/web/src/pages/ansible/nginx/components/hosts-field.tsx @@ -0,0 +1,46 @@ +import { FormInput } from '@/components/form/form-input'; +import { Plus, Trash2 } from 'lucide-react'; +import { FC } from 'react'; +import { useFieldArray, useFormContext } from 'react-hook-form'; + +const HostsField: FC = () => { + const { control } = useFormContext(); + + const { fields, append, remove } = useFieldArray({ + control, + name: 'hosts', + }); + + return ( +
+
+

Hosts

+ +
+
+ {fields.map((_, hostIdx) => ( +
+ + {hostIdx > 0 && ( + + )} +
+ ))} +
+
+ ); +}; + +export default HostsField; diff --git a/web/src/pages/ansible/nginx/nginx.tsx b/web/src/pages/ansible/nginx/nginx.tsx index 3544aa8c..23f69fae 100644 --- a/web/src/pages/ansible/nginx/nginx.tsx +++ b/web/src/pages/ansible/nginx/nginx.tsx @@ -1,7 +1,125 @@ +import { zodResolver } from '@hookform/resolvers/zod'; import { FC } from 'react'; +import { useForm } from 'react-hook-form'; +import { + NginxAnsibleBody, + NginxAnsibleResponse, + nginxAnsibleSchema, + nginxTemplateValidationError, +} from './nginx.types'; +import { AnsibleTemplateAPI } from '@/enums/api.enums'; +import { usePost } from '@/core/react-query'; +import { useDownload } from '@/hooks'; +import { isAxiosError } from 'axios'; +import { toast } from 'sonner'; +import { FormWrapper } from '@/components/form/form-wrapper'; +import { FormInput } from '@/components/form/form-input'; +import { FormSelect } from '@/components/form/form-select'; +import HostsField from './components/hosts-field'; +import { OSOptions } from './data/select-options'; +import type { NginxAnsible } from './nginx.types'; const NginxAnsible: FC = () => { - return <>Nginx; + const defaultValues = { + ansible_user: '', + os: { label: 'Ubuntu', value: 'ubuntu' }, + hosts: [{ value: '' }], + version: '', + }; + + const methods = useForm({ + resolver: zodResolver(nginxAnsibleSchema), + defaultValues, + }); + + const { mutateAsync: nginxAnsibleMutate, isPending: nginxAnsiblePending } = + usePost( + AnsibleTemplateAPI.Nginx, + 'ansible-nginx', + ); + + const { download, isPending: downloadPending } = useDownload({ + downloadFileName: 'NginxAnsible', + source: 'nginx', + folderName: 'MyAnsible', + }); + + const handleSubmit = async (data: NginxAnsible) => { + try { + const body = { + ...data, + hosts: data.hosts.map((host) => host.value), + os: data.os.value, + }; + + await nginxAnsibleMutate(body); + await download(); + } catch (error) { + console.log(error); + if (isAxiosError(error)) { + toast.error( + `${error.response?.data.detail[0].loc[error.response?.data.detail[0].loc.length - 1]} ${error.response?.data.detail[0].msg}`, + ); + } else { + toast.error('Something went wrong'); + } + } + }; + + return ( +
+ +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+ +
+
+ ); }; export default NginxAnsible; diff --git a/web/src/pages/ansible/nginx/nginx.types.ts b/web/src/pages/ansible/nginx/nginx.types.ts new file mode 100644 index 00000000..0ba1f355 --- /dev/null +++ b/web/src/pages/ansible/nginx/nginx.types.ts @@ -0,0 +1,45 @@ +import { z as zod } from 'zod'; + +export interface NginxAnsibleResponse { + output: string; +} + +export interface NginxAnsibleBody { + ansible_user: string; + ansible_port: number; + os: string; + hosts: string[]; + version: string; +} + +export interface nginxTemplateValidationError { + detail: [ + { + type: string; + loc: string[]; + msg: string; + input: null; + }, + ]; +} + +export const nginxAnsibleSchema = zod.object({ + ansible_user: zod.string().min(1, 'User is required!'), + ansible_port: zod + .number({ invalid_type_error: 'Port is required!' }) + .min(1, 'Port is required!'), + os: zod.object({ + label: zod.string(), + value: zod.string(), + }), + hosts: zod + .array( + zod.object({ + value: zod.string().min(1, 'Host is required!'), + }), + ) + .min(1), + version: zod.string().min(1, 'Version is required!'), +}); + +export type NginxAnsible = zod.infer;