import React, { useState } from 'react'; import { useApp } from '../contexts/AppContext'; import { Sprint, UserStory } from '../types'; import { Card } from './ui/card'; import { Badge } from './ui/badge'; import { Button } from './ui/button'; import { Dialog, DialogContent, DialogHeader, DialogTitle } from './ui/dialog'; import { Input } from './ui/input'; import { Textarea } from './ui/textarea'; import { Label } from './ui/label'; import { format } from 'date-fns'; import { Calendar, Plus, Edit, XCircle, PlayCircle } from 'lucide-react'; export const SprintManagement: React.FC = () => { const { sprints, userStories, updateSprint, closeSprint, addSprint, setActiveSprint, updateUserStory } = useApp(); const [editDialogOpen, setEditDialogOpen] = useState(false); const [createDialogOpen, setCreateDialogOpen] = useState(false); const [selectedSprint, setSelectedSprint] = useState(null); const [formData, setFormData] = useState({ name: '', goal: '', startDate: '', endDate: '', capacity: 0 }); const handleEdit = (sprint: Sprint) => { setSelectedSprint(sprint); setFormData({ name: sprint.name, goal: sprint.goal, startDate: format(new Date(sprint.startDate), 'yyyy-MM-dd'), endDate: format(new Date(sprint.endDate), 'yyyy-MM-dd'), capacity: sprint.capacity }); setEditDialogOpen(true); }; const handleSave = () => { if (selectedSprint) { updateSprint(selectedSprint.id, { name: formData.name, goal: formData.goal, startDate: new Date(formData.startDate), endDate: new Date(formData.endDate), capacity: formData.capacity }); setEditDialogOpen(false); setSelectedSprint(null); } }; const handleCreate = () => { addSprint({ name: formData.name, goal: formData.goal, startDate: new Date(formData.startDate), endDate: new Date(formData.endDate), capacity: formData.capacity, status: 'planning', userStories: [] }); setCreateDialogOpen(false); setFormData({ name: '', goal: '', startDate: '', endDate: '', capacity: 0 }); }; const handleCloseSprint = (sprint: Sprint) => { if (confirm(`Are you sure you want to close ${sprint.name}? Unfinished items will be moved back to the backlog.`)) { closeSprint(sprint.id); } }; const handleActivate = (sprint: Sprint) => { updateSprint(sprint.id, { status: 'active' }); setActiveSprint(sprint); }; const getSprintStories = (sprintId: string) => { return userStories.filter(story => story.sprintId === sprintId); }; const getTotalPoints = (sprintId: string) => { return getSprintStories(sprintId).reduce((sum, story) => sum + story.storyPoints, 0); }; const getStatusBadge = (status: Sprint['status']) => { const variants: Record = { planning: { variant: 'outline', label: 'Planning' }, active: { variant: 'default', label: 'Active' }, closed: { variant: 'secondary', label: 'Closed' } }; const { variant, label } = variants[status]; return {label}; }; return (

Sprint Management

Create, edit, and manage sprints

{sprints.map(sprint => { const sprintStories = getSprintStories(sprint.id); const totalPoints = getTotalPoints(sprint.id); return (

{sprint.name}

{getStatusBadge(sprint.status)}

{sprint.goal}

{format(new Date(sprint.startDate), 'MMM dd')} - {format(new Date(sprint.endDate), 'MMM dd, yyyy')}
Capacity: {sprint.capacity} pts
Committed: {totalPoints} pts
Stories: {sprintStories.length}
{sprint.status !== 'closed' && ( <> {sprint.status === 'planning' && ( )} {sprint.status === 'active' && ( )} )}
); })}
{sprints.length === 0 && (
No sprints yet. Create your first sprint to get started.
)} {/* Edit Dialog */} Edit Sprint
setFormData({ ...formData, name: e.target.value })} />