# All files / src/utils taskStatus.tsx

84.61% Statements 11/13
50% Branches 4/8
100% Functions 3/3
84.61% Lines 11/13

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155

    40x

    718x

    718x

    40x

    78x

    40x

    40x

    40x

    1130x
    1130x

    40x

     /**
     * Shared task-status metadata: labels, icons, colors, and column order.
     *
     * Every view (sidebar, DAG, board, task page) should import from here so that
     * labels, icons, colors, and ordering stay consistent across the UI.
     */

    import type { ReactNode } from "react";
    import { Ban, Check, Circle, Pause, X } from "lucide-react";
    import { ICON_SM } from "./iconSize.js";

    // ---------------------------------------------------------------------------
    // Core types
    // ---------------------------------------------------------------------------

    /** Canonical task statuses displayed in the UI. */
    export type TaskStatusKey = "not_started" | "working" | "paused" | "complete" | "failed";

    /** Virtual status for tasks with unresolved dependencies. Not stored on the task itself. */
    export type VirtualStatus = "blocked";

    /** All statuses the UI may display, including virtual ones. */
    export type DisplayStatus = TaskStatusKey | VirtualStatus;

    /** Visual metadata for a single task status. */
    export interface TaskStatusStyle {
      /** CSS color value (typically a custom-property reference). */
      color: string;
      /** Status icon element. */
      icon: ReactNode;
      /** Human-readable label. */
      label: string;
    }

    // ---------------------------------------------------------------------------
    // Style map
    // ---------------------------------------------------------------------------

    /** Complete style map for every displayable status (canonical + virtual). */
    export const TASK_STATUS_STYLES: Record<DisplayStatus, TaskStatusStyle> = {
      not_started: {
        color: "var(--text-tertiary)",
        icon: <Circle size={ICON_SM} />,
        label: "Not Started",
      },
      working: {
        color: "var(--accent-green)",
        icon: <Circle size={ICON_SM} fill="currentColor" />,
        label: "Working",
      },
      paused: { color: "var(--accent-yellow)", icon: <Pause size={ICON_SM} />, label: "Paused" },
      complete: { color: "var(--accent-green)", icon: <Check size={ICON_SM} />, label: "Complete" },
      failed: { color: "var(--accent-red)", icon: <X size={ICON_SM} />, label: "Failed" },
      blocked: { color: "var(--accent-yellow)", icon: <Ban size={ICON_SM} />, label: "Blocked" },
    };

    /** Safe accessor — returns a style for any status string, falling back to `not_started`. */
    export function getStatusStyle(status: string): TaskStatusStyle {
      Iif (status === "blocked") {
        return TASK_STATUS_STYLES.blocked;
      }

      return TASK_STATUS_STYLES[resolveStatus(status)];
    }

    // ---------------------------------------------------------------------------
    // CSS-class map for badge-style rendering (TaskPage)
    // ---------------------------------------------------------------------------

    /** Maps a canonical status key to a CSS class suffix used for badge coloring. */
    export const STATUS_BADGE_CLASS_MAP: Record<string, string> = {
      not_started: "statusPending",
      working: "statusInProgress",
      paused: "statusWaitingInput",
      complete: "statusDone",
      failed: "statusFailed",
    };

    /** Resolve a task status to the corresponding badge class key. */
    export function getStatusBadgeClassKey(status: string): string {
      return STATUS_BADGE_CLASS_MAP[resolveStatus(status)] ?? "statusPending";
    }

    // ---------------------------------------------------------------------------
    // Ordering
    // ---------------------------------------------------------------------------

    /**
     * Sidebar group order — includes virtual "blocked" group.
     * This is the urgency-first ordering used by the sidebar grouped view.
     */
    export const SIDEBAR_STATUS_ORDER: DisplayStatus[] = [
      "working",
      "paused",
      "failed",
      "not_started",
      "blocked",
      "complete",
    ];

    /**
     * Board columns — the five concrete columns shown on the Kanban board.
     * "blocked" is NOT a column; blocked tasks stay in their original column
     * with a badge overlay.
     */
    export const BOARD_COLUMN_ORDER: TaskStatusKey[] = [
      "not_started",
      "working",
      "paused",
      "complete",
      "failed",
    ];

    // ---------------------------------------------------------------------------
    // Alias resolution (legacy proto names → canonical)
    // ---------------------------------------------------------------------------

    /** Maps legacy / proto status strings to canonical UI status keys. */
    const STATUS_ALIASES: Record<string, TaskStatusKey> = {
      pending: "not_started",
      assigned: "not_started",
      in_progress: "working",
      waiting_input: "paused",
      review: "paused",
      done: "complete",
    };

    /** Resolve a raw status string to a canonical `TaskStatusKey`, treating unknown values as `not_started`. */
    export function resolveStatus(raw: string): TaskStatusKey {
      if (raw in TASK_STATUS_STYLES && raw !== "blocked") {
        return raw as TaskStatusKey;
      }
      return STATUS_ALIASES[raw] ?? "not_started";
    }

    // ---------------------------------------------------------------------------
    // MiniMap color resolution (DagView)
    // ---------------------------------------------------------------------------

    /** CSS variable names used for MiniMap node coloring by task status. */
    export const STATUS_CSS_VAR_MAP: Record<string, string> = {
      not_started: "--text-tertiary",
      working: "--accent-green",
      paused: "--accent-yellow",
      complete: "--accent-green",
      failed: "--accent-red",
      // Legacy aliases
      pending: "--text-tertiary",
      assigned: "--text-tertiary",
      in_progress: "--accent-green",
      review: "--accent-yellow",
      done: "--accent-green",
      waiting_input: "--accent-yellow",
    };