YuJian920
3 years ago
11 changed files with 212 additions and 63 deletions
@ -1,20 +1,93 @@
@@ -1,20 +1,93 @@
|
||||
import React from "react"; |
||||
import { Button, Drawer } from "antd"; |
||||
import React, { useEffect } from "react"; |
||||
import { Button, Drawer, Form, Input, Spin, Typography } from "antd"; |
||||
import useProjectModal from "../hook/useProjectModal"; |
||||
import UserSelect from "./UserSelect"; |
||||
import { useAddProject, useEditProject } from "../hook/useProjects"; |
||||
import { useForm } from "antd/es/form/Form"; |
||||
import styled from "@emotion/styled"; |
||||
|
||||
const ProjectModal = () => { |
||||
const { projectModalOpen, close, editeingProject, isLoading } = |
||||
useProjectModal(); |
||||
const useMutateProject = editeingProject ? useEditProject : useAddProject; |
||||
|
||||
const { mutateAsync, error, isLoading: mutateLoading } = useMutateProject(); |
||||
const [form] = useForm(); |
||||
const onFinish = (values: any) => { |
||||
mutateAsync({ ...editeingProject, ...values }).then(() => { |
||||
form.resetFields(); |
||||
close(); |
||||
}); |
||||
}; |
||||
|
||||
const title = editeingProject ? "编辑项目" : "创建项目"; |
||||
|
||||
useEffect(() => { |
||||
form.setFieldsValue(editeingProject); |
||||
}, [editeingProject, form]); |
||||
|
||||
const ProjectModal = (props: { |
||||
projectModalOpen: boolean; |
||||
onClose: () => void; |
||||
}) => { |
||||
return ( |
||||
<Drawer |
||||
onClose={props.onClose} |
||||
visible={props.projectModalOpen} |
||||
forceRender={true} |
||||
onClose={close} |
||||
visible={projectModalOpen} |
||||
width="100%" |
||||
> |
||||
<h1>Project Modal</h1> |
||||
<Button onClick={props.onClose}>关闭</Button> |
||||
<Container> |
||||
{isLoading ? ( |
||||
<Spin size="large" /> |
||||
) : ( |
||||
<> |
||||
<h1>{title}</h1> |
||||
{/* {error ? ( |
||||
<Typography.Text type="danger">{error.message}</Typography.Text> |
||||
) : null} */} |
||||
<Form |
||||
form={form} |
||||
layout="vertical" |
||||
style={{ width: "40rem" }} |
||||
onFinish={onFinish} |
||||
> |
||||
<Form.Item |
||||
label="名称" |
||||
name="name" |
||||
rules={[{ required: true, message: "请输入项目名" }]} |
||||
> |
||||
<Input placeholder="请输入项目名称" /> |
||||
</Form.Item> |
||||
<Form.Item |
||||
label="部门" |
||||
name="organization" |
||||
rules={[{ required: true, message: "请输入部门名" }]} |
||||
> |
||||
<Input placeholder="请输入部门名称" /> |
||||
</Form.Item> |
||||
<Form.Item label="负责人" name="personId"> |
||||
<UserSelect defaultOptionName="负责人" /> |
||||
</Form.Item> |
||||
<Form.Item style={{ textAlign: 'right' }}> |
||||
<Button |
||||
loading={mutateLoading} |
||||
type="primary" |
||||
htmlType="submit" |
||||
> |
||||
提交 |
||||
</Button> |
||||
</Form.Item> |
||||
</Form> |
||||
</> |
||||
)} |
||||
</Container> |
||||
</Drawer> |
||||
); |
||||
}; |
||||
|
||||
export default React.memo(ProjectModal); |
||||
|
||||
const Container = styled.div` |
||||
height: 80vh; |
||||
display: flex; |
||||
flex-direction: column; |
||||
justify-content: center; |
||||
align-items: center; |
||||
`;
|
||||
|
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
import { useProject } from "./useProjects"; |
||||
import useSetUrlSearchParam from "./useSetUrlSearchParam"; |
||||
import useUrlQueryParams from "./useUrlQueryParams"; |
||||
|
||||
const useProjectModal = () => { |
||||
const [{ projectCreate }, setProjectCreate] = useUrlQueryParams([ |
||||
"projectCreate", |
||||
]); |
||||
const [{ editeingProjectId }, setEditingProjectId] = useUrlQueryParams([ |
||||
"editeingProjectId", |
||||
]); |
||||
const setUrlParams = useSetUrlSearchParam(); |
||||
const { data: editeingProject, isLoading } = useProject( |
||||
Number(editeingProjectId) |
||||
); |
||||
|
||||
const open = () => setProjectCreate({ projectCreate: "true" }); |
||||
const close = () => |
||||
setUrlParams({ projectCreate: undefined, editeingProjectId: undefined }); |
||||
const startEdit = (id: number) => |
||||
setEditingProjectId({ editeingProjectId: id }); |
||||
|
||||
return { |
||||
projectModalOpen: projectCreate === "true" || Boolean(editeingProject), |
||||
open, |
||||
close, |
||||
startEdit, |
||||
editeingProject, |
||||
isLoading, |
||||
}; |
||||
}; |
||||
|
||||
export default useProjectModal; |
@ -1,38 +1,45 @@
@@ -1,38 +1,45 @@
|
||||
import { useEffect } from "react"; |
||||
import { Project } from "../type"; |
||||
import { cleanObject } from "../utils"; |
||||
import useRequest from "./useRequest"; |
||||
import useAsync from "./useAsync"; |
||||
import { useMutation, useQuery, useQueryClient } from "react-query"; |
||||
|
||||
const useProjects = (param?: Partial<Project>) => { |
||||
const request = useRequest(); |
||||
const { run, ...result } = useAsync<Project[]>(); |
||||
|
||||
useEffect(() => { |
||||
run(request("/projects", { data: cleanObject(param || {}) })); |
||||
}, [param]); |
||||
|
||||
return result; |
||||
return useQuery<Project[], Error>(["projects", param], () => |
||||
request("/projects", { data: param }) |
||||
); |
||||
}; |
||||
|
||||
const useEditProject = () => { |
||||
const { run, ...asyncResult } = useAsync(); |
||||
const request = useRequest(); |
||||
const mutate = (params: Partial<Project>) => { |
||||
return run(request(`/projects/${params.id}`, { data: params, method: "PATCH" })); |
||||
}; |
||||
|
||||
return { mutate, ...asyncResult }; |
||||
const queryClient = useQueryClient(); |
||||
return useMutation( |
||||
(params: Partial<Project>) => |
||||
request(`/projects/${params.id}`, { method: "PATCH", data: params }), |
||||
{ onSuccess: () => queryClient.invalidateQueries("projects") } |
||||
); |
||||
}; |
||||
|
||||
const useAddProject = () => { |
||||
const { run, ...asyncResult } = useAsync(); |
||||
const request = useRequest(); |
||||
const mutate = (params: Partial<Project>) => { |
||||
return run(request(`/projects/${params.id}`, { data: params, method: "POST" })); |
||||
}; |
||||
const queryClient = useQueryClient(); |
||||
|
||||
return { mutate, ...asyncResult }; |
||||
return useMutation( |
||||
(params: Partial<Project>) => |
||||
request(`/projects`, { method: "POST", data: params }), |
||||
{ onSuccess: () => queryClient.invalidateQueries("projects") } |
||||
); |
||||
}; |
||||
|
||||
const useProject = (id?: number) => { |
||||
const request = useRequest(); |
||||
return ( |
||||
useQuery<Project>( |
||||
["project", { id }], |
||||
() => request(`/projects/${id}`, {}), |
||||
{ enabled: !!id } |
||||
) |
||||
); |
||||
}; |
||||
|
||||
export { useProjects, useEditProject, useAddProject }; |
||||
export { useProjects, useEditProject, useAddProject, useProject }; |
||||
|
@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
|
||||
import { URLSearchParamsInit, useSearchParams } from "react-router-dom"; |
||||
import { cleanObject } from "../utils"; |
||||
|
||||
const useSetUrlSearchParam = () => { |
||||
const [searchParams, setSearchParam] = useSearchParams(); |
||||
return (params: { [key in string]: unknown }) => { |
||||
const o = cleanObject({ |
||||
...Object.fromEntries(searchParams), |
||||
...params, |
||||
}) as URLSearchParamsInit; |
||||
return setSearchParam(o); |
||||
}; |
||||
}; |
||||
|
||||
export default useSetUrlSearchParam; |
Loading…
Reference in new issue