| 1 |
912788f |
Mardin |
2y ago |
|
| 2 |
912788f |
Mardin |
2y ago |
import { |
| 3 |
912788f |
Mardin |
2y ago |
Alert, |
| 4 |
912788f |
Mardin |
2y ago |
AlertIcon, |
| 5 |
912788f |
Mardin |
2y ago |
Flex, |
| 6 |
912788f |
Mardin |
2y ago |
Button, |
| 7 |
912788f |
Mardin |
2y ago |
Tooltip, |
| 8 |
912788f |
Mardin |
2y ago |
HStack, |
| 9 |
912788f |
Mardin |
2y ago |
Spinner, |
| 10 |
912788f |
Mardin |
2y ago |
ModalBody, |
| 11 |
912788f |
Mardin |
2y ago |
ModalCloseButton, |
| 12 |
912788f |
Mardin |
2y ago |
ModalContent, |
| 13 |
912788f |
Mardin |
2y ago |
Modal, |
| 14 |
912788f |
Mardin |
2y ago |
VStack, |
| 15 |
912788f |
Mardin |
2y ago |
useToast, |
| 16 |
912788f |
Mardin |
2y ago |
ModalOverlay, |
| 17 |
912788f |
Mardin |
2y ago |
IconButton, |
| 18 |
912788f |
Mardin |
2y ago |
} from '@chakra-ui/react'; |
| 19 |
912788f |
Mardin |
2y ago |
import { zodResolver } from '@hookform/resolvers/zod'; |
| 20 |
912788f |
Mardin |
2y ago |
import { FC, useEffect, useState } from 'react'; |
| 21 |
912788f |
Mardin |
2y ago |
import { FormProvider, useForm } from 'react-hook-form'; |
| 22 |
912788f |
Mardin |
2y ago |
import { useTranslation } from 'react-i18next'; |
| 23 |
5825ea4 |
Mardin |
2y ago |
import { |
| 24 |
5825ea4 |
Mardin |
2y ago |
AddIcon, |
| 25 |
5825ea4 |
Mardin |
2y ago |
DialogModalHeader, |
| 26 |
5825ea4 |
Mardin |
2y ago |
DialogModalFooter, |
| 27 |
5825ea4 |
Mardin |
2y ago |
DeleteIcon, |
| 28 |
5825ea4 |
Mardin |
2y ago |
EditIcon |
| 29 |
5825ea4 |
Mardin |
2y ago |
} from 'components/dialog'; |
| 30 |
bedeeff |
Mardin |
2y ago |
import { getDefaultValues } from './default-values'; |
| 31 |
bedeeff |
Mardin |
2y ago |
import { schema, FormType } from './form-schema'; |
| 32 |
bedeeff |
Mardin |
2y ago |
import { InboundsField } from './inbounds-field'; |
| 33 |
bedeeff |
Mardin |
2y ago |
import { NameField } from './name-field'; |
| 34 |
89f8f93 |
Mardin |
2y ago |
import { InboundType, Service, ServiceCreate } from 'types'; |
| 35 |
a61ba53 |
Mrdn |
2y ago |
import { fetchInbounds, useInbounds, useServices } from 'stores'; |
| 36 |
a61ba53 |
Mrdn |
2y ago |
import { useQuery } from 'react-query'; |
| 37 |
a61ba53 |
Mrdn |
2y ago |
import { queryIds } from 'constants/query-ids'; |
| 38 |
912788f |
Mardin |
2y ago |
|
| 39 |
912788f |
Mardin |
2y ago |
const formatService = (service: Service): FormType => { |
| 40 |
912788f |
Mardin |
2y ago |
const inbounds: number[] = service.inbounds.map((inbound: number | InboundType): number => { |
| 41 |
912788f |
Mardin |
2y ago |
return (typeof inbound !== 'number') ? inbound.id : inbound; |
| 42 |
912788f |
Mardin |
2y ago |
}); |
| 43 |
912788f |
Mardin |
2y ago |
return { |
| 44 |
912788f |
Mardin |
2y ago |
...service, |
| 45 |
912788f |
Mardin |
2y ago |
inbounds, |
| 46 |
912788f |
Mardin |
2y ago |
}; |
| 47 |
912788f |
Mardin |
2y ago |
}; |
| 48 |
912788f |
Mardin |
2y ago |
|
| 49 |
912788f |
Mardin |
2y ago |
export type ServiceDialogProps = {}; |
| 50 |
912788f |
Mardin |
2y ago |
|
| 51 |
912788f |
Mardin |
2y ago |
export const ServiceDialog: FC<ServiceDialogProps> = () => { |
| 52 |
912788f |
Mardin |
2y ago |
const { |
| 53 |
912788f |
Mardin |
2y ago |
editingService, |
| 54 |
912788f |
Mardin |
2y ago |
isCreatingNewService, |
| 55 |
912788f |
Mardin |
2y ago |
onCreateService, |
| 56 |
912788f |
Mardin |
2y ago |
editService, |
| 57 |
912788f |
Mardin |
2y ago |
onEditingService, |
| 58 |
912788f |
Mardin |
2y ago |
createService, |
| 59 |
912788f |
Mardin |
2y ago |
onDeletingService, |
| 60 |
4205669 |
Mardin |
2y ago |
} = useServices(); |
| 61 |
a61ba53 |
Mrdn |
2y ago |
const { refetchInbounds } = useInbounds(); |
| 62 |
4205669 |
Mardin |
2y ago |
const { |
| 63 |
a61ba53 |
Mrdn |
2y ago |
data: inbounds, |
| 64 |
a61ba53 |
Mrdn |
2y ago |
} = useQuery(queryIds.inbounds, () => fetchInbounds()); |
| 65 |
912788f |
Mardin |
2y ago |
const isEditing = !!editingService; |
| 66 |
912788f |
Mardin |
2y ago |
const isOpen = isCreatingNewService || isEditing; |
| 67 |
912788f |
Mardin |
2y ago |
const [loading, setLoading] = useState(false); |
| 68 |
912788f |
Mardin |
2y ago |
const [error, setError] = useState<string | null>(''); |
| 69 |
912788f |
Mardin |
2y ago |
const toast = useToast(); |
| 70 |
912788f |
Mardin |
2y ago |
const { t } = useTranslation(); |
| 71 |
912788f |
Mardin |
2y ago |
|
| 72 |
912788f |
Mardin |
2y ago |
const form = useForm<FormType>({ |
| 73 |
912788f |
Mardin |
2y ago |
defaultValues: getDefaultValues(), |
| 74 |
912788f |
Mardin |
2y ago |
resolver: zodResolver(schema), |
| 75 |
912788f |
Mardin |
2y ago |
}); |
| 76 |
912788f |
Mardin |
2y ago |
|
| 77 |
912788f |
Mardin |
2y ago |
useEffect(() => { |
| 78 |
912788f |
Mardin |
2y ago |
if (isOpen) { |
| 79 |
912788f |
Mardin |
2y ago |
refetchInbounds(); |
| 80 |
be72a83 |
Mardin |
2y ago |
form.reset(); |
| 81 |
912788f |
Mardin |
2y ago |
} |
| 82 |
912788f |
Mardin |
2y ago |
}, [isOpen]); |
| 83 |
912788f |
Mardin |
2y ago |
|
| 84 |
912788f |
Mardin |
2y ago |
|
| 85 |
912788f |
Mardin |
2y ago |
useEffect(() => { |
| 86 |
912788f |
Mardin |
2y ago |
if (editingService) { |
| 87 |
912788f |
Mardin |
2y ago |
form.reset(formatService(editingService)); |
| 88 |
912788f |
Mardin |
2y ago |
} |
| 89 |
912788f |
Mardin |
2y ago |
}, [editingService]); |
| 90 |
912788f |
Mardin |
2y ago |
|
| 91 |
912788f |
Mardin |
2y ago |
const submit = async (values: FormType) => { |
| 92 |
912788f |
Mardin |
2y ago |
setLoading(true); |
| 93 |
912788f |
Mardin |
2y ago |
const methods = { edited: editService, created: createService }; |
| 94 |
912788f |
Mardin |
2y ago |
const method = isEditing ? 'edited' : 'created'; |
| 95 |
912788f |
Mardin |
2y ago |
setError(null); |
| 96 |
912788f |
Mardin |
2y ago |
const { inbounds, name } = values; |
| 97 |
912788f |
Mardin |
2y ago |
|
| 98 |
123de7e |
Mardin |
2y ago |
let body: ServiceCreate = { name, inbounds, id: editingService?.id }; |
| 99 |
912788f |
Mardin |
2y ago |
|
| 100 |
912788f |
Mardin |
2y ago |
await methods[method](body) |
| 101 |
912788f |
Mardin |
2y ago |
.then(() => { |
| 102 |
912788f |
Mardin |
2y ago |
toast({ |
| 103 |
912788f |
Mardin |
2y ago |
title: t( |
| 104 |
912788f |
Mardin |
2y ago |
isEditing ? 'serviceDialog.serviceEdited' : 'serviceDialog.serviceCreated', |
| 105 |
912788f |
Mardin |
2y ago |
{ name: values.name } |
| 106 |
912788f |
Mardin |
2y ago |
), |
| 107 |
912788f |
Mardin |
2y ago |
status: 'success', |
| 108 |
912788f |
Mardin |
2y ago |
isClosable: true, |
| 109 |
912788f |
Mardin |
2y ago |
position: 'top', |
| 110 |
912788f |
Mardin |
2y ago |
duration: 3000, |
| 111 |
912788f |
Mardin |
2y ago |
}); |
| 112 |
912788f |
Mardin |
2y ago |
onClose(); |
| 113 |
912788f |
Mardin |
2y ago |
}) |
| 114 |
912788f |
Mardin |
2y ago |
.catch((err) => { |
| 115 |
912788f |
Mardin |
2y ago |
if (err?.response?.status === 409 || err?.response?.status === 400) |
| 116 |
912788f |
Mardin |
2y ago |
setError(err?.response?._data?.detail); |
| 117 |
912788f |
Mardin |
2y ago |
if (err?.response?.status === 422) { |
| 118 |
912788f |
Mardin |
2y ago |
Object.keys(err.response._data.detail).forEach((key) => { |
| 119 |
912788f |
Mardin |
2y ago |
setError(err?.response._data.detail[key] as string); |
| 120 |
912788f |
Mardin |
2y ago |
form.setError(key as 'name' | 'inbounds', { type: 'custom', message: err.response._data.detail[key], }); |
| 121 |
912788f |
Mardin |
2y ago |
}); |
| 122 |
912788f |
Mardin |
2y ago |
} |
| 123 |
912788f |
Mardin |
2y ago |
}) |
| 124 |
912788f |
Mardin |
2y ago |
.finally(() => { |
| 125 |
912788f |
Mardin |
2y ago |
setLoading(false); |
| 126 |
912788f |
Mardin |
2y ago |
}); |
| 127 |
912788f |
Mardin |
2y ago |
}; |
| 128 |
912788f |
Mardin |
2y ago |
|
| 129 |
912788f |
Mardin |
2y ago |
const onClose = () => { |
| 130 |
912788f |
Mardin |
2y ago |
form.reset(getDefaultValues()); |
| 131 |
912788f |
Mardin |
2y ago |
onCreateService(false); |
| 132 |
912788f |
Mardin |
2y ago |
onEditingService(null); |
| 133 |
912788f |
Mardin |
2y ago |
setError(null); |
| 134 |
912788f |
Mardin |
2y ago |
}; |
| 135 |
912788f |
Mardin |
2y ago |
|
| 136 |
912788f |
Mardin |
2y ago |
const disabled = loading; |
| 137 |
912788f |
Mardin |
2y ago |
|
| 138 |
912788f |
Mardin |
2y ago |
return ( |
| 139 |
2ae554f |
Mardin |
2y ago |
<Modal isOpen={isOpen} onClose={onClose} size="lg"> |
| 140 |
912788f |
Mardin |
2y ago |
<ModalOverlay bg="blackAlpha.300" backdropFilter="blur(10px)" /> |
| 141 |
912788f |
Mardin |
2y ago |
<FormProvider {...form} formState={form.formState}> |
| 142 |
912788f |
Mardin |
2y ago |
<ModalContent mx="3"> |
| 143 |
912788f |
Mardin |
2y ago |
<form onSubmit={form.handleSubmit(submit)}> |
| 144 |
912788f |
Mardin |
2y ago |
<DialogModalHeader HeaderIcon={isEditing ? EditIcon : AddIcon} title={isEditing ? t('serviceDialog.editServiceTitle') : t('serviceDialog.createNewService')} /> |
| 145 |
912788f |
Mardin |
2y ago |
<ModalCloseButton mt={3} disabled={disabled} /> |
| 146 |
912788f |
Mardin |
2y ago |
<ModalBody> |
| 147 |
912788f |
Mardin |
2y ago |
<VStack justifyContent="space-between"> |
| 148 |
912788f |
Mardin |
2y ago |
<Flex |
| 149 |
912788f |
Mardin |
2y ago |
flexDirection="column" |
| 150 |
912788f |
Mardin |
2y ago |
gridAutoRows="min-content" |
| 151 |
912788f |
Mardin |
2y ago |
w="full" |
| 152 |
912788f |
Mardin |
2y ago |
> |
| 153 |
912788f |
Mardin |
2y ago |
<NameField form={form} disabled={disabled} isEditing={isEditing} t={t} /> |
| 154 |
a61ba53 |
Mrdn |
2y ago |
<InboundsField t={t} inbounds={inbounds || []} form={form} /> |
| 155 |
912788f |
Mardin |
2y ago |
</Flex> |
| 156 |
912788f |
Mardin |
2y ago |
{error && ( |
| 157 |
912788f |
Mardin |
2y ago |
<Alert |
| 158 |
912788f |
Mardin |
2y ago |
status="error" |
| 159 |
912788f |
Mardin |
2y ago |
display={{ base: 'none', md: 'flex' }} |
| 160 |
912788f |
Mardin |
2y ago |
> |
| 161 |
912788f |
Mardin |
2y ago |
<AlertIcon /> |
| 162 |
912788f |
Mardin |
2y ago |
{error} |
| 163 |
912788f |
Mardin |
2y ago |
</Alert> |
| 164 |
912788f |
Mardin |
2y ago |
)} |
| 165 |
912788f |
Mardin |
2y ago |
</VStack> |
| 166 |
912788f |
Mardin |
2y ago |
{error && ( |
| 167 |
912788f |
Mardin |
2y ago |
<Alert |
| 168 |
912788f |
Mardin |
2y ago |
mt="3" |
| 169 |
912788f |
Mardin |
2y ago |
status="error" |
| 170 |
912788f |
Mardin |
2y ago |
display={{ base: 'flex', md: 'none' }} |
| 171 |
912788f |
Mardin |
2y ago |
> |
| 172 |
912788f |
Mardin |
2y ago |
<AlertIcon /> |
| 173 |
912788f |
Mardin |
2y ago |
{error} |
| 174 |
912788f |
Mardin |
2y ago |
</Alert> |
| 175 |
912788f |
Mardin |
2y ago |
)} |
| 176 |
912788f |
Mardin |
2y ago |
</ModalBody> |
| 177 |
912788f |
Mardin |
2y ago |
<DialogModalFooter> |
| 178 |
912788f |
Mardin |
2y ago |
<HStack |
| 179 |
912788f |
Mardin |
2y ago |
justifyContent="flex-start" |
| 180 |
912788f |
Mardin |
2y ago |
w={{ |
| 181 |
912788f |
Mardin |
2y ago |
base: 'full', |
| 182 |
912788f |
Mardin |
2y ago |
sm: 'unset', |
| 183 |
912788f |
Mardin |
2y ago |
}} |
| 184 |
912788f |
Mardin |
2y ago |
> |
| 185 |
912788f |
Mardin |
2y ago |
{isEditing && editingService !== null && ( |
| 186 |
912788f |
Mardin |
2y ago |
<> |
| 187 |
912788f |
Mardin |
2y ago |
<Tooltip label={t('delete')} placement="top"> |
| 188 |
912788f |
Mardin |
2y ago |
<IconButton |
| 189 |
912788f |
Mardin |
2y ago |
aria-label="Delete" |
| 190 |
912788f |
Mardin |
2y ago |
size="sm" |
| 191 |
912788f |
Mardin |
2y ago |
onClick={() => { |
| 192 |
912788f |
Mardin |
2y ago |
onDeletingService(editingService); |
| 193 |
912788f |
Mardin |
2y ago |
onClose(); |
| 194 |
912788f |
Mardin |
2y ago |
}} |
| 195 |
912788f |
Mardin |
2y ago |
> |
| 196 |
912788f |
Mardin |
2y ago |
<DeleteIcon /> |
| 197 |
912788f |
Mardin |
2y ago |
</IconButton> |
| 198 |
912788f |
Mardin |
2y ago |
</Tooltip> |
| 199 |
912788f |
Mardin |
2y ago |
</> |
| 200 |
912788f |
Mardin |
2y ago |
)} |
| 201 |
912788f |
Mardin |
2y ago |
</HStack> |
| 202 |
912788f |
Mardin |
2y ago |
<HStack |
| 203 |
912788f |
Mardin |
2y ago |
w="full" |
| 204 |
912788f |
Mardin |
2y ago |
maxW={{ md: '50%', base: 'full' }} |
| 205 |
912788f |
Mardin |
2y ago |
justify="end" |
| 206 |
912788f |
Mardin |
2y ago |
> |
| 207 |
912788f |
Mardin |
2y ago |
<Button |
| 208 |
912788f |
Mardin |
2y ago |
type="submit" |
| 209 |
912788f |
Mardin |
2y ago |
size="sm" |
| 210 |
912788f |
Mardin |
2y ago |
px="8" |
| 211 |
912788f |
Mardin |
2y ago |
colorScheme="primary" |
| 212 |
912788f |
Mardin |
2y ago |
leftIcon={loading ? <Spinner size="xs" /> : undefined} |
| 213 |
912788f |
Mardin |
2y ago |
disabled={false} |
| 214 |
912788f |
Mardin |
2y ago |
> |
| 215 |
912788f |
Mardin |
2y ago |
{isEditing ? t('serviceDialog.editService') : t('createService')} |
| 216 |
912788f |
Mardin |
2y ago |
</Button> |
| 217 |
912788f |
Mardin |
2y ago |
</HStack> |
| 218 |
912788f |
Mardin |
2y ago |
</DialogModalFooter> |
| 219 |
912788f |
Mardin |
2y ago |
</form> |
| 220 |
912788f |
Mardin |
2y ago |
</ModalContent> |
| 221 |
912788f |
Mardin |
2y ago |
</FormProvider> |
| 222 |
912788f |
Mardin |
2y ago |
</Modal > |
| 223 |
912788f |
Mardin |
2y ago |
); |
| 224 |
912788f |
Mardin |
2y ago |
}; |