Intelligence

Artifacts

Browse the repository, read documents, and manage the governance folders. Source, runtime, and infrastructure are read-only.

Repository
.gitignoreDockerfilenext-env.d.tsnext.config.mjspackage-lock.jsonpackage.jsonpostcss.config.mjsREADME.mdtailwind.config.tstsconfig.jsontsconfig.tsbuildinfo
README.md
CONSTITUTION_COMPLIANCE_AUDIT_V1.mdREADME.md
repositories/aaf-holdings/hq01/components/sessions/session-card.tsx
2.8 KB
import Link from "next/link";
import { FolderGit2, GitBranch, Target, Clock } from "lucide-react";
import { Card } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { SessionStatusBadge } from "./session-status-badge";
import { RuntimeClock } from "./runtime-clock";
import { StopButton } from "./stop-button";
import type { Session } from "@/lib/sessions/types";

/**
 * A single session card on the dashboard — mirrors the briefed layout:
 * executive name, status, mission, runtime, repository, branch, and the
 * Open / Stop actions.
 */

function repoLabel(workingDirectory: string): string {
  const parts = workingDirectory.split("/").filter(Boolean);
  return parts[parts.length - 1] ?? workingDirectory;
}

export function SessionCard({ session }: { session: Session }) {
  const running = session.status === "running" || session.status === "starting";

  return (
    <Card className="flex flex-col p-5">
      <div className="flex items-start justify-between gap-3">
        <div className="min-w-0">
          <div className="truncate text-[15px] font-semibold tracking-tight text-foreground">
            {session.name}
          </div>
          <div className="mt-0.5 truncate font-mono text-[11px] text-muted-foreground">
            {session.executive}
          </div>
        </div>
        <SessionStatusBadge status={session.status} />
      </div>

      <dl className="mt-4 grid grid-cols-2 gap-x-4 gap-y-3 text-[13px]">
        <Field icon={Target} label="Mission">
          {session.mission_id ?? "—"}
        </Field>
        <Field icon={Clock} label="Runtime">
          <RuntimeClock
            startedAt={session.started_at}
            endedAt={session.stopped_at}
            running={running}
            className="tabular-nums"
          />
        </Field>
        <Field icon={FolderGit2} label="Repository">
          {repoLabel(session.working_directory)}
        </Field>
        <Field icon={GitBranch} label="Branch">
          {session.branch ?? "—"}
        </Field>
      </dl>

      <div className="mt-5 flex items-center gap-2">
        <Link href={`/sessions/${session.id}`} className="flex-1">
          <Button variant="default" size="sm" className="w-full">
            Open
          </Button>
        </Link>
        <StopButton id={session.id} running={running} />
      </div>
    </Card>
  );
}

function Field({
  icon: Icon,
  label,
  children,
}: {
  icon: typeof Target;
  label: string;
  children: React.ReactNode;
}) {
  return (
    <div className="min-w-0">
      <dt className="flex items-center gap-1.5 text-[10px] font-medium uppercase tracking-[0.1em] text-muted-foreground">
        <Icon className="h-3 w-3" />
        {label}
      </dt>
      <dd className="mt-0.5 truncate font-medium text-foreground">{children}</dd>
    </div>
  );
}

root · /srv/aaf