Skip to content

Commit 75d5e6e

Browse files
authored
Merge pull request #63 from ssdeanx/develop
Develop
2 parents 242e5b9 + 6e88eea commit 75d5e6e

11 files changed

Lines changed: 1028 additions & 585 deletions

File tree

app/dashboard/_components/sidebar.tsx

Lines changed: 86 additions & 179 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,25 @@ import {
1414
FileText,
1515
BarChart3,
1616
LayoutDashboard,
17-
Settings,
1817
ChevronLeft,
19-
ChevronRight,
20-
Home,
21-
LogOut,
22-
User,
2318
} from "lucide-react"
2419
import { Button } from "@/ui/button"
25-
import { ScrollArea } from "@/ui/scroll-area"
26-
import { Separator } from "@/ui/separator"
20+
import { Badge } from "@/ui/badge"
2721
import {
2822
Tooltip,
2923
TooltipContent,
3024
TooltipProvider,
3125
TooltipTrigger,
3226
} from "@/ui/tooltip"
27+
import { useApiHealthQuery } from "@/lib/hooks/use-dashboard-queries"
3328
import {
34-
DropdownMenu,
35-
DropdownMenuContent,
36-
DropdownMenuItem,
37-
DropdownMenuLabel,
38-
DropdownMenuSeparator,
39-
DropdownMenuTrigger,
40-
} from "@/ui/dropdown-menu"
29+
Sidebar as UiSidebar,
30+
SidebarProvider,
31+
SidebarHeader,
32+
SidebarContent,
33+
SidebarFooter,
34+
SidebarMenuItem,
35+
} from "@/ui/sidebar"
4136

