diff --git a/app/dashboard/src/components/inbounds-card/index.tsx b/app/dashboard/src/components/inbounds-card/index.tsx
@@ -0,0 +1,46 @@
+/* Inbounds Card Component
+ *
+ * - name
+ * - protocol
+ * - Nodes number
+*/
+
+import { FC, PropsWithChildren } from 'react'
+import { ProtocolType } from 'types'
+import { Text, Spacer, VStack, chakra, Flex } from '@chakra-ui/react';
+import { IconBaseStyle } from 'constants/IconBaseStyle';
+import { ServerStackIcon } from '@heroicons/react/24/outline';
+import { SystemPropertyStatus } from 'components/system-property-status';
+
+type InboundCardProps = {
+ tag: string,
+ protocol: ProtocolType,
+ nodeName: string;
+}
+
+const InboundsIcon = chakra(ServerStackIcon, IconBaseStyle);
+
+export const BadgeTag: FC<PropsWithChildren> = ({ children }) => {
+ return (
+ <Text fontSize="sm" color="primary.700" _dark={{ color: 'gray.100' }} bg="gray.100" pl="3px" pr="3px" border="1px" borderRadius="md" borderColor="primary.700" fontWeight="light">
+ {children}
+ </Text>
+ )
+}
+
+export const InboundCard: FC<InboundCardProps> = ({ tag, protocol, nodeName }) => {
+ return (
+ <VStack justifyContent={'start'} alignItems={'start'} w="full">
+ <Text fontSize="md" color="gray.700" _dark={{ color: 'gray.100' }} fontWeight="semibold">
+ {tag}
+ </Text>
+ <Flex justifyContent={'spaced-between'} flexDir="row" w="full">
+ <SystemPropertyStatus value={nodeName} StatusIcon={InboundsIcon} />
+ <Spacer />
+ <BadgeTag>
+ {protocol}
+ </BadgeTag>
+ </Flex>
+ </VStack >
+ )
+}
diff --git a/app/dashboard/src/pages/users/dialog/service-property-status.tsx b/app/dashboard/src/components/system-property-status/index.tsx
rename from app/dashboard/src/pages/users/dialog/service-property-status.tsx
rename to app/dashboard/src/components/system-property-status/index.tsx
@@ -2,13 +2,12 @@ import { Flex } from '@chakra-ui/react';
import { FC, useState } from 'react';
import { ChakraIcon } from 'types';
-
-type ServicePropertyStatusProps = {
- value: number;
- StatusIcon: ChakraIcon;
+type SystemPropertyStatusProps = {
+ value: number | string;
+ StatusIcon: ChakraIcon;
}
-export const ServicePropertyStatus: FC<ServicePropertyStatusProps> = ({ value, StatusIcon }) => {
+export const SystemPropertyStatus: FC<SystemPropertyStatusProps> = ({ value, StatusIcon }) => {
const [valueState,] = useState(value);
return (
<Flex flexDirection="row">
diff --git a/app/dashboard/src/pages/services/dialog/inbounds-field.tsx b/app/dashboard/src/pages/services/dialog/inbounds-field.tsx
@@ -1,8 +1,9 @@
-import { FormControl, FormLabel, FormErrorMessage, Center, Spinner, Text, Spacer, Flex } from '@chakra-ui/react';
+import { FormControl, FormLabel, FormErrorMessage, Center, Spinner } from '@chakra-ui/react';
import { Inbounds, InboundType } from 'types';
import { TFunction } from 'i18next';
import { Controller } from 'react-hook-form';
import { InboundsSelectList } from './inbounds-select-list';
+import { InboundCard } from 'components/inbounds-card';
interface InboundsFieldProps {
@@ -29,14 +30,7 @@ export const InboundsField = ({ form, t, inbounds }: InboundsFieldProps) => {
<InboundsSelectList
list={inbounds}
renderCheckboxContent={(inbound: InboundType) => (
- <>
- <Text fontSize="sm" color="gray.700" _dark={{ color: 'gray.100' }} fontWeight="medium">
- {inbound.tag} {inbound.protocol}
- </Text>
- <Spacer />
- <Flex flexDirection="row" alignItems="center">
- </Flex>
- </>
+ <InboundCard tag={inbound.tag} protocol={inbound.protocol} nodeName={inbound.node.name} />
)}
/>
);
diff --git a/app/dashboard/src/pages/services/dialog/inbounds-select-list.tsx b/app/dashboard/src/pages/services/dialog/inbounds-select-list.tsx
@@ -1,12 +1,10 @@
import {
- Box,
- Flex,
Stack,
} from '@chakra-ui/react';
import { ListCheckBox } from 'components/list-check-box';
import { Inbounds, InboundType } from 'types';
-import { forwardRef, ReactNode } from 'react';
+import { forwardRef, Fragment, ReactNode } from 'react';
import {
useFormContext,
} from 'react-hook-form';
@@ -36,16 +34,14 @@ export const InboundsSelectList = forwardRef<HTMLDivElement, InboundsSelectListP
return (
<Stack spacing={3} ref={ref}>
{list.map((inbound: InboundType) => (
- <Box key={inbound.id}>
- <Flex align="center">
- <ListCheckBox
- isChecked={form.getValues('inbounds').includes(inbound.id)}
- onChange={() => handleInboundToggle(inbound.id)}
- value={String(inbound.id)}
- renderContent={() => renderCheckboxContent(inbound)}
- />
- </Flex>
- </Box>
+ <Fragment key={inbound.id}>
+ <ListCheckBox
+ isChecked={form.getValues('inbounds').includes(inbound.id)}
+ onChange={() => handleInboundToggle(inbound.id)}
+ value={String(inbound.id)}
+ renderContent={() => renderCheckboxContent(inbound)}
+ />
+ </Fragment>
))}
</Stack>
);
diff --git a/app/dashboard/src/pages/services/dialog/index.tsx b/app/dashboard/src/pages/services/dialog/index.tsx
@@ -130,7 +130,7 @@ export const ServiceDialog: FC<ServiceDialogProps> = () => {
const disabled = loading;
return (
- <Modal isOpen={isOpen} onClose={onClose} size="2xl">
+ <Modal isOpen={isOpen} onClose={onClose} size="lg">
<ModalOverlay bg="blackAlpha.300" backdropFilter="blur(10px)" />
<FormProvider {...form} formState={form.formState}>
<ModalContent mx="3">
diff --git a/app/dashboard/src/pages/users/dialog/services-field.tsx b/app/dashboard/src/pages/users/dialog/services-field.tsx
@@ -4,7 +4,7 @@ import { IconBaseStyle } from 'constants/IconBaseStyle';
import { TFunction } from 'i18next';
import { Controller } from 'react-hook-form';
import { Service } from 'types';
-import { ServicePropertyStatus } from './service-property-status';
+import { SystemPropertyStatus } from 'components/system-property-status';
import { ServicesSelectList } from './services-select-list';
const UsersServiceIcon = chakra(UsersIcon, IconBaseStyle);
@@ -39,9 +39,9 @@ export const ServicesField = ({ form, t, services }: ServicesFieldProps) => {
{service.name}
</Text>
<Flex flexDirection="row" alignItems="center">
- <ServicePropertyStatus value={service.users.length} StatusIcon={UsersServiceIcon} />
+ <SystemPropertyStatus value={service.users.length} StatusIcon={UsersServiceIcon} />
<Text color="primary.600" _dark={{ color: 'gray.100' }} mx="8px" fontSize="sm">/</Text>
- <ServicePropertyStatus value={service.inbounds.length} StatusIcon={InboundsServiceIcon} />
+ <SystemPropertyStatus value={service.inbounds.length} StatusIcon={InboundsServiceIcon} />
</Flex>
</Flex>
)}
diff --git a/app/dashboard/src/types/inbounds.ts b/app/dashboard/src/types/inbounds.ts
@@ -1,10 +1,12 @@
import { ProtocolType } from './protocol';
+import { NodeType } from 'stores';
export type InboundType = {
id: number;
tag: string;
protocol: ProtocolType;
network: string;
+ node: NodeType;
tls: string;
port?: number;
};