mirror of
https://github.com/dyzulk/trustlab.git
synced 2026-01-26 13:32:06 +07:00
feat: implement mirror download for CA certificates
This commit is contained in:
102
src/app/(public)/download/ca-certificate/page.tsx
Normal file
102
src/app/(public)/download/ca-certificate/page.tsx
Normal file
@@ -0,0 +1,102 @@
|
||||
"use client";
|
||||
|
||||
import { Suspense, useEffect, useState } from "react";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import CommonGridShape from "@/components/common/CommonGridShape";
|
||||
|
||||
function DownloadMirrorContent() {
|
||||
const searchParams = useSearchParams();
|
||||
const [status, setStatus] = useState("Preparing your download...");
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const serial = searchParams.get("serial");
|
||||
const format = searchParams.get("format");
|
||||
const target = searchParams.get("target");
|
||||
|
||||
if (!serial) {
|
||||
setError("Missing certificate serial.");
|
||||
setStatus("");
|
||||
return;
|
||||
}
|
||||
|
||||
// Construct backend URL
|
||||
const baseUrl = process.env.NEXT_PUBLIC_BACKEND_URL;
|
||||
let downloadUrl = `${baseUrl}/api/public/ca-certificates/${serial}/download`;
|
||||
|
||||
// Append target if specified (windows/mac)
|
||||
if (target) {
|
||||
downloadUrl += `/${target}`;
|
||||
}
|
||||
|
||||
// Append format if specified (der)
|
||||
if (format) {
|
||||
downloadUrl += `?format=${format}`;
|
||||
}
|
||||
|
||||
// Mirroring: Redirect to the backend download URL
|
||||
setStatus("Redirecting to download...");
|
||||
window.location.href = downloadUrl;
|
||||
|
||||
// Optional: Auto close or go back after some time
|
||||
// But usually the download happens in the background and the page stays
|
||||
const timeout = setTimeout(() => {
|
||||
setStatus("If your download didn't start automatically, please refresh this page.");
|
||||
}, 5000);
|
||||
|
||||
return () => clearTimeout(timeout);
|
||||
}, [searchParams]);
|
||||
|
||||
return (
|
||||
<div className="relative z-1 bg-white p-6 sm:p-0 dark:bg-gray-900 flex-grow flex items-center justify-center min-h-screen">
|
||||
<div className="relative z-10 w-full max-w-md p-8 text-center">
|
||||
{error ? (
|
||||
<div className="space-y-6">
|
||||
<div className="mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-red-100 dark:bg-red-900/20">
|
||||
<svg className="h-8 w-8 text-red-600 dark:text-red-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<h2 className="text-xl font-bold text-gray-900 dark:text-white">Download Error</h2>
|
||||
<p className="mt-2 text-sm text-gray-600 dark:text-gray-400">{error}</p>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => window.history.back()}
|
||||
className="inline-flex w-full justify-center rounded-lg bg-brand-500 px-4 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-brand-600 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand-600"
|
||||
>
|
||||
Go Back
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-6">
|
||||
<div className="mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-brand-100 dark:bg-brand-900/20">
|
||||
<svg className="animate-spin h-8 w-8 text-brand-600 dark:text-brand-400" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<h2 className="text-xl font-bold text-gray-900 dark:text-white">{status}</h2>
|
||||
<p className="text-sm text-gray-500 dark:text-gray-400">Mirroring Download from TrustLab Trust Store</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
||||
<CommonGridShape />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function DownloadMirror() {
|
||||
return (
|
||||
<Suspense fallback={
|
||||
<div className="flex h-screen items-center justify-center bg-white dark:bg-gray-900">
|
||||
<div className="h-10 w-10 animate-spin rounded-full border-4 border-brand-500 border-t-transparent"></div>
|
||||
</div>
|
||||
}>
|
||||
<DownloadMirrorContent />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user