From 04ba00d1087c5208f67d21dfaa7fda4a1704c496 Mon Sep 17 00:00:00 2001 From: Yaojia Wang Date: Wed, 5 Nov 2025 13:30:48 +0100 Subject: [PATCH] fix(frontend): Align Epic field names with backend API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix frontend-backend API field mismatches for Epic entity by: 1. Changed Epic.title to Epic.name in type definitions 2. Added Epic.createdBy field (required by backend) 3. Updated all Epic references from epic.title to epic.name 4. Fixed Epic form to use name field and include createdBy Files modified: - types/project.ts: Updated Epic, CreateEpicDto, UpdateEpicDto interfaces - components/epics/epic-form.tsx: Fixed defaultValues to use epic.name - components/projects/hierarchy-tree.tsx: Replaced epic.title with epic.name - components/projects/story-form.tsx: Fixed epic dropdown to show epic.name - app/(dashboard)/projects/[id]/epics/page.tsx: Display epic.name in list - app/(dashboard)/projects/[id]/page.tsx: Display epic.name in preview - app/(dashboard)/api-test/page.tsx: Display epic.name in test page This resolves the 400 Bad Request error when creating Epics caused by missing 'Name' field (was sending 'title' instead) and missing 'CreatedBy' field. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- app/(dashboard)/api-test/page.tsx | 2 +- app/(dashboard)/projects/[id]/epics/page.tsx | 2 +- app/(dashboard)/projects/[id]/page.tsx | 2 +- components/epics/epic-form.tsx | 14 +++++++++++--- components/projects/hierarchy-tree.tsx | 2 +- components/projects/story-form.tsx | 2 +- types/project.ts | 8 +++++--- 7 files changed, 21 insertions(+), 11 deletions(-) diff --git a/app/(dashboard)/api-test/page.tsx b/app/(dashboard)/api-test/page.tsx index 4b5386a..5deffc1 100644 --- a/app/(dashboard)/api-test/page.tsx +++ b/app/(dashboard)/api-test/page.tsx @@ -61,7 +61,7 @@ export default function ApiTestPage() {
{epics.map((epic) => ( -

{epic.title}

+

{epic.name}

{epic.description && (

{epic.description}

)} diff --git a/app/(dashboard)/projects/[id]/epics/page.tsx b/app/(dashboard)/projects/[id]/epics/page.tsx index d8947a2..a510848 100644 --- a/app/(dashboard)/projects/[id]/epics/page.tsx +++ b/app/(dashboard)/projects/[id]/epics/page.tsx @@ -207,7 +207,7 @@ export default function EpicsPage({ params }: EpicsPageProps) { className="block hover:underline" > - {epic.title} + {epic.name}
diff --git a/app/(dashboard)/projects/[id]/page.tsx b/app/(dashboard)/projects/[id]/page.tsx index d19a5a8..36faccc 100644 --- a/app/(dashboard)/projects/[id]/page.tsx +++ b/app/(dashboard)/projects/[id]/page.tsx @@ -239,7 +239,7 @@ export default function ProjectDetailPage({ params }: ProjectDetailPageProps) { >
-

{epic.title}

+

{epic.name}

{epic.status} diff --git a/components/epics/epic-form.tsx b/components/epics/epic-form.tsx index 6abd1bb..d3e858d 100644 --- a/components/epics/epic-form.tsx +++ b/components/epics/epic-form.tsx @@ -26,9 +26,10 @@ import { useCreateEpic, useUpdateEpic } from '@/lib/hooks/use-epics'; import type { Epic, WorkItemPriority } from '@/types/project'; import { toast } from 'sonner'; import { Loader2 } from 'lucide-react'; +import { useAuthStore } from '@/stores/authStore'; const epicSchema = z.object({ - title: z + name: z .string() .min(1, 'Title is required') .max(200, 'Title must be less than 200 characters'), @@ -57,11 +58,12 @@ export function EpicForm({ projectId, epic, onSuccess, onCancel }: EpicFormProps const isEditing = !!epic; const createEpic = useCreateEpic(); const updateEpic = useUpdateEpic(); + const user = useAuthStore((state) => state.user); const form = useForm({ resolver: zodResolver(epicSchema), defaultValues: { - title: epic?.title || '', + name: epic?.name || '', // Fixed: use 'name' instead of 'title' description: epic?.description || '', priority: epic?.priority || 'Medium', estimatedHours: epic?.estimatedHours || ('' as any), @@ -70,6 +72,11 @@ export function EpicForm({ projectId, epic, onSuccess, onCancel }: EpicFormProps async function onSubmit(data: EpicFormValues) { try { + if (!user?.id) { + toast.error('User not authenticated'); + return; + } + const payload = { ...data, estimatedHours: data.estimatedHours || undefined, @@ -83,6 +90,7 @@ export function EpicForm({ projectId, epic, onSuccess, onCancel }: EpicFormProps } else { await createEpic.mutateAsync({ projectId, + createdBy: user.id, ...payload, }); } @@ -107,7 +115,7 @@ export function EpicForm({ projectId, epic, onSuccess, onCancel }: EpicFormProps
( Epic Title * diff --git a/components/projects/hierarchy-tree.tsx b/components/projects/hierarchy-tree.tsx index 0d5d78b..8914760 100644 --- a/components/projects/hierarchy-tree.tsx +++ b/components/projects/hierarchy-tree.tsx @@ -102,7 +102,7 @@ function EpicNode({ epic, onEpicClick, onStoryClick, onTaskClick }: EpicNodeProp onEpicClick?.(epic); }} > - {epic.title} + {epic.name} diff --git a/components/projects/story-form.tsx b/components/projects/story-form.tsx index b2bd0f5..837600a 100644 --- a/components/projects/story-form.tsx +++ b/components/projects/story-form.tsx @@ -144,7 +144,7 @@ export function StoryForm({ ) : ( epics.map((epic) => ( - {epic.title} + {epic.name} )) )} diff --git a/types/project.ts b/types/project.ts index cba37ce..a1bde95 100644 --- a/types/project.ts +++ b/types/project.ts @@ -28,7 +28,7 @@ export interface UpdateProjectDto { // ==================== Epic ==================== export interface Epic { id: string; - title: string; + name: string; // Changed from 'title' to match backend API description?: string; projectId: string; status: WorkItemStatus; @@ -36,6 +36,7 @@ export interface Epic { estimatedHours?: number; actualHours?: number; assigneeId?: string; + createdBy: string; // Added to match backend API (required field) tenantId: string; createdAt: string; updatedAt: string; @@ -43,14 +44,15 @@ export interface Epic { export interface CreateEpicDto { projectId: string; - title: string; + name: string; // Changed from 'title' to match backend API description?: string; priority: WorkItemPriority; estimatedHours?: number; + createdBy: string; // Added to match backend API (required field) } export interface UpdateEpicDto { - title?: string; + name?: string; // Changed from 'title' to match backend API description?: string; priority?: WorkItemPriority; estimatedHours?: number;