Files
agent/src/pages/Demo/TaskBoard/index.tsx

336 lines
9.1 KiB
TypeScript

import {
addTask,
queryTaskList,
removeTask,
updateTask,
} from '@/services/demo/task';
import { DeleteOutlined, EditOutlined, PlusOutlined } from '@ant-design/icons';
import type { ActionType, ProColumns } from '@ant-design/pro-components';
import {
ModalForm,
PageContainer,
ProFormSelect,
ProFormText,
ProTable,
} from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import { Button, Tag, message } from 'antd';
import { useRef, useState } from 'react';
import type { TaskItem } from './data';
export default () => {
const actionRef = useRef<ActionType>();
const [createModalOpen, handleModalOpen] = useState<boolean>(false);
const [currentRow, setCurrentRow] = useState<TaskItem>();
const [updateModalOpen, handleUpdateModalOpen] = useState<boolean>(false);
const intl = useIntl();
const columns: ProColumns<TaskItem>[] = [
{
title: intl.formatMessage({
id: 'pages.demo.task.id',
defaultMessage: 'Task ID',
}),
dataIndex: 'id',
hideInSearch: true,
width: 80,
},
{
title: intl.formatMessage({
id: 'pages.demo.task.title',
defaultMessage: 'Title',
}),
dataIndex: 'title',
copyable: true,
ellipsis: true,
tip: 'The task title is unique key',
formItemProps: {
rules: [
{
required: true,
message:
intl.formatMessage({
id: 'pages.demo.task.title',
defaultMessage: 'Title',
}) + ' is required',
},
],
},
},
{
title: intl.formatMessage({
id: 'pages.demo.task.status',
defaultMessage: 'Status',
}),
dataIndex: 'status',
filters: true,
onFilter: true,
valueEnum: {
todo: {
text: intl.formatMessage({
id: 'pages.demo.task.status.todo',
defaultMessage: 'To Do',
}),
status: 'Default',
},
doing: {
text: intl.formatMessage({
id: 'pages.demo.task.status.doing',
defaultMessage: 'Doing',
}),
status: 'Processing',
},
done: {
text: intl.formatMessage({
id: 'pages.demo.task.status.done',
defaultMessage: 'Done',
}),
status: 'Success',
},
},
render: (_, record) => {
const colorMap: Record<string, string> = {
todo: 'default',
doing: 'orange',
done: 'success',
};
// handle undefined status
const color = colorMap[record.status || 'todo'] || 'default';
const statusText = record.status
? intl.formatMessage({
id: `pages.demo.task.status.${record.status}`,
defaultMessage: record.status.toUpperCase(),
})
: '-';
return <Tag color={color}>{statusText}</Tag>;
},
},
{
title: intl.formatMessage({
id: 'pages.demo.task.priority',
defaultMessage: 'Priority',
}),
dataIndex: 'priority',
valueType: 'digit',
sorter: true,
hideInForm: true,
hideInSearch: true,
},
{
title: intl.formatMessage({
id: 'pages.demo.task.createdAt',
defaultMessage: 'Created At',
}),
dataIndex: 'createdAt',
valueType: 'dateTime',
sorter: true,
hideInSearch: true,
hideInForm: true,
},
{
title: intl.formatMessage({
id: 'pages.demo.task.action',
defaultMessage: 'Action',
}),
dataIndex: 'option',
valueType: 'option',
render: (_, record) => [
<Button
key="edit"
size="small"
type="text"
icon={<EditOutlined />}
onClick={() => {
setCurrentRow(record);
handleUpdateModalOpen(true);
}}
>
{intl.formatMessage({
id: 'pages.demo.task.edit',
defaultMessage: 'Edit',
})}
</Button>,
<Button
key="delete"
size="small"
type="text"
danger
icon={<DeleteOutlined />}
onClick={async () => {
await removeTask({ id: record.id });
actionRef.current?.reload();
message.success('Deleted successfully');
}}
>
{intl.formatMessage({
id: 'pages.demo.task.delete',
defaultMessage: 'Delete',
})}
</Button>,
],
},
];
return (
<PageContainer>
<ProTable<TaskItem>
headerTitle={intl.formatMessage({
id: 'menu.demo.task-board',
defaultMessage: 'Task List',
})}
actionRef={actionRef}
rowKey="id"
form={{
layout: 'vertical',
}}
search={{
labelWidth: 'auto',
}}
toolBarRender={() => [
<Button
type="primary"
key="primary"
onClick={() => {
handleModalOpen(true);
}}
>
<PlusOutlined />{' '}
{intl.formatMessage({
id: 'pages.product.add',
defaultMessage: 'New Task',
})}
</Button>,
]}
request={async (params) => {
// ProTable already integrates useRequest logic internally when 'request' is provided
const msg = await queryTaskList({ ...params });
return {
data: msg.data,
success: msg.success,
total: msg.total,
};
}}
columns={columns}
/>
{/* Create Form */}
<ModalForm
title={intl.formatMessage({
id: 'pages.product.add',
defaultMessage: 'New Task',
})}
width="400px"
layout="vertical"
labelCol={{ span: 24 }}
wrapperCol={{ span: 24 }}
open={createModalOpen}
onOpenChange={handleModalOpen}
onFinish={async (value) => {
await addTask(value as TaskItem);
message.success('Added successfully');
handleModalOpen(false);
actionRef.current?.reload();
return true;
}}
>
<ProFormText
rules={[{ required: true, message: 'Title is required' }]}
name="title"
label={intl.formatMessage({
id: 'pages.demo.task.title',
defaultMessage: 'Title',
})}
/>
<ProFormSelect
name="status"
label={intl.formatMessage({
id: 'pages.demo.task.status',
defaultMessage: 'Status',
})}
valueEnum={{
todo: intl.formatMessage({
id: 'pages.demo.task.status.todo',
defaultMessage: 'To Do',
}),
doing: intl.formatMessage({
id: 'pages.demo.task.status.doing',
defaultMessage: 'Doing',
}),
done: intl.formatMessage({
id: 'pages.demo.task.status.done',
defaultMessage: 'Done',
}),
}}
placeholder="Please select a status"
rules={[{ required: true, message: 'Please select your status!' }]}
/>
</ModalForm>
{/* Edit Form */}
<ModalForm
title={intl.formatMessage({
id: 'pages.product.edit',
defaultMessage: 'Edit Task',
})}
width="400px"
layout="vertical"
labelCol={{ span: 24 }}
wrapperCol={{ span: 24 }}
open={updateModalOpen}
onOpenChange={handleUpdateModalOpen}
onFinish={async (value) => {
const data = { ...currentRow, ...value };
await updateTask(data as TaskItem);
message.success('Updated successfully');
handleUpdateModalOpen(false);
actionRef.current?.reload();
return true;
}}
initialValues={currentRow}
modalProps={{
destroyOnClose: true,
}}
>
<ProFormText
name="id"
label={intl.formatMessage({
id: 'pages.demo.task.id',
defaultMessage: 'ID',
})}
disabled
hidden
/>
<ProFormText
name="title"
label={intl.formatMessage({
id: 'pages.demo.task.title',
defaultMessage: 'Title',
})}
rules={[{ required: true, message: 'Title is required' }]}
/>
<ProFormSelect
name="status"
label={intl.formatMessage({
id: 'pages.demo.task.status',
defaultMessage: 'Status',
})}
valueEnum={{
todo: intl.formatMessage({
id: 'pages.demo.task.status.todo',
defaultMessage: 'To Do',
}),
doing: intl.formatMessage({
id: 'pages.demo.task.status.doing',
defaultMessage: 'Doing',
}),
done: intl.formatMessage({
id: 'pages.demo.task.status.done',
defaultMessage: 'Done',
}),
}}
/>
</ModalForm>
</PageContainer>
);
};