125 lines
4.1 KiB
TypeScript
125 lines
4.1 KiB
TypeScript
|
|
import type { ReactNode } from 'react';
|
||
|
|
import { Link } from 'react-router-dom';
|
||
|
|
import { Panel } from '@/components/ui/Panel';
|
||
|
|
import { Pill } from '@/components/ui/Pill';
|
||
|
|
import { Button } from '@/components/ui/Button';
|
||
|
|
import { MOCK_ENGAGEMENTS } from '@/mocks/fixtures';
|
||
|
|
import type { MockEngagement } from '@/mocks/fixtures';
|
||
|
|
|
||
|
|
const STATUS_TONE: Record<MockEngagement['status'], 'running' | 'soc' | 'success' | 'pending'> = {
|
||
|
|
active: 'running',
|
||
|
|
reporting: 'soc',
|
||
|
|
archived: 'pending',
|
||
|
|
planning: 'success',
|
||
|
|
};
|
||
|
|
|
||
|
|
export function EngagementsPage() {
|
||
|
|
return (
|
||
|
|
<div className="px-8 py-6 space-y-6 max-w-[1400px] mx-auto">
|
||
|
|
<header className="flex items-end justify-between">
|
||
|
|
<div>
|
||
|
|
<div className="label-system mb-1">// Engagements</div>
|
||
|
|
<h1 className="font-display text-fg-default" style={{ fontSize: '22px', letterSpacing: '0.02em' }}>
|
||
|
|
Mission roster
|
||
|
|
</h1>
|
||
|
|
<p className="text-fg-muted mt-1" style={{ fontSize: '12.5px' }}>
|
||
|
|
Each engagement is a multi-tenant container. Pick one to access its hosts, scenarios,
|
||
|
|
runs, and reports.
|
||
|
|
</p>
|
||
|
|
</div>
|
||
|
|
<Button variant="primary">+ New engagement</Button>
|
||
|
|
</header>
|
||
|
|
|
||
|
|
<Panel
|
||
|
|
title="Active and recent"
|
||
|
|
meta={
|
||
|
|
<span className="tabular">
|
||
|
|
{MOCK_ENGAGEMENTS.length} entries · sorted by start date
|
||
|
|
</span>
|
||
|
|
}
|
||
|
|
>
|
||
|
|
<table className="w-full" style={{ fontSize: 12.5 }}>
|
||
|
|
<thead>
|
||
|
|
<tr className="text-fg-subtle">
|
||
|
|
<Th>Codename</Th>
|
||
|
|
<Th>Client</Th>
|
||
|
|
<Th>Status</Th>
|
||
|
|
<Th>C2</Th>
|
||
|
|
<Th align="right">Operators</Th>
|
||
|
|
<Th align="right">SOC</Th>
|
||
|
|
<Th>Window</Th>
|
||
|
|
<Th />
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody>
|
||
|
|
{MOCK_ENGAGEMENTS.map((eng, idx) => (
|
||
|
|
<tr
|
||
|
|
key={eng.id}
|
||
|
|
style={{
|
||
|
|
borderTop: idx === 0 ? '1px solid var(--line-default)' : '1px solid var(--line-faint)',
|
||
|
|
}}
|
||
|
|
>
|
||
|
|
<Td>
|
||
|
|
<div className="font-display text-fg-default" style={{ letterSpacing: '0.06em' }}>
|
||
|
|
{eng.codename}
|
||
|
|
</div>
|
||
|
|
<div className="font-mono text-fg-faint" style={{ fontSize: '10.5px' }}>
|
||
|
|
{eng.id}
|
||
|
|
</div>
|
||
|
|
</Td>
|
||
|
|
<Td>{eng.client}</Td>
|
||
|
|
<Td>
|
||
|
|
<Pill tone={STATUS_TONE[eng.status]}>
|
||
|
|
<span className="status-dot" style={{ color: 'currentColor' }} />
|
||
|
|
{eng.status}
|
||
|
|
</Pill>
|
||
|
|
</Td>
|
||
|
|
<Td>
|
||
|
|
<span className="font-mono tabular">{eng.c2Type.toUpperCase()}</span>
|
||
|
|
</Td>
|
||
|
|
<Td align="right">
|
||
|
|
<span className="font-mono tabular">{eng.operators}</span>
|
||
|
|
</Td>
|
||
|
|
<Td align="right">
|
||
|
|
<span className="font-mono tabular">{eng.socAnalysts}</span>
|
||
|
|
</Td>
|
||
|
|
<Td>
|
||
|
|
<span className="font-mono tabular text-fg-muted">
|
||
|
|
{eng.startDate} → {eng.endDate}
|
||
|
|
</span>
|
||
|
|
</Td>
|
||
|
|
<Td align="right">
|
||
|
|
<Link to="/runs">
|
||
|
|
<Button variant="ghost" size="sm">
|
||
|
|
Enter →
|
||
|
|
</Button>
|
||
|
|
</Link>
|
||
|
|
</Td>
|
||
|
|
</tr>
|
||
|
|
))}
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
</Panel>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
function Th({ children, align = 'left' }: { children?: ReactNode; align?: 'left' | 'right' }) {
|
||
|
|
return (
|
||
|
|
<th
|
||
|
|
className="label-system px-3 py-2"
|
||
|
|
style={{ textAlign: align, fontWeight: 500 }}
|
||
|
|
>
|
||
|
|
{children}
|
||
|
|
</th>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
function Td({ children, align = 'left' }: { children?: ReactNode; align?: 'left' | 'right' }) {
|
||
|
|
return (
|
||
|
|
<td className="px-3 py-3 align-middle" style={{ textAlign: align }}>
|
||
|
|
{children}
|
||
|
|
</td>
|
||
|
|
);
|
||
|
|
}
|