"use client";
import Link from "next/link";
import CommonGridShape from "@/components/common/CommonGridShape";
import { useEffect, useState } from "react";
import axios from '@/lib/axios';
import { useTranslations } from "next-intl";
interface CaCertificate {
name: string;
type: string;
serial: string;
family_id?: string | null;
expires_at: string;
last_synced_at?: string | null;
cdn_url?: string | null;
der_cdn_url?: string | null;
bat_cdn_url?: string | null;
mac_cdn_url?: string | null;
linux_cdn_url?: string | null;
}
// Simple internal ScrollToTop component
function ScrollToTop() {
const [show, setShow] = useState(false);
useEffect(() => {
const handleScroll = () => {
setShow(window.pageYOffset > 500);
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
const scrollToTop = () => {
const element = document.querySelector('#home');
if (element) {
const navbarOffset = 80;
const elementPosition = element.getBoundingClientRect().top;
const offsetPosition = elementPosition + window.pageYOffset - navbarOffset;
window.scrollTo({
top: offsetPosition,
behavior: "smooth",
});
}
};
if (!show) return null;
return (
);
}
// UI Sub-components
function Badge({ children, variant = 'brand' }: { children: React.ReactNode, variant?: 'brand' | 'blue' | 'purple' | 'green' | 'gray' }) {
const variants = {
brand: 'bg-brand-50 text-brand-700 dark:bg-brand-500/10 dark:text-brand-400 border-brand-100 dark:border-brand-500/20',
blue: 'bg-blue-50 text-blue-700 dark:bg-blue-500/10 dark:text-blue-400 border-blue-100 dark:border-blue-500/20',
purple: 'bg-purple-50 text-purple-700 dark:bg-purple-500/10 dark:text-purple-400 border-purple-100 dark:border-purple-500/20',
green: 'bg-green-50 text-green-700 dark:bg-green-500/10 dark:text-green-400 border-green-100 dark:border-green-500/20',
gray: 'bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-400 border-gray-200 dark:border-gray-700',
};
return (
{children}
);
}
function TabButton({ id, label, active, onClick, icon }: { id: string, label: string, active: boolean, onClick: () => void, icon?: React.ReactNode }) {
return (
);
}
function CliSnippet({ label, command, t }: { label: string, command: string, t: any }) {
const [copied, setCopied] = useState(false);
const copyCli = () => {
if (!command) return;
navigator.clipboard.writeText(command);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
};
return (
{label}
$
{command || t('no_script')}
);
}
function OsGuideContent({ title, steps, selectedOs, certificates, t, linuxDistro, setLinuxDistro }: { title: string, steps: string[], selectedOs: string, certificates: CaCertificate[], t: any, linuxDistro?: string, setLinuxDistro?: (distro: any) => void }) {
return (
{title}
{steps.map((step, idx) => (
-
{idx + 1}
{step}
))}
{/* Global Bundle Section (Recommendations) */}
{t('recommended')}
{t('bundle_guide_title')}
{t('bundle_guide_desc')}
{(selectedOs === 'linux' || selectedOs === 'windows' || selectedOs === 'macos') && (
{(selectedOs === 'linux') && (
{linuxDistro === 'debian' && (
)}
{linuxDistro === 'rhel' && (
)}
{linuxDistro === 'arch' && (
)}
{linuxDistro === 'other' && (
)}
)}
{(selectedOs === 'windows' || selectedOs === 'macos') && (
:
}
onClick={() => {}}
variant="blue"
/>
)}
)}
{selectedOs === 'linux' && (
{t('guide_linux_shortcut_title')}
{t('guide_linux_shortcut_desc')}
{/* Distro Selection for Individual Certs */}
{/* Function to generate smart command */}
{(() => {
const getSmartCommand = (url: string | null) => {
if (!url) return '';
if (linuxDistro === 'debian') return `sudo apt install -y curl && curl -sL ${url} | sudo bash`;
if (linuxDistro === 'rhel') return `(sudo yum install -y curl || sudo dnf install -y curl) && curl -sL ${url} | sudo bash`;
if (linuxDistro === 'arch') return `sudo pacman -Sy curl && curl -sL ${url} | sudo bash`;
return `curl -sL ${url} | sudo bash`;
};
return (
<>
{/* Root CAs */}
{certificates.filter(c => c.type === 'root').map(c => (
))}
{/* Intermediate CAs */}
{certificates.filter(c => c.type !== 'root').map(c => (
))}
>
);
})()}
)}
);
}
function CaCard({ cert, isRoot, t, selectedOs, setSelectedOs }: { cert: CaCertificate, isRoot: boolean, t: any, selectedOs: string, setSelectedOs: (os: any) => void }) {
return (
{/* Sync Status Badge */}
{cert.last_synced_at && (
{t('synced_to_cdn')}
)}
{isRoot ? t('root_ca') : t('intermediate_ca')}
{cert.name}
ID: {cert.serial}
}
onClick={() => {}}
/>
}
onClick={() => setSelectedOs('mobile')}
variant="green"
/>
}
onClick={() => setSelectedOs('windows')}
variant="blue"
/>
}
onClick={() => setSelectedOs('macos')}
variant="gray"
/>
{cert.linux_cdn_url && (
}
onClick={() => setSelectedOs('linux')}
variant="gray"
isFullWidth
/>
)}
);
}
function DownloadBtn({ href, label, icon, onClick, variant = 'white', isFullWidth = false }: { href: string, label: string, icon: React.ReactNode, onClick: () => void, variant?: 'white' | 'green' | 'blue' | 'gray', isFullWidth?: boolean }) {
const variants = {
white: 'bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-200 border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-700',
green: 'bg-green-50 dark:bg-green-500/10 text-green-700 dark:text-green-400 border-green-200 dark:border-green-500/20 hover:bg-green-100 dark:hover:bg-green-500/20',
blue: 'bg-blue-50 dark:bg-blue-500/10 text-blue-700 dark:text-blue-400 border-blue-200 dark:border-blue-500/20 hover:bg-blue-100 dark:hover:bg-blue-500/20',
gray: 'bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-100 border-gray-200 dark:border-gray-600 hover:bg-gray-200 dark:hover:bg-gray-600',
};
return (
{icon}
{label}
);
}
// Icons
const WindowsIcon = ({ className }: { className?: string }) => (
);
const AppleIcon = ({ className }: { className?: string }) => (
);
const LinuxIcon = ({ className }: { className?: string }) => (
);
const MobileIcon = ({ className }: { className?: string }) => (
);
const FileIcon = ({ className }: { className?: string }) => (
);
const CopyIcon = ({ className }: { className?: string }) => (
);
const CheckIcon = ({ className }: { className?: string }) => (
);
const ChevronDownIcon = ({ className }: { className?: string }) => (
);
export default function HomeClient() {
const t = useTranslations("Home");
const [certificates, setCertificates] = useState([]);
const [loadingCerts, setLoadingCerts] = useState(true);
const [selectedOs, setSelectedOs] = useState<'windows' | 'macos' | 'linux' | 'mobile'>('windows');
const [linuxDistro, setLinuxDistro] = useState<'debian' | 'rhel' | 'arch' | 'other'>('debian');
useEffect(() => {
const fetchCertificates = async () => {
try {
const response = await axios.get('/api/public/ca-certificates');
if (response.data.success) {
setCertificates(response.data.data);
}
} catch (error) {
console.error("Failed to fetch certificates", error);
} finally {
setLoadingCerts(false);
}
};
fetchCertificates();
}, []);
const handleScroll = (e: React.MouseEvent, id: string) => {
e.preventDefault();
const element = document.querySelector(id);
if (element) {
const navbarOffset = 80;
const elementPosition = element.getBoundingClientRect().top;
const offsetPosition = elementPosition + window.pageYOffset - navbarOffset;
window.scrollTo({
top: offsetPosition,
behavior: "smooth",
});
}
};
return (
{/* Hero Section */}
{/* Features Section */}
{t('features_title')}
{t('features_desc')}
{/* Feature 1 */}
{t('feature_1_title')}
{t('feature_1_desc')}
{/* Feature 2 */}
{t('feature_2_title')}
{t('feature_2_desc')}
{/* Feature 3 */}
{t('feature_3_title')}
{t('feature_3_desc')}
{/* Trust Store Section */}
{/* Gradient Background */}
{t('trust_store_title')}
{t('trust_store_desc')}
{loadingCerts ? (
) : (
{Object.entries(
certificates.reduce((acc, cert) => {
const famId = cert.family_id || 'unknown';
if (!acc[famId]) acc[famId] = [];
acc[famId].push(cert);
return acc;
}, {} as Record
)
).map(([famId, familyCerts]) => (
{/* Root Section of the Family */}
{t('root_ca_hierarchy')}
{familyCerts.filter(c => c.type === 'root').map((cert) => (
))}
{/* Connecting Line */}
{/* Intermediates Section of the Family */}
{t('intermediate_ca_hierarchy')}
{familyCerts.filter(c => c.type !== 'root').map((cert) => (
))}
))}
{/* OS Selection Tabs for Global Guide */}
{t('install_guide_title')}
{t('install_guide_desc')}
setSelectedOs('windows')} icon={} />
setSelectedOs('macos')} icon={} />
setSelectedOs('linux')} icon={} />
setSelectedOs('mobile')} icon={} />
{selectedOs === 'windows' && }
{selectedOs === 'macos' && }
{selectedOs === 'linux' && }
{selectedOs === 'mobile' && }
)}
{/* CTA Section */}
{t('cta_ready_title')}
{t('cta_ready_desc')}
{t('cta_free_account')}
{t('cta_signin_portal')}
{/* Abstract Design */}
{/* Back to Top Button */}
);
}