messy react file
- 📅 2022-06-09T21:26:10.158Z
- 👁️ 167 katselukertaa
- 🔓 Julkinen
import {
Button,
Center,
createStyles,
Group,
ScrollArea,
Table,
Text,
TextInput,
UnstyledButton,
} from '@mantine/core';
import { useModals } from '@mantine/modals';
import { showNotification } from '@mantine/notifications';
import React, { useState } from 'react';
import { ChevronDown, ChevronUp, Search, Selector, Trash } from 'tabler-icons-react';
import { create_license, delete_license } from '../../data/licensingAPI';
import { IClient, ILicense, IProject } from '../../types';
import CreateNewLicense from '../CreateNewLicense/CreateNewLicense';
const useStyles = createStyles((theme) => ({
th: {
padding: '0 !important',
},
control: {
width: '100%',
padding: `${theme.spacing.xs}px ${theme.spacing.md}px`,
'&:hover': {
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[0],
},
},
icon: {
width: 21,
height: 21,
borderRadius: 21,
},
}));
interface TableSortProps {
data: ILicense[];
clients: IClient[];
projects: IProject[];
}
interface ThProps {
children: React.ReactNode;
reversed: boolean;
sorted: boolean;
onSort(): void;
}
function Th({ children, reversed, sorted, onSort }: ThProps) {
const { classes } = useStyles();
const Icon = sorted ? (reversed ? ChevronUp : ChevronDown) : Selector;
return (
<th className={classes.th}>
<UnstyledButton onClick={onSort} className={classes.control}>
<Group position="apart">
<Text weight={500} size="sm">
{children}
</Text>
<Center className={classes.icon}>
<Icon size={14} />
</Center>
</Group>
</UnstyledButton>
</th>
);
}
function filterData(data: ILicense[], search: string) {
const keys = Object.keys(data[0]);
const query = search.toLowerCase().trim();
return data.filter((item: any) =>
// eslint-disable-next-line array-callback-return, consistent-return
keys.some((key) => {
if (key === 'client') {
return item.client.name.toLowerCase().includes(query);
}
if (key === 'project') {
return item.project.name.toLowerCase().includes(query);
}
if (typeof item[key] === 'string') {
return item[key].toLowerCase().includes(query);
}
return false;
})
);
}
function sortData(
data: ILicense[],
payload: { sortBy: keyof ILicense | null; reversed: boolean; search: string }
) {
if (!payload.sortBy || payload.sortBy == null) {
return filterData(data, payload.search);
}
return filterData(
[...data].sort((a: any, b: any) => {
if ((payload.sortBy as any) === 'client.name') {
if (payload.reversed) {
return b.client.name.localeCompare(a.client.name);
}
return a.client.name.localeCompare(b.client.name);
}
if ((payload.sortBy as any) === 'project.name') {
if (payload.reversed) {
return b.project.name.localeCompare(a.project.name);
}
return a.project.name.localeCompare(b.project.name);
}
if (payload.reversed) {
return b[payload.sortBy!].localeCompare(a[payload.sortBy!]);
}
return a[payload.sortBy!].localeCompare(b[payload.sortBy!]);
}),
payload.search
);
}
export function DashboardTable({ data, projects, clients }: TableSortProps) {
const [search, setSearch] = useState('');
const [sortedData, setSortedData] = useState(data);
const [sortBy, setSortBy] = useState<keyof ILicense | null>(null);
const [reverseSortDirection, setReverseSortDirection] = useState(false);
const modals = useModals();
const setSorting = (field: keyof ILicense) => {
const reversed = field === sortBy ? !reverseSortDirection : false;
setReverseSortDirection(reversed);
setSortBy(field);
setSortedData(sortData(data, { sortBy: field, reversed, search }));
};
const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const { value } = event.currentTarget;
setSearch(value);
setSortedData(sortData(data, { sortBy, reversed: reverseSortDirection, search: value }));
};
const createNewLicense = async (
values: { license?: string; client: string; project: string; max_ips?: number },
id: any
) => {
modals.closeModal(id);
const result = await create_license(values);
if ((result as any).code || (result as any).error) {
showNotification({
title: (result as any).error,
message: (result as any).message,
color: 'red',
autoClose: 5000,
});
} else {
showNotification({
title: 'Successfully',
message: 'Successfully created new license',
color: 'green',
});
setSearch('');
const clie = clients.find((clien) => clien.id === values.client)!;
const proj = projects.find((proje) => proje.id === values.project)!;
setSortedData([
...data,
{
...result,
client: clie,
project: proj,
},
]);
}
};
const openCreateModal = () => {
const id = modals.openModal({
title: 'Create New License',
children: (
<CreateNewLicense
createNewLicense={(values) => createNewLicense(values, id)}
clients={clients}
projects={projects}
/>
),
});
};
const openConfirmModal = (row: ILicense) =>
modals.openConfirmModal({
title: 'Are you sure that you want to delete this license',
children: (
<Text size="sm">If you delete '{row.license}', you cannot undo the action.</Text>
),
labels: { confirm: 'Confirm', cancel: 'Cancel' },
onCancel: () =>
showNotification({
title: 'Cancelled',
message: `Cancelled deletetion of '${row.license}'`,
color: 'red',
}),
onConfirm: async () => {
const res = await delete_license(row.id);
if (!res.success) {
showNotification({
title: 'Failed to delete license',
message: res,
color: 'red',
});
return;
}
setSortedData(sortedData.filter((item) => item.id !== row.id));
showNotification({
title: 'Deleted license',
message: `Successfully deleted license '${row.license}'`,
color: 'green',
autoClose: 3600,
});
},
});
const rows = sortedData.map((row) => (
<tr key={row.id}>
<td>{row.license}</td>
<td>{row.client.name}</td>
<td>{row.project.name}</td>
<td>{row.max_ips}</td>
<td>
<Button color="red" variant="outline" onClick={() => openConfirmModal(row)}>
<Trash size={18} />
</Button>
</td>
</tr>
));
return (
<ScrollArea>
<Group>
<TextInput
placeholder="Search by any field"
mb="md"
icon={<Search size={14} />}
value={search}
onChange={handleSearchChange}
/>
<Button onClick={openCreateModal} mb="md">
Add
</Button>
</Group>
<Table
horizontalSpacing="md"
verticalSpacing="xs"
sx={{ tableLayout: 'fixed', width: '100%' }}
>
<thead>
<tr>
<Th
sorted={sortBy === 'license'}
reversed={reverseSortDirection}
onSort={() => setSorting('license')}
>
License
</Th>
<Th
sorted={sortBy === ('client.name' as any)}
reversed={reverseSortDirection}
onSort={() => setSorting('client.name' as any)}
>
Client
</Th>
<Th
sorted={sortBy === ('project.name' as any)}
reversed={reverseSortDirection}
onSort={() => setSorting('project.name' as any)}
>
Project
</Th>
<Th
sorted={sortBy === 'max_ips'}
reversed={reverseSortDirection}
onSort={() => setSorting('max_ips')}
>
Max IPs
</Th>
<th>
<Text>Manage</Text>
</th>
</tr>
</thead>
<tbody>
{rows.length > 0 ? (
rows
) : (
<tr>
<td colSpan={4}>
<Text weight={500} align="center">
Nothing found
</Text>
</td>
</tr>
)}
</tbody>
</Table>
</ScrollArea>
);
}