1import { type FC, useEffect } from "react";
2import {
3 DialogTitle,
4 DialogContent,
5 Dialog,
6 DialogHeader,
7 Form,
8 FormItem,
9 FormControl,
10 FormMessage,
11 FormLabel,
12 Input,
13 FormField,
14 Button,
15 Select,
16 SelectContent,
17 SelectItem,
18 SelectTrigger,
19 SelectValue,
20 FormDescription,
21 HStack,
22} from "@marzneshin/components";
23import { useTranslation } from "react-i18next";
24import {
25 NodeSchema,
26 useNodesCreationMutation,
27 useNodesUpdateMutation,
28} from "../..";
29import type { NodeType } from "../..";
30import { useMutationDialog } from "@marzneshin/hooks";
31
32interface MutationDialogProps {
33 entity: NodeType | null;
34 open: boolean;
35 onOpenChange: (state: boolean) => void;
36 onClose: () => void;
37}
38
39const getDefaultValue = (): NodeType => ({
40 name: "",
41 address: "",
42 status: "none",
43 port: 62050,
44 usage_coefficient: 1,
45 connection_backend: "grpclib",
46});
47
48export const MutationDialog: FC<MutationDialogProps> = ({
49 entity,
50 open,
51 onOpenChange,
52 onClose,
53}) => {
54 const updateMutation = useNodesUpdateMutation();
55 const createMutation = useNodesCreationMutation();
56 const { t } = useTranslation();
57 const { form, handleSubmit } = useMutationDialog({
58 onOpenChange,
59 entity,
60 schema: NodeSchema,
61 createMutation,
62 updateMutation,
63 getDefaultValue,
64 });
65
66 useEffect(() => {
67 if (!open) onClose();
68 }, [open, onClose]);
69
70 return (
71 <Dialog open={open} onOpenChange={onOpenChange} defaultOpen={true}>
72 <DialogContent>
73 <DialogHeader>
74 <DialogTitle className="text-primary">
75 {entity
76 ? t("page.nodes.dialogs.edition.title")
77 : t("page.nodes.dialogs.creation.title")}
78 </DialogTitle>
79 </DialogHeader>
80 <Form {...form}>
81 <form onSubmit={handleSubmit}>
82 <FormField
83 control={form.control}
84 name="name"
85 render={({ field }) => (
86 <FormItem className="w-full">
87 <FormLabel>{t("name")}</FormLabel>
88 <FormControl>
89 <Input {...field} />
90 </FormControl>
91 <FormMessage />
92 </FormItem>
93 )}
94 />
95 <div className="flex flex-row gap-2 items-center">
96 <FormField
97 control={form.control}
98 name="address"
99 render={({ field }) => (
100 <FormItem className="w-2/3">
101 <FormLabel>{t("address")}</FormLabel>
102 <FormControl>
103 <Input {...field} />
104 </FormControl>
105 <FormMessage />
106 </FormItem>
107 )}
108 />
109 <FormField
110 control={form.control}
111 name="port"
112 render={({ field }) => (
113 <FormItem className="w-1/3">
114 <FormLabel>{t("port")}</FormLabel>
115 <FormControl>
116 <Input type="number" {...field} />
117 </FormControl>
118 <FormMessage />
119 </FormItem>
120 )}
121 />
122 </div>
123 <HStack>
124 <FormField
125 control={form.control}
126 name="connection_backend"
127 render={({ field }) => (
128 <FormItem className="w-full">
129 <FormLabel>{t("page.nodes.connection_backend")}</FormLabel>
130 <Select
131 onValueChange={field.onChange}
132 defaultValue={field.value}
133 >
134 <FormControl>
135 <SelectTrigger>
136 <SelectValue placeholder="Nodes Connection" />
137 </SelectTrigger>
138 </FormControl>
139 <SelectContent>
140 <SelectItem value="grpclib">grpclib</SelectItem>
141 <SelectItem value="grpcio">grpcio</SelectItem>
142 </SelectContent>
143 </Select>
144 <FormDescription>
145 {t("page.nodes.connection_backend_desc")}
146 </FormDescription>
147 <FormMessage />
148 </FormItem>
149 )}
150 />
151 <FormField
152 control={form.control}
153 name="usage_coefficient"
154 render={({ field }) => (
155 <FormItem className="w-1/2">
156 <FormLabel>{t("page.nodes.usage_coefficient")}</FormLabel>
157 <FormControl>
158 <Input {...field} />
159 </FormControl>
160 <FormMessage />
161 </FormItem>
162 )}
163 />
164 </HStack>
165 <Button
166 className="mt-3 w-full font-semibold"
167 type="submit"
168 disabled={form.formState.isSubmitting}
169 >
170 {t("submit")}
171 </Button>
172 </form>
173 </Form>
174 </DialogContent>
175 </Dialog>
176 );
177};