feat: 3-click SSO registration - unified /auth page, Google/Apple/GitHub OAuth, email fallback, provider model

This commit is contained in:
root
2026-06-15 12:42:03 +02:00
parent 64ae34e9c9
commit d194e295ad
12 changed files with 1150 additions and 294 deletions
+6 -154
View File
@@ -1,166 +1,18 @@
"use client";
import { useState, FormEvent } from "react";
import { useAuth } from "@/lib/AuthContext";
import { useEffect } from "react";
import { useRouter } from "next/navigation";
import Link from "next/link";
export default function RegisterPage() {
const { register } = useAuth();
const router = useRouter();
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
setError("");
if (!name.trim() || !email.trim() || !password.trim()) {
setError("Please fill in all fields");
return;
}
if (password.length < 6) {
setError("Password must be at least 6 characters");
return;
}
setLoading(true);
try {
await register(email.trim(), name.trim(), password);
router.push("/");
} catch (err: unknown) {
const message =
err instanceof Error
? err.message
: "Registration failed. Please try again.";
setError(message);
} finally {
setLoading(false);
}
};
useEffect(() => {
router.replace("/auth");
}, [router]);
return (
<div className="min-h-dvh bg-[#0a0a0f] flex flex-col items-center justify-center px-6">
<div className="w-full max-w-sm">
{/* Logo / Brand */}
<div className="text-center mb-8">
<div className="w-16 h-16 rounded-2xl bg-gradient-to-br from-[#D4AF37]/20 to-[#D4AF37]/5 border border-[#D4AF37]/30 flex items-center justify-center mx-auto mb-4">
<span className="text-3xl"></span>
</div>
<h1 className="text-2xl font-bold text-white">Join Falah</h1>
<p className="text-sm text-gray-500 mt-1">
Start your Islamic lifestyle journey
</p>
</div>
{/* Error */}
{error && (
<div className="mb-4 p-3 rounded-xl bg-red-900/20 border border-red-800/40 text-red-400 text-sm text-center">
{error}
</div>
)}
{/* Form */}
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<label
htmlFor="name"
className="block text-xs font-medium text-gray-500 mb-1.5 uppercase tracking-wider"
>
Name
</label>
<input
id="name"
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Your name"
autoComplete="name"
autoFocus
className="w-full bg-[#111118] border border-gray-800/60 rounded-xl px-4 py-3 text-white placeholder-gray-600 focus:outline-none focus:border-[#D4AF37]/50 focus:ring-1 focus:ring-[#D4AF37]/30 transition"
/>
</div>
<div>
<label
htmlFor="email"
className="block text-xs font-medium text-gray-500 mb-1.5 uppercase tracking-wider"
>
Email
</label>
<input
id="email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="you@example.com"
autoComplete="email"
className="w-full bg-[#111118] border border-gray-800/60 rounded-xl px-4 py-3 text-white placeholder-gray-600 focus:outline-none focus:border-[#D4AF37]/50 focus:ring-1 focus:ring-[#D4AF37]/30 transition"
/>
</div>
<div>
<label
htmlFor="password"
className="block text-xs font-medium text-gray-500 mb-1.5 uppercase tracking-wider"
>
Password
</label>
<input
id="password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="At least 6 characters"
autoComplete="new-password"
className="w-full bg-[#111118] border border-gray-800/60 rounded-xl px-4 py-3 text-white placeholder-gray-600 focus:outline-none focus:border-[#D4AF37]/50 focus:ring-1 focus:ring-[#D4AF37]/30 transition"
/>
</div>
<button
type="submit"
disabled={loading}
className="w-full py-3 rounded-xl bg-[#D4AF37] text-[#0a0a0f] font-semibold text-sm active:opacity-80 disabled:opacity-50 transition"
>
{loading ? (
<span className="flex items-center justify-center gap-2">
<span className="w-4 h-4 rounded-full border-2 border-[#0a0a0f]/30 border-t-[#0a0a0f] animate-spin" />
Creating account...
</span>
) : (
"Create Account"
)}
</button>
</form>
{/* Sign in link */}
<div className="text-center mt-6">
<p className="text-xs text-gray-600">
Already have an account?{" "}
<Link
href="/login"
className="text-[#D4AF37] font-medium hover:underline"
>
Sign in
</Link>
</p>
</div>
{/* Bonus info */}
<div className="mt-6 rounded-xl bg-[#111118] border border-gray-800/60 p-3 text-center">
<p className="text-xs text-gray-600 uppercase tracking-wider mb-1">
New Member Bonus
</p>
<p className="text-xs text-gray-500">
Get <span className="text-[#D4AF37] font-semibold">5,000 FLH</span>{" "}
free on sign up + 7-day premium trial
</p>
</div>
</div>
<div className="min-h-dvh bg-[#0a0a0f] flex items-center justify-center">
<div className="w-6 h-6 rounded-full border-2 border-[#D4AF37]/30 border-t-[#D4AF37] animate-spin" />
</div>
);
}