diff --git a/src/app/(public)/HomeClient.tsx b/src/app/(public)/HomeClient.tsx index 524b47e..5b520b7 100644 --- a/src/app/(public)/HomeClient.tsx +++ b/src/app/(public)/HomeClient.tsx @@ -11,8 +11,12 @@ interface CaCertificate { type: string; serial: string; 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 @@ -55,10 +59,203 @@ function ScrollToTop() { ); } +// 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 OsGuideContent({ title, steps }: { title: string, steps: string[] }) { + return ( +
+

+
+ {title} +

+ +
+ ); +} + +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 }) => ( + + + +); + 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'); useEffect(() => { const fetchCertificates = async () => { @@ -227,161 +424,54 @@ export default function HomeClient() {
) : ( - <> - {/* Root CA - Centered */} -
- {certificates.filter(c => c.type === 'root').map((cert) => ( -
-
-
- - {t('root_ca')} - -

{cert.name}

-

{t('serial')}: {cert.serial}

-
-
- - - -
-
- -
-
- - - - - {t('download_standard')} - - - - - - {t('download_android')} - -
-
- - - - - {t('download_windows')} - - - - - - {t('download_macos')} - -
-
-
- ))} +
+ {/* Root CA Section */} +
+

+ {t('root_ca_hierarchy')} +

+
+ {certificates.filter(c => c.type === 'root').map((cert) => ( + + ))} +
- {/* Intermediate CAs - Grid */} -
- {certificates.filter(c => c.type !== 'root').map((cert) => ( -
-
-
- - {t('intermediate_ca')} - -

{cert.name}

-

{t('serial')}: {cert.serial}

-
-
- - - -
-
- - -
- ))} + {/* Intermediate CAs Section */} +
+
+

+ {t('intermediate_ca_hierarchy')} +

+
+ {certificates.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' && } +
+
+
)}
diff --git a/src/messages/en.json b/src/messages/en.json index 39840d1..9a9a5a5 100644 --- a/src/messages/en.json +++ b/src/messages/en.json @@ -182,13 +182,42 @@ "download_android": "Android", "download_windows": "Windows", "download_macos": "macOS", + "download_linux": "Linux", + "download_mobile": "Android/iOS", "download_standard_title": "Download Standard CRT (PEM)", "download_android_title": "Download for Android (DER)", "download_windows_title": "Download Windows Installer (.bat)", "download_macos_title": "Download macOS Profile (.mobileconfig)", + "download_linux_title": "Download Linux Installer (.sh)", "root_ca": "Root CA", "intermediate_ca": "Intermediate CA", + "root_ca_hierarchy": "Root Trust Foundation", + "intermediate_ca_hierarchy": "Secure Issuance Layer", "serial": "Serial", + "last_synced": "Last synced", + "synced_to_cdn": "Ready on CDN", + "install_guide_title": "How to Install", + "install_guide_desc": "One-click installers or manual steps for your device.", + "guide_steps_windows": [ + "Download the .bat installer.", + "Right-click and Choose 'Run as Administrator'.", + "Confirm the security prompt to add to 'Root' store." + ], + "guide_steps_macos": [ + "Download the .mobileconfig profile.", + "Open System Settings > Profiles (or Privacy & Security).", + "Double-click the TrustLab profile and click Install.", + "Go to 'About' > 'Certificate Trust Settings' and enable full trust." + ], + "guide_steps_linux": [ + "Download the .sh installer script.", + "Open terminal and run: sudo bash install-*.sh", + "The script will automatically detect and update your CA store." + ], + "guide_steps_mobile": [ + "Android: Settings > Security > Install from storage > CA Certificate.", + "iOS: Install the profile, then Settings > General > About > Certificate Trust Settings." + ], "cta_ready_title": "Ready to secure your application?", "cta_ready_desc": "Manage your internal security infrastructure independently and securely.", "cta_free_account": "Register Now", diff --git a/src/messages/id.json b/src/messages/id.json index 44ef5d3..621de10 100644 --- a/src/messages/id.json +++ b/src/messages/id.json @@ -182,13 +182,42 @@ "download_android": "Android", "download_windows": "Windows", "download_macos": "macOS", + "download_linux": "Linux", + "download_mobile": "Android/iOS", "download_standard_title": "Unduh CRT Standar (PEM)", "download_android_title": "Unduh untuk Android (DER)", "download_windows_title": "Unduh Penginstal Windows (.bat)", "download_macos_title": "Unduh Profil macOS (.mobileconfig)", - "root_ca": "CA Akar", + "download_linux_title": "Unduh Penginstal Linux (.sh)", + "root_ca": "Root CA", "intermediate_ca": "Intermediate CA", + "root_ca_hierarchy": "Fondasi Kepercayaan Akar", + "intermediate_ca_hierarchy": "Lapisan Penerbitan Aman", "serial": "Serial", + "last_synced": "Terakhir disinkronkan", + "synced_to_cdn": "Siap di CDN", + "install_guide_title": "Cara Instalasi", + "install_guide_desc": "Penginstal satu-klik atau langkah manual untuk perangkat Anda.", + "guide_steps_windows": [ + "Unduh penginstal .bat.", + "Klik kanan dan pilih 'Run as Administrator'.", + "Konfirmasi jendela keamanan untuk menambahkan ke penyimpanan 'Root'. Kesalahan umum: Memilih toko 'Personal' akan membuat cert tidak dikenal sistem." + ], + "guide_steps_macos": [ + "Unduh profil .mobileconfig.", + "Buka System Settings > Profiles (atau Privacy & Security).", + "Klik dua kali profil TrustLab dan klik Install.", + "Buka 'About' > 'Certificate Trust Settings' dan aktifkan kepercayaan penuh." + ], + "guide_steps_linux": [ + "Unduh skrip penginstal .sh.", + "Buka terminal dan jalankan: sudo bash install-*.sh", + "Skrip akan secara otomatis mendeteksi distro dan memperbarui penyimpanan CA Anda." + ], + "guide_steps_mobile": [ + "Android: Pengaturan > Keamanan > Instal dari penyimpanan > Sertifikat CA.", + "iOS: Instal profil, lalu Pengaturan > Umum > Mengenai > Pengaturan Kepercayaan Sertifikat." + ], "cta_ready_title": "Siap untuk mengamankan aplikasi Anda?", "cta_ready_desc": "Kelola infrastruktur keamanan internal Anda secara mandiri, aman, dan terorganisir.", "cta_free_account": "Daftar Sekarang",