Spaces:
Sleeping
Sleeping
| 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> | |
| ); | |
| } | |