Intelligence
Artifacts
Browse the repository, read documents, and manage the governance folders. Source, runtime, and infrastructure are read-only.
Repository
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