Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
223 changes: 152 additions & 71 deletions sites/mainweb/app/(portal)/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,118 +10,199 @@ export default function Home() {
const router = useRouter();
const [mounted, setMounted] = useState(false);

const [logs, setLogs] = useState<string[]>([
"Initializing terminal...",
"System check: OK",
"Loading background modules..."
]);

const { data: adminStatus } = trpc.admin.isAdmin.useQuery(undefined, {
enabled: !!session,
});

const { data: memberStatus } = trpc.member.checkStatus.useQuery(undefined, {
enabled: !!session,
});

const { data: judgeStatus } = trpc.judge.isJudge.useQuery(undefined, {
enabled: !!session,
});

const { mutate: sayHello, isPending: helloLoading } =
trpc.hello.sayHello.useMutation({
onSuccess: (res) => {
setLogs(prev => [...prev.slice(-4), `> Response: ${res.message}`]);
},
onError: () => {
setLogs(prev => [...prev.slice(-4), "> Error: Connection failed"]);
}
});

useEffect(() => {
setMounted(true);

const timeout = setTimeout(() => {
setLogs(prev => [...prev.slice(-4), "> Network: Established", "> Session: Awaiting user..."]);
}, 800);

return () => clearTimeout(timeout);
}, []);

useEffect(() => {
if (adminStatus) {
const roleLog = adminStatus.isAdmin
? `> Admin Access: ${adminStatus.role?.toUpperCase()}`
: "> Access Level: Standard User";
setLogs(prev => [...prev.slice(-4), roleLog]);
}
}, [adminStatus]);

useEffect(() => {
if (memberStatus) {
const memberLog = memberStatus.isMember
? `> Membership: ${memberStatus.memberType?.toUpperCase()} (${memberStatus.daysRemaining} days remaining)`
: "> Membership: Not Active";
setLogs(prev => [...prev.slice(-4), memberLog]);
}
}, [memberStatus]);

useEffect(() => {
if (judgeStatus?.isJudge) {
setLogs(prev => [...prev.slice(-4), "> Role Detected: JUDGE"]);
}
}, [judgeStatus]);

useEffect(() => {
if (status === 'authenticated' && session) {
setLogs(prev => [...prev.slice(-4), "> Auth success. Handshaking...", "> Redirecting to secure node..."]);

const redirectTimeout = setTimeout(() => {
if (judgeStatus?.isJudge && !adminStatus?.isAdmin) {
router.push('/judge');
} else {
router.push('/dashboard');
}
}, 800);
}, 1200);

return () => clearTimeout(redirectTimeout);
}
}, [status, session, router, judgeStatus, adminStatus]);

const handleTestEndpoint = () => {
setLogs(prev => [...prev.slice(-4), "> Executing: public.sayHello()"]);
sayHello();
};

const handleSignIn = () => {
setLogs(prev => [...prev.slice(-4), "> Initializing OAuth..."]);
signIn('google', { callbackUrl: '/dashboard' });
};

if (!mounted) return <div className="min-h-screen bg-black" />;
if (!mounted) return <div className="min-h-screen bg-[#050505]" />;

const isRedirecting = status === 'authenticated';
const isLoading = status === 'loading';

