Files

321 lines
17 KiB
TypeScript

/* eslint-disable */
// @ts-nocheck
"use client";
import { useState, useEffect } from "react";
import { useDictionary } from "@/lib/dictionary";
import { io, Socket } from "@/lib/zero-socket";
import { useOmni } from "@/components/OmniSyncProvider";
export default function Home() {
const { t } = useDictionary();
const { theme, setTheme, locale, setLocale } = useOmni();
const [isRegister, setIsRegister] = useState(false);
const [loginMode, setLoginMode] = useState<'email' | 'qr'>('email');
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [loading, setLoading] = useState(false);
const [errorMsg, setErrorMsg] = useState("");
const [successMsg, setSuccessMsg] = useState("");
const [qrScanned, setQrScanned] = useState(false);
const [qrSessionId, setQrSessionId] = useState("");
// 1. Quantum QR Sync
useEffect(() => {
if (loginMode === 'qr' && !qrSessionId) {
const sessionId = (crypto.getRandomValues(new Uint32Array(1))[0] % 900000 + 100000).toString();
setQrSessionId(sessionId);
const socket: Socket = io(typeof window !== 'undefined' ? window.location.origin : '');
socket.on("connect", () => {
socket.emit("qr_auth_init", { sessionId });
});
socket.on("qr_auth_approved", async (data: unknown) => {
const payload = data as { signature: string; email: string };
setQrScanned(true);
setSuccessMsg("Quantum Sync Approved! Verifying Handshake...");
try {
const res = await fetch('/api/auth/qr-auth', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
sessionId: sessionId,
signature: payload.signature,
email: payload.email
})
});
const verifyData = await res.json();
if (verifyData.token) {
setSuccessMsg("Handshake Valid! Accessing Multiverse...");
setTimeout(() => {
window.location.href = `/${locale}/dashboard?auth_token=${verifyData.token}`;
}, 1000);
} else {
setErrorMsg("Verification Failed: Invalid Quantum Signature.");
setQrScanned(false);
}
} catch (_e) {
setErrorMsg("Connection to Crypto Vault Interrupted.");
setQrScanned(false);
}
});
return () => { socket.disconnect(); };
}
}, [loginMode, qrSessionId, locale]);
// 2. Auth Actions
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
setErrorMsg("");
setSuccessMsg("");
const endpoint = isRegister ? '/api/auth/register' : '/api/auth/login';
try {
const res = await fetch(endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password })
});
const data = await res.json();
if (!res.ok) {
setErrorMsg(data.error || 'Authentication Failed');
setLoading(false);
return;
}
setSuccessMsg(isRegister ? "Registration Successful! Constructing Identity..." : "Identity Verified! Syncing Neural Path...");
setTimeout(() => {
if (data.user && data.user.role === 'superadmin') {
window.location.href = '/supreme-admin';
} else if (data.user && data.user.role === 'admin') {
window.location.href = '/admin';
} else {
window.location.href = '/dashboard';
}
}, 800);
} catch (_err) {
setErrorMsg('Quantum Tunnel to Database Lost.');
setLoading(false);
}
};
return (
<div className="min-h-screen relative overflow-hidden flex flex-col items-center justify-center p-6 selection:bg-emerald-500/30">
{/* 🌌 QUANTUM MESH BACKGROUND (Innovative Technology) */}
<div className="quantum-mesh" />
{/* Header Bar - Zoom Style Minimalist */}
<header className="fixed top-0 w-full h-20 px-8 flex items-center justify-between z-50 bg-black/10 backdrop-blur-md border-b border-white/5">
<div className="flex items-center gap-3 group cursor-pointer">
<div className="w-10 h-10 bg-emerald-600 rounded-xl flex items-center justify-center shadow-[0_0_20px_rgba(16,185,129,0.4)] group-hover:scale-110 transition-transform">
<svg className="w-6 h-6 text-black" fill="currentColor" viewBox="0 0 24 24"><path d="M4 4h10a2 2 0 0 1 2 2v3.5l4-3v11l-4-3V18a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z"></path></svg>
</div>
<span className="text-xl font-black tracking-tighter text-white uppercase italic">JUMPA.ID <span className="text-emerald-500 not-italic">MESH</span></span>
</div>
<div className="flex items-center gap-6">
{/* Multi-Language Switcher */}
<div className="flex bg-white/5 p-1 rounded-xl border border-white/10">
<button onClick={() => setLocale('id')} className={`px-3 py-1 text-[10px] font-black rounded-lg transition-all ${locale === 'id' ? 'bg-emerald-600 text-black shadow-lg' : 'text-white/40 hover:text-white'}`}>ID</button>
<button onClick={() => setLocale('en')} className={`px-3 py-1 text-[10px] font-black rounded-lg transition-all ${locale === 'en' ? 'bg-emerald-600 text-black shadow-lg' : 'text-white/40 hover:text-white'}`}>EN</button>
</div>
<button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')} className="text-white/40 hover:text-white transition-colors">
{theme === 'dark' ? (
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"><path fillRule="evenodd" 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" clipRule="evenodd"></path></svg>
) : (
<svg className="w-5 h-5" 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>
</div>
</header>
{/* 🛡️ MAIN LOGIN CARD - SPECTACULAR WEDDING OF DESIGN */}
<div className="relative z-10 w-full max-w-[440px] animate-in fade-in slide-in-from-bottom-8 duration-700">
{/* Top Status Indicators (WhatsApp Style) */}
<div className="flex justify-center mb-8">
<div className="bg-emerald-950/30 border border-emerald-500/20 backdrop-blur-xl px-4 py-1.5 rounded-full flex items-center gap-2">
<div className="w-2 h-2 bg-emerald-500 rounded-full animate-pulse shadow-[0_0_10px_#10b981]"></div>
<span className="text-[10px] font-black uppercase tracking-[0.3em] text-emerald-500">Quantum Vault Synchronized</span>
</div>
</div>
<div className="glass-card p-10">
<div className="text-center mb-10">
<h2 className="text-4xl font-black text-white tracking-tighter mb-2">
{isRegister ? t("Index.initialize_account") : t("Index.title")}
</h2>
<p className="text-slate-400 text-sm font-medium">{t("Index.subtitle")}</p>
</div>
{!isRegister && (
<div className="flex bg-white/5 p-1 rounded-2xl border border-white/10 mb-8">
<button
onClick={() => setLoginMode('email')}
className={`flex-1 py-3 text-xs font-black uppercase tracking-widest rounded-xl transition-all ${loginMode === 'email' ? 'bg-white text-black shadow-xl scale-100' : 'text-slate-500 hover:text-white'}`}
>
{t("Index.credentials")}
</button>
<button
onClick={() => setLoginMode('qr')}
className={`flex-1 py-3 text-xs font-black uppercase tracking-widest rounded-xl transition-all flex items-center justify-center gap-2 ${loginMode === 'qr' ? 'bg-white text-black shadow-xl scale-100' : 'text-slate-500 hover:text-white'}`}
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M12 4v1m6 11h2m-6 0h-2v4m0-11v3m0 0h.01M12 12h4.01M16 20h4M4 12h4m12 0h.01M5 8h2a1 1 0 001-1V5a1 1 0 00-1-1H5a1 1 0 00-1 1v2a1 1 0 001 1zm14 0h2a1 1 0 001-1V5a1 1 0 00-1-1h-2a1 1 0 00-1 1v2a1 1 0 001 1zM5 20h2a1 1 0 001-1v-2a1 1 0 00-1-1H5a1 1 0 00-1 1v2a1 1 0 001 1z"></path></svg>
{t("Index.quantum_qr")}
</button>
</div>
)}
{loginMode === 'email' || isRegister ? (
<form onSubmit={handleSubmit} className="space-y-6">
{errorMsg && (
<div className="bg-red-500/10 border border-red-500/20 text-red-500 p-4 rounded-2xl text-xs text-center font-bold uppercase tracking-widest animate-shake">
{errorMsg}
</div>
)}
{successMsg && (
<div className="bg-emerald-500/10 border border-emerald-500/20 text-emerald-500 p-4 rounded-2xl text-xs text-center font-bold uppercase tracking-widest animate-pulse">
{successMsg}
</div>
)}
<div className="group relative">
<input
type="email" required
className="w-full input-ambient rounded-2xl px-5 py-4 text-[15px] placeholder-slate-500 font-medium"
placeholder={t("Index.email_placeholder")}
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<div className="absolute right-5 top-1/2 -translate-y-1/2 text-slate-600 group-focus-within:text-emerald-500 transition-colors">
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"><path d="M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z"></path><path d="M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z"></path></svg>
</div>
</div>
<div className="group relative">
<input
type="password" required minLength={6}
className="w-full input-ambient rounded-2xl px-5 py-4 text-[15px] placeholder-slate-500 font-medium"
placeholder={t("Index.password_placeholder")}
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<div className="absolute right-5 top-1/2 -translate-y-1/2 text-slate-600 group-focus-within:text-emerald-500 transition-colors">
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20"><path fillRule="evenodd" d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z" clipRule="evenodd"></path></svg>
</div>
</div>
{!isRegister && (
<div className="flex items-center justify-between text-[11px] px-1 font-black uppercase tracking-widest">
<label className="flex items-center text-slate-500 gap-3 cursor-pointer hover:text-white transition-colors">
<input type="checkbox" className="rounded-lg border-white/10 bg-white/5 text-emerald-500 focus:ring-emerald-500 w-5 h-5 transition-all" />
<span>{t("Index.persistent_session")}</span>
</label>
<a href="#" className="text-emerald-500 hover:text-white transition-colors">{t("Index.reset_key")}</a>
</div>
)}
<button
type="submit"
disabled={loading}
className={`w-full btn-ultra rounded-2xl py-5 flex items-center justify-center gap-3 ${loading ? 'opacity-50 cursor-not-allowed' : ''}`}
>
{loading ? (
<div className="w-6 h-6 border-4 border-black/20 border-t-black rounded-full animate-spin"></div>
) : (
<>
<span>{isRegister ? t("Index.initialize_account") : t("Index.enter_multiverse")}</span>
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="3" d="M13 7l5 5m0 0l-5 5m5-5H6"></path></svg>
</>
)}
</button>
</form>
) : (
<div className="flex flex-col items-center justify-center py-4 animate-in fade-in zoom-in duration-500">
<div className="relative w-56 h-56 p-4 rounded-[40px] bg-white/5 border border-white/10 mb-8 flex items-center justify-center overflow-hidden group">
{/* SCANNING LASER EFFECT */}
<div className="absolute top-0 left-0 w-full h-1 bg-emerald-500 shadow-[0_0_20px_#10b981] animate-[scan_3s_linear_infinite] z-20"></div>
<div className="w-full h-full rounded-[30px] bg-black/40 flex flex-col items-center justify-center relative z-10 border border-white/5">
{!qrScanned ? (
<>
<div className="text-[10px] text-emerald-500 mb-2 font-black tracking-[0.4em] uppercase">QUANTUM SESSION</div>
<div className="text-3xl text-white font-black tracking-[0.2em]">{qrSessionId || '••••••'}</div>
<div className="mt-4 flex gap-1">
{[...Array(6)].map((_,i) => <div key={i} className="w-1.5 h-1.5 bg-emerald-500/20 rounded-full animate-pulse" style={{animationDelay: `${i*0.2}s`}}></div>)}
</div>
</>
) : (
<div className="flex flex-col items-center justify-center text-emerald-500 animate-in zoom-in scale-110">
<svg className="w-20 h-20 mb-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2.5" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
<span className="font-black tracking-[0.5em] text-xs uppercase">CONNECTED</span>
</div>
)}
</div>
</div>
<h3 className="text-2xl font-black text-white mb-2 tracking-tighter">{t("Index.instant_sync")}</h3>
<p className="text-slate-500 text-[13px] text-center max-w-[280px] leading-relaxed font-medium">
{t("Index.scan_instructions")}
</p>
{qrScanned && <p className="text-emerald-500 font-black text-[10px] mt-6 animate-pulse uppercase tracking-[0.3em]">Neural Handshake in Progress...</p>}
</div>
)}
<div className="mt-12 pt-8 border-t border-white/5 text-center text-[11px] font-black uppercase tracking-widest">
<span className="text-slate-600">
{isRegister ? t("Index.known_identity") : t("Index.new_to_multiverse")}
</span>
<button
type="button"
onClick={() => { setIsRegister(!isRegister); setErrorMsg(""); setSuccessMsg(""); setLoginMode('email'); }}
className="ml-3 text-emerald-500 hover:text-white transition-all hover:scale-105"
>
{isRegister ? t("Index.sign_in") : t("Index.access_now")}
</button>
</div>
</div>
{/* Footer Info */}
<div className="mt-12 text-center text-[10px] text-slate-600 font-black uppercase tracking-[0.4em] space-y-4">
<p className="hover:text-slate-400 transition-colors">Enterprise Quantum Mesh Node #Alpha</p>
<div className="flex justify-center gap-8 text-slate-700">
<a href="#" className="hover:text-emerald-500 transition-colors">Protocol</a>
<a href="#" className="hover:text-emerald-500 transition-colors">Sovereignty</a>
<a href="#" className="hover:text-emerald-500 transition-colors">Neural Sync</a>
</div>
<p className="opacity-30">&copy; 2026 JUMPA.ID | XCom Ultra Engine v2.0</p>
</div>
</div>
<style jsx>{`
@keyframes scan {
0%, 100% { top: 0; }
50% { top: 100%; }
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-5px); }
75% { transform: translateX(5px); }
}
.animate-shake {
animation: shake 0.4s ease-in-out;
}
`}</style>
</div>
);
}