refactor: rename Issue → Task throughout frontend

- Rename files: IssuesPage → TasksPage, IssueDetailPage → TaskDetailPage,
  CreateIssuePage → CreateTaskPage
- Rename TypeScript interface: Issue → Task (keep backend field names)
- Update routes: /issues → /tasks, /issues/new → /tasks/new, /issues/:id → /tasks/:id
- Update CSS class names: issue-* → task-*, create-issue → create-task
- Update UI text: 'Issues' → 'Tasks', 'Create Issue' → 'Create Task'
- Keep 'issue' as a task subtype value in TASK_TYPES dropdown
- Keep all backend API endpoint paths unchanged (/issues, /comments, etc.)
- Rename local Task interface in MilestoneDetailPage to MilestoneTask
  to avoid conflict with the global Task type
This commit is contained in:
zhi
2026-03-16 07:47:58 +00:00
parent 9880cfc41e
commit 01affdb020
11 changed files with 94 additions and 94 deletions

View File

@@ -1,10 +1,10 @@
import { useState, useEffect } from 'react'
import { useParams, useNavigate } from 'react-router-dom'
import api from '@/services/api'
import type { Milestone, MilestoneProgress, Issue } from '@/types'
import type { Milestone, MilestoneProgress, Task } from '@/types'
import dayjs from 'dayjs'
interface Task {
interface MilestoneTask {
id: number
title: string
description?: string
@@ -24,9 +24,9 @@ export default function MilestoneDetailPage() {
const navigate = useNavigate()
const [milestone, setMilestone] = useState<Milestone | null>(null)
const [progress, setProgress] = useState<MilestoneProgress | null>(null)
const [tasks, setTasks] = useState<Task[]>([])
const [supports, setSupports] = useState<Issue[]>([])
const [meetings, setMeetings] = useState<Issue[]>([])
const [tasks, setTasks] = useState<MilestoneTask[]>([])
const [supports, setSupports] = useState<Task[]>([])
const [meetings, setMeetings] = useState<Task[]>([])
const [activeTab, setActiveTab] = useState<'tasks' | 'supports' | 'meetings'>('tasks')
const [showCreateTask, setShowCreateTask] = useState(false)
const [showCreateSupport, setShowCreateSupport] = useState(false)
@@ -52,9 +52,9 @@ export default function MilestoneDetailPage() {
useEffect(() => {
if (!projectCode || !id) return
api.get<Task[]>(`/tasks/${projectCode}/${id}`).then(({ data }) => setTasks(data)).catch(() => {})
api.get<Issue[]>(`/supports/${projectCode}/${id}`).then(({ data }) => setSupports(data)).catch(() => {})
api.get<Issue[]>(`/meetings/${projectCode}/${id}`).then(({ data }) => setMeetings(data)).catch(() => {})
api.get<MilestoneTask[]>(`/tasks/${projectCode}/${id}`).then(({ data }) => setTasks(data)).catch(() => {})
api.get<Task[]>(`/supports/${projectCode}/${id}`).then(({ data }) => setSupports(data)).catch(() => {})
api.get<Task[]>(`/meetings/${projectCode}/${id}`).then(({ data }) => setMeetings(data)).catch(() => {})
}, [projectCode, id])
const createItem = async (type: 'tasks' | 'supports' | 'meetings') => {
@@ -74,19 +74,19 @@ export default function MilestoneDetailPage() {
setShowCreateSupport(false)
setShowCreateMeeting(false)
// Refresh
api.get<Task[]>(`/tasks/${projectCode}/${id}`).then(({ data }) => setTasks(data))
api.get<Issue[]>(`/supports/${projectCode}/${id}`).then(({ data }) => setSupports(data))
api.get<Issue[]>(`/meetings/${projectCode}/${id}`).then(({ data }) => setMeetings(data))
api.get<MilestoneTask[]>(`/tasks/${projectCode}/${id}`).then(({ data }) => setTasks(data))
api.get<Task[]>(`/supports/${projectCode}/${id}`).then(({ data }) => setSupports(data))
api.get<Task[]>(`/meetings/${projectCode}/${id}`).then(({ data }) => setMeetings(data))
}
const isProgressing = milestone?.status === 'progressing'
if (!milestone) return <div className="loading">Loading...</div>
const renderTaskRow = (t: Task) => (
const renderTaskRow = (t: MilestoneTask) => (
<tr key={t.id} className="clickable" onClick={() => navigate(`/milestones/${id}`)}>
<td>{t.task_code || t.id}</td>
<td className="issue-title">{t.title}</td>
<td className="task-title">{t.title}</td>
<td><span className={`badge status-${t.task_status || t.status}`}>{t.task_status || t.status}</span></td>
<td>{t.estimated_effort || '-'}</td>
<td>{t.estimated_working_time || '-'}</td>
@@ -97,9 +97,9 @@ export default function MilestoneDetailPage() {
<div className="milestone-detail">
<button className="btn-back" onClick={() => navigate('/milestones')}> Back to Milestones</button>
<div className="issue-header">
<div className="task-header">
<h2>🏁 {milestone.title}</h2>
<div className="issue-meta">
<div className="task-meta">
<span className={`badge status-${milestone.status === 'progressing' ? 'in_progress' : milestone.status}`}>{milestone.status}</span>
{milestone.due_date && <span className="text-dim">Due {dayjs(milestone.due_date).format('YYYY-MM-DD')}</span>}
{milestone.planned_release_date && <span className="text-dim">Planned Release: {dayjs(milestone.planned_release_date).format('YYYY-MM-DD')}</span>}
@@ -207,7 +207,7 @@ export default function MilestoneDetailPage() {
{supports.map((i) => (
<tr key={i.id} className="clickable" onClick={() => navigate(`/supports/${projectCode}/${id}/${i.id}`)}>
<td>{i.id}</td>
<td className="issue-title">{i.title}</td>
<td className="task-title">{i.title}</td>
<td><span className={`badge status-${i.status}`}>{i.status}</span></td>
<td><span className={`badge priority-${i.priority}`}>{i.priority}</span></td>
</tr>
@@ -224,7 +224,7 @@ export default function MilestoneDetailPage() {
{meetings.map((i) => (
<tr key={i.id} className="clickable" onClick={() => navigate(`/meetings/${projectCode}/${id}/${i.id}`)}>
<td>{i.id}</td>
<td className="issue-title">{i.title}</td>
<td className="task-title">{i.title}</td>
<td><span className={`badge status-${i.status}`}>{i.status}</span></td>
<td><span className={`badge priority-${i.priority}`}>{i.priority}</span></td>
</tr>