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