import { useState } from 'react'; import { Card, CardHeader, CardTitle, CardContent } from '../../components/ui/card'; import { Button } from '../../components/ui/button'; import { Input, Label } from '../../components/ui'; import { Alert, AlertDescription } from '../../components/ui/alert'; import { Badge } from '../../components/ui/badge'; import { Shield, Loader2, CheckCircle, AlertCircle, RefreshCw, Plus, ShieldCheck, ShieldAlert, X } from 'lucide-react'; import { useCert } from '../../hooks/useCert'; import { usePageHelp } from '../../hooks/usePageHelp'; export function CertificatesPage() { const { status: certStatus, isLoading, provision: provisionCert, isProvisioning, renew: renewCerts, isRenewing, } = useCert(); const [provisioningDomain, setProvisioningDomain] = useState(null); const [showWildcardForm, setShowWildcardForm] = useState(false); const [wildcardInput, setWildcardInput] = useState(''); usePageHelp({ title: 'TLS Certificates', description: (

Wild Central provisions TLS certificates for services that need HTTPS. Each service gets its own certificate by default. You can also provision a wildcard certificate to cover multiple services under the same domain.

), }); const certs = certStatus?.certs ?? []; const canProvision = certStatus?.canProvision ?? false; const handleProvision = async (domain: string) => { setProvisioningDomain(domain); try { await provisionCert(domain); } finally { setProvisioningDomain(null); } }; const handleProvisionWildcard = async () => { if (!wildcardInput) return; const domain = wildcardInput.startsWith('*.') ? wildcardInput : `*.${wildcardInput}`; setProvisioningDomain(domain); try { await provisionCert(domain); setShowWildcardForm(false); setWildcardInput(''); } finally { setProvisioningDomain(null); } }; if (isLoading) { return (

Loading certificate status...

); } const allExist = certs.length > 0 && certs.every((c) => c.cert?.exists || c.coveredBy); const someExist = certs.some((c) => c.cert?.exists || c.coveredBy); return (

TLS Certificates

Manage HTTPS certificates for registered services

{allExist ? ( All Valid ) : someExist ? ( Incomplete ) : certs.length > 0 ? ( Missing ) : null}
{!canProvision && ( Certificate provisioning requires a Cloudflare API token and operator email. {!certStatus?.hasToken && ' Configure the token on the Cloudflare page.'} {!certStatus?.hasEmail && ' Set the operator email in Overview.'} )} {certs.length === 0 ? (

No Services Registered

Register services with Wild Central to manage their certificates here.

) : (
Service Certificates
{canProvision && ( )}
{showWildcardForm && (
*. setWildcardInput(e.target.value)} placeholder="cloud.payne.io" className="font-mono" />

A wildcard cert covers all subdomains. E.g., *.cloud.payne.io covers app1.cloud.payne.io, app2.cloud.payne.io, etc.

)}
{certs.map((entry) => { const exists = entry.cert?.exists; const covered = entry.coveredBy; const isThisProvisioning = provisioningDomain === entry.domain; return (
{entry.domain}
{entry.source}
{exists ? ( {entry.cert.daysLeft}d ) : covered ? ( {covered} ) : ( <> Missing {canProvision && ( )} )}
); })}
)}
); }