# All files / src/components/layout CodeHeaderStatus.tsx

66.66% Statements 8/12
37.5% Branches 6/16
50% Functions 1/2
66.66% Lines 8/12

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

    5x

    5x
    12x
    9x

    12x
    9x

    5x

    1x

     /**
     * CodeHeaderStatus — presentational status line for the Code context header.
     * Contains both the pure computation ({@link describeCodeStatus}) and the
     * React component ({@link CodeHeaderStatus}).
     *
     * @module
     */

    import type { CSSProperties, JSX } from "react";
    import type { Session } from "../../hooks/types.js";
    import { isActiveSession } from "../sessions/sessionsView.js";
    import { formatRelativeTime } from "../../utils/time.js";

    // ---------------------------------------------------------------------------
    // Pure logic
    // ---------------------------------------------------------------------------

    /** Summary of session activity for the Code context header. */
    export interface CodeStatusSummary {
      /** Number of currently active (live) sessions. */
      activeCount: number;
      /** ISO timestamp of the most recently started session, or `undefined` if none. */
      lastActivityAt: string | undefined;
    }

    /** Derive a Code context status summary from the sessions array. */
    export function describeCodeStatus(
      sessions: readonly Pick<Session, "status" | "endReason" | "startedAt">[],
    ): CodeStatusSummary {
      let activeCount: number = 0;
      let lastActivityAt: string | undefined;
      for (const s of sessions) {
        if (isActiveSession(s)) {
          activeCount++;
        }
        if (!lastActivityAt || s.startedAt > lastActivityAt) {
          lastActivityAt = s.startedAt;
        }
      }
      return { activeCount, lastActivityAt };
    }

    // ---------------------------------------------------------------------------
    // Presentational component
    // ---------------------------------------------------------------------------

    /** Inline styles matching the agent header's HeartbeatStatus pattern. */
    const STATUS_ITEM_STYLE: CSSProperties = {
      fontSize: "var(--font-size-xs)",
      color: "var(--text-tertiary)",
      whiteSpace: "nowrap",
    };

    /** Props for {@link CodeHeaderStatus}. */
    export interface CodeHeaderStatusProps {
      /** Summary computed by {@link describeCodeStatus}. */
      summary: CodeStatusSummary;
    }

    /** Renders the Code context header status line. Returns nothing when there is no data. */
    export function CodeHeaderStatus({ summary }: CodeHeaderStatusProps): JSX.Element | undefined {
      const { activeCount, lastActivityAt } = summary;

      if (activeCount === 0 && !lastActivityAt) {
        return undefined;
      }

      return (
        <div
          style={{ display: "flex", alignItems: "center", gap: "var(--space-md)", flexWrap: "wrap" }}
          data-testid="code-header-status"
        >
          {activeCount > 0 && (
            <span style={STATUS_ITEM_STYLE} data-testid="code-header-active-sessions">
              {activeCount} active {activeCount === 1 ? "session" : "sessions"}
            </span>
          )}
          {lastActivityAt && (
            <span style={STATUS_ITEM_STYLE} data-testid="code-header-last-activity">
              Last activity {formatRelativeTime(lastActivityAt)}
            </span>
          )}
        </div>
      );
    }