First commit

This commit is contained in:
dyzulk
2025-12-30 12:11:04 +07:00
commit 34dc111344
322 changed files with 31972 additions and 0 deletions

View File

@@ -0,0 +1,102 @@
"use client";
import React, { useState } from "react";
import useSWR from "swr";
import axios from "@/lib/axios";
import PageBreadcrumb from "@/components/common/PageBreadCrumb";
import ComponentCard from "@/components/common/ComponentCard";
import RootCaTable from "@/components/admin/RootCaTable";
import { useAuth } from "@/hooks/useAuth";
import { useRouter } from "next/navigation";
import { useToast } from "@/context/ToastContext";
import ConfirmationModal from "@/components/common/ConfirmationModal";
import PageLoader from "@/components/ui/PageLoader";
import { useTranslations } from "next-intl";
const fetcher = (url: string) => axios.get(url).then((res) => res.data);
export default function RootCaManagementClient() {
const t = useTranslations("RootCA");
const { user } = useAuth();
const router = useRouter();
const { addToast } = useToast();
const { data, error, mutate, isLoading } = useSWR("/api/admin/ca-certificates", fetcher);
const [isRenewing, setIsRenewing] = useState(false);
const [confirmRenewUuid, setConfirmRenewUuid] = useState<string | null>(null);
// Redirect if not admin (double security, backend also checks)
React.useEffect(() => {
if (user && user.role !== "admin") {
router.push("/dashboard");
}
}, [user, router]);
const handleRenew = async (uuid: string) => {
setIsRenewing(true);
try {
await axios.post(`/api/admin/ca-certificates/${uuid}/renew`, {
days: 3650
});
mutate();
addToast(t("toast_renew_success"), "success");
setConfirmRenewUuid(null);
} catch (err: any) {
console.error(err);
addToast(err.response?.data?.message || t("toast_renew_failed"), "error");
} finally {
setIsRenewing(false);
}
};
if (error) return <div className="p-10 text-center text-error-500">{t("load_failed")}</div>;
const certificates = data?.data || [];
return (
<div>
<PageBreadcrumb pageTitle={t("management_title")} />
<div className="space-y-6">
<ComponentCard
title={t("card_title")}
desc={t("card_desc")}
className="relative"
>
<RootCaTable
certificates={certificates}
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>
<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>
<ConfirmationModal
isOpen={confirmRenewUuid !== null}
onClose={() => setConfirmRenewUuid(null)}
onConfirm={() => confirmRenewUuid && handleRenew(confirmRenewUuid)}
title={t("renew_modal_title")}
message={t("renew_modal_msg")}
isLoading={isRenewing}
confirmLabel={t("renew_modal_confirm")}
variant="warning"
requiredInput="RENEW"
/>
</div>
);
}