Files
the-other-dude/frontend/src/components/certificates/CertificatesPage.tsx
Jason Staack 17037e4936 feat(ui): replace skeleton loaders with honest loading states
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:40:58 -05:00

112 lines
3.1 KiB
TypeScript

/**
* CertificatesPage -- Main certificate management page.
*
* Two sections:
* 1. CA Status Card -- shows CA state or initialization prompt
* 2. Device Certificates Table -- per-device cert status with actions
*/
import { useQuery } from '@tanstack/react-query'
import { useUIStore } from '@/lib/store'
import { Shield, Building2 } from 'lucide-react'
import { certificatesApi } from '@/lib/certificatesApi'
import { useAuth, isSuperAdmin } from '@/lib/auth'
import { canWrite } from '@/lib/auth'
import { CAStatusCard } from './CAStatusCard'
import { DeviceCertTable } from './DeviceCertTable'
import { EmptyState } from '@/components/ui/empty-state'
import { TableSkeleton } from '@/components/ui/page-skeleton'
export function CertificatesPage() {
const { user } = useAuth()
const writable = canWrite(user)
const { selectedTenantId } = useUIStore()
const tenantId = isSuperAdmin(user)
? (selectedTenantId ?? '')
: (user?.tenant_id ?? '')
// ── Queries ──
const {
data: ca,
isLoading: caLoading,
} = useQuery({
queryKey: ['ca', tenantId],
queryFn: () => certificatesApi.getCA(tenantId),
enabled: !!tenantId,
})
const {
data: deviceCerts = [],
isLoading: certsLoading,
} = useQuery({
queryKey: ['deviceCerts', tenantId],
queryFn: () => certificatesApi.getDeviceCerts(undefined, tenantId),
enabled: !!tenantId && ca !== undefined,
})
// Super admin needs to select a tenant from the header
if (isSuperAdmin(user) && !tenantId) {
return (
<div className="p-6 space-y-6">
<div className="flex items-center gap-3">
<Shield className="h-5 w-5 text-text-muted" />
<h1 className="text-2xl font-bold text-text-primary">
Certificate Authority
</h1>
</div>
<EmptyState
icon={Building2}
title="No Organization Selected"
description="Select an organization from the header to manage certificates."
/>
</div>
)
}
if (caLoading) {
return (
<div className="p-6 space-y-6">
<div className="flex items-center gap-3">
<Shield className="h-5 w-5 text-text-muted" />
<h1 className="text-2xl font-bold text-text-primary">
Certificate Authority
</h1>
</div>
<TableSkeleton />
</div>
)
}
return (
<div className="p-6 space-y-6">
{/* Header */}
<div className="flex items-center gap-3">
<Shield className="h-5 w-5 text-text-muted" />
<h1 className="text-2xl font-bold text-text-primary">
Certificate Authority
</h1>
</div>
{/* CA Status */}
<section>
<CAStatusCard ca={ca ?? null} canWrite={writable} tenantId={tenantId} />
</section>
{/* Device Certificates (only when CA exists) */}
{ca && (
<section>
<DeviceCertTable
certs={deviceCerts}
loading={certsLoading}
caExists={!!ca}
canWrite={writable}
tenantId={tenantId}
/>
</section>
)}
</div>
)
}