112 lines
3.2 KiB
TypeScript
112 lines
3.2 KiB
TypeScript
import { Alert, Input, Modal, Select, Space, Switch, Typography } from '@arco-design/web-react'
|
|
import { useEffect, useMemo, useState } from 'react'
|
|
import type { ProjectWorkspace, TaskItem } from './project-types'
|
|
|
|
const { Text } = Typography
|
|
const { TextArea } = Input
|
|
|
|
export type ProjectTaskUpdate = {
|
|
taskId: string
|
|
title: string
|
|
summary: string
|
|
tag: string
|
|
completed: boolean
|
|
}
|
|
|
|
type TaskDraft = {
|
|
title: string
|
|
summary: string
|
|
tag: string
|
|
completed: boolean
|
|
}
|
|
|
|
export function ProjectTaskEditModal({
|
|
task,
|
|
workspace,
|
|
onClose,
|
|
onSubmit,
|
|
}: {
|
|
task: TaskItem | null
|
|
workspace: ProjectWorkspace
|
|
onClose: () => void
|
|
onSubmit: (update: ProjectTaskUpdate) => Promise<void>
|
|
}) {
|
|
const tagOptions = useMemo(() => workspace.tags.filter((tag) => tag !== 'all' && tag !== '全部'), [workspace.tags])
|
|
const [draft, setDraft] = useState<TaskDraft>({ title: '', summary: '', tag: '', completed: false })
|
|
const [saving, setSaving] = useState(false)
|
|
const [saveError, setSaveError] = useState('')
|
|
|
|
useEffect(() => {
|
|
if (!task) return
|
|
setSaveError('')
|
|
setDraft({
|
|
title: task.title,
|
|
summary: task.summary,
|
|
tag: task.tag,
|
|
completed: task.completed,
|
|
})
|
|
}, [task])
|
|
|
|
async function saveTask() {
|
|
if (!task || saving) return
|
|
setSaving(true)
|
|
setSaveError('')
|
|
try {
|
|
await onSubmit({
|
|
taskId: task.id,
|
|
title: draft.title.trim() || task.title,
|
|
summary: draft.summary.trim(),
|
|
tag: draft.tag.trim(),
|
|
completed: draft.completed,
|
|
})
|
|
onClose()
|
|
} catch (error) {
|
|
setSaveError(error instanceof Error ? error.message : '任务保存失败,请稍后重试')
|
|
} finally {
|
|
setSaving(false)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<Modal
|
|
className="action-modal"
|
|
title="编辑计划"
|
|
visible={Boolean(task)}
|
|
confirmLoading={saving}
|
|
maskClosable={!saving}
|
|
cancelButtonProps={{ disabled: saving }}
|
|
onCancel={() => { if (!saving) onClose() }}
|
|
onOk={() => void saveTask()}
|
|
>
|
|
<Space direction="vertical" size={12} className="action-form">
|
|
{saveError && <Alert type="error" content={saveError} />}
|
|
<label>
|
|
<Text>标题</Text>
|
|
<Input value={draft.title} onChange={(title) => setDraft((value) => ({ ...value, title }))} />
|
|
</label>
|
|
<label>
|
|
<Text>正文</Text>
|
|
<TextArea rows={4} value={draft.summary} onChange={(summary) => setDraft((value) => ({ ...value, summary }))} />
|
|
</label>
|
|
<label>
|
|
<Text>标签</Text>
|
|
<Select
|
|
allowClear
|
|
value={draft.tag || undefined}
|
|
placeholder="不设置标签"
|
|
onChange={(tag) => setDraft((value) => ({ ...value, tag: tag ?? '' }))}
|
|
>
|
|
{tagOptions.map((tag) => (
|
|
<Select.Option key={tag} value={tag}>{tag}</Select.Option>
|
|
))}
|
|
</Select>
|
|
</label>
|
|
<label className="action-switch">
|
|
<Text>完成状态</Text>
|
|
<Switch checked={draft.completed} checkedText="完成" uncheckedText="未完成" onChange={(completed) => setDraft((value) => ({ ...value, completed }))} />
|
|
</label>
|
|
</Space>
|
|
</Modal>
|
|
)
|
|
}
|