Files
ColaFlow/docs/plans/sprint_1_story_2_task_3.md
Yaojia Wang 08b317e789
Some checks failed
Code Coverage / Generate Coverage Report (push) Has been cancelled
Tests / Run Tests (9.0.x) (push) Has been cancelled
Tests / Docker Build Test (push) Has been cancelled
Tests / Test Summary (push) Has been cancelled
Add trace files.
2025-11-04 23:28:56 +01:00

3.1 KiB

Task 7: Implement Epic/Story/Task Forms

Task ID: TASK-007 | Story: STORY-002 | Sprint: Sprint 1 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

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<typeof epicSchema>;

export const EpicForm: React.FC<{ epic?: Epic, onSuccess: () => void }> = ({ epic, onSuccess }) => {
  const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm<EpicFormData>({
    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 (
    <form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
      <div>
        <label htmlFor="title">Title *</label>
        <input id="title" {...register('title')} className="form-input" />
        {errors.title && <span className="text-red-500">{errors.title.message}</span>}
      </div>

      <div>
        <label htmlFor="description">Description</label>
        <textarea id="description" {...register('description')} className="form-textarea" />
      </div>

      <div>
        <label htmlFor="priority">Priority *</label>
        <select id="priority" {...register('priority')} className="form-select">
          <option value="Low">Low</option>
          <option value="Medium">Medium</option>
          <option value="High">High</option>
          <option value="Critical">Critical</option>
        </select>
      </div>

      <button type="submit" disabled={isSubmitting} className="btn-primary">
        {isSubmitting ? 'Saving...' : (epic ? 'Update Epic' : 'Create Epic')}
      </button>
    </form>
  );
};

Acceptance Criteria

  • EpicForm component with validation
  • StoryForm with parent epic selection dropdown
  • TaskForm with parent story selection dropdown
  • Zod schemas for all forms
  • Loading states during submission
  • Error messages displayed

Deliverables

  1. EpicForm.tsx
  2. StoryForm.tsx (with parent epic selector)
  3. TaskForm.tsx (with parent story selector)
  4. Validation schemas
  5. Unit tests (15+ tests)

Status: Not Started | Created: 2025-11-04