return (
<div className="relative min-h-screen min-h-[100dvh] bg-black text-gray-400 font-sans overflow-hidden flex items-center justify-center">
{/* Background */}
<div className="relative min-h-screen bg-[#050505] text-gray-400 font-sans selection:bg-[#00A8A8]/30 overflow-hidden flex items-center justify-center">

<div className="absolute inset-0 z-0">
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[800px] h-[800px] bg-teal-500/10 rounded-full blur-[200px]" />
<div className="absolute inset-0 bg-[linear-gradient(to_right,#ffffff03_1px,transparent_1px),linear-gradient(to_bottom,#ffffff03_1px,transparent_1px)] bg-[size:60px_60px]" />
<div className="absolute inset-0 bg-[radial-gradient(circle_at_center,rgba(0,168,168,0.05)_0%,transparent_70%)]" />
<div className="absolute inset-0 bg-[linear-gradient(to_right,#80808012_1px,transparent_1px),linear-gradient(to_bottom,#80808012_1px,transparent_1px)] bg-[size:40px_40px] [mask-image:radial-gradient(ellipse_60%_50%_at_50%_0%,#000_70%,transparent_100%)]" />
</div>

<main className="relative z-10 w-full max-w-md mx-auto px-6 text-center">
{/* Logo */}
<div className="mb-10">
<div className="relative inline-block">
<div className="absolute inset-0 bg-gradient-to-b from-teal-500/30 to-transparent blur-[60px] scale-150" />
<img
src="/images/dsgt/apple-touch-icon.png"
alt="DSGT Logo"
className="relative w-24 h-24 mx-auto drop-shadow-[0_0_30px_rgba(0,168,168,0.4)]"
/>
<main className="relative z-10 max-w-7xl mx-auto px-6 lg:px-12 w-full grid grid-cols-1 lg:grid-cols-2 gap-20 items-center">

<div className="space-y-12">
<div className="space-y-6">
<div className="flex items-center gap-4">
<div className="h-px w-12 bg-[#00A8A8]/30" />
<span className="text-xs font-mono text-gray-500 uppercase tracking-[0.4em]">Query Engine // V.1</span>
</div>

<h1 className="text-7xl lg:text-9xl font-black text-white leading-[0.8] tracking-tighter uppercase">
Query <br />
<span className="text-transparent bg-clip-text bg-gradient-to-r from-[#00A8A8] to-[#005a5a] italic">
DSGT.
</span>
</h1>

<div className="max-w-md space-y-4">
<p className="text-sm text-gray-500 leading-relaxed border-l-2 border-[#00A8A8]/20 pl-4 italic font-medium">
The collective intelligence of Georgia Tech's largest data science community. Authenticate to access your dashboard.
</p>

<div className="bg-black/60 backdrop-blur-md border border-white/5 p-5 rounded-lg font-mono text-[11px] leading-relaxed shadow-2xl relative overflow-hidden group">
<div className="absolute top-0 left-0 w-full h-[1px] bg-gradient-to-r from-transparent via-[#00A8A8]/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity" />
{logs.map((log, i) => (
<p key={i} className={i === logs.length - 1 ? "text-[#00A8A8]" : "text-gray-600"}>
{log}
</p>
))}
{(helloLoading || isRedirecting || status === 'loading') && (
<p className="text-[#00A8A8] animate-pulse">
{'>'} {status === 'loading' ? 'Syncing_Identity...' : 'Processing request...'}
</p>
)}
</div>
</div>
</div>

<div className="flex flex-col sm:flex-row items-center gap-6">
<button
onClick={handleSignIn}
disabled={helloLoading || isRedirecting || status === 'loading'}
className="w-full sm:w-auto px-12 py-5 bg-white text-black font-black text-[11px] uppercase tracking-[0.2em] rounded-sm hover:bg-[#00A8A8] hover:text-white transition-all active:scale-95 disabled:opacity-30 shadow-[0_0_30px_rgba(0,168,168,0.1)]"
>
{isRedirecting ? 'Verified' : 'Sign In'}
</button>

<button
onClick={handleTestEndpoint}
disabled={helloLoading || isRedirecting || status === 'loading'}
className="w-full sm:w-auto px-8 py-5 border border-white/10 text-white font-black text-[11px] uppercase tracking-[0.2em] rounded-sm hover:bg-white/5 transition-all active:scale-95 disabled:opacity-30"
>
Click me!
</button>
</div>
</div>

{/* Title */}
<h1 className="text-5xl font-black text-white leading-tight tracking-tight mb-3">
Query <span className="bg-gradient-to-r from-teal-400 to-emerald-400 bg-clip-text text-transparent">DSGT</span>
</h1>
<p className="text-gray-500 text-sm mb-10 max-w-xs mx-auto">
Georgia Tech's largest data science community. Sign in to access your dashboard.
</p>

{/* Sign In Button */}
<button
onClick={handleSignIn}
disabled={isLoading || isRedirecting}
className="w-full px-8 py-5 bg-gradient-to-r from-teal-500 to-emerald-500 text-white font-bold text-base rounded-2xl active:scale-[0.98] transition-transform shadow-xl shadow-teal-500/30 disabled:opacity-50 mb-4"
>
{isRedirecting ? (
<span className="flex items-center justify-center gap-2">
<svg className="w-5 h-5 animate-spin" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
</svg>
Redirecting...
</span>
) : isLoading ? (
<span className="flex items-center justify-center gap-2">
<svg className="w-5 h-5 animate-spin" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
</svg>
Loading...
</span>
) : (
<span className="flex items-center justify-center gap-3">
<svg className="w-5 h-5" viewBox="0 0 24 24" fill="currentColor">
<path d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" />
<path d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" />
<path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" />
<path d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" />
</svg>
Sign in with Google
</span>
)}
</button>

{/* Status indicator */}
<div className="flex items-center justify-center gap-2 text-xs text-gray-600">
<div className={`w-1.5 h-1.5 rounded-full ${isRedirecting ? 'bg-emerald-500' : isLoading ? 'bg-yellow-500 animate-pulse' : 'bg-teal-500'}`} />
<span className="uppercase tracking-widest font-mono">
{isRedirecting ? 'Authenticated' : isLoading ? 'Syncing...' : 'Ready'}
</span>
<div className="hidden lg:flex flex-col items-center justify-center relative">
<div className="absolute w-[500px] h-[500px] bg-[#00A8A8]/10 blur-[120px] rounded-full animate-pulse" />

<div className="relative group">
<div className="absolute -inset-4 border border-white/5 rounded-full animate-[spin_20s_linear_infinite]" />
<div className="absolute -inset-8 border border-white/5 rounded-full animate-[spin_35s_linear_infinite_reverse] opacity-50" />

<div className="relative z-10 p-8">
<img
src="/images/dsgt/apple-touch-icon.png"
alt="DSGT Logo"
className="w-72 h-72 object-contain drop-shadow-[0_0_50px_rgba(0,168,168,0.3)] transition-all duration-700 group-hover:scale-105"
/>
</div>

<div className="absolute -bottom-16 left-1/2 -translate-x-1/2 w-full text-center space-y-3">
<p className="text-[10px] font-mono text-[#00A8A8]/50 uppercase tracking-[0.5em] animate-pulse">
{isRedirecting ? "Handshake Verified" : status === 'loading' ? "Synchronizing..." : "Core Operational"}
</p>
<div className="flex justify-center gap-6 text-[8px] font-mono text-gray-700">
<span className="flex items-center gap-1">
<div className={`w-1 h-1 rounded-full ${isRedirecting ? 'bg-green-500' : 'bg-[#00A8A8]'}`} />
STATUS: {status.toUpperCase()}
</span>
<span className="flex items-center gap-1">
<div className="w-1 h-1 bg-[#00A8A8] rounded-full" />
REGION: ATL-08
</span>
</div>
</div>
</div>
</div>
</main>

{/* Footer */}
<footer className="absolute bottom-8 left-0 right-0 text-center">
<p className="text-[10px] text-gray-700 uppercase tracking-[0.3em] font-mono">
Data Science @ Georgia Tech
</p>
<footer className="absolute bottom-8 left-12 right-12 flex justify-between items-center opacity-20 pointer-events-none">
<div className="text-[9px] font-mono uppercase tracking-[0.4em]">Internal Terminal // Auth Gateway</div>
<div className="text-[9px] font-mono uppercase tracking-[0.4em]">Access Node: 0812-ATL</div>
</footer>
</div>
);
Expand Down
Loading