4237
interface NavItem {
4338
title: string
@@ -114,180 +109,92 @@ interface SidebarProps {
114109

115110
export function Sidebar({ collapsed, onCollapsedChange }: SidebarProps) {
116111
const pathname = usePathname()
112+
const { data: apiHealth, isLoading: apiLoading, refetch: refetchApi } = useApiHealthQuery()
117113

118114
return (
119115
<TooltipProvider delayDuration={0}>
120-
<aside
121-
className={cn(
122-
"flex flex-col border-r bg-card transition-all duration-300",
123-
collapsed ? "w-16" : "w-64"
124-
)}
125-
>
126-
{/* Header */}
127-
<div className="flex h-14 items-center justify-between border-b px-4">
128-
{!collapsed && (
129-
<Link href={"/dashboard" as Route} className="flex items-center gap-2">
130-
<div className="flex h-8 w-8 items-center justify-center rounded-lg bg-primary">
131-
<Activity className="h-4 w-4 text-primary-foreground" />
132-
</div>
133-
<span className="font-semibold">Mastra Admin</span>
134-
</Link>
135-
)}
136-
{collapsed && (
137-
<Link href={"/dashboard" as Route} className="mx-auto">
138-
<div className="flex h-8 w-8 items-center justify-center rounded-lg bg-primary">
139-
<Activity className="h-4 w-4 text-primary-foreground" />
140-
</div>
141-
</Link>
142-
)}
143-
{!collapsed && (
144-
<Button
145-
variant="ghost"
146-
size="icon"
147-
onClick={() => onCollapsedChange(!collapsed)}
148-
>
149-
<ChevronLeft className="h-4 w-4" />
150-
</Button>
151-
)}
152-
</div>
153-
154-
{/* Expand button when collapsed */}
155-
{collapsed && (
156-
<div className="flex justify-center py-2 border-b">
157-
<Button
158-
variant="ghost"
159-
size="icon"
160-
onClick={() => onCollapsedChange(false)}
161-
>
162-
<ChevronRight className="h-4 w-4" />
163-
</Button>
164-
</div>
165-
)}
166-
167-
{/* Navigation */}
168-
<ScrollArea className="flex-1 py-2">
169-
<nav className="flex flex-col gap-1 px-2">
170-
{navItems.map((item) => {
171-
const isActive =
172-
pathname === item.href ||
173-
(item.href !== "/dashboard" && pathname.startsWith(item.href))
174-
175-
const linkContent = (
176-
<Link
177-
key={item.href}
178-
href={item.href as Route}
179-
className={cn(
180-
"flex items-center gap-3 rounded-md px-3 py-2 text-sm transition-colors group",
181-
isActive
182-
? "bg-primary text-primary-foreground"
183-
: "text-muted-foreground hover:bg-accent hover:text-accent-foreground",
184-
collapsed && "justify-center px-2"
185-
)}
186-
>
187-
<item.icon className="h-4 w-4 shrink-0" />
188-
{!collapsed && (
189-
<>
190-
<span className="flex-1">{item.title}</span>
191-
{item.badge && (
192-
<span
193-
className={cn(
194-
"text-xs px-1.5 py-0.5 rounded-full",
195-
isActive
196-
? "bg-primary-foreground/20 text-primary-foreground"
197-
: "bg-muted text-muted-foreground"
198-
)}
199-
>
200-
{item.badge}
201-
</span>
202-
)}
203-
</>
204-
)}
205-
</Link>
206-
)
116+
<SidebarProvider open={!collapsed} onOpenChange={(open) => onCollapsedChange(!open)}>
117+
<UiSidebar collapsible="icon">
118+
<SidebarHeader className="flex items-center justify-between px-4">
119+
<div className="flex items-center gap-2">
120+
<Link href={'/dashboard' as Route} className="flex items-center gap-2">
121+
<div className="flex h-8 w-8 items-center justify-center rounded-lg bg-primary">
122+
<Activity className="h-4 w-4 text-primary-foreground" />
123+
</div>
124+
{!collapsed && <span className="font-semibold">Mastra Admin</span>}
125+
</Link>
126+
</div>
127+
{!collapsed && (
128+
<Button variant="ghost" size="icon" onClick={() => onCollapsedChange(!collapsed)}>
129+
<ChevronLeft className="h-4 w-4" />
130+
</Button>
131+
)}
132+
</SidebarHeader>
207133

208-
if (collapsed) {
134+
<SidebarContent>
135+
<nav className="flex flex-col gap-1 px-2">
136+
{navItems.map((item) => {
137+
const isActive = pathname === item.href || (item.href !== '/dashboard' && pathname.startsWith(item.href))
209138
return (
210-
<Tooltip key={item.href}>
211-
<TooltipTrigger asChild>{linkContent}</TooltipTrigger>
212-
<TooltipContent side="right" className="flex flex-col">
213-
<span className="font-medium">{item.title}</span>
214-
{item.description && (
215-
<span className="text-xs text-muted-foreground">
216-
{item.description}
217-
</span>
139+
<SidebarMenuItem key={item.href}>
140+
<Link
141+
href={item.href as Route}
142+
className={cn(
143+
"flex items-center gap-3 rounded-md px-3 py-2 text-sm transition-colors",
144+
isActive ? "bg-primary text-primary-foreground" : "text-muted-foreground hover:bg-accent hover:text-accent-foreground",
145+
collapsed && "justify-center px-2"
218146
)}
219-
</TooltipContent>
220-
</Tooltip>
147+
>
148+
<item.icon className="h-4 w-4 shrink-0" />
149+
{!collapsed && (
150+
<>
151+
<span className="flex-1">{item.title}</span>
152+
{item.badge ? (<span className="text-xs px-1.5 py-0.5 rounded-full bg-muted text-muted-foreground">{item.badge}</span>) : null}
153+
</>
154+
)}
155+
</Link>
156+
</SidebarMenuItem>
221157
)
222-
}
223-
224-
return linkContent
225-
})}
226-
</nav>
227-
</ScrollArea>
228-
229-
{/* Footer */}
230-
<div className="border-t p-2">
231-
<Separator className="my-2" />
232-
233-
{/* Back to Site */}
234-
{collapsed ? (
235-
<Tooltip>
236-
<TooltipTrigger asChild>
237-
<Link
238-
href={"/" as Route}
239-
className="flex items-center justify-center gap-3 rounded-md px-2 py-2 text-sm text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground"
240-
>
241-
<Home className="h-4 w-4 shrink-0" />
242-
</Link>
243-
</TooltipTrigger>
244-
<TooltipContent side="right">Back to Site</TooltipContent>
245-
</Tooltip>
246-
) : (
247-
<Link
248-
href={"/" as Route}
249-
className="flex items-center gap-3 rounded-md px-3 py-2 text-sm text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground"
250-
>
251-
<Home className="h-4 w-4 shrink-0" />
252-
<span>Back to Site</span>
253-
</Link>
254-
)}
158+
})}
159+
</nav>
160+
</SidebarContent>
255161

256-
{/* User Menu */}
257-
<DropdownMenu>
258-
<DropdownMenuTrigger asChild>
259-
<button
260-
className={cn(
261-
"flex w-full items-center gap-3 rounded-md px-3 py-2 text-sm text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground",
262-
collapsed && "justify-center px-2"
162+
<SidebarFooter>
163+
<div className="flex items-center justify-between gap-2">
164+
<div className="flex items-center gap-2">
165+
<span className="text-xs text-muted-foreground">API</span>
166+
{apiHealth?.ok ? (
167+
<Badge variant="secondary" className="text-xs">OK</Badge>
168+
) : apiHealth && !apiHealth?.ok ? (
169+
<Tooltip>
170+
<TooltipTrigger asChild>
171+
<Badge variant="destructive" className="text-xs cursor-help">Error</Badge>
172+
</TooltipTrigger>
173+
<TooltipContent side="top" className="max-w-xs">
174+
<div className="text-sm">
175+
<div className="font-medium">API checks failed</div>
176+
<ul className="mt-2 text-xs list-disc list-inside">
177+
{Object.entries(apiHealth?.checks ?? {}).map(([k, v]) => (
178+
<li key={k}>{k}: {v?.ok ? 'ok' : (v?.error ?? 'error')}</li>
179+
))}
180+
</ul>
181+
</div>
182+
</TooltipContent>
183+
</Tooltip>
184+
) : (
185+
<Badge className="text-xs">Unknown</Badge>
263186
)}
264-
>
265-
<div className="flex h-6 w-6 items-center justify-center rounded-full bg-muted">
266-
<User className="h-3 w-3" />
267-
</div>
268-
{!collapsed && <span className="flex-1 text-left">Account</span>}
269-
</button>
270-
</DropdownMenuTrigger>
271-
<DropdownMenuContent align={collapsed ? "center" : "start"} side="top">
272-
<DropdownMenuLabel>My Account</DropdownMenuLabel>
273-
<DropdownMenuSeparator />
274-
<DropdownMenuItem asChild>
275-
<Link href={"/dashboard/settings" as Route}>
276-
<Settings className="h-4 w-4 mr-2" />
277-
Settings
278-
</Link>
279-
</DropdownMenuItem>
280-
<DropdownMenuSeparator />
281-
<DropdownMenuItem asChild>
282-
<Link href={"/login" as Route}>
283-
<LogOut className="h-4 w-4 mr-2" />
284-
Sign out
285-
</Link>
286-
</DropdownMenuItem>
287-
</DropdownMenuContent>
288-
</DropdownMenu>
289-
</div>
290-
</aside>
187+
</div>
188+
189+
<div>
190+
<Button size="sm" variant="ghost" onClick={() => refetchApi()}>
191+
Check
192+
</Button>
193+
</div>
194+
</div>
195+
</SidebarFooter>
196+
</UiSidebar>
197+
</SidebarProvider>
291198
</TooltipProvider>
292199
)
293200
}

app/dashboard/page.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ export default function DashboardPage() {
274274
<Bot className="h-4 w-4 text-muted-foreground" />
275275
</div>
276276
<div>
277-
<span className="font-medium text-sm">{agent.name || agent.id}</span>
277+
<span className="font-medium text-sm">{agent.name ?? agent.id}</span>
278278
{agent.description && (
279279
<p className="text-xs text-muted-foreground truncate max-w-[200px]">
280280
{agent.description}
@@ -341,7 +341,7 @@ export default function DashboardPage() {
341341
<Workflow className="h-4 w-4 text-muted-foreground" />
342342
</div>
343343
<div>
344-
<span className="font-medium text-sm">{wf.name || wf.id}</span>
344+
<span className="font-medium text-sm">{wf.name ?? wf.id}</span>
345345
{wf.description && (
346346
<p className="text-xs text-muted-foreground truncate max-w-[200px]">
347347
{wf.description}
@@ -410,10 +410,10 @@ export default function DashboardPage() {
410410
</div>
411411
<div>
412412
<span className="font-medium text-sm">
413-
{span.name || span.traceId}
413+
{span.name ?? span.traceId}
414414
</span>
415415
<div className="text-xs text-muted-foreground">
416-
{(span as unknown as Record<string, unknown>).startTime
416+
{((span as unknown as Record<string, unknown>).startTime)
417417
? new Date((span as unknown as Record<string, unknown>).startTime as string).toLocaleString()
418418
: "No timestamp"}
419419
</div>

0 commit comments

Comments
 (0)