feat: unify project milestone and task editing with modals
This commit is contained in:
@@ -17,13 +17,27 @@ type Props = {
|
||||
isOpen: boolean
|
||||
onClose: () => void
|
||||
onCreated?: (task: Task) => void | Promise<void>
|
||||
onSaved?: (task: Task) => void | Promise<void>
|
||||
initialProjectId?: number
|
||||
initialMilestoneId?: number
|
||||
lockProject?: boolean
|
||||
lockMilestone?: boolean
|
||||
task?: Task | null
|
||||
}
|
||||
|
||||
const makeInitialForm = (projectId = 0, milestoneId = 0) => ({
|
||||
type FormState = {
|
||||
title: string
|
||||
description: string
|
||||
project_id: number
|
||||
milestone_id: number
|
||||
task_type: string
|
||||
task_subtype: string
|
||||
priority: string
|
||||
tags: string
|
||||
reporter_id: number
|
||||
}
|
||||
|
||||
const makeInitialForm = (projectId = 0, milestoneId = 0): FormState => ({
|
||||
title: '',
|
||||
description: '',
|
||||
project_id: projectId,
|
||||
@@ -39,16 +53,19 @@ export default function CreateTaskModal({
|
||||
isOpen,
|
||||
onClose,
|
||||
onCreated,
|
||||
onSaved,
|
||||
initialProjectId,
|
||||
initialMilestoneId,
|
||||
lockProject = false,
|
||||
lockMilestone = false,
|
||||
task,
|
||||
}: Props) {
|
||||
const [projects, setProjects] = useState<Project[]>([])
|
||||
const [milestones, setMilestones] = useState<Milestone[]>([])
|
||||
const [saving, setSaving] = useState(false)
|
||||
const [form, setForm] = useState(makeInitialForm(initialProjectId, initialMilestoneId))
|
||||
const [form, setForm] = useState<FormState>(makeInitialForm(initialProjectId, initialMilestoneId))
|
||||
|
||||
const isEdit = Boolean(task)
|
||||
const currentType = useMemo(
|
||||
() => TASK_TYPES.find((t) => t.value === form.task_type) || TASK_TYPES[2],
|
||||
[form.task_type]
|
||||
@@ -76,13 +93,26 @@ export default function CreateTaskModal({
|
||||
const { data } = await api.get<Project[]>('/projects')
|
||||
setProjects(data)
|
||||
|
||||
const chosenProjectId = initialProjectId || data[0]?.id || 0
|
||||
setForm(makeInitialForm(chosenProjectId, initialMilestoneId || 0))
|
||||
await loadMilestones(chosenProjectId, initialMilestoneId)
|
||||
const chosenProjectId = task?.project_id || initialProjectId || data[0]?.id || 0
|
||||
const chosenMilestoneId = task?.milestone_id || initialMilestoneId || 0
|
||||
|
||||
setForm(task ? {
|
||||
title: task.title,
|
||||
description: task.description || '',
|
||||
project_id: task.project_id,
|
||||
milestone_id: task.milestone_id || 0,
|
||||
task_type: task.task_type,
|
||||
task_subtype: task.task_subtype || '',
|
||||
priority: task.priority,
|
||||
tags: task.tags || '',
|
||||
reporter_id: task.reporter_id,
|
||||
} : makeInitialForm(chosenProjectId, chosenMilestoneId))
|
||||
|
||||
await loadMilestones(chosenProjectId, chosenMilestoneId)
|
||||
}
|
||||
|
||||
init().catch(console.error)
|
||||
}, [isOpen, initialProjectId, initialMilestoneId])
|
||||
}, [isOpen, initialProjectId, initialMilestoneId, task])
|
||||
|
||||
const handleProjectChange = async (projectId: number) => {
|
||||
setForm((f) => ({ ...f, project_id: projectId, milestone_id: 0 }))
|
||||
@@ -105,8 +135,11 @@ export default function CreateTaskModal({
|
||||
|
||||
setSaving(true)
|
||||
try {
|
||||
const { data } = await api.post<Task>('/tasks', payload)
|
||||
const { data } = isEdit
|
||||
? await api.patch<Task>(`/tasks/${task!.id}`, payload)
|
||||
: await api.post<Task>('/tasks', payload)
|
||||
await onCreated?.(data)
|
||||
await onSaved?.(data)
|
||||
onClose()
|
||||
} finally {
|
||||
setSaving(false)
|
||||
@@ -119,7 +152,7 @@ export default function CreateTaskModal({
|
||||
<div className="modal-overlay" onClick={onClose}>
|
||||
<div className="modal task-create-modal" onClick={(e) => e.stopPropagation()}>
|
||||
<div className="modal-header">
|
||||
<h3>Create Task</h3>
|
||||
<h3>{isEdit ? 'Edit Task' : 'Create Task'}</h3>
|
||||
<button type="button" className="btn-secondary" onClick={onClose}>✕</button>
|
||||
</div>
|
||||
|
||||
@@ -226,7 +259,7 @@ export default function CreateTaskModal({
|
||||
|
||||
<div className="modal-actions">
|
||||
<button data-testid="create-task-button" type="submit" className="btn-primary" disabled={saving}>
|
||||
{saving ? 'Creating...' : 'Create'}
|
||||
{saving ? (isEdit ? 'Saving...' : 'Creating...') : (isEdit ? 'Save' : 'Create')}
|
||||
</button>
|
||||
<button type="button" className="btn-secondary" onClick={onClose} disabled={saving}>Cancel</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user