style: refine Root CA Management layout and restore spec-sync buttons

This commit is contained in:
dyzulk
2026-01-07 04:58:44 +07:00
parent fc04d0112f
commit 713fab3fba
5 changed files with 144 additions and 99 deletions

View File

@@ -53,7 +53,7 @@ export default function RootCaManagementClient() {
const { addToast } = useToast();
const { data, error, mutate, isLoading } = useSWR("/api/admin/ca-certificates", fetcher);
const [isRenewing, setIsRenewing] = useState(false);
const [isSyncing, setIsSyncing] = useState(false);
const [activeSync, setActiveSync] = useState<string | null>(null);
const [isPromoting, setIsPromoting] = useState(false);
const [confirmRenewUuid, setConfirmRenewUuid] = useState<string | null>(null);
@@ -83,7 +83,8 @@ export default function RootCaManagementClient() {
};
const handleSyncCdn = async (type: 'all' | 'crt' | 'installers' | 'bundles', mode: 'latest' | 'archive' | 'both' = 'both') => {
setIsSyncing(true);
const syncKey = `${type}-${mode}`;
setActiveSync(syncKey);
try {
let endpoint = "/api/admin/ca-certificates/sync-cdn";
let msg = `Sync successful (Mode: ${mode})`;
@@ -106,7 +107,7 @@ export default function RootCaManagementClient() {
console.error(err);
addToast(err.response?.data?.message || "Sync failed", "error");
} finally {
setIsSyncing(false);
setActiveSync(null);
}
};
@@ -129,61 +130,58 @@ export default function RootCaManagementClient() {
const certificates = data?.data || [];
return (
<div>
<div className="flex flex-col md:flex-row md:items-center justify-between mb-4 gap-4">
<div className="space-y-6">
<div className="flex flex-col md:flex-row md:items-center justify-between mb-2 gap-4">
<PageBreadcrumb pageTitle={t("management_title")} />
</div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
{/* Left Column: Management & Renew Table */}
<div className="lg:col-span-2 space-y-6">
<CdnManagementCard
onSync={handleSyncCdn}
isSyncing={isSyncing}
disabled={isLoading}
<div className="space-y-6">
{/* Main CA Management Table */}
<ComponentCard
title={t("card_title")}
desc={t("card_desc")}
className="relative"
>
<RootCaTable
certificates={certificates.filter((c: any) => c.is_latest || certificates.length === 1)}
onRenew={setConfirmRenewUuid}
isRenewing={isRenewing}
/>
<ComponentCard
title={t("card_title")}
desc={t("card_desc")}
className="relative"
>
<RootCaTable
certificates={certificates.filter((c: any) => c.is_latest || certificates.length === 1)}
onRenew={setConfirmRenewUuid}
isRenewing={isRenewing}
/>
{(isLoading || isRenewing) && (
<div className="absolute inset-0 bg-white/50 dark:bg-gray-900/50 flex items-center justify-center z-10 backdrop-blur-sm rounded-2xl">
<PageLoader text={t("processing")} className="h-full" />
</div>
)}
</ComponentCard>
{(isLoading || isRenewing) && (
<div className="absolute inset-0 bg-white/50 dark:bg-gray-900/50 flex items-center justify-center z-10 backdrop-blur-sm rounded-2xl">
<PageLoader text={t("processing")} className="h-full" />
</div>
)}
</ComponentCard>
{/* CDN Synchronization Controls */}
<CdnManagementCard
onSync={handleSyncCdn}
activeSync={activeSync}
disabled={isLoading || isPromoting}
/>
<div className="p-4 bg-blue-50 border-l-4 border-blue-400 dark:bg-blue-900/20 dark:border-blue-600 rounded-md">
<h4 className="text-sm font-bold text-blue-800 dark:text-blue-200">{t("info_title")}</h4>
<ul className="mt-2 text-xs text-blue-700 dark:text-blue-300 list-disc list-inside space-y-1">
<li>{t("info_point_1")}</li>
<li>{t("info_point_2")}</li>
<li>{t("info_point_3")}</li>
<li>{t("info_point_4")}</li>
</ul>
</div>
</div>
{/* Full-width Archive History */}
<ComponentCard
title="Version Archives"
desc="Browse historical versions and promote them back to Latest if needed. This table provides full visibility into your CDN audit trail."
>
<ArchiveManagementTable
certificates={certificates}
onPromote={handlePromote}
isPromoting={isPromoting}
/>
</ComponentCard>
{/* Right Column: Archives */}
<div className="lg:col-span-1">
<ComponentCard
title="Version Archives"
desc="Browse historical versions and promote them back to Latest if needed."
>
<ArchiveManagementTable
certificates={certificates}
onPromote={handlePromote}
isPromoting={isPromoting}
/>
</ComponentCard>
<div className="p-4 bg-blue-50 border-l-4 border-blue-400 dark:bg-blue-900/20 dark:border-blue-600 rounded-md">
<h4 className="text-sm font-bold text-blue-800 dark:text-blue-200">{t("info_title")}</h4>
<ul className="mt-2 text-xs text-blue-700 dark:text-blue-300 list-disc list-inside space-y-1">
<li>{t("info_point_1")}</li>
<li>{t("info_point_2")}</li>
<li>{t("info_point_3")}</li>
<li>{t("info_point_4")}</li>
</ul>
</div>
</div>