File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 1+ import { RoutesWorkspace } from "@/components/routes/routes-workspace"
2+
3+ export default function RoutesPage ( ) {
4+ return < RoutesWorkspace />
5+ }
File renamed without changes.
Original file line number Diff line number Diff line change 1+ "use client"
2+
3+ import { Route } from "@/types/route"
4+ import { Route as RouteIcon } from "lucide-react"
5+ type Props = {
6+ route : Route | null
7+ }
8+
9+ export function RouteInspector ( {
10+ route,
11+ } : Props ) {
12+ if ( ! route ) {
13+ return (
14+ < div className = "flex h-full items-center justify-center text-muted-foreground" >
15+ Select a route
16+ </ div >
17+ )
18+ }
19+
20+ return (
21+ < div className = "flex h-full flex-col" >
22+
23+ < div className = "border-b border-border p-5" >
24+
25+ < div className = "flex items-center gap-3" >
26+
27+ < RouteIcon className = "h-5 w-5 text-orange-400" />
28+
29+ < div >
30+ < h2 className = "font-semibold" >
31+ Route Inspector
32+ </ h2 >
33+
34+ < p className = "text-sm text-muted-foreground" >
35+ route details
36+ </ p >
37+ </ div >
38+
39+ </ div >
40+
41+ </ div >
42+
43+ < div className = "space-y-4 p-5 text-sm" >
44+
45+ < Info
46+ label = "Provider"
47+ value = { route . provider }
48+ />
49+
50+ < Info
51+ label = "Status"
52+ value = { route . status }
53+ />
54+
55+ < Info
56+ label = "Throughput"
57+ value = { `${ route . throughput } /m` }
58+ />
59+
60+ < Info
61+ label = "Failures"
62+ value = { route . failures }
63+ />
64+
65+ < Info
66+ label = "Destinations"
67+ value = { route . destinations }
68+ />
69+
70+ </ div >
71+
72+ < div className = "border-t border-border p-5" >
73+
74+ < h3 className = "mb-3 font-medium" >
75+ Destinations
76+ </ h3 >
77+
78+ < div className = "space-y-2 text-sm" >
79+ < div > production-api</ div >
80+ < div > analytics-worker</ div >
81+ < div > audit-logger</ div >
82+ </ div >
83+
84+ </ div >
85+
86+ </ div >
87+ )
88+ }
89+
90+ function Info ( {
91+ label,
92+ value,
93+ } : {
94+ label : string
95+ value : React . ReactNode
96+ } ) {
97+ return (
98+ < div className = "flex justify-between" >
99+ < span > { label } </ span >
100+ < span > { value } </ span >
101+ </ div >
102+ )
103+ }
Original file line number Diff line number Diff line change 1+ "use client"
2+
3+ import { cn } from "@/lib/utils"
4+ import { Route } from "@/types/route"
5+
6+ type Props = {
7+ route : Route
8+ selected ?: boolean
9+ onClick ?: ( ) => void
10+ }
11+
12+ export function RouteRow ( {
13+ route,
14+ selected,
15+ onClick,
16+ } : Props ) {
17+ return (
18+ < button
19+ onClick = { onClick }
20+ className = { cn (
21+ `
22+ grid
23+ grid-cols-[120px_1fr_120px_120px_120px_120px_140px]
24+ items-center
25+ border-b border-border
26+ px-5 py-4
27+ text-left
28+ hover:bg-white/[0.03]
29+ ` ,
30+ selected &&
31+ "bg-white/[0.04]"
32+ ) }
33+ >
34+ < div > { route . provider } </ div >
35+
36+ < div > { route . path } </ div >
37+
38+ < div >
39+ < span
40+ className = { cn (
41+ "rounded-full px-2 py-1 text-xs" ,
42+
43+ route . status ===
44+ "active" &&
45+ "bg-emerald-500/10 text-emerald-400" ,
46+
47+ route . status ===
48+ "paused" &&
49+ "bg-amber-500/10 text-amber-400" ,
50+
51+ route . status ===
52+ "error" &&
53+ "bg-rose-500/10 text-rose-400"
54+ ) }
55+ >
56+ { route . status }
57+ </ span >
58+ </ div >
59+
60+ < div > { route . throughput } /m</ div >
61+
62+ < div > { route . failures } </ div >
63+
64+ < div > { route . destinations } </ div >
65+
66+ < div > { route . lastSeen } </ div >
67+ </ button >
68+ )
69+ }
Original file line number Diff line number Diff line change 1+ "use client"
2+
3+ import { Route } from "@/types/route"
4+
5+ type Props = {
6+ routes : Route [ ]
7+ }
8+
9+ export function RoutesStats ( {
10+ routes,
11+ } : Props ) {
12+ const active =
13+ routes . filter (
14+ ( r ) => r . status === "active"
15+ ) . length
16+
17+ const paused =
18+ routes . filter (
19+ ( r ) => r . status === "paused"
20+ ) . length
21+
22+ const errors =
23+ routes . filter (
24+ ( r ) => r . status === "error"
25+ ) . length
26+
27+ return (
28+ < div className = "grid grid-cols-4 border-b border-border" >
29+
30+ < Stat
31+ label = "Total Routes"
32+ value = { routes . length }
33+ />
34+
35+ < Stat
36+ label = "Active"
37+ value = { active }
38+ />
39+
40+ < Stat
41+ label = "Paused"
42+ value = { paused }
43+ />
44+
45+ < Stat
46+ label = "Errors"
47+ value = { errors }
48+ />
49+
50+ </ div >
51+ )
52+ }
53+
54+ function Stat ( {
55+ label,
56+ value,
57+ } : {
58+ label : string
59+ value : number
60+ } ) {
61+ return (
62+ < div className = "border-r border-border p-5 last:border-r-0" >
63+ < p className = "text-sm text-muted-foreground" >
64+ { label }
65+ </ p >
66+
67+ < h3 className = "mt-2 text-4xl font-bold" >
68+ { value }
69+ </ h3 >
70+ </ div >
71+ )
72+ }
Original file line number Diff line number Diff line change 1+ "use client"
2+
3+ import { Route } from "@/types/route"
4+ import { RouteRow } from "./route-row"
5+
6+ type Props = {
7+ routes : Route [ ]
8+ selected : Route | null
9+ onSelect : ( route : Route ) => void
10+ }
11+
12+ export function RoutesStream ( {
13+ routes,
14+ selected,
15+ onSelect,
16+ } : Props ) {
17+ return (
18+ < div className = "h-full overflow-auto" >
19+
20+ < div
21+ className = "
22+ grid
23+ grid-cols-[120px_1fr_120px_120px_120px_120px_140px]
24+ border-b border-border
25+ px-5 py-4
26+ text-xs uppercase
27+ text-muted-foreground
28+ "
29+ >
30+ < div > Provider</ div >
31+ < div > Route</ div >
32+ < div > Status</ div >
33+ < div > Throughput</ div >
34+ < div > Failures</ div >
35+ < div > Destinations</ div >
36+ < div > Last Seen</ div >
37+ </ div >
38+
39+ { routes . map ( ( route ) => (
40+ < RouteRow
41+ key = { route . id }
42+ route = { route }
43+ selected = {
44+ selected ?. id ===
45+ route . id
46+ }
47+ onClick = { ( ) =>
48+ onSelect ( route )
49+ }
50+ />
51+ ) ) }
52+ </ div >
53+ )
54+ }
Original file line number Diff line number Diff line change 1+ "use client"
2+
3+ import { Search , Route } from "lucide-react"
4+
5+ type Props = {
6+ query : string
7+ setQuery : React . Dispatch < React . SetStateAction < string > >
8+ }
9+
10+ export function RoutesToolbar ( {
11+ query,
12+ setQuery,
13+ } : Props ) {
14+ return (
15+ < div className = "flex items-center justify-between border-b border-border px-5 py-4" >
16+
17+ < div className = "flex items-center gap-3" >
18+ < Route className = "h-5 w-5 text-orange-400" />
19+
20+ < div >
21+ < h2 className = "text-xl font-semibold" >
22+ Routes Explorer
23+ </ h2 >
24+
25+ < p className = "text-sm text-muted-foreground" >
26+ monitor ingress routes
27+ </ p >
28+ </ div >
29+ </ div >
30+
31+ < div className = "flex items-center gap-2 rounded-xl border border-border px-3 py-2" >
32+ < Search className = "h-4 w-4 text-muted-foreground" />
33+
34+ < input
35+ value = { query }
36+ onChange = { ( e ) =>
37+ setQuery ( e . target . value )
38+ }
39+ placeholder = "Search routes..."
40+ className = "bg-transparent outline-none"
41+ />
42+ </ div >
43+
44+ </ div >
45+ )
46+ }
You can’t perform that action at this time.
0 commit comments