import { useMemo } from 'react' import { Link } from 'react-router-dom' import { Loader2 } from 'lucide-react' import type { Certificate } from '../api/certificates' import type { ProxyHost } from '../api/proxyHosts' interface CertificateStatusCardProps { certificates: Certificate[] hosts: ProxyHost[] } export default function CertificateStatusCard({ certificates, hosts }: CertificateStatusCardProps) { const validCount = certificates.filter(c => c.status === 'valid').length const expiringCount = certificates.filter(c => c.status === 'expiring').length const untrustedCount = certificates.filter(c => c.status === 'untrusted').length // Build a set of all domains that have certificates (case-insensitive) // ACME certificates (Let's Encrypt) are auto-managed and don't set certificate_id, // so we match by domain name instead const certifiedDomains = useMemo(() => { const domains = new Set() certificates.forEach(cert => { // Handle missing or undefined domain field if (!cert.domain) return // Certificate domain field can be comma-separated cert.domain.split(',').forEach(d => { const trimmed = d.trim().toLowerCase() if (trimmed) domains.add(trimmed) }) }) return domains }, [certificates]) // Calculate pending hosts: SSL-enabled hosts without any domain covered by a certificate const { pendingCount, totalSSLHosts, hostsWithCerts } = useMemo(() => { const sslHosts = hosts.filter(h => h.ssl_forced && h.enabled) let withCerts = 0 sslHosts.forEach(host => { // Check if any of the host's domains have a certificate const hostDomains = host.domain_names.split(',').map(d => d.trim().toLowerCase()) if (hostDomains.some(domain => certifiedDomains.has(domain))) { withCerts++ } }) return { pendingCount: sslHosts.length - withCerts, totalSSLHosts: sslHosts.length, hostsWithCerts: withCerts, } }, [hosts, certifiedDomains]) const hasProvisioning = pendingCount > 0 const progressPercent = totalSSLHosts > 0 ? Math.round((hostsWithCerts / totalSSLHosts) * 100) : 100 return (
SSL Certificates
{certificates.length}
{/* Status breakdown */}
{validCount} valid {expiringCount > 0 && {expiringCount} expiring} {untrustedCount > 0 && {untrustedCount} staging}
{/* Pending indicator */} {hasProvisioning && (
{pendingCount} host{pendingCount !== 1 ? 's' : ''} awaiting certificate
{progressPercent}% provisioned
)} ) }