# Task 7: Implement Epic/Story/Task Forms **Task ID**: TASK-007 | **Story**: [STORY-002](sprint_1_story_2.md) | **Sprint**: [Sprint 1](sprint_1.md) **Estimated Hours**: 5h | **Assignee**: Frontend Developer 2 | **Priority**: P0 | **Status**: Not Started ## Task Description Build React forms for creating/editing Epic/Story/Task with validation, parent selection, and error handling. ## Implementation ### Example: EpicForm.tsx ```typescript import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { useCreateEpic, useUpdateEpic } from '../hooks/useEpics'; const epicSchema = z.object({ title: z.string().min(3, 'Title must be at least 3 characters'), description: z.string().optional(), projectId: z.string().uuid('Invalid project ID'), priority: z.enum(['Low', 'Medium', 'High', 'Critical']), status: z.enum(['Backlog', 'Todo', 'InProgress', 'Done']) }); type EpicFormData = z.infer; export const EpicForm: React.FC<{ epic?: Epic, onSuccess: () => void }> = ({ epic, onSuccess }) => { const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm({ resolver: zodResolver(epicSchema), defaultValues: epic || {} }); const createEpic = useCreateEpic(); const updateEpic = useUpdateEpic(); const onSubmit = async (data: EpicFormData) => { try { if (epic) { await updateEpic.mutateAsync({ id: epic.id, dto: data }); } else { await createEpic.mutateAsync(data); } onSuccess(); } catch (error) { console.error('Form submission error:', error); } }; return (
{errors.title && {errors.title.message}}