feat: add Inventory page — composites and layout sections
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
140
src/pages/Inventory/sections/LayoutSection.tsx
Normal file
140
src/pages/Inventory/sections/LayoutSection.tsx
Normal file
@@ -0,0 +1,140 @@
|
||||
import styles from './LayoutSection.module.css'
|
||||
import { Sidebar } from '../../../design-system/layout/Sidebar/Sidebar'
|
||||
import { TopBar } from '../../../design-system/layout/TopBar/TopBar'
|
||||
|
||||
// ── DemoCard helper ──────────────────────────────────────────────────────────
|
||||
|
||||
interface DemoCardProps {
|
||||
id: string
|
||||
title: string
|
||||
description: string
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
function DemoCard({ id, title, description, children }: DemoCardProps) {
|
||||
return (
|
||||
<div id={id} className={styles.componentCard}>
|
||||
<h3 className={styles.componentTitle}>{title}</h3>
|
||||
<p className={styles.componentDesc}>{description}</p>
|
||||
<div className={styles.demoArea}>{children}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// ── Sample data ───────────────────────────────────────────────────────────────
|
||||
|
||||
const SAMPLE_APPS = [
|
||||
{ id: 'app1', name: 'cameleer-prod', agentCount: 3, health: 'live' as const, execCount: 14320 },
|
||||
{ id: 'app2', name: 'cameleer-staging', agentCount: 2, health: 'stale' as const, execCount: 871 },
|
||||
{ id: 'app3', name: 'cameleer-dev', agentCount: 1, health: 'dead' as const, execCount: 42 },
|
||||
]
|
||||
|
||||
const SAMPLE_ROUTES = [
|
||||
{ id: 'r1', name: 'order-ingest', execCount: 5421 },
|
||||
{ id: 'r2', name: 'payment-validate', execCount: 3102 },
|
||||
{ id: 'r3', name: 'notify-customer', execCount: 2201 },
|
||||
]
|
||||
|
||||
const SAMPLE_AGENTS = [
|
||||
{
|
||||
id: 'ag1',
|
||||
name: 'agent-prod-1',
|
||||
service: 'camel-core',
|
||||
version: 'v3.2.1',
|
||||
tps: '42 tps',
|
||||
lastSeen: '1m ago',
|
||||
status: 'live' as const,
|
||||
},
|
||||
{
|
||||
id: 'ag2',
|
||||
name: 'agent-prod-2',
|
||||
service: 'camel-core',
|
||||
version: 'v3.2.1',
|
||||
tps: '38 tps',
|
||||
lastSeen: '2m ago',
|
||||
status: 'live' as const,
|
||||
errorRate: '0.4%',
|
||||
},
|
||||
{
|
||||
id: 'ag3',
|
||||
name: 'agent-staging-1',
|
||||
service: 'camel-core',
|
||||
version: 'v3.1.9',
|
||||
tps: '5 tps',
|
||||
lastSeen: '8m ago',
|
||||
status: 'stale' as const,
|
||||
},
|
||||
]
|
||||
|
||||
// ── LayoutSection ─────────────────────────────────────────────────────────────
|
||||
|
||||
export function LayoutSection() {
|
||||
return (
|
||||
<section id="layout" className={styles.section}>
|
||||
<h2 className={styles.sectionTitle}>Layout</h2>
|
||||
|
||||
{/* 1. AppShell */}
|
||||
<DemoCard
|
||||
id="appshell"
|
||||
title="AppShell"
|
||||
description="Full-page shell that composes Sidebar + TopBar + main content area. Cannot be nested — shown as a structural diagram."
|
||||
>
|
||||
<div className={styles.shellDiagram}>
|
||||
<div className={styles.shellDiagramTop}>
|
||||
TopBar — breadcrumb · search · env badge · shift · user avatar
|
||||
</div>
|
||||
<div className={styles.shellDiagramBody}>
|
||||
<div className={styles.shellDiagramSide}>
|
||||
<span>Sidebar</span>
|
||||
<span style={{ fontWeight: 400, fontSize: 10, marginTop: 4 }}>Logo</span>
|
||||
<span style={{ fontWeight: 400, fontSize: 10 }}>Search</span>
|
||||
<span style={{ fontWeight: 400, fontSize: 10 }}>Navigation</span>
|
||||
<span style={{ fontWeight: 400, fontSize: 10 }}>Applications</span>
|
||||
<span style={{ fontWeight: 400, fontSize: 10 }}>Routes</span>
|
||||
<span style={{ fontWeight: 400, fontSize: 10 }}>Agents</span>
|
||||
</div>
|
||||
<div className={styles.shellDiagramMain}>
|
||||
<children> — page content rendered here
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</DemoCard>
|
||||
|
||||
{/* 2. Sidebar */}
|
||||
<DemoCard
|
||||
id="sidebar"
|
||||
title="Sidebar"
|
||||
description="Navigation sidebar with app/route/agent sections, search filter, health dots, and exec counts."
|
||||
>
|
||||
<div className={styles.sidebarPreview}>
|
||||
<Sidebar
|
||||
apps={SAMPLE_APPS}
|
||||
routes={SAMPLE_ROUTES}
|
||||
agents={SAMPLE_AGENTS}
|
||||
/>
|
||||
</div>
|
||||
</DemoCard>
|
||||
|
||||
{/* 3. TopBar */}
|
||||
<DemoCard
|
||||
id="topbar"
|
||||
title="TopBar"
|
||||
description="Top navigation bar with breadcrumb, search trigger, environment badge, shift info, and user avatar."
|
||||
>
|
||||
<div className={styles.topbarPreview}>
|
||||
<TopBar
|
||||
breadcrumb={[
|
||||
{ label: 'Dashboard', href: '#' },
|
||||
{ label: 'Applications', href: '#' },
|
||||
{ label: 'order-ingest' },
|
||||
]}
|
||||
environment="production"
|
||||
shift="Morning"
|
||||
user={{ name: 'Hendrik' }}
|
||||
onSearchClick={() => undefined}
|
||||
/>
|
||||
</div>
|
||||
</DemoCard>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user