diff --git a/dashboard/src/components/stacks/vertical.tsx b/dashboard/src/components/stacks/vertical.tsx index 8998b3e..6c7251f 100644 --- a/dashboard/src/components/stacks/vertical.tsx +++ b/dashboard/src/components/stacks/vertical.tsx @@ -1,5 +1,14 @@ -import { FC, PropsWithChildren } from "react"; +import type { FC, PropsWithChildren, HTMLAttributes } from "react"; +import { cn } from "@marzneshin/utils"; -export const VStack: FC = ({ children }) => { - return
{children}
; +export const VStack: FC> = ({ + children, + className, + ...props +}) => { + return ( +
+ {children} +
+ ); }; diff --git a/dashboard/src/features/services/dialogs/mutation.dialog.tsx b/dashboard/src/features/services/dialogs/mutation.dialog.tsx index 5cfe9ea..3b376e0 100644 --- a/dashboard/src/features/services/dialogs/mutation.dialog.tsx +++ b/dashboard/src/features/services/dialogs/mutation.dialog.tsx @@ -1,147 +1,170 @@ - - import { - DialogTitle, - DialogContent, - Dialog, - DialogHeader, - Form, - FormItem, - FormControl, - FormMessage, - FormLabel, - Input, - FormField, - Button, - Checkbox, - Badge -} from '@marzneshin/components' -import { FC } from 'react' + DialogTitle, + DialogContent, + Dialog, + DialogHeader, + Form, + FormItem, + FormControl, + FormMessage, + FormLabel, + Input, + FormField, + Button, + Checkbox, + Badge, +} from "@marzneshin/components"; +import { FC } from "react"; import { - ServiceType, - useServicesCreationMutation, - useServicesUpdateMutation, -} from '@marzneshin/features/services' -import { useInboundsQuery } from '@marzneshin/features/inbounds' -import { useTranslation } from 'react-i18next' -import { z } from 'zod' -import { cn } from '@marzneshin/utils' -import { Box, GlobeLock } from 'lucide-react' -import { useMutationDialog } from '@marzneshin/hooks' + ServiceType, + useServicesCreationMutation, + useServicesUpdateMutation, +} from "@marzneshin/features/services"; +import { useInboundsQuery } from "@marzneshin/features/inbounds"; +import { useTranslation } from "react-i18next"; +import { z } from "zod"; +import { cn } from "@marzneshin/utils"; +import { Box, GlobeLock } from "lucide-react"; +import { useMutationDialog } from "@marzneshin/hooks"; export const ServiceSchema = z.object({ - id: z.number().optional(), - inbounds: z.array(z.number()).refine((value) => value.some((item) => item), { - message: "You have to select at least one inbound.", - }), - name: z.string().trim().min(1) -}) -type ServiceCreateType = z.infer + id: z.number().optional(), + inbounds: z.array(z.number()).refine((value) => value.some((item) => item), { + message: "You have to select at least one inbound.", + }), + name: z.string().trim().min(1), +}); +type ServiceCreateType = z.infer; interface MutationDialogProps { - entity: ServiceType | null - open: boolean - onOpenChange: (state: boolean) => void + entity: ServiceType | null; + open: boolean; + onOpenChange: (state: boolean) => void; } const getDefaultValues = (): ServiceCreateType => ({ - name: '', - inbounds: [], -}) + name: "", + inbounds: [], +}); -export const MutationDialog: FC = ({ entity, open, onOpenChange }) => { - const isEditing = entity !== null - const updateMutation = useServicesUpdateMutation(); - const createMutation = useServicesCreationMutation(); - const { data: inbounds } = useInboundsQuery() - const { form, handleSubmit } = useMutationDialog({ - entity, - updateMutation, - createMutation, - getDefaultValue: getDefaultValues, - schema: ServiceSchema, - onOpenChange, - }) - const { t } = useTranslation() - return ( - - - - - {isEditing ? - t('page.services.dialogs.edition.title') : - t('page.services.dialogs.creation.title')} - - -
- - ( - - {t('name')} - - - - - - )} - /> - ( - - {t('inbounds')} - {inbounds.map((inbound) => ( - ( - - -
- { - return checked - ? field.onChange([...field.value, inbound.id]) - : field.onChange( - field.value?.filter( - (value: number) => value !== inbound.id - ) - ) - }} - /> - - {inbound.tag} -
- {inbound.protocol} - {inbound.node.name} -
-
-
-
-
- )} - /> - ))} - -
- )} - /> - - - -
-
- ) -} +export const MutationDialog: FC = ({ + entity, + open, + onOpenChange, +}) => { + const isEditing = entity !== null; + const updateMutation = useServicesUpdateMutation(); + const createMutation = useServicesCreationMutation(); + const { data: inbounds } = useInboundsQuery(); + const { form, handleSubmit } = useMutationDialog({ + entity, + updateMutation, + createMutation, + getDefaultValue: getDefaultValues, + schema: ServiceSchema, + onOpenChange, + }); + const { t } = useTranslation(); + return ( + + + + + {isEditing + ? t("page.services.dialogs.edition.title") + : t("page.services.dialogs.creation.title")} + + +
+ + ( + + {t("name")} + + + + + + )} + /> + ( + + {t("inbounds")} + {inbounds.map((inbound) => ( + ( + + +
+ { + return checked + ? field.onChange([ + ...field.value, + inbound.id, + ]) + : field.onChange( + field.value?.filter( + (value: number) => + value !== inbound.id, + ), + ); + }} + /> + + {inbound.tag} +
+ + {" "} + {" "} + {inbound.protocol}{" "} + + + {" "} + {" "} + {inbound.node.name}{" "} + +
+
+
+
+
+ )} + /> + ))} + +
+ )} + /> + + + +
+
+ ); +}; diff --git a/dashboard/src/features/users/dialogs/mutation/fields/services.tsx b/dashboard/src/features/users/dialogs/mutation/fields/services.tsx index bcfc081..9f444b9 100644 --- a/dashboard/src/features/users/dialogs/mutation/fields/services.tsx +++ b/dashboard/src/features/users/dialogs/mutation/fields/services.tsx @@ -1,68 +1,71 @@ import { - Checkbox, - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, - ScrollArea, -} from '@marzneshin/components'; -import { useServicesQuery } from '@marzneshin/features/services'; -import { ServiceCard } from '@marzneshin/features/users'; -import { cn } from '@marzneshin/utils'; -import { FC } from 'react' -import { useFormContext } from 'react-hook-form'; -import { useTranslation } from 'react-i18next'; + Checkbox, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, + ScrollArea, +} from "@marzneshin/components"; +import { useServicesQuery } from "@marzneshin/features/services"; +import { ServiceCard } from "@marzneshin/features/users"; +import { cn } from "@marzneshin/utils"; +import type { FC } from "react"; +import { useFormContext } from "react-hook-form"; +import { useTranslation } from "react-i18next"; -interface ServicesFieldProps { } +export const ServicesField: FC = () => { + const form = useFormContext(); + const { data } = useServicesQuery({ page: 1, size: 100 }); + const { t } = useTranslation(); -export const ServicesField: FC = () => { - const form = useFormContext(); - const { data } = useServicesQuery({ page: 1, size: 100 }); - const { t } = useTranslation(); - - return ( - ( - - {t('services')} - - {data.entity.map(service => ( - ( - - -
- { - return checked - ? field.onChange([...field.value, service.id]) - : field.onChange( - field.value?.filter( - (value: number) => value !== service.id - ) - ) - }} - /> - - - -
-
- -
- )} - /> - ))} -
-
- )} - /> - ); + return ( + ( + + {t("services")} + + {data.entity.map((service) => ( + ( + + +
+ { + return checked + ? field.onChange([...field.value, service.id]) + : field.onChange( + field.value?.filter( + (value: number) => value !== service.id, + ), + ); + }} + /> + + + +
+
+ +
+ )} + /> + ))} +
+
+ )} + /> + ); }; diff --git a/dashboard/src/features/users/dialogs/mutation/index.tsx b/dashboard/src/features/users/dialogs/mutation/index.tsx index 0bbe1fa..180ed74 100644 --- a/dashboard/src/features/users/dialogs/mutation/index.tsx +++ b/dashboard/src/features/users/dialogs/mutation/index.tsx @@ -1,4 +1,5 @@ -import { FC, useCallback } from "react"; +import type { FC } from "react"; +import { useCallback } from "react"; import { DialogTitle, DialogContent, @@ -6,20 +7,19 @@ import { DialogHeader, Form, Button, -} from '@marzneshin/components'; -import { useTranslation } from 'react-i18next'; + ScrollArea, + VStack, +} from "@marzneshin/components"; +import { useTranslation } from "react-i18next"; +import type { UserMutationType } from "@marzneshin/features/users"; import { DATA_LIMIT_METRIC, - UserMutationType, useUsersCreationMutation, - useUsersUpdateMutation + useUsersUpdateMutation, } from "@marzneshin/features/users"; + import { UserSchema } from "./schema"; -import { - UsernameField, - NoteField, - ServicesField, -} from "./fields"; +import { UsernameField, NoteField, ServicesField } from "./fields"; import { useMutationDialog } from "@marzneshin/hooks"; import { DataLimitFields, ExpirationMethodFields } from "./sections"; @@ -35,17 +35,20 @@ export const UsersMutationDialog: FC = ({ onOpenChange, }) => { const { t } = useTranslation(); - const getDefaultValues = useCallback((): UserMutationType => ({ - services: [], - data_limit: 1, - expire: null, - username: '', - data_limit_reset_strategy: 'no_reset', - status: 'active', - note: '', - on_hold_expire_duration: 0, - on_hold_timeout: undefined, - }), []); + const getDefaultValues = useCallback( + (): UserMutationType => ({ + services: [], + data_limit: 1, + expire: null, + username: "", + data_limit_reset_strategy: "no_reset", + status: "active", + note: "", + on_hold_expire_duration: 0, + on_hold_timeout: undefined, + }), + [], + ); const { form, handleSubmit } = useMutationDialog({ entity, @@ -54,41 +57,46 @@ export const UsersMutationDialog: FC = ({ updateMutation: useUsersUpdateMutation(), schema: UserSchema, getDefaultValue: getDefaultValues, - loadFormtter: (d) => ({ ...d, data_limit: (d.data_limit ? d.data_limit : 0) / DATA_LIMIT_METRIC }) - }) + loadFormtter: (d) => ({ + ...d, + data_limit: (d.data_limit ? d.data_limit : 0) / DATA_LIMIT_METRIC, + }), + }); return ( - - - - {entity - ? t('page.users.dialogs.edition.title') - : t('page.users.dialogs.creation.title')} - - -
- -
-
- - - - -
-
- + + + + + {entity + ? t("page.users.dialogs.edition.title") + : t("page.users.dialogs.creation.title")} + + + + +
+
+ + + + +
+ + +
-
- - - + + + +
);