Spaces:
Sleeping
Sleeping
File size: 11,577 Bytes
aaa634c a95fdd1 aaa634c 2538dbc aaa634c a95fdd1 aaa634c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | import { useState } from 'react';
import { supabase } from '../supabaseClient';
import { Mail, Lock, ShieldCheck, ArrowRight } from 'lucide-react';
export default function Auth() {
const [isSignUp, setIsSignUp] = useState(false);
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [loading, setLoading] = useState(false);
const [message, setMessage] = useState<{ type: 'error' | 'success'; text: string } | null>(null);
const handleAuth = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
setMessage(null);
try {
if (isSignUp) {
const { error } = await supabase.auth.signUp({
email,
password,
});
if (error) throw error;
setMessage({ type: 'success', text: 'Registration successful! Check your email for validation link.' });
} else {
const { error } = await supabase.auth.signInWithPassword({
email,
password,
});
if (error) throw error;
}
} catch (err: any) {
setMessage({ type: 'error', text: err.message || 'An error occurred during authentication' });
} finally {
setLoading(false);
}
};
const handleGoogleSignIn = async () => {
try {
setLoading(true);
const redirectUrl = window.location.origin.endsWith('/') ? window.location.origin : `${window.location.origin}/`;
alert('Sending redirect URL: ' + redirectUrl);
const { error } = await supabase.auth.signInWithOAuth({
provider: 'google',
options: {
redirectTo: redirectUrl
}
});
if (error) throw error;
} catch (err: any) {
setMessage({ type: 'error', text: err.message || 'Google OAuth failed to initialize' });
setLoading(false);
}
};
const handleSandboxEntrance = () => {
localStorage.setItem('algospaced_sandbox_mode', 'true');
window.location.reload();
};
return (
<div className="min-h-screen w-screen flex items-center justify-center p-4 relative selection:bg-highlight-pink selection:text-white">
{/* Background Wallpaper image */}
<div
className="absolute inset-0 w-full h-full bg-cover bg-center z-0 saturate-150 contrast-125"
style={{ backgroundImage: "url('https://lh3.googleusercontent.com/aida-public/AB6AXuAMJHVhhK8_G7F8sbhn8F7w4AZWXb1O_-HLKvrZ_fJlbUVMcVuxxEOO_LlOh8qIwtAn2KvzvCwzmtNLLEZ5uYkCEsx8ZWXJR609qgSMRSX8LBBeskk4VzVXnyzsgIKCedeV2PvGxJlUNnledcWKCXqG9egQi8dgTcA7C2z82QyM73KZ4s7ZRzZHNupuQt1ocfcMl9E_x1PWFRridl751LIpyGZgednS5CmVw2rZvFc_tbp2QTxgVHJ_59myEBmy6aajbO06AhkKmCvI')" }}
/>
{/* OS System Setup Dialog Box */}
<div className="w-full max-w-md bg-paper-white border-[4px] border-ink-black window-shadow z-10 flex flex-col overflow-hidden shadow-[inset_2px_2px_0px_rgba(255,255,255,0.8)] relative animate-float">
{/* Title Bar */}
<div className="bg-[#0ea5e9] border-b-[4px] border-ink-black px-4 py-2.5 flex justify-between items-center text-white select-none">
<div className="flex items-center gap-2">
<span className="material-symbols-outlined select-none" style={{ fontVariationSettings: "'FILL' 1" }}>
sports_esports
</span>
<span className="font-window-title text-sm md:text-base font-bold tracking-wide">System_Setup.exe</span>
</div>
</div>
{/* Content Box */}
<div className="p-6 bg-[#fdf8e1] flex-1 flex flex-col">
{typeof window !== 'undefined' && window.self !== window.top && (
<div className="mb-5 p-3.5 border-[3px] border-[#ea580c] bg-[#ffedd5] text-[#9a3412] text-xs font-bold font-arcade leading-relaxed shadow-[2px_2px_0px_0px_rgba(30,41,59,1)]">
⚠️ RUNNING INSIDE IFRAME
<p className="mt-1 font-sans text-[11px] font-normal text-ink-black normal-case leading-normal">
Google Sign-In is restricted inside Hugging Face's iframe wrapper due to browser security.
</p>
<a
href="https://iamfebin-algospaced-dsa.hf.space/"
target="_top"
className="mt-2.5 inline-block w-full text-center bg-[#ea580c] hover:bg-[#c2410c] text-white border-[2.5px] border-ink-black py-1.5 px-3 rounded-lg font-window-title text-xs font-bold transition-all shadow-[1.5px_1.5px_0px_rgba(0,0,0,1)] active:translate-y-0.5 active:shadow-none"
>
OPEN FULLSCREEN / MOBILE SITE
</a>
</div>
)}
<div className="flex flex-col items-center mb-6">
<div className="w-16 h-16 bg-paper-white border-[3px] border-ink-black flex items-center justify-center gadget-shadow shadow-[inset_2px_2px_0px_rgba(255,255,255,0.8)] mb-4">
<ShieldCheck className="w-9 h-9 text-primary" />
</div>
<h2 className="text-3xl font-extrabold tracking-tight text-ink-black font-headline-md leading-none m-0">AlgoSpaced</h2>
<p className="text-xs font-arcade text-trash-gray mt-2 tracking-wide uppercase text-center">Spaced Repetition for DSA</p>
</div>
{/* Form Tabs */}
<div className="flex gap-2 mb-6 font-arcade text-[10px]">
<button
onClick={() => { setIsSignUp(false); setMessage(null); }}
className={`flex-1 py-2.5 border-[3px] border-ink-black cursor-pointer font-bold tracking-wider outline-none transition-all shadow-[2px_2px_0px_0px_rgba(30,41,59,1)] active:shadow-none active:translate-y-0.5 ${
!isSignUp
? 'bg-secondary-container text-ink-black translate-y-0.5 shadow-[1px_1px_0px_0px_rgba(30,41,59,1)]'
: 'bg-white text-trash-gray hover:bg-surface-container'
}`}
>
SIGN IN
</button>
<button
onClick={() => { setIsSignUp(true); setMessage(null); }}
className={`flex-1 py-2.5 border-[3px] border-ink-black cursor-pointer font-bold tracking-wider outline-none transition-all shadow-[2px_2px_0px_0px_rgba(30,41,59,1)] active:shadow-none active:translate-y-0.5 ${
isSignUp
? 'bg-secondary-container text-ink-black translate-y-0.5 shadow-[1px_1px_0px_0px_rgba(30,41,59,1)]'
: 'bg-white text-trash-gray hover:bg-surface-container'
}`}
>
CREATE COMP
</button>
</div>
{message && (
<div
className={`mb-6 p-4 border-[3px] border-ink-black text-xs font-arcade leading-relaxed ${
message.type === 'error'
? 'bg-red-100 border-red-500 text-error shadow-[2px_2px_0px_0px_rgba(30,41,59,1)]'
: 'bg-emerald-100 border-emerald-500 text-emerald-700 shadow-[2px_2px_0px_0px_rgba(30,41,59,1)]'
}`}
>
{message.text}
</div>
)}
<form onSubmit={handleAuth} className="space-y-4">
<div>
<label className="block text-xs font-bold text-ink-black uppercase tracking-wider mb-2 font-headline-md">Email Address</label>
<div className="relative">
<Mail className="absolute left-3.5 top-1/2 -translate-y-1/2 w-4 h-4 text-ink-black" />
<input
type="email"
required
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="name@arcade.com"
className="w-full bg-white border-[3px] border-ink-black rounded-lg py-2.5 pl-10 pr-4 text-ink-black placeholder-trash-gray focus:outline-none focus:bg-white text-sm font-code-mono shadow-[inset_2px_2px_0px_rgba(0,0,0,0.1)]"
/>
</div>
</div>
<div>
<label className="block text-xs font-bold text-ink-black uppercase tracking-wider mb-2 font-headline-md">Password</label>
<div className="relative">
<Lock className="absolute left-3.5 top-1/2 -translate-y-1/2 w-4 h-4 text-ink-black" />
<input
type="password"
required
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="••••••••"
className="w-full bg-white border-[3px] border-ink-black rounded-lg py-2.5 pl-10 pr-4 text-ink-black placeholder-trash-gray focus:outline-none focus:bg-white text-sm font-code-mono shadow-[inset_2px_2px_0px_rgba(0,0,0,0.1)]"
/>
</div>
</div>
<button
type="submit"
disabled={loading}
className="w-full bg-[#ffcc00] border-[4px] border-ink-black rounded-xl py-3.5 font-window-title text-base text-ink-black arcade-btn cursor-pointer disabled:opacity-50 flex items-center justify-center gap-2 uppercase font-bold tracking-wide"
>
{loading ? 'RUNNING...' : isSignUp ? 'RUN SETUP.EXE' : 'EXEC LOGON'}
{!loading && <ArrowRight className="w-4 h-4 stroke-[3px]" />}
</button>
</form>
<div className="relative my-5 select-none">
<div className="absolute inset-0 flex items-center"><div className="w-full border-t-[3px] border-ink-black border-dashed" /></div>
<div className="relative flex justify-center text-[10px] uppercase font-arcade"><span className="bg-[#fdf8e1] px-3 text-trash-gray font-bold">OR LOAD ALTERNATE</span></div>
</div>
<button
onClick={handleGoogleSignIn}
disabled={loading}
className="w-full bg-white hover:bg-slate-100 border-[3px] border-ink-black text-ink-black font-bold py-3 px-4 rounded-xl flex items-center justify-center gap-3 transition-all text-xs cursor-pointer shadow-[3px_3px_0px_0px_rgba(30,41,59,1)] active:translate-y-0.5 active:shadow-none"
>
<svg className="w-4 h-4 shrink-0" 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" fill="#4285F4" />
<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" fill="#34A853" />
<path d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.06H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.94l2.85-2.22.81-.63z" fill="#FBBC05" />
<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.06l3.66 2.84c.87-2.6 3.3-4.52 6.16-4.52z" fill="#EA4335" />
</svg>
SIGN IN WITH GOOGLE
</button>
<button
onClick={handleSandboxEntrance}
disabled={loading}
className="mt-3 w-full bg-[#10b981] hover:bg-emerald-600 text-white font-window-title py-3 px-4 border-[3px] border-ink-black rounded-xl flex items-center justify-center gap-2 cursor-pointer shadow-[3px_3px_0px_0px_rgba(30,41,59,1)] active:translate-y-0.5 active:shadow-none uppercase font-bold text-xs"
>
<span className="material-symbols-outlined text-sm font-bold">sports_esports</span>
Enter Sandbox Mode (No Login)
</button>
</div>
</div>
</div>
);
}
|