gitscope
← marzneshin / v0.3.0-alpha2 / 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} from '@marzneshin/components';
 13import { useTranslation } from 'react-i18next';
 14import {
 15    UserMutationType,
 16    useUsersCreationMutation,
 17    useUsersUpdateMutation
 18} from "@marzneshin/features/users";
 19import { UserSchema } from "./schema";
 20import {
 21    UsernameField,
 22    DataLimitField,
 23    ExpireDateField,
 24    DataLimitResetStrategyField,
 25    NoteField,
 26    ServicesField,
 27} from "./fields";
 28import { useMutationDialog } from "@marzneshin/hooks";
 29import { TabsList } from "@radix-ui/react-tabs";
 30import { OnHoldExpireDurationField } from "./fields/onhold-expire-duration";
 31import { OnHoldTimeoutField } from "./fields/onhold-timeout";
 32
 33interface UsersMutationDialogProps {
 34    entity: UserMutationType | null;
 35    open: boolean;
 36    onOpenChange: (state: boolean) => void;
 37}
 38
 39export const UsersMutationDialog: FC<UsersMutationDialogProps> = ({
 40    entity,
 41    open,
 42    onOpenChange,
 43}) => {
 44    const { t } = useTranslation();
 45    const getDefaultValues = useCallback((): UserMutationType => ({
 46        services: [],
 47        data_limit: 0,
 48        expire: null,
 49        username: '',
 50        data_limit_reset_strategy: 'no_reset',
 51        status: 'active',
 52        note: '',
 53        on_hold_expire_duration: 0,
 54        on_hold_timeout: null,
 55    }), []);
 56
 57    const [services, setServices] = useState<number[]>(entity ? entity.services : [])
 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    useEffect(() => {
 69        form.setValue("services", services.map(Number).filter(item => typeof item === 'number'))
 70    }, [services, form])
 71
 72
 73    const [selectedTab, setSelectedTab] = useState<'determined' | 'onhold' | string>('determined');
 74
 75    useEffect(() => {
 76        if (selectedTab === 'onhold') {
 77            form.setValue("status", "on_hold")
 78            form.setValue("expire", null);
 79            form.clearErrors("expire");
 80        } else {
 81            form.setValue("status", "active")
 82            form.setValue("on_hold_expire_duration", 0);
 83            form.setValue("on_hold_timeout", null);
 84            form.clearErrors("on_hold_expire_duration");
 85            form.clearErrors("on_hold_timeout");
 86        }
 87    }, [selectedTab, form]);
 88
 89    return (
 90        <Dialog open={open} onOpenChange={onOpenChange} defaultOpen={true}>
 91            <DialogContent>
 92                <DialogHeader>
 93                    <DialogTitle className="text-primary">
 94                        {entity
 95                            ? t('page.users.dialogs.edition.title')
 96                            : t('page.users.dialogs.creation.title')}
 97                    </DialogTitle>
 98                </DialogHeader>
 99                <Form {...form}>
100                    <form onSubmit={handleSubmit}>
101                        <div className="flex-col grid-cols-2 gap-2 sm:flex md:grid">
102                            <div>
103                                <UsernameField />
104                                <div className="flex gap-2 items-center w-full sm:flex-row md:flex-col">
105                                    <DataLimitField />
106                                    {form.watch().data_limit !== 0 && <DataLimitResetStrategyField />}
107                                </div>
108                                <Tabs defaultValue="determined" onValueChange={setSelectedTab} className="mt-2 w-full">
109                                    <TabsList className="flex flex-row items-center p-1 w-full rounded-md bg-accent">
110                                        <TabsTrigger
111                                            className="w-full"
112                                            value="determined">
113                                            {t('page.users.determined_expire')}
114                                        </TabsTrigger>
115                                        <TabsTrigger
116                                            className="w-full"
117                                            value="onhold">
118                                            {t('page.users.onhold_expire')}
119                                        </TabsTrigger>
120                                    </TabsList>
121                                    <TabsContent value="determined">
122                                        <ExpireDateField />
123                                    </TabsContent>
124                                    <TabsContent value="onhold">
125                                        <OnHoldExpireDurationField />
126                                        <OnHoldTimeoutField />
127                                    </TabsContent>
128                                </Tabs>
129                                <NoteField />
130                            </div>
131                            <div>
132                                <ServicesField services={services} setServices={setServices} />
133                            </div>
134                        </div>
135                        <Button
136                            className="mt-3 w-full font-semibold"
137                            type="submit"
138                            disabled={form.formState.isSubmitting}
139                        >
140                            {t('submit')}
141                        </Button>
142                    </form>
143                </Form>
144            </DialogContent>
145        </Dialog>
146    );
147};