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 -139
View File
@@ -1,151 +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 LoginPage() {
const { login } = useAuth();
const router = useRouter();
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 (!email.trim() || !password.trim()) {
setError("Please fill in all fields");
return;
}
setLoading(true);
try {
await login(email.trim(), password);
router.push("/");
} catch (err: unknown) {
const message =
err instanceof Error ? err.message : "Login 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">Welcome Back</h1>
<p className="text-sm text-gray-500 mt-1">
Sign in to continue your 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="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"
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="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="••••••••"
autoComplete="current-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" />
Signing in...
</span>
) : (
"Sign In"
)}
</button>
</form>
{/* Divider */}
<div className="flex items-center gap-3 my-6">
<div className="flex-1 h-px bg-gray-800/60" />
<span className="text-xs text-gray-600">or</span>
<div className="flex-1 h-px bg-gray-800/60" />
</div>
{/* Demo hint */}
<div className="text-center mb-6">
<p className="text-xs text-gray-600">
Don&apos;t have an account?{" "}
<Link
href="/register"
className="text-[#D4AF37] font-medium hover:underline"
>
Create one
</Link>
</p>
</div>
{/* Demo credentials */}
<div className="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">
Demo Account
</p>
<p className="text-xs text-gray-500">
Email:{" "}
<span className="text-gray-300 font-mono">demo@falahos.my</span>
</p>
<p className="text-xs text-gray-500">
Password:{" "}
<span className="text-gray-300 font-mono">password123</span>
</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>
);
}