|
1 | 1 | "use client"; |
2 | 2 |
|
3 | | -import { signIn } from "next-auth/react"; |
4 | | -import { useState } from "react"; |
| 3 | +import { signIn, getProviders } from "next-auth/react"; |
| 4 | +import { useState, useEffect } from "react"; |
5 | 5 | import Link from "next/link"; |
6 | 6 | import { useLocale } from "@/components/LocaleProvider"; |
7 | 7 |
|
| 8 | +type Providers = Record<string, { id: string; name: string }>; |
| 9 | + |
| 10 | +const providerIcons: Record<string, JSX.Element> = { |
| 11 | + google: ( |
| 12 | + <svg className="w-5 h-5" viewBox="0 0 24 24"> |
| 13 | + <path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 01-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z" /> |
| 14 | + <path fill="#34A853" 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" /> |
| 15 | + <path fill="#FBBC05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" /> |
| 16 | + <path fill="#EA4335" 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.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" /> |
| 17 | + </svg> |
| 18 | + ), |
| 19 | + twitter: ( |
| 20 | + <svg className="w-5 h-5" viewBox="0 0 24 24" fill="currentColor"> |
| 21 | + <path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" /> |
| 22 | + </svg> |
| 23 | + ), |
| 24 | + linkedin: ( |
| 25 | + <svg className="w-5 h-5" viewBox="0 0 24 24" fill="currentColor"> |
| 26 | + <path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" /> |
| 27 | + </svg> |
| 28 | + ), |
| 29 | +}; |
| 30 | + |
8 | 31 | export default function SignupPage() { |
9 | 32 | const { t } = useLocale(); |
10 | 33 | const [email, setEmail] = useState(""); |
11 | 34 | const [name, setName] = useState(""); |
12 | 35 | const [password, setPassword] = useState(""); |
13 | 36 | const [loading, setLoading] = useState(false); |
14 | 37 | const [error, setError] = useState(""); |
| 38 | + const [providers, setProviders] = useState<Providers>({}); |
| 39 | + |
| 40 | + useEffect(() => { |
| 41 | + getProviders().then((p) => { |
| 42 | + if (p) setProviders(p as Providers); |
| 43 | + }); |
| 44 | + }, []); |
15 | 45 |
|
16 | 46 | async function handleSignup(e: React.FormEvent) { |
17 | 47 | e.preventDefault(); |
@@ -46,6 +76,10 @@ export default function SignupPage() { |
46 | 76 | } |
47 | 77 | } |
48 | 78 |
|
| 79 | + const oauthProviders = Object.values(providers).filter( |
| 80 | + (p) => p.id !== "credentials" |
| 81 | + ); |
| 82 | + |
49 | 83 | return ( |
50 | 84 | <div className="min-h-screen bg-bg flex items-center justify-center p-4"> |
51 | 85 | <div className="max-w-sm w-full"> |
@@ -98,24 +132,28 @@ export default function SignupPage() { |
98 | 132 | </button> |
99 | 133 | </form> |
100 | 134 |
|
101 | | - <div className="mt-6 flex items-center gap-3"> |
102 | | - <div className="flex-1 h-px bg-white/[0.06]" /> |
103 | | - <span className="text-xs text-[#5a5870]">or</span> |
104 | | - <div className="flex-1 h-px bg-white/[0.06]" /> |
105 | | - </div> |
| 135 | + {oauthProviders.length > 0 && ( |
| 136 | + <> |
| 137 | + <div className="mt-6 flex items-center gap-3"> |
| 138 | + <div className="flex-1 h-px bg-white/[0.06]" /> |
| 139 | + <span className="text-xs text-[#5a5870]">or</span> |
| 140 | + <div className="flex-1 h-px bg-white/[0.06]" /> |
| 141 | + </div> |
106 | 142 |
|
107 | | - <button |
108 | | - onClick={() => signIn("google", { callbackUrl: "/dashboard" })} |
109 | | - className="w-full flex items-center justify-center gap-3 rounded-xl border border-white/[0.1] bg-white/[0.03] px-4 py-3 text-sm text-[#e8e6f0] hover:bg-white/[0.06] transition-colors mt-4" |
110 | | - > |
111 | | - <svg className="w-5 h-5" viewBox="0 0 24 24"> |
112 | | - <path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 01-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z" /> |
113 | | - <path fill="#34A853" 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" /> |
114 | | - <path fill="#FBBC05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" /> |
115 | | - <path fill="#EA4335" 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.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" /> |
116 | | - </svg> |
117 | | - {t("signup.google")} |
118 | | - </button> |
| 143 | + <div className="mt-4 space-y-3"> |
| 144 | + {oauthProviders.map((provider) => ( |
| 145 | + <button |
| 146 | + key={provider.id} |
| 147 | + onClick={() => signIn(provider.id, { callbackUrl: "/dashboard" })} |
| 148 | + className="w-full flex items-center justify-center gap-3 rounded-xl border border-white/[0.1] bg-white/[0.03] px-4 py-3 text-sm text-[#e8e6f0] hover:bg-white/[0.06] transition-colors" |
| 149 | + > |
| 150 | + {providerIcons[provider.id]} |
| 151 | + {t("login.continueWith").replace("{provider}", provider.name)} |
| 152 | + </button> |
| 153 | + ))} |
| 154 | + </div> |
| 155 | + </> |
| 156 | + )} |
119 | 157 |
|
120 | 158 | <div className="mt-8 text-center text-xs text-[#5a5870] space-y-2"> |
121 | 159 | <p> |
|
0 commit comments