feat(frontend): Refactor Kanban board to focus on Story management

Refactored the Kanban board from a mixed Epic/Story/Task view to focus exclusively on Stories, which are the right granularity for Kanban management.

Changes:
- Created StoryCard component with Epic breadcrumb, priority badges, and estimated hours display
- Updated KanbanColumn to use Story type and display epic names
- Created CreateStoryDialog for story creation with epic selection
- Added useProjectStories hook to fetch all stories across epics for a project
- Refactored Kanban page to show Stories only with drag-and-drop status updates
- Updated SignalR event handlers to focus on Story events only
- Changed UI text from 'New Issue' to 'New Story' and 'update issue status' to 'update story status'
- Implemented story status change via useChangeStoryStatus hook

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Yaojia Wang
2025-11-05 15:03:12 +01:00
parent 2a0394b5ab
commit 90e3d2416c
6 changed files with 493 additions and 127 deletions

View File

@@ -15,8 +15,10 @@ import type {
// ==================== Epics API ====================
export const epicsApi = {
list: async (projectId?: string): Promise<Epic[]> => {
const params = projectId ? { projectId } : undefined;
return api.get('/api/v1/epics', { params });
if (!projectId) {
throw new Error('projectId is required for listing epics');
}
return api.get(`/api/v1/projects/${projectId}/epics`);
},
get: async (id: string): Promise<Epic> => {
@@ -47,8 +49,10 @@ export const epicsApi = {
// ==================== Stories API ====================
export const storiesApi = {
list: async (epicId?: string): Promise<Story[]> => {
const params = epicId ? { epicId } : undefined;
return api.get('/api/v1/stories', { params });
if (!epicId) {
throw new Error('epicId is required for listing stories');
}
return api.get(`/api/v1/epics/${epicId}/stories`);
},
get: async (id: string): Promise<Story> => {
@@ -79,8 +83,10 @@ export const storiesApi = {
// ==================== Tasks API ====================
export const tasksApi = {
list: async (storyId?: string): Promise<Task[]> => {
const params = storyId ? { storyId } : undefined;
return api.get('/api/v1/tasks', { params });
if (!storyId) {
throw new Error('storyId is required for listing tasks');
}
return api.get(`/api/v1/stories/${storyId}/tasks`);
},
get: async (id: string): Promise<Task> => {