1import { FC, useCallback, useEffect, useState } from "react";
2import {
3 DialogTitle,
4 DialogContent,
5 Dialog,
6 DialogHeader,
7 Form,
8 Button,
9 Tabs,
10 TabsTrigger,
11 TabsContent,
12 FormLabel
13} from '@marzneshin/components';
14import { useTranslation } from 'react-i18next';
15import {
16 UserMutationType,
17 useUsersCreationMutation,
18 useUsersUpdateMutation
19} from "@marzneshin/features/users";
20import { UserSchema } from "./schema";
21import {
22 UsernameField,
23 DataLimitField,
24 ExpireDateField,
25 DataLimitResetStrategyField,
26 NoteField,
27 ServicesField,
28} from "./fields";
29import { useMutationDialog } from "@marzneshin/hooks";
30import { TabsList } from "@radix-ui/react-tabs";
31import { OnHoldExpireDurationField } from "./fields/onhold-expire-duration";
32import { OnHoldTimeoutField } from "./fields/onhold-timeout";
33
34interface UsersMutationDialogProps {
35 entity: UserMutationType | null;
36 open: boolean;
37 onOpenChange: (state: boolean) => void;
38}
39
40export const UsersMutationDialog: FC<UsersMutationDialogProps> = ({
41 entity,
42 open,
43 onOpenChange,
44}) => {
45 const { t } = useTranslation();
46 const getDefaultValues = useCallback((): UserMutationType => ({
47 services: [],
48 data_limit: 1,
49 expire: null,
50 username: '',
51 data_limit_reset_strategy: 'no_reset',
52 status: 'active',
53 note: '',
54 on_hold_expire_duration: 0,
55 on_hold_timeout: undefined,
56 }), []);
57
58
59 const { form, handleSubmit } = useMutationDialog({
60 entity,
61 onOpenChange,
62 createMutation: useUsersCreationMutation(),
63 updateMutation: useUsersUpdateMutation(),
64 schema: UserSchema,
65 getDefaultValue: getDefaultValues,
66 })
67
68 const [
69 selectedDataLimitTab,
70 setSelectedDataLimitTab
71 ] = useState<'limited' | 'unlimited' | string>('limited');
72 useEffect(() => {
73 if (selectedDataLimitTab === 'limited') {
74 form.setValue("data_limit", 1)
75 form.setValue("data_limit_reset_strategy", "no_reset");
76 } else {
77 form.setValue("data_limit", 0)
78 form.setValue("data_limit_reset_strategy", "no_reset");
79 }
80 }, [selectedDataLimitTab, form]);
81
82 const getUserExpirationMethod = useCallback((entity: UserMutationType) => {
83 if (entity.status === "on_hold")
84 return 'onhold'
85 else if (entity.expire !== undefined)
86 return 'determined'
87 else
88 return 'unlimited'
89 }, [])
90
91 const defaultExpirationMethodTab = entity?.username ? getUserExpirationMethod(entity) : 'determined'
92 const [
93 selectedExpirationMethodTab,
94 setSelectedExpirationMethodTab
95 ] = useState<'determined' | 'onhold' | 'unlimited' | string>(defaultExpirationMethodTab);
96
97 useEffect(() => {
98 form.setValue("status", "active")
99 if (selectedExpirationMethodTab === 'onhold') {
100 form.setValue("status", "on_hold")
101 form.setValue("expire", null);
102 form.clearErrors("expire");
103 } else if (selectedExpirationMethodTab === "unlimited") {
104 form.setValue("expire", undefined);
105 form.setValue("on_hold_expire_duration", undefined);
106 form.setValue("on_hold_timeout", undefined);
107 form.clearErrors("expire");
108 form.clearErrors("on_hold_expire_duration");
109 form.clearErrors("on_hold_timeout");
110 } else {
111 form.setValue("on_hold_expire_duration", 0);
112 form.setValue("on_hold_timeout", null);
113 form.clearErrors("on_hold_expire_duration");
114 form.clearErrors("on_hold_timeout");
115 }
116 }, [selectedExpirationMethodTab, form]);
117
118 return (
119 <Dialog open={open} onOpenChange={onOpenChange} defaultOpen={true}>
120 <DialogContent className="sm:max-w-full md:max-w-[600px]">
121 <DialogHeader>
122 <DialogTitle className="text-primary">
123 {entity
124 ? t('page.users.dialogs.edition.title')
125 : t('page.users.dialogs.creation.title')}
126 </DialogTitle>
127 </DialogHeader>
128 <Form {...form}>
129 <form onSubmit={handleSubmit}>
130 <div className="flex-col grid-cols-2 gap-2 sm:flex md:grid">
131 <div>
132 <UsernameField />
133 <FormLabel>
134 {t('page.users.data_limit_method')}
135 </FormLabel>
136 <div className="flex gap-2 items-center w-full sm:flex-row md:flex-col">
137 <Tabs defaultValue="limited" onValueChange={setSelectedDataLimitTab} className="mt-2 w-full">
138 <TabsList className="flex flex-row items-center p-1 w-full rounded-md bg-accent">
139 <TabsTrigger
140 className="w-full"
141 value="limited">
142 {t('page.users.limited')}
143 </TabsTrigger>
144 <TabsTrigger
145 className="w-full"
146 value="unlimited">
147 {t('page.users.unlimited')}
148 </TabsTrigger>
149 </TabsList>
150 <TabsContent value="limited">
151 <DataLimitField />
152 {form.watch().data_limit !== 0 && <DataLimitResetStrategyField />}
153 </TabsContent>
154 </Tabs>
155 </div>
156 <FormLabel>
157 {t('page.users.expire_method')}
158 </FormLabel>
159 <Tabs defaultValue={defaultExpirationMethodTab} onValueChange={setSelectedExpirationMethodTab} className="mt-2 w-full">
160 <TabsList className="flex flex-row items-center p-1 w-full rounded-md bg-accent">
161 <TabsTrigger
162 className="w-full"
163 value="determined">
164 {t('page.users.determined_expire')}
165 </TabsTrigger>
166 <TabsTrigger
167 className="w-full"
168 value="onhold">
169 {t('page.users.onhold_expire')}
170 </TabsTrigger>
171 <TabsTrigger
172 className="w-full"
173 value="unlimited">
174 {t('page.users.unlimited')}
175 </TabsTrigger>
176 </TabsList>
177 <TabsContent value="determined">
178 <ExpireDateField />
179 </TabsContent>
180 <TabsContent value="onhold">
181 <OnHoldExpireDurationField />
182 <OnHoldTimeoutField />
183 </TabsContent>
184 </Tabs>
185 <NoteField />
186 </div>
187 <div>
188 <ServicesField />
189 </div>
190 </div>
191 <Button
192 className="mt-3 w-full font-semibold"
193 type="submit"
194 disabled={form.formState.isSubmitting}
195 >
196 {t('submit')}
197 </Button>
198 </form>
199 </Form>
200 </DialogContent>
201 </Dialog>
202 );
203};