source: src/sections/employee/view/employee-list-view.tsx@ 057453c

main
Last change on this file since 057453c was 057453c, checked in by Naum Shapkarovski <naumshapkarovski@…>, 5 weeks ago

feat: implement employees

  • Property mode set to 100644
File size: 7.8 KB
Line 
1'use client';
2
3import isEqual from 'lodash/isEqual';
4import { useState, useCallback } from 'react';
5// @mui
6import { alpha } from '@mui/material/styles';
7import Tab from '@mui/material/Tab';
8import Tabs from '@mui/material/Tabs';
9import Card from '@mui/material/Card';
10import Table from '@mui/material/Table';
11import Button from '@mui/material/Button';
12import Container from '@mui/material/Container';
13import TableBody from '@mui/material/TableBody';
14import TableContainer from '@mui/material/TableContainer';
15// routes
16import { paths } from 'src/routes/paths';
17import { RouterLink } from 'src/routes/components';
18// hooks
19import { useBoolean } from 'src/hooks/use-boolean';
20// components
21import Label from 'src/components/label';
22import Iconify from 'src/components/iconify';
23import Scrollbar from 'src/components/scrollbar';
24import { useSettingsContext } from 'src/components/settings';
25import CustomBreadcrumbs from 'src/components/custom-breadcrumbs';
26import {
27 useTable,
28 getComparator,
29 emptyRows,
30 TableNoData,
31 TableEmptyRows,
32 TableHeadCustom,
33 TablePaginationCustom,
34} from 'src/components/table';
35// types
36import { Employee, EmployeeTableFilters, EmployeeTableFilterValue } from 'src/schemas';
37//
38import { useGetEmployees } from 'src/api/employee';
39import EmployeeTableRow from '../employee-table-row';
40import EmployeeTableFiltersResult from '../employee-table-filters-result';
41
42const STATUS_OPTIONS = [
43 { value: 'all', label: 'All' },
44 { value: 'active', label: 'Active' },
45 { value: 'inactive', label: 'Inactive' },
46];
47
48const TABLE_HEAD = [
49 { id: 'name', label: 'Name' },
50 { id: 'email', label: 'Email' },
51 { id: 'project', label: 'Project' },
52 { id: 'status', label: 'Status', width: 100 },
53 { id: '', width: 88 },
54];
55
56const defaultFilters: EmployeeTableFilters = {
57 name: '',
58 status: 'all',
59};
60
61export default function EmployeeListView() {
62 const table = useTable({ defaultDense: true });
63 const settings = useSettingsContext();
64 const { employees } = useGetEmployees();
65 const [filters, setFilters] = useState(defaultFilters);
66
67 const dataFiltered = applyFilter({
68 inputData: employees,
69 comparator: getComparator(table.order, table.orderBy),
70 filters,
71 });
72
73 const dataInPage = dataFiltered.slice(
74 table.page * table.rowsPerPage,
75 table.page * table.rowsPerPage + table.rowsPerPage
76 );
77
78 const denseHeight = table.dense ? 52 : 72;
79
80 const canReset = !isEqual(defaultFilters, filters);
81
82 const notFound = (!dataFiltered.length && canReset) || !dataFiltered.length;
83
84 const handleFilters = useCallback(
85 (name: string, value: EmployeeTableFilterValue) => {
86 table.onResetPage();
87 setFilters((prevState: EmployeeTableFilters) => ({
88 ...prevState,
89 [name]: value,
90 }));
91 },
92 [table]
93 );
94
95 const handleFilterStatus = useCallback(
96 (event: React.SyntheticEvent, newValue: string) => {
97 handleFilters('status', newValue);
98 },
99 [handleFilters]
100 );
101
102 const handleResetFilters = useCallback(() => {
103 setFilters(defaultFilters);
104 }, []);
105
106 return (
107 <>
108 <Container maxWidth={settings.themeStretch ? false : 'lg'}>
109 <CustomBreadcrumbs
110 heading="List"
111 links={[
112 { name: 'Dashboard', href: paths.dashboard.root },
113 { name: 'Employee', href: paths.dashboard.employee.list },
114 { name: 'List' },
115 ]}
116 action={
117 <Button
118 component={RouterLink}
119 href={paths.dashboard.employee.new}
120 variant="contained"
121 startIcon={<Iconify icon="mingcute:add-line" />}
122 >
123 New Employee
124 </Button>
125 }
126 sx={{
127 mb: { xs: 3, md: 5 },
128 }}
129 />
130
131 <Card>
132 <Tabs
133 value={filters.status}
134 onChange={handleFilterStatus}
135 sx={{
136 px: 2.5,
137 boxShadow: (theme) => `inset 0 -2px 0 0 ${alpha(theme.palette.grey[500], 0.08)}`,
138 }}
139 >
140 {STATUS_OPTIONS.map((tab) => (
141 <Tab
142 key={tab.value}
143 iconPosition="end"
144 value={tab.value}
145 label={tab.label}
146 icon={
147 <Label
148 variant={
149 ((tab.value === 'all' || tab.value === filters.status) && 'filled') || 'soft'
150 }
151 color={
152 (tab.value === 'active' && 'success') ||
153 (tab.value === 'inactive' && 'warning') ||
154 'default'
155 }
156 >
157 {tab.value === 'all' && employees.length}
158 {tab.value === 'active' &&
159 employees.filter((employee) => employee.status === 'active').length}
160 {tab.value === 'inactive' &&
161 employees.filter((employee) => employee.status === 'inactive').length}
162 </Label>
163 }
164 />
165 ))}
166 </Tabs>
167
168 {canReset && (
169 <EmployeeTableFiltersResult
170 filters={filters}
171 onFilters={handleFilters}
172 onResetFilters={handleResetFilters}
173 results={dataFiltered.length}
174 sx={{ p: 2.5, pt: 0 }}
175 />
176 )}
177
178 <TableContainer sx={{ position: 'relative', overflow: 'unset' }}>
179 <Scrollbar>
180 <Table size={table.dense ? 'small' : 'medium'} sx={{ minWidth: 960 }}>
181 <TableHeadCustom
182 order={table.order}
183 orderBy={table.orderBy}
184 headLabel={TABLE_HEAD}
185 rowCount={employees.length}
186 numSelected={table.selected.length}
187 onSort={table.onSort}
188 />
189
190 <TableBody>
191 {dataFiltered
192 .slice(
193 table.page * table.rowsPerPage,
194 table.page * table.rowsPerPage + table.rowsPerPage
195 )
196 .map((row) => (
197 <EmployeeTableRow
198 key={row.id}
199 row={row}
200 selected={table.selected.includes(row.id!)}
201 onEditRow={() => {}}
202 />
203 ))}
204
205 <TableEmptyRows
206 height={denseHeight}
207 emptyRows={emptyRows(table.page, table.rowsPerPage, employees.length)}
208 />
209
210 <TableNoData notFound={notFound} />
211 </TableBody>
212 </Table>
213 </Scrollbar>
214 </TableContainer>
215
216 <TablePaginationCustom
217 count={dataFiltered.length}
218 page={table.page}
219 rowsPerPage={table.rowsPerPage}
220 onPageChange={table.onChangePage}
221 onRowsPerPageChange={table.onChangeRowsPerPage}
222 dense={table.dense}
223 onChangeDense={table.onChangeDense}
224 />
225 </Card>
226 </Container>
227 </>
228 );
229}
230
231// ----------------------------------------------------------------------
232
233function applyFilter({
234 inputData,
235 comparator,
236 filters,
237}: {
238 inputData: Employee[];
239 comparator: (a: any, b: any) => number;
240 filters: EmployeeTableFilters;
241}) {
242 const { name, status } = filters;
243
244 const stabilizedThis = inputData.map((el, index) => [el, index] as const);
245
246 stabilizedThis.sort((a, b) => {
247 const order = comparator(a[0], b[0]);
248 if (order !== 0) return order;
249 return a[1] - b[1];
250 });
251
252 inputData = stabilizedThis.map((el) => el[0]);
253
254 if (name) {
255 inputData = inputData.filter(
256 (employee) => employee.name.toLowerCase().indexOf(name.toLowerCase()) !== -1
257 );
258 }
259
260 if (status !== 'all') {
261 inputData = inputData.filter((employee) => employee.status === status);
262 }
263
264 return inputData;
265}
Note: See TracBrowser for help on using the repository browser.