gitscope
← marzneshin / v0.6.5 / dashboard/src/modules/hosts/dialogs/mutation/index.tsx
https://dev.kronoz.win/r/marzneshin.git
dashboard/src/modules/hosts/dialogs/mutation/index.tsx · TypeScript
Blame Raw
  1import { type FC, useEffect } from "react";
  2import {
  3    DialogTitle,
  4    DialogContent,
  5    Dialog,
  6    DialogHeader,
  7    Form,
  8    Button,
  9    ScrollArea,
 10} from "@marzneshin/common/components";
 11import { useForm } from "react-hook-form";
 12import { zodResolver } from "@hookform/resolvers/zod";
 13import { useTranslation } from "react-i18next";
 14import {
 15    useHostsCreationMutation,
 16    useHostsUpdateMutation,
 17    type HostWithProfileType,
 18    type HostWithProfileSchemaType
 19} from "@marzneshin/modules/hosts";
 20import { useDialog, type MutationDialogProps } from "@marzneshin/common/hooks";
 21import { ProtocolType } from "@marzneshin/modules/inbounds";
 22import { useProfileStrategy } from "./profiles";
 23
 24interface HostMutationDialogProps extends MutationDialogProps<HostWithProfileType> {
 25    inboundId?: number;
 26    protocol?: ProtocolType;
 27}
 28
 29const transformFormValue = (values: any) => {
 30    if (!(values.alpn && values.fingerprint))
 31        return values;
 32    const port = values.port === "" ? null : values.port;
 33    const alpn = values.alpn === "none" ? "" : values.alpn;
 34    const fingerprint = values.fingerprint === "none" ? "" : values.fingerprint;
 35    return { ...values, alpn, fingerprint, port };
 36};
 37
 38export const HostsMutationDialog: FC<HostMutationDialogProps> = ({
 39    entity,
 40    inboundId,
 41    onClose,
 42    protocol,
 43}) => {
 44    const [open, onOpenChange] = useDialog(true);
 45    const [Schema, ProfileFields, defaultValue] = useProfileStrategy(protocol)
 46    const form = useForm<HostWithProfileSchemaType>({
 47        defaultValues: entity ? entity : defaultValue,
 48        resolver: zodResolver(Schema),
 49    });
 50    const updateMutation = useHostsUpdateMutation();
 51    const createMutation = useHostsCreationMutation();
 52    const { t } = useTranslation();
 53
 54    const submit = (values: HostWithProfileSchemaType) => {
 55        const host = transformFormValue(values);
 56        if (entity && entity.id !== undefined) {
 57            updateMutation.mutate({ hostId: entity.id, host });
 58            onOpenChange(false);
 59        } else if (inboundId !== undefined) {
 60            createMutation.mutate({ inboundId, host });
 61            onOpenChange(false);
 62        }
 63    };
 64
 65    useEffect(() => {
 66        if (!open) onClose();
 67    }, [open, onClose]);
 68
 69    useEffect(() => {
 70        if (entity) form.reset(entity);
 71        else form.reset(defaultValue);
 72    }, [entity, form, open, defaultValue]);
 73
 74    return (
 75        <Dialog open={open} onOpenChange={onOpenChange} defaultOpen={true}>
 76            <DialogContent className="min-w-full h-full md:h-auto md:min-w-[32rem]">
 77                <ScrollArea className="flex flex-col h-full p-0">
 78                    <DialogHeader className="mb-3">
 79                        <DialogTitle className="text-primary">
 80                            {entity
 81                                ? t("page.hosts.dialogs.edition.title")
 82                                : t("page.hosts.dialogs.creation.title")}
 83                        </DialogTitle>
 84                    </DialogHeader>
 85                    <Form {...form}>
 86                        <form
 87                            onSubmit={form.handleSubmit(submit)}
 88                            className="h-full flex flex-col justify-between"
 89                        >
 90                            <ProfileFields />
 91                            <Button
 92                                className="mt-3 w-full font-semibold"
 93                                type="submit"
 94                                disabled={form.formState.isSubmitting}
 95                            >
 96                                {t("submit")}
 97                            </Button>
 98                        </form>
 99                    </Form>
100                </ScrollArea>
101            </DialogContent>
102        </Dialog>
103    );
104};