Spaces:
Runtime error
Runtime error
File size: 7,276 Bytes
7e92e00 | 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 | "use client";
import React, { useState } from "react";
import Image from "next/image";
import { X, Mail, Lock, User, ArrowRight, ShieldCheck, Check, Sparkles } from "lucide-react";
import { supabase } from "@/lib/supabase";
interface AuthModalProps {
isOpen: boolean;
onClose: () => void;
onSuccess?: () => void;
}
export const AuthModal: React.FC<AuthModalProps> = ({ isOpen, onClose, onSuccess }) => {
const [isSignUp, setIsSignUp] = useState(true);
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [username, setUsername] = useState("");
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [successMsg, setSuccessMsg] = useState<string | null>(null);
if (!isOpen) return null;
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
setError(null);
setSuccessMsg(null);
try {
if (isSignUp) {
const { data, error: signUpErr } = await supabase.auth.signUp({
email,
password,
options: {
data: {
username: username || email.split("@")[0],
},
},
});
if (signUpErr) throw signUpErr;
setSuccessMsg(data.session ? "Account created and signed in!" : "Account created. Check your email to confirm.");
setTimeout(() => {
onClose();
if (onSuccess) onSuccess();
}, 1200);
} else {
const { data, error: signInErr } = await supabase.auth.signInWithPassword({
email,
password,
});
if (signInErr) throw signInErr;
setSuccessMsg("Signed in successfully!");
setTimeout(() => {
onClose();
if (onSuccess) onSuccess();
}, 1000);
}
} catch (err: any) {
setError(err?.message || "Authentication error occurred");
} finally {
setLoading(false);
}
};
return (
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/80 backdrop-blur-xl">
<div className="relative w-full max-w-md p-6 rounded-3xl glass border border-white/10 shadow-2xl bg-[#09090b]">
{/* Close Button */}
<button
onClick={onClose}
className="absolute top-4 right-4 p-2 rounded-full text-zinc-400 hover:text-white hover:bg-white/10 transition-colors"
>
<X className="w-4 h-4" />
</button>
{/* Header */}
<div className="flex flex-col items-center text-center space-y-3 mb-6">
<div className="relative w-14 h-14 rounded-2xl overflow-hidden border border-white/20 shadow-xl ring-4 ring-white/5">
<Image src="/purcar-logo.png" alt="Purcar Logo" fill className="object-cover" />
</div>
<div>
<h3 className="text-lg font-bold text-white font-mono tracking-tight">
{isSignUp ? "Create Your Purcar Account" : "Welcome Back to Purcar"}
</h3>
<p className="text-xs text-zinc-400 mt-1">
{isSignUp ? "Get 5,000 free tokens daily & full API key access" : "Sign in to manage your reasoning quota & chats"}
</p>
</div>
</div>
{/* Form */}
<form onSubmit={handleSubmit} className="space-y-4">
{isSignUp && (
<div className="space-y-1.5">
<label className="text-xs font-mono text-zinc-400">Username</label>
<div className="relative">
<User className="w-4 h-4 text-zinc-500 absolute left-3.5 top-1/2 -translate-y-1/2" />
<input
type="text"
required
placeholder="e.g. Vlad"
value={username}
onChange={(e) => setUsername(e.target.value)}
className="w-full pl-10 pr-4 py-2.5 rounded-xl bg-black/50 border border-white/10 text-white text-xs font-mono placeholder:text-zinc-600 focus:outline-none focus:border-white/30 transition-colors"
/>
</div>
</div>
)}
<div className="space-y-1.5">
<label className="text-xs font-mono text-zinc-400">Email Address</label>
<div className="relative">
<Mail className="w-4 h-4 text-zinc-500 absolute left-3.5 top-1/2 -translate-y-1/2" />
<input
type="email"
required
placeholder="vlad@purcar.me"
value={email}
onChange={(e) => setEmail(e.target.value)}
className="w-full pl-10 pr-4 py-2.5 rounded-xl bg-black/50 border border-white/10 text-white text-xs font-mono placeholder:text-zinc-600 focus:outline-none focus:border-white/30 transition-colors"
/>
</div>
</div>
<div className="space-y-1.5">
<label className="text-xs font-mono text-zinc-400">Password</label>
<div className="relative">
<Lock className="w-4 h-4 text-zinc-500 absolute left-3.5 top-1/2 -translate-y-1/2" />
<input
type="password"
required
placeholder="••••••••••••"
value={password}
onChange={(e) => setPassword(e.target.value)}
className="w-full pl-10 pr-4 py-2.5 rounded-xl bg-black/50 border border-white/10 text-white text-xs font-mono placeholder:text-zinc-600 focus:outline-none focus:border-white/30 transition-colors"
/>
</div>
</div>
{error && (
<div className="p-3 rounded-xl bg-red-500/10 border border-red-500/20 text-red-400 text-xs font-mono">
{error}
</div>
)}
{successMsg && (
<div className="p-3 rounded-xl bg-emerald-500/10 border border-emerald-500/20 text-emerald-400 text-xs font-mono flex items-center gap-2">
<Check className="w-4 h-4" />
<span>{successMsg}</span>
</div>
)}
<button
type="submit"
disabled={loading}
className="w-full py-3 rounded-xl bg-white text-black font-semibold text-xs hover:bg-zinc-200 transition-all shadow-lg active:scale-95 flex items-center justify-center gap-2 disabled:opacity-50"
>
<span>{loading ? "Authenticating..." : isSignUp ? "Create Free Account" : "Sign In"}</span>
<ArrowRight className="w-4 h-4" />
</button>
</form>
{/* Footer switch */}
<div className="mt-6 pt-4 border-t border-white/[0.08] text-center text-xs font-mono text-zinc-400">
<span>{isSignUp ? "Already have an account?" : "Don't have an account yet?"} </span>
<button
onClick={() => {
setIsSignUp(!isSignUp);
setError(null);
setSuccessMsg(null);
}}
className="text-white font-semibold underline underline-offset-4 hover:text-zinc-300 transition-colors"
>
{isSignUp ? "Sign In" : "Register"}
</button>
</div>
</div>
</div>
);
};
|