feat(14-03): replace site detail placeholder with tabbed dashboard
- Add Health Grid, Sectors, Links tabs using useState pattern - Default tab is Health Grid showing device status cards - Remove placeholder "Assigned Devices" section - Site info card and health stats remain above tabs unchanged
This commit is contained in:
@@ -1,9 +1,13 @@
|
|||||||
|
import { useState } from 'react'
|
||||||
import { createFileRoute, Link } from '@tanstack/react-router'
|
import { createFileRoute, Link } from '@tanstack/react-router'
|
||||||
import { useQuery } from '@tanstack/react-query'
|
import { useQuery } from '@tanstack/react-query'
|
||||||
import { sitesApi } from '@/lib/api'
|
import { sitesApi } from '@/lib/api'
|
||||||
import { MapPin, ArrowLeft } from 'lucide-react'
|
import { MapPin, ArrowLeft } from 'lucide-react'
|
||||||
import { Button } from '@/components/ui/button'
|
import { Button } from '@/components/ui/button'
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import { SiteHealthGrid } from '@/components/sites/SiteHealthGrid'
|
||||||
|
import { SiteSectorView } from '@/components/sites/SiteSectorView'
|
||||||
|
import { SiteLinksTab } from '@/components/sites/SiteLinksTab'
|
||||||
|
|
||||||
export const Route = createFileRoute('/_authenticated/tenants/$tenantId/sites/$siteId')({
|
export const Route = createFileRoute('/_authenticated/tenants/$tenantId/sites/$siteId')({
|
||||||
component: SiteDetailPage,
|
component: SiteDetailPage,
|
||||||
@@ -11,6 +15,7 @@ export const Route = createFileRoute('/_authenticated/tenants/$tenantId/sites/$s
|
|||||||
|
|
||||||
function SiteDetailPage() {
|
function SiteDetailPage() {
|
||||||
const { tenantId, siteId } = Route.useParams()
|
const { tenantId, siteId } = Route.useParams()
|
||||||
|
const [activeTab, setActiveTab] = useState<'health' | 'sectors' | 'links'>('health')
|
||||||
|
|
||||||
const { data: site, isLoading } = useQuery({
|
const { data: site, isLoading } = useQuery({
|
||||||
queryKey: ['sites', tenantId, siteId],
|
queryKey: ['sites', tenantId, siteId],
|
||||||
@@ -111,15 +116,28 @@ function SiteDetailPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Placeholder for device list -- Phase 14 will add full site dashboard */}
|
{/* Tab bar */}
|
||||||
<div className="rounded-lg border border-border bg-surface p-6">
|
<div className="flex gap-1 border-b border-border">
|
||||||
<h2 className="text-sm font-semibold mb-2">Assigned Devices</h2>
|
{(['health', 'sectors', 'links'] as const).map((tab) => (
|
||||||
<p className="text-sm text-text-muted">
|
<button
|
||||||
{site.device_count > 0
|
key={tab}
|
||||||
? `${site.device_count} device${site.device_count !== 1 ? 's' : ''} assigned to this site. Full device list coming in site dashboard.`
|
onClick={() => setActiveTab(tab)}
|
||||||
: 'No devices assigned to this site yet. Assign devices from the fleet page.'}
|
className={cn(
|
||||||
</p>
|
'px-4 py-2 text-sm font-medium border-b-2 -mb-px transition-colors',
|
||||||
|
activeTab === tab
|
||||||
|
? 'border-accent text-accent'
|
||||||
|
: 'border-transparent text-text-muted hover:text-text-secondary',
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{tab === 'health' ? 'Health Grid' : tab === 'sectors' ? 'Sectors' : 'Links'}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Tab content */}
|
||||||
|
{activeTab === 'health' && <SiteHealthGrid tenantId={tenantId} siteId={siteId} />}
|
||||||
|
{activeTab === 'sectors' && <SiteSectorView tenantId={tenantId} siteId={siteId} />}
|
||||||
|
{activeTab === 'links' && <SiteLinksTab tenantId={tenantId} siteId={siteId} />}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user