moved most api stuff to web-api and built out a better monitoring solution for web-app

This commit is contained in:
Boki 2025-06-23 09:01:29 -04:00
parent fbff428e90
commit da1c52a841
45 changed files with 2986 additions and 312 deletions

View file

@ -10,7 +10,17 @@ export function Layout() {
// Determine title from current route
const getTitle = () => {
const path = location.pathname.replace('/', '');
if (!path || path === 'dashboard') {return 'Dashboard';}
if (!path || path === 'dashboard') return 'Dashboard';
// Handle nested routes
if (path.includes('/')) {
const parts = path.split('/');
// For system routes, show the sub-page name
if (parts[0] === 'system' && parts[1]) {
return parts[1].charAt(0).toUpperCase() + parts[1].slice(1);
}
}
return path.charAt(0).toUpperCase() + path.slice(1);
};

View file

@ -1,9 +1,9 @@
import { navigation } from '@/lib/constants';
import { cn } from '@/lib/utils';
import { Dialog, Transition } from '@headlessui/react';
import { XMarkIcon } from '@heroicons/react/24/outline';
import { Fragment } from 'react';
import { NavLink } from 'react-router-dom';
import { XMarkIcon, ChevronDownIcon, ChevronRightIcon } from '@heroicons/react/24/outline';
import { Fragment, useState } from 'react';
import { NavLink, useLocation } from 'react-router-dom';
interface SidebarProps {
sidebarOpen: boolean;
@ -76,6 +76,35 @@ export function Sidebar({ sidebarOpen, setSidebarOpen }: SidebarProps) {
}
function SidebarContent() {
const location = useLocation();
// Auto-expand items that have active children
const getInitialExpanded = () => {
const expanded = new Set<string>();
navigation.forEach(item => {
if (item.children && item.children.some(child => location.pathname === child.href)) {
expanded.add(item.name);
}
});
return expanded;
};
const [expandedItems, setExpandedItems] = useState<Set<string>>(getInitialExpanded());
const toggleExpanded = (name: string) => {
const newExpanded = new Set(expandedItems);
if (newExpanded.has(name)) {
newExpanded.delete(name);
} else {
newExpanded.add(name);
}
setExpandedItems(newExpanded);
};
const isChildActive = (children: any[]) => {
return children.some(child => location.pathname === child.href);
};
return (
<div className="flex grow flex-col gap-y-3 overflow-y-auto border-r border-border bg-background px-3">
<div className="flex h-12 shrink-0 items-center border-b border-border">
@ -87,32 +116,96 @@ function SidebarContent() {
<ul role="list" className="-mx-1 space-y-0.5">
{navigation.map(item => (
<li key={item.name}>
<NavLink
to={item.href}
className={({ isActive }) =>
cn(
isActive
? 'bg-surface-secondary text-primary-400 border-l-2 border-primary-500'
: 'text-text-secondary hover:text-primary-400 hover:bg-surface-secondary',
'group flex gap-x-2 rounded-r-md px-2 py-1.5 text-sm leading-tight font-medium transition-colors'
)
}
>
{({ isActive }) => (
<>
{item.children ? (
<>
<button
onClick={() => toggleExpanded(item.name)}
className={cn(
isChildActive(item.children)
? 'bg-surface-secondary text-primary-400'
: 'text-text-secondary hover:text-primary-400 hover:bg-surface-secondary',
'group flex w-full gap-x-2 rounded-r-md px-2 py-1.5 text-sm leading-tight font-medium transition-colors'
)}
>
<item.icon
className={cn(
isActive
isChildActive(item.children)
? 'text-primary-400'
: 'text-text-muted group-hover:text-primary-400',
'h-4 w-4 shrink-0 transition-colors'
)}
aria-hidden="true"
/>
{item.name}
</>
)}
</NavLink>
<span className="flex-1 text-left">{item.name}</span>
{expandedItems.has(item.name) ? (
<ChevronDownIcon className="h-3 w-3 text-text-muted" />
) : (
<ChevronRightIcon className="h-3 w-3 text-text-muted" />
)}
</button>
{expandedItems.has(item.name) && (
<ul className="mt-1 space-y-0.5 pl-8">
{item.children.map(child => (
<li key={child.name}>
<NavLink
to={child.href!}
className={({ isActive }) =>
cn(
isActive
? 'bg-surface-secondary text-primary-400 border-l-2 border-primary-500'
: 'text-text-secondary hover:text-primary-400 hover:bg-surface-secondary',
'group flex gap-x-2 rounded-r-md px-2 py-1 text-sm leading-tight font-medium transition-colors'
)
}
>
{({ isActive }) => (
<>
<child.icon
className={cn(
isActive
? 'text-primary-400'
: 'text-text-muted group-hover:text-primary-400',
'h-3 w-3 shrink-0 transition-colors'
)}
aria-hidden="true"
/>
{child.name}
</>
)}
</NavLink>
</li>
))}
</ul>
)}
</>
) : (
<NavLink
to={item.href!}
className={({ isActive }) =>
cn(
isActive
? 'bg-surface-secondary text-primary-400 border-l-2 border-primary-500'
: 'text-text-secondary hover:text-primary-400 hover:bg-surface-secondary',
'group flex gap-x-2 rounded-r-md px-2 py-1.5 text-sm leading-tight font-medium transition-colors'
)
}
>
{({ isActive }) => (
<>
<item.icon
className={cn(
isActive
? 'text-primary-400'
: 'text-text-muted group-hover:text-primary-400',
'h-4 w-4 shrink-0 transition-colors'
)}
aria-hidden="true"
/>
{item.name}
</>
)}
</NavLink>
)}
</li>
))}
</ul>

View file

@ -1,15 +1,13 @@
import { cn } from '@/lib/utils';
import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/24/outline';
import {
ColumnDef,
flexRender,
getCoreRowModel,
getExpandedRowModel,
getSortedRowModel,
Row,
SortingState,
useReactTable,
} from '@tanstack/react-table';
import type { ColumnDef, Row, SortingState } from '@tanstack/react-table';
import { useState, useRef } from 'react';
import { TableVirtuoso } from 'react-virtuoso';