Initial commit: Agile Project Manager
- Complete React + TypeScript application with Vite - Dashboard with charts and metrics visualization - Kanban board with drag-and-drop functionality - Product backlog management with user stories - Sprint planning and tracking features - Comprehensive UI component library (shadcn/ui) - Tailwind CSS styling with dark mode support - Context-based state management - Mock data for immediate testing and demonstration
This commit is contained in:
250
contexts/AppContext.tsx
Normal file
250
contexts/AppContext.tsx
Normal file
@@ -0,0 +1,250 @@
|
||||
import React, { createContext, useContext, useState, ReactNode } from 'react';
|
||||
import { Task, UserStory, Sprint } from '../types';
|
||||
|
||||
interface AppContextType {
|
||||
tasks: Task[];
|
||||
userStories: UserStory[];
|
||||
sprints: Sprint[];
|
||||
activeSprint: Sprint | null;
|
||||
addTask: (task: Omit<Task, 'id' | 'createdAt' | 'updatedAt' | 'comments'>) => void;
|
||||
updateTask: (id: string, updates: Partial<Task>) => void;
|
||||
deleteTask: (id: string) => void;
|
||||
addComment: (taskId: string, comment: string, author: string) => void;
|
||||
addUserStory: (story: Omit<UserStory, 'id'>) => void;
|
||||
updateUserStory: (id: string, updates: Partial<UserStory>) => void;
|
||||
reorderUserStories: (stories: UserStory[]) => void;
|
||||
addSprint: (sprint: Omit<Sprint, 'id'>) => void;
|
||||
updateSprint: (id: string, updates: Partial<Sprint>) => void;
|
||||
closeSprint: (id: string) => void;
|
||||
setActiveSprint: (sprint: Sprint) => void;
|
||||
}
|
||||
|
||||
const AppContext = createContext<AppContextType | undefined>(undefined);
|
||||
|
||||
export const useApp = () => {
|
||||
const context = useContext(AppContext);
|
||||
if (!context) {
|
||||
throw new Error('useApp must be used within AppProvider');
|
||||
}
|
||||
return context;
|
||||
};
|
||||
|
||||
const mockUserStories: UserStory[] = [
|
||||
{
|
||||
id: 'us-1',
|
||||
title: 'User Authentication',
|
||||
description: 'As a user, I want to log in securely',
|
||||
storyPoints: 5,
|
||||
businessValue: 8,
|
||||
acceptanceCriteria: 'User can login with email and password',
|
||||
status: 'in-sprint',
|
||||
priority: 1,
|
||||
sprintId: 'sprint-1'
|
||||
},
|
||||
{
|
||||
id: 'us-2',
|
||||
title: 'Dashboard View',
|
||||
description: 'As a user, I want to see my dashboard',
|
||||
storyPoints: 8,
|
||||
businessValue: 9,
|
||||
acceptanceCriteria: 'Dashboard shows key metrics and recent activity',
|
||||
status: 'in-sprint',
|
||||
priority: 2,
|
||||
sprintId: 'sprint-1'
|
||||
},
|
||||
{
|
||||
id: 'us-3',
|
||||
title: 'Data Export',
|
||||
description: 'As a user, I want to export my data',
|
||||
storyPoints: 3,
|
||||
businessValue: 5,
|
||||
acceptanceCriteria: 'User can export data in CSV format',
|
||||
status: 'sprint-ready',
|
||||
priority: 3
|
||||
}
|
||||
];
|
||||
|
||||
const mockSprint: Sprint = {
|
||||
id: 'sprint-1',
|
||||
name: 'Sprint 1',
|
||||
goal: 'Deliver core authentication and dashboard features',
|
||||
startDate: new Date('2025-10-13'),
|
||||
endDate: new Date('2025-10-27'),
|
||||
capacity: 40,
|
||||
status: 'active',
|
||||
userStories: ['us-1', 'us-2']
|
||||
};
|
||||
|
||||
const mockTasks: Task[] = [
|
||||
{
|
||||
id: 'task-1',
|
||||
title: 'Design login form',
|
||||
description: 'Create mockups for the login interface',
|
||||
timeComplexity: '4 hours',
|
||||
status: 'done',
|
||||
userStoryId: 'us-1',
|
||||
comments: [
|
||||
{
|
||||
id: 'c-1',
|
||||
text: 'Mockups look great!',
|
||||
author: 'Jane Smith',
|
||||
timestamp: new Date('2025-10-14')
|
||||
}
|
||||
],
|
||||
createdAt: new Date('2025-10-13'),
|
||||
updatedAt: new Date('2025-10-14')
|
||||
},
|
||||
{
|
||||
id: 'task-2',
|
||||
title: 'Implement authentication API',
|
||||
description: 'Set up backend authentication endpoints',
|
||||
timeComplexity: '8 hours',
|
||||
status: 'in-progress',
|
||||
userStoryId: 'us-1',
|
||||
comments: [],
|
||||
createdAt: new Date('2025-10-13'),
|
||||
updatedAt: new Date('2025-10-15')
|
||||
},
|
||||
{
|
||||
id: 'task-3',
|
||||
title: 'Create dashboard layout',
|
||||
description: 'Build responsive dashboard layout',
|
||||
timeComplexity: '6 hours',
|
||||
status: 'todo',
|
||||
userStoryId: 'us-2',
|
||||
comments: [],
|
||||
createdAt: new Date('2025-10-13'),
|
||||
updatedAt: new Date('2025-10-13')
|
||||
}
|
||||
];
|
||||
|
||||
export const AppProvider = ({ children }: { children: ReactNode }) => {
|
||||
const [tasks, setTasks] = useState<Task[]>(mockTasks);
|
||||
const [userStories, setUserStories] = useState<UserStory[]>(mockUserStories);
|
||||
const [sprints, setSprints] = useState<Sprint[]>([mockSprint]);
|
||||
const [activeSprint, setActiveSprintState] = useState<Sprint | null>(mockSprint);
|
||||
|
||||
const addTask = (taskData: Omit<Task, 'id' | 'createdAt' | 'updatedAt' | 'comments'>) => {
|
||||
const newTask: Task = {
|
||||
...taskData,
|
||||
id: `task-${Date.now()}`,
|
||||
comments: [],
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date()
|
||||
};
|
||||
setTasks([...tasks, newTask]);
|
||||
};
|
||||
|
||||
const updateTask = (id: string, updates: Partial<Task>) => {
|
||||
setTasks(tasks.map(task =>
|
||||
task.id === id ? { ...task, ...updates, updatedAt: new Date() } : task
|
||||
));
|
||||
};
|
||||
|
||||
const deleteTask = (id: string) => {
|
||||
setTasks(tasks.filter(task => task.id !== id));
|
||||
};
|
||||
|
||||
const addComment = (taskId: string, text: string, author: string) => {
|
||||
setTasks(tasks.map(task => {
|
||||
if (task.id === taskId) {
|
||||
return {
|
||||
...task,
|
||||
comments: [
|
||||
...task.comments,
|
||||
{
|
||||
id: `c-${Date.now()}`,
|
||||
text,
|
||||
author,
|
||||
timestamp: new Date()
|
||||
}
|
||||
],
|
||||
updatedAt: new Date()
|
||||
};
|
||||
}
|
||||
return task;
|
||||
}));
|
||||
};
|
||||
|
||||
const addUserStory = (storyData: Omit<UserStory, 'id'>) => {
|
||||
const newStory: UserStory = {
|
||||
...storyData,
|
||||
id: `us-${Date.now()}`
|
||||
};
|
||||
setUserStories([...userStories, newStory]);
|
||||
};
|
||||
|
||||
const updateUserStory = (id: string, updates: Partial<UserStory>) => {
|
||||
setUserStories(userStories.map(story =>
|
||||
story.id === id ? { ...story, ...updates } : story
|
||||
));
|
||||
};
|
||||
|
||||
const reorderUserStories = (stories: UserStory[]) => {
|
||||
setUserStories(stories);
|
||||
};
|
||||
|
||||
const addSprint = (sprintData: Omit<Sprint, 'id'>) => {
|
||||
const newSprint: Sprint = {
|
||||
...sprintData,
|
||||
id: `sprint-${Date.now()}`
|
||||
};
|
||||
setSprints([...sprints, newSprint]);
|
||||
};
|
||||
|
||||
const updateSprint = (id: string, updates: Partial<Sprint>) => {
|
||||
setSprints(sprints.map(sprint =>
|
||||
sprint.id === id ? { ...sprint, ...updates } : sprint
|
||||
));
|
||||
if (activeSprint?.id === id) {
|
||||
setActiveSprintState(prev => prev ? { ...prev, ...updates } : null);
|
||||
}
|
||||
};
|
||||
|
||||
const closeSprint = (id: string) => {
|
||||
// Move unfinished items back to backlog
|
||||
const sprint = sprints.find(s => s.id === id);
|
||||
if (sprint) {
|
||||
setUserStories(userStories.map(story => {
|
||||
if (story.sprintId === id) {
|
||||
return { ...story, status: 'backlog', sprintId: undefined };
|
||||
}
|
||||
return story;
|
||||
}));
|
||||
|
||||
setSprints(sprints.map(s =>
|
||||
s.id === id ? { ...s, status: 'closed' as const } : s
|
||||
));
|
||||
|
||||
if (activeSprint?.id === id) {
|
||||
setActiveSprintState(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const setActiveSprint = (sprint: Sprint) => {
|
||||
setActiveSprintState(sprint);
|
||||
};
|
||||
|
||||
return (
|
||||
<AppContext.Provider value={{
|
||||
tasks,
|
||||
userStories,
|
||||
sprints,
|
||||
activeSprint,
|
||||
addTask,
|
||||
updateTask,
|
||||
deleteTask,
|
||||
addComment,
|
||||
addUserStory,
|
||||
updateUserStory,
|
||||
reorderUserStories,
|
||||
addSprint,
|
||||
updateSprint,
|
||||
closeSprint,
|
||||
setActiveSprint
|
||||
}}>
|
||||
{children}
|
||||
</AppContext.Provider>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user