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