Intelligence

Artifacts

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

Repository
README.md
CONSTITUTION_COMPLIANCE_AUDIT_V1.mdREADME.md
repositories/aaf-holdings/hq01/app/assets/[aid]/page.tsx
6.6 KB
import Link from "next/link";
import { notFound } from "next/navigation";
import { Network, Box, History as HistoryIcon } from "lucide-react";
import { PageHeader } from "@/components/layout/page-header";
import { Card, CardContent } from "@/components/ui/card";
import { Separator } from "@/components/ui/separator";
import { MetaItem } from "@/components/shared/field-list";
import { AssetEdit } from "@/components/assets/asset-edit";
import { getAssetView } from "@/lib/assets/ledger";
import type { AssetEventType } from "@/lib/assets/types";

export const dynamic = "force-dynamic";

const EVENT_LABEL: Record<AssetEventType, string> = {
  asset_registered: "Asset registered",
  asset_updated: "Asset updated",
  state_changed: "Status changed",
};

export default function AssetDetailPage({
  params,
}: {
  params: { aid: string };
}) {
  const view = getAssetView(params.aid);
  if (!view) notFound();
  const { asset, history, mission, objective, work_order } = view;

  const lineage = [
    { label: "Mission", value: mission?.title ?? asset.mission_id, href: `/mission-control/${asset.mission_id}` },
    { label: "Objective", value: objective?.title ?? asset.objective_id, href: `/mission-control/${asset.mission_id}/objectives/${asset.objective_id}` },
    { label: "Work Order", value: work_order?.title ?? asset.work_order_id, href: `/mission-control/${asset.mission_id}` },
    { label: "Assignment", value: asset.assignment_id, href: `/mission-control/${asset.mission_id}/assignments/${asset.assignment_id}` },
    { label: "Report", value: asset.report_id, href: `/mission-control/${asset.mission_id}/assignments/${asset.assignment_id}/reports/${asset.report_id}` },
  ];

  return (
    <div>
      <PageHeader
        eyebrow={`${asset.asset_id} · ${asset.type}`}
        title={asset.name}
        description={asset.description || undefined}
        back={{ label: "Asset Ledger", href: "/assets" }}
        actions={<AssetEdit asset={asset} />}
      />

      <div className="grid grid-cols-1 gap-8 lg:grid-cols-3">
        <div className="space-y-6 lg:col-span-2">
          <Card>
            <CardContent className="space-y-5 p-6">
              <div className="flex items-center gap-2 text-[11px] font-semibold uppercase tracking-[0.1em] text-muted-foreground">
                <Box className="h-3.5 w-3.5" /> Reference
              </div>
              <MetaItem label="Repository">
                <span className="font-mono text-[13px]">{asset.repository}</span>
              </MetaItem>
              <Separator />
              <MetaItem label="Relative Path">
                <span className="break-all font-mono text-[13px]">{asset.relative_path}</span>
              </MetaItem>
              <p className="text-[12px] text-muted-foreground">
                The ledger references this file; it does not duplicate it.
              </p>
              {asset.tags.length > 0 && (
                <>
                  <Separator />
                  <div className="flex flex-wrap gap-1.5">
                    {asset.tags.map((t) => (
                      <span key={t} className="rounded-full bg-secondary px-2.5 py-0.5 text-[11px] font-medium text-foreground/70">
                        #{t}
                      </span>
                    ))}
                  </div>
                </>
              )}
            </CardContent>
          </Card>

          <Card>
            <CardContent className="p-6">
              <div className="mb-4 flex items-center gap-2 text-[11px] font-semibold uppercase tracking-[0.1em] text-muted-foreground">
                <HistoryIcon className="h-3.5 w-3.5" /> History
              </div>
              <ol className="space-y-3">
                {history.map((e, i) => (
                  <li key={i} className="flex gap-3">
                    <div className="mt-1 h-1.5 w-1.5 shrink-0 rounded-full bg-accent" />
                    <div>
                      <div className="text-[13px] font-medium text-foreground">
                        {EVENT_LABEL[e.type] ?? e.type}
                        {e.detail && (
                          <span className="font-normal text-muted-foreground"> — {e.detail}</span>
                        )}
                      </div>
                      <div className="text-[11px] text-muted-foreground">
                        {new Date(e.at).toLocaleString()}
                      </div>
                    </div>
                  </li>
                ))}
              </ol>
            </CardContent>
          </Card>
        </div>

        <aside className="space-y-6">
          <Card>
            <CardContent className="p-6">
              <div className="mb-4 flex items-center gap-2 text-[11px] font-semibold uppercase tracking-[0.1em] text-muted-foreground">
                <Network className="h-3.5 w-3.5" /> Lineage
              </div>
              <ol className="space-y-3">
                {lineage.map((l, i) => (
                  <li key={l.label} className="flex gap-3">
                    <div className="flex flex-col items-center">
                      <div className="h-1.5 w-1.5 rounded-full bg-accent" />
                      {i < lineage.length - 1 && <div className="my-0.5 w-px flex-1 bg-border" />}
                    </div>
                    <div className="min-w-0 pb-1">
                      <div className="text-[10px] font-medium uppercase tracking-[0.1em] text-muted-foreground">
                        {l.label}
                      </div>
                      <Link href={l.href} className="truncate text-[13px] font-medium text-foreground hover:underline">
                        {l.value}
                      </Link>
                    </div>
                  </li>
                ))}
              </ol>
            </CardContent>
          </Card>

          <Card>
            <CardContent className="space-y-4 p-6">
              <MetaItem label="Type">{asset.type}</MetaItem>
              <Separator />
              <MetaItem label="Status">{asset.status}</MetaItem>
              <Separator />
              <MetaItem label="Created By">
                <span className="font-mono text-[13px]">{asset.created_by_executive}</span>
              </MetaItem>
              <Separator />
              <MetaItem label="Created">
                <span className="text-[12px] text-muted-foreground">
                  {new Date(asset.created_at).toLocaleString()}
                </span>
              </MetaItem>
            </CardContent>
          </Card>

          <div className="font-mono text-[11px] text-muted-foreground">
            /srv/aaf/assets/{asset.asset_id}/
          </div>
        </aside>
      </div>
    </div>
  );
}

root · /srv/aaf