1
2import {
3 Accordion,
4 Box,
5 HStack,
6 Table,
7 TableProps,
8 Tbody,
9 Td,
10 Th,
11 Thead,
12 Tr,
13 useBreakpointValue,
14} from '@chakra-ui/react';
15
16import classNames from 'classnames';
17import { FC, useState, } from 'react';
18import { useTranslation } from 'react-i18next';
19import {
20 EmptySection,
21 handleSort,
22 Pagination,
23 Sort
24} from 'components/table';
25import { fetchServices, useServices } from 'stores';
26import { pageSizeManagers } from 'utils/userPreferenceStorage';
27import { useQuery } from 'react-query';
28import { queryIds } from 'constants/query-ids';
29
30type ExpandedIndex = number | number[];
31type ServicesTableProps = {} & TableProps;
32
33export const ServicesTable: FC<ServicesTableProps> = (props) => {
34 const {
35 servicesFilters: filters,
36 onEditingService,
37 onCreateService,
38 onFilterChange,
39 } = useServices();
40 const { data: services } = useQuery(queryIds.services, () => { return fetchServices(filters) });
41 const useTable = useBreakpointValue({ base: false, md: true });
42 const { t } = useTranslation();
43 const [selectedRow,] = useState<ExpandedIndex | undefined>(
44 undefined
45 );
46
47 return (
48 <Box id="services-table" h="45vh" overflowX={{ base: 'unset', md: 'unset' }} >
49 <Accordion
50 allowMultiple
51 display={{ base: 'block', md: 'none' }}
52 index={selectedRow}
53 >
54 <Table orientation="vertical" zIndex="docked" {...props}>
55 <Thead zIndex="docked" position="relative">
56 <Tr>
57 <Tr>
58 <Th
59 position="sticky"
60 minW="200px"
61 pl={4}
62 pr={4}
63 cursor={'pointer'}
64 onClick={handleSort.bind(null, filters, 'name', onFilterChange)}
65 >
66 <HStack>
67 <span>{t('services')}</span>
68 <Sort sort={filters.sort} column="name" />
69 </HStack>
70 </Th>
71 <Th
72 position="sticky"
73 minW="50px"
74 cursor={'pointer'}
75 pr={0}
76 onClick={handleSort.bind(null, filters, 'users_number', onFilterChange)}
77 >
78 <HStack>
79 <span>{t('servicesTable.usersNumber')}</span>
80 <Sort sort={filters.sort} column="users_number" />
81 </HStack>
82 </Th>
83 <Th
84 position="sticky"
85 minW="50px"
86 cursor={'pointer'}
87 pr={0}
88 onClick={handleSort.bind(null, filters, 'inbounds_number', onFilterChange)}
89 >
90 <HStack>
91 <span>{t('servicesTable.inboundsNumber')}</span>
92 <Sort sort={filters.sort} column="inbounds_number" />
93 </HStack>
94 </Th>
95 </Tr>
96 </Tr>
97 </Thead>
98 <Tbody>
99 {!useTable &&
100 services?.map((service, i) => {
101 return (
102 <Tr
103 cursor="pointer"
104 key={service.id}
105 className={classNames('interactive', {
106 'last-row': i === (services.length - 1),
107 })}
108 onClick={(e) => {
109 e.stopPropagation();
110 onEditingService(service);
111 }}
112 >
113 <Td borderBottom={0} minW="100px" pl={4} pr={4}>
114 {service.name}
115 </Td>
116 <Td borderBottom={0} minW="50px" pl={6} pr={6}>
117 {service.users.length}
118 </Td>
119 <Td borderBottom={0} minW="50px" pr={0}>
120 {service.inbounds.length}
121 </Td>
122 </Tr>
123 );
124 })}
125 </Tbody>
126 </Table>
127 </Accordion>
128 <Table orientation="vertical" zIndex="docked" {...props}>
129 <Thead zIndex="docked" position="relative">
130 <Tr>
131 <Th
132 position="sticky"
133 minW="200px"
134 pl={4}
135 pr={4}
136 cursor={'pointer'}
137 onClick={handleSort.bind(null, filters, 'name', onFilterChange)}
138 >
139 <HStack>
140 <span>{t('services')}</span>
141 <Sort sort={filters.sort} column="name" />
142 </HStack>
143 </Th>
144 <Th
145 position="sticky"
146 minW="50px"
147 cursor={'pointer'}
148 pr={0}
149 onClick={handleSort.bind(null, filters, 'users_number', onFilterChange)}
150 >
151 <HStack>
152 <span>{t('servicesTable.usersNumber')}</span>
153 <Sort sort={filters.sort} column="users_number" />
154 </HStack>
155 </Th>
156 <Th
157 position="sticky"
158 minW="50px"
159 cursor={'pointer'}
160 pr={0}
161 onClick={handleSort.bind(null, filters, 'inbounds_number', onFilterChange)}
162 >
163 <HStack>
164 <span>{t('servicesTable.inboundsNumber')}</span>
165 <Sort sort={filters.sort} column="inbounds_number" />
166 </HStack>
167 </Th>
168 </Tr>
169 </Thead>
170 <Tbody>
171 {useTable &&
172 services?.map((service, i) => {
173 return (
174 <Tr
175 cursor="pointer"
176 key={service.id}
177 className={classNames('interactive', {
178 'last-row': i === (services.length - 1),
179 })}
180 onClick={(e) => {
181 e.stopPropagation();
182 onEditingService(service);
183 }}
184 >
185 <Td borderBottom={0} minW="100px" pl={4} pr={4}>
186 {service.name}
187 </Td>
188 <Td borderBottom={0} minW="50px" pl={6} pr={6}>
189 {service.users.length}
190 </Td>
191 <Td borderBottom={0} minW="50px" pr={0}>
192 {service.inbounds.length}
193 </Td>
194 </Tr>
195 );
196 })}
197 {services?.length == 0 && (
198 <Tr>
199 <Td colSpan={3}>
200 <EmptySection
201 isFiltered={false}
202 createObjectT='createService'
203 onCreateObject={onCreateService}
204 noObjectT="servicesTable.noService"
205 noObjectMatchedT='servicesTable.noServiceMatched'
206 />
207 </Td>
208 </Tr>
209 )}
210 </Tbody>
211 </Table>
212 <Pagination
213 total={services?.length || 0}
214 onFilterChange={onFilterChange}
215 filters={filters}
216 pageSizeManager={pageSizeManagers.services}
217 />
218 </Box>
219 );
220};