feat(11-02): add Sites to sidebar navigation and tenant index page

- MapPin icon and Sites nav link in sidebar Fleet section
- Tenant index shows Sites count card in 3-column grid
- "Manage sites" link added to tenant index bottom links

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jason Staack
2026-03-18 21:46:53 -05:00
parent 40f2bcd9aa
commit e8c69fb6a6
2 changed files with 39 additions and 4 deletions

View File

@@ -14,6 +14,7 @@ import {
ClipboardList,
Wifi,
BarChart3,
MapPin,
} from 'lucide-react'
import { cn } from '@/lib/utils'
import { useAuth, isSuperAdmin, isTenantAdmin } from '@/lib/auth'
@@ -110,6 +111,15 @@ export function Sidebar() {
},
]
: []),
...(!isSuperAdmin(user) && user?.tenant_id
? [
{
label: 'Sites',
href: `/tenants/${user.tenant_id}/sites`,
icon: MapPin,
},
]
: []),
{
label: 'Wireless',
href: '/wireless',

View File

@@ -1,7 +1,7 @@
import { createFileRoute, Link } from '@tanstack/react-router'
import { useQuery } from '@tanstack/react-query'
import { Users, Monitor, Building2 } from 'lucide-react'
import { tenantsApi } from '@/lib/api'
import { Users, Monitor, Building2, MapPin } from 'lucide-react'
import { tenantsApi, sitesApi } from '@/lib/api'
import { formatDate } from '@/lib/utils'
import { CardGridSkeleton } from '@/components/ui/page-skeleton'
@@ -17,8 +17,13 @@ function TenantDetailPage() {
queryFn: () => tenantsApi.get(tenantId),
})
const { data: sitesData } = useQuery({
queryKey: ['sites', tenantId],
queryFn: () => sitesApi.list(tenantId),
})
if (isLoading) {
return <CardGridSkeleton cards={2} />
return <CardGridSkeleton cards={3} />
}
if (!tenant) {
@@ -40,7 +45,7 @@ function TenantDetailPage() {
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="grid grid-cols-3 gap-4">
<Link
to="/tenants/$tenantId/users"
params={{ tenantId }}
@@ -53,6 +58,18 @@ function TenantDetailPage() {
</div>
</Link>
<Link
to="/tenants/$tenantId/sites"
params={{ tenantId }}
className="flex items-center gap-3 rounded-lg border border-border bg-surface p-4 hover:bg-elevated/50 transition-colors group"
>
<MapPin className="h-8 w-8 text-text-muted group-hover:text-text-muted transition-colors" />
<div>
<p className="text-2xl font-semibold">{sitesData?.sites.length ?? 0}</p>
<p className="text-xs text-text-secondary">Sites</p>
</div>
</Link>
<Link
to="/tenants/$tenantId/devices"
params={{ tenantId }}
@@ -75,6 +92,14 @@ function TenantDetailPage() {
Manage users
</Link>
<span className="text-text-muted">·</span>
<Link
to="/tenants/$tenantId/sites"
params={{ tenantId }}
className="text-sm text-text-secondary hover:text-text-primary transition-colors underline-offset-2 hover:underline"
>
Manage sites
</Link>
<span className="text-text-muted">·</span>
<Link
to="/tenants/$tenantId/devices"
params={{ tenantId }}