66 lines
1.6 KiB
TypeScript
66 lines
1.6 KiB
TypeScript
import type {
|
|
WorkspaceMilestoneTarget,
|
|
WorkspaceSliceTarget,
|
|
WorkspaceTaskTarget,
|
|
} from "./workspace-types.js";
|
|
|
|
export type ItemStatus = "done" | "in-progress" | "pending";
|
|
|
|
export function getMilestoneStatus(
|
|
milestone: WorkspaceMilestoneTarget,
|
|
active: { milestoneId?: string },
|
|
): ItemStatus {
|
|
// Prefer authoritative milestone status from SF state registry (#2807)
|
|
if (milestone.status) {
|
|
switch (milestone.status) {
|
|
case "complete":
|
|
return "done";
|
|
case "active":
|
|
return "in-progress";
|
|
case "pending":
|
|
case "parked":
|
|
return "pending";
|
|
}
|
|
}
|
|
|
|
// Fallback: infer from slice completion (legacy / no status field)
|
|
if (
|
|
milestone.slices.length > 0 &&
|
|
milestone.slices.every((slice: WorkspaceSliceTarget) => slice.done)
|
|
) {
|
|
return "done";
|
|
}
|
|
if (active.milestoneId === milestone.id) {
|
|
return "in-progress";
|
|
}
|
|
return milestone.slices.some((slice: WorkspaceSliceTarget) => slice.done)
|
|
? "in-progress"
|
|
: "pending";
|
|
}
|
|
|
|
export function getSliceStatus(
|
|
milestoneId: string,
|
|
slice: WorkspaceSliceTarget,
|
|
active: { milestoneId?: string; sliceId?: string },
|
|
): ItemStatus {
|
|
if (slice.done) return "done";
|
|
if (active.milestoneId === milestoneId && active.sliceId === slice.id)
|
|
return "in-progress";
|
|
return "pending";
|
|
}
|
|
|
|
export function getTaskStatus(
|
|
milestoneId: string,
|
|
sliceId: string,
|
|
task: WorkspaceTaskTarget,
|
|
active: { milestoneId?: string; sliceId?: string; taskId?: string },
|
|
): ItemStatus {
|
|
if (task.done) return "done";
|
|
if (
|
|
active.milestoneId === milestoneId &&
|
|
active.sliceId === sliceId &&
|
|
active.taskId === task.id
|
|
)
|
|
return "in-progress";
|
|
return "pending";
|
|
}
|