import { useState, useEffect } from 'react' import { useParams, useNavigate } from 'react-router-dom' import api from '@/services/api' import type { Milestone, MilestoneProgress, MilestoneItems, Issue } from '@/types' import dayjs from 'dayjs' export default function MilestoneDetailPage() { const { id } = useParams() const navigate = useNavigate() const [milestone, setMilestone] = useState(null) const [progress, setProgress] = useState(null) const [items, setItems] = useState(null) const [activeTab, setActiveTab] = useState<'tasks' | 'supports' | 'meetings'>('tasks') const [showCreateTask, setShowCreateTask] = useState(false) const [showCreateSupport, setShowCreateSupport] = useState(false) const [showCreateMeeting, setShowCreateMeeting] = useState(false) const [newTitle, setNewTitle] = useState('') const [newDesc, setNewDesc] = useState('') const [newEffort, setNewEffort] = useState(5) const [newTime, setNewTime] = useState('09:00') useEffect(() => { api.get(`/milestones/${id}`).then(({ data }) => setMilestone(data)) api.get(`/milestones/${id}/progress`).then(({ data }) => setProgress(data)).catch(() => {}) api.get(`/milestones/${id}/items`).then(({ data }) => setItems(data)).catch(() => {}) }, [id]) const createItem = async (type: 'tasks' | 'supports' | 'meetings') => { if (!newTitle.trim()) return const payload: any = { title: newTitle, description: newDesc || null, status: 'open', priority: 'medium' } if (type === 'tasks') { payload.estimated_effort = newEffort payload.estimated_working_time = newTime } await api.post(`/milestones/${id}/${type}`, payload) setNewTitle('') setNewDesc('') setShowCreateTask(false) setShowCreateSupport(false) setShowCreateMeeting(false) api.get(`/milestones/${id}/items`).then(({ data }) => setItems(data)) } const isProgressing = milestone?.status === 'progressing' if (!milestone) return
Loading...
const tasks = items?.tasks || [] const supports = items?.supports || [] const meetings = items?.meetings || [] const renderTaskRow = (t: any) => ( navigate(`/issues/${t.id}`)}> {t.task_code || t.id} {t.title} {t.task_status || t.status} {t.estimated_effort || '-'} {t.estimated_working_time || '-'} ) return (

🏁 {milestone.title}

{milestone.status} {milestone.due_date && Due {dayjs(milestone.due_date).format('YYYY-MM-DD')}} {milestone.planned_release_date && Planned Release: {dayjs(milestone.planned_release_date).format('YYYY-MM-DD')}}
{milestone.description && (

Description

{milestone.description}

)} {progress && (

Progress (Tasks: {progress.completed}/{progress.total})

{progress.progress_pct.toFixed(0)}%
{progress.time_progress_pct !== null && ( <>

Time Progress

{progress.time_progress_pct.toFixed(0)}%
)}
)}
{!isProgressing && ( <> )} {isProgressing && Milestone is in progress - cannot add new items}
{(showCreateTask || showCreateSupport || showCreateMeeting) && (
setNewTitle(e.target.value)} style={{ marginBottom: 8 }} />