bid-tool/auto-bid-admin/src/pages/admins.tsx

181 lines
6.4 KiB
TypeScript

import { ActionIcon, Box, Menu } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
import { IconEdit, IconMenu, IconPassword, IconTrash } from '@tabler/icons-react';
import { useCallback, useMemo, useRef, useState } from 'react';
import { deleteAdmin, getAdmins } from '../apis/admin';
import { AdminModal, GrantNewPasswordModal } from '../components/admin';
import Table from '../lib/table/table';
import { IColumn, TRefTableFn } from '../lib/table/type';
import { useConfirmStore } from '../lib/zustand/use-confirm';
import { IAdmin } from '../system/type';
import { formatTime } from '../utils';
export default function Admins() {
const { setConfirm } = useConfirmStore();
const refTableFn: TRefTableFn<IAdmin> = useRef({});
const [adminModelOpened, adminModel] = useDisclosure(false);
const [grantOpened, grantModel] = useDisclosure(false);
const [clickData, setClickData] = useState<IAdmin | null>(null);
const columns: IColumn<IAdmin>[] = [
{
key: 'id',
title: 'ID',
typeFilter: 'number',
},
{
key: 'username',
title: 'Username',
typeFilter: 'text',
},
{
key: 'email',
title: 'Email',
typeFilter: 'text',
},
{
key: 'created_at',
title: 'Created at',
typeFilter: 'none',
renderRow(row) {
return <span>{formatTime(row.created_at)}</span>;
},
},
{
key: 'updated_at',
title: 'Update at',
typeFilter: 'none',
renderRow(row) {
return <span>{formatTime(row.updated_at)}</span>;
},
},
];
const handleDelete = (admin: IAdmin) => {
setConfirm({
title: 'Delete ?',
message: 'This admin will be delete',
handleOk: async () => {
await deleteAdmin(admin);
if (refTableFn.current?.fetchData) {
refTableFn.current.fetchData();
}
},
});
};
const getAdminsFn = useCallback(getAdmins, []);
const table = useMemo(() => {
return (
<Table
actionsOptions={{
actions: [
{
key: 'add',
title: 'Add',
callback: () => {
adminModel.open();
},
},
],
}}
refTableFn={refTableFn}
striped
showLoading={true}
highlightOnHover
styleDefaultHead={{
justifyContent: 'flex-start',
width: 'fit-content',
}}
options={{
query: getAdminsFn,
pathToData: 'data.data',
keyOptions: {
last_page: 'lastPage',
per_page: 'perPage',
from: 'from',
to: 'to',
total: 'total',
},
}}
rows={[]}
withColumnBorders
showChooses={false}
withTableBorder
columns={columns}
actions={{
title: <Box className="w-full text-center">Action</Box>,
body: (row) => {
return (
<Menu shadow="md" width={200}>
<Menu.Target>
<Box className="flex w-full items-center justify-center">
<ActionIcon size="sm" variant="light">
<IconMenu size={14} />
</ActionIcon>
</Box>
</Menu.Target>
<Menu.Dropdown>
<Menu.Item
onClick={() => {
setClickData(row);
adminModel.open();
}}
leftSection={<IconEdit size={14} />}
>
Edit
</Menu.Item>
<Menu.Item
onClick={() => {
setClickData(row);
grantModel.open();
}}
leftSection={<IconPassword size={14} />}
>
Grant new password
</Menu.Item>
<Menu.Item disabled={row.is_system_account} onClick={() => handleDelete(row)} leftSection={<IconTrash color="red" size={14} />}>
Delete
</Menu.Item>
</Menu.Dropdown>
</Menu>
);
},
}}
rowKey="id"
/>
);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<Box>
{table}
<AdminModal
onUpdated={refTableFn.current.fetchData}
data={clickData}
opened={adminModelOpened}
onClose={() => {
setClickData(null);
adminModel.close();
}}
/>
<GrantNewPasswordModal
opened={grantOpened}
data={clickData}
onClose={() => {
setClickData(null);
grantModel.close();
}}
/>
</Box>
);
}