[TSM.ID].[11031972] PXE : Platform X Ecosystem I [118 Module -LIVE-]
This commit is contained in:
@@ -0,0 +1,219 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useDictionary } from "@/lib/dictionary";
|
||||
import { useOmni } from "@/components/OmniSyncProvider";
|
||||
|
||||
export default function Dashboard() {
|
||||
const { t } = useDictionary();
|
||||
const { theme, setTheme, currency, setCurrency, locale, setLocale } = useOmni();
|
||||
const [email, setEmail] = useState("");
|
||||
const [role, setRole] = useState("user");
|
||||
const [licenses, setLicenses] = useState<Record<string, string>>({});
|
||||
const [, setEngineStrategy] = useState("XCU_GLOBAL_MESH");
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
try {
|
||||
const resp = await fetch("/api/auth/me");
|
||||
const data = await resp.json();
|
||||
if (data.error) {
|
||||
window.location.href = "/";
|
||||
} else {
|
||||
setEmail(data.email);
|
||||
setRole(data.role);
|
||||
setLicenses(data.licenses || {});
|
||||
if (data.mediaEngineStrategy) {
|
||||
setEngineStrategy(data.mediaEngineStrategy);
|
||||
}
|
||||
}
|
||||
} catch (_e) {
|
||||
window.location.href = "/";
|
||||
}
|
||||
})();
|
||||
}, []);
|
||||
|
||||
const handleLogout = async () => {
|
||||
try {
|
||||
await fetch('/api/auth/logout', { method: 'POST' });
|
||||
window.location.href = '/';
|
||||
} catch (e) {
|
||||
console.error("Logout failed", e);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-[#050b14] text-white selection:bg-brand/30 selection:text-white relative overflow-x-hidden pb-24 md:pb-6">
|
||||
{/* Dynamic Background */}
|
||||
<div className="fixed inset-0 z-0 pointer-events-none">
|
||||
<div className="absolute top-[-10%] left-[-10%] w-[50%] h-[50%] bg-brand/10 rounded-full blur-[120px] animate-pulse"></div>
|
||||
<div className="absolute bottom-[-10%] right-[-10%] w-[40%] h-[40%] bg-blue-600/10 rounded-full blur-[100px]" style={{animationDelay: '2s'}}></div>
|
||||
</div>
|
||||
|
||||
<div className="max-w-6xl mx-auto px-4 md:px-6 pt-6 md:pt-10 relative z-10">
|
||||
|
||||
{/* Top Header - Ultra Refined */}
|
||||
<header className="flex justify-between items-center glass-panel p-4 md:p-5 rounded-2xl mb-8 border-white/5 shadow-2xl">
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="relative group">
|
||||
<div className="absolute -inset-1 bg-linear-to-r from-brand to-blue-600 rounded-full blur opacity-40 group-hover:opacity-75 transition duration-1000 group-hover:duration-200"></div>
|
||||
<div className="relative w-12 h-12 md:w-14 md:h-14 rounded-full bg-black flex items-center justify-center text-white font-black text-lg border border-white/10">
|
||||
{email ? email.substring(0, 2).toUpperCase() : "US"}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="text-lg md:text-xl font-black tracking-tighter uppercase text-white/90">
|
||||
JUMPA.ID <span className="text-brand">ULTRA</span>
|
||||
</h1>
|
||||
<p className="text-[10px] md:text-xs text-gray-500 font-mono uppercase tracking-widest">
|
||||
{role} • node-alpha-synchronized
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
{/* SETTINGS MATRIX - DUAL BHS / THEME / CURRENCY */}
|
||||
<div className="hidden lg:flex items-center gap-2 p-1.5 glass-panel rounded-xl border-white/5 mr-2">
|
||||
<button onClick={() => setLocale(locale === 'id' ? 'en' : 'id')} className="px-3 py-1.5 rounded-lg bg-white/5 hover:bg-white/10 text-[10px] font-black uppercase tracking-widest border border-white/5 transition-all">
|
||||
{locale === 'id' ? 'ID 🇮🇩' : 'EN 🇺🇸'}
|
||||
</button>
|
||||
<button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')} className="p-1.5 rounded-lg bg-white/5 hover:bg-white/10 border border-white/5 transition-all text-amber-500">
|
||||
{theme === 'dark' ? (
|
||||
<svg className="w-4 h-4" fill="currentColor" viewBox="0 0 20 20"><path d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"></path></svg>
|
||||
) : (
|
||||
<svg className="w-4 h-4" fill="currentColor" viewBox="0 0 20 20"><path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"></path></svg>
|
||||
)}
|
||||
</button>
|
||||
<select value={currency} onChange={(e) => setCurrency(e.target.value as any)} className="bg-transparent text-[10px] font-black uppercase tracking-widest border-none focus:ring-0 cursor-pointer text-emerald-500">
|
||||
<option value="Rp" className="bg-[#050b14]">IDR</option>
|
||||
<option value="USD" className="bg-[#050b14]">USD</option>
|
||||
<option value="Crypto" className="bg-[#050b14]">XCU</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="hidden lg:flex items-center gap-3 bg-black/40 border border-white/5 rounded-xl px-4 py-2 mr-4">
|
||||
<div className="flex flex-col items-end">
|
||||
<span className="text-[9px] text-gray-500 uppercase font-bold">{t('Dashboard.mesh_sync')}</span>
|
||||
<span className="text-[10px] text-brand font-mono">3/3 NODES READY</span>
|
||||
</div>
|
||||
<div className="flex gap-1">
|
||||
<div className="w-1.5 h-4 bg-brand rounded-full animate-pulse"></div>
|
||||
<div className="w-1.5 h-4 bg-brand/60 rounded-full animate-pulse" style={{animationDelay: '0.2s'}}></div>
|
||||
<div className="w-1.5 h-4 bg-brand/30 rounded-full animate-pulse" style={{animationDelay: '0.4s'}}></div>
|
||||
</div>
|
||||
</div>
|
||||
<button onClick={handleLogout} className="p-3 bg-red-500/10 hover:bg-red-500/20 text-red-500 border border-red-500/20 rounded-xl transition-all">
|
||||
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"></path></svg>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{/* Hero Section - Mobile First */}
|
||||
<section className="mb-10 text-center md:text-left">
|
||||
<h2 className="text-3xl md:text-5xl font-black tracking-tight mb-2">{t('Dashboard.welcome')}, <span className="text-transparent bg-clip-text bg-linear-to-r from-white to-gray-500">{email.split('@')[0]}</span></h2>
|
||||
<p className="text-gray-400 text-sm md:text-base max-w-2xl">{t('Index.subtitle')}. Cepat, Aman, dan Tersinkronisasi secara Kuantum.</p>
|
||||
</section>
|
||||
|
||||
{/* Main Grid */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
|
||||
{/* Chat Pilar */}
|
||||
{licenses['chat'] !== 'HIDDEN' && (
|
||||
<button
|
||||
onClick={() => router.push('/c')}
|
||||
className="group relative p-6 md:p-10 glass-panel rounded-3xl border-white/5 hover:border-emerald-500/30 transition-all duration-500 text-left overflow-hidden"
|
||||
>
|
||||
<div className="absolute top-0 right-0 w-32 h-32 bg-emerald-500/10 rounded-full blur-3xl group-hover:bg-emerald-500/20 transition-all"></div>
|
||||
<div className="flex items-center gap-6 mb-6">
|
||||
<div className="w-16 h-16 rounded-2xl bg-emerald-500/10 flex items-center justify-center text-emerald-500 group-hover:scale-110 transition-transform">
|
||||
<svg className="w-8 h-8" fill="currentColor" viewBox="0 0 24 24"><path d="M19.005 3.175H4.674C3.642 3.175 3 3.789 3 4.821V21.02l3.544-3.514h12.461c1.033 0 2.064-1.06 2.064-2.093V4.821c-.001-1.032-1.032-1.646-2.064-1.646zm-4.989 9.869H7.041V11.1h6.975v1.944zm3-4H7.041V7.1h9.975v1.944z"></path></svg>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl md:text-2xl font-black text-white group-hover:text-emerald-400 transition-colors">JUMPA Chat</h3>
|
||||
<span className="text-[10px] bg-emerald-500/20 text-emerald-400 px-2 py-0.5 rounded-full font-mono uppercase">E2EE Secured</span>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-gray-400 text-sm leading-relaxed">Komunikasi teks dan kolaborasi tim dengan enkripsi tingkat militer dan fitur Chameleon Mirage.</p>
|
||||
<div className="mt-6 flex items-center text-emerald-500 font-bold text-xs tracking-widest uppercase gap-2 group-hover:translate-x-2 transition-transform">
|
||||
Luncurkan Obrolan <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path></svg>
|
||||
</div>
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* VC Pilar */}
|
||||
{licenses['vc'] !== 'HIDDEN' && (
|
||||
<button
|
||||
onClick={() => router.push('/vc')}
|
||||
className="group relative p-6 md:p-10 glass-panel rounded-3xl border-white/5 hover:border-red-500/30 transition-all duration-500 text-left overflow-hidden"
|
||||
>
|
||||
<div className="absolute top-0 right-0 w-32 h-32 bg-red-500/10 rounded-full blur-3xl group-hover:bg-red-500/20 transition-all"></div>
|
||||
<div className="flex items-center gap-6 mb-6">
|
||||
<div className="w-16 h-16 rounded-2xl bg-red-500/10 flex items-center justify-center text-red-500 group-hover:scale-110 transition-transform">
|
||||
<svg className="w-8 h-8" fill="currentColor" viewBox="0 0 24 24"><path d="M17 10.5V7c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4z"></path></svg>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl md:text-2xl font-black text-white group-hover:text-red-400 transition-colors">JUMPA Meet</h3>
|
||||
<span className="text-[10px] bg-red-500/20 text-red-400 px-2 py-0.5 rounded-full font-mono uppercase">XCU Engine v2</span>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-gray-400 text-sm leading-relaxed">Video conference definisi tinggi dengan latensi ultra-rendah dan integrasi eBPF kernel bypass.</p>
|
||||
<div className="mt-6 flex items-center text-red-500 font-bold text-xs tracking-widest uppercase gap-2 group-hover:translate-x-2 transition-transform">
|
||||
Mulai Rapat <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path></svg>
|
||||
</div>
|
||||
</button>
|
||||
)}
|
||||
|
||||
</div>
|
||||
|
||||
{/* Admin Section if authorized */}
|
||||
{(role === 'admin' || role === 'superadmin') && (
|
||||
<div className="mt-8">
|
||||
<button
|
||||
onClick={() => router.push('/admin')}
|
||||
className="w-full p-6 glass-panel rounded-2xl border-white/5 border-dashed hover:border-amber-500/30 transition-all flex items-center justify-between group"
|
||||
>
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="w-10 h-10 rounded-lg bg-amber-500/10 flex items-center justify-center text-amber-500">
|
||||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path></svg>
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<h4 className="font-bold text-white group-hover:text-amber-400 transition-colors">Admin Management Center</h4>
|
||||
<p className="text-[10px] text-gray-500 uppercase tracking-widest">Atur Pengguna, Lisensi, dan Matrix Modul</p>
|
||||
</div>
|
||||
</div>
|
||||
<svg className="w-5 h-5 text-gray-500 group-hover:text-amber-500 transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 5l7 7-7 7"></path></svg>
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
</div>
|
||||
|
||||
{/* Mobile Bottom Navigation - 100% Mobile Compatible */}
|
||||
<nav className="fixed bottom-4 left-4 right-4 md:hidden glass-panel rounded-2xl p-2 z-50 border-white/10 shadow-[0_-10px_40px_rgba(0,0,0,0.5)] flex justify-around items-center">
|
||||
<button onClick={() => router.push('/dashboard')} className="flex flex-col items-center gap-1 p-2 text-brand">
|
||||
<svg className="w-6 h-6" fill="currentColor" viewBox="0 0 24 24"><path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"></path></svg>
|
||||
<span className="text-[9px] font-bold uppercase">Home</span>
|
||||
</button>
|
||||
<button onClick={() => router.push('/c')} className="flex flex-col items-center gap-1 p-2 text-gray-400">
|
||||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"></path></svg>
|
||||
<span className="text-[9px] font-bold uppercase">Chat</span>
|
||||
</button>
|
||||
<button onClick={() => router.push('/vc')} className="flex flex-col items-center gap-1 p-2 text-gray-400">
|
||||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z"></path></svg>
|
||||
<span className="text-[9px] font-bold uppercase">Meet</span>
|
||||
</button>
|
||||
<button onClick={() => router.push('/admin')} className="flex flex-col items-center gap-1 p-2 text-gray-400">
|
||||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path></svg>
|
||||
<span className="text-[9px] font-bold uppercase">Profile</span>
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
{/* Ultra Footer */}
|
||||
<footer className="text-center py-10 opacity-30">
|
||||
<p className="text-[10px] font-mono tracking-[0.2em] uppercase">Jumpa.ID Ecosystem • Harmonic OS Optimized</p>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user