gitscope
https://dev.kronoz.win/r/marzneshin.git
app/dashboard/src/pages/services/dialog/index.tsx · v0.2.1
Source
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 16e5ea1 Mrdn 2y ago import { useQuery } from '@tanstack/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 16e5ea1 Mrdn 2y ago } = useQuery({ queryKey: [queryIds.inbounds], queryFn: () => 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 };