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