integrating firebase
This commit is contained in:
parent
166324c2b5
commit
c93f5f24e3
2
.vscode/settings.json
vendored
Normal file
2
.vscode/settings.json
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
{
|
||||
}
|
||||
57
app/firebase/components/GoogleSignInButton.tsx
Normal file
57
app/firebase/components/GoogleSignInButton.tsx
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
'use client';
|
||||
import React from 'react';
|
||||
import { getAuth, GoogleAuthProvider, signInWithPopup } from 'firebase/auth';
|
||||
import { auth } from '@/app/firebase/config';
|
||||
interface GoogleSignInButtonProps {
|
||||
onLoginSuccess?: (user: any) => void; // Callback function when login succeeds
|
||||
}
|
||||
|
||||
const GoogleSignInButton: React.FC<GoogleSignInButtonProps> = ({ onLoginSuccess }) => {
|
||||
const provider = new GoogleAuthProvider();
|
||||
|
||||
const handleGoogleSignIn = async () => {
|
||||
try {
|
||||
const result = await signInWithPopup(auth, provider);
|
||||
const user = result.user;
|
||||
console.log('Google Sign-In successful:', user);
|
||||
if(onLoginSuccess){
|
||||
onLoginSuccess(user);
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('Error during Google Sign-In:', error.message);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<button
|
||||
onClick={handleGoogleSignIn}
|
||||
className="w-full py-3 bg-blue-600 text-white rounded-md hover:bg-green-500 transition duration-300 flex items-center justify-center gap-2"
|
||||
>
|
||||
<svg
|
||||
className="w-5 h-5"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 48 48"
|
||||
>
|
||||
<path
|
||||
fill="#EA4335"
|
||||
d="M24 9.5c3.6 0 6.6 1.3 9 3.9l6.7-6.7C35.2 2.8 30.1 0 24 0 14.9 0 7.2 5.5 3.5 13.4l7.9 6.2C13.4 11.1 18.2 9.5 24 9.5z"
|
||||
/>
|
||||
<path
|
||||
fill="#34A853"
|
||||
d="M24 48c6.5 0 12-2.2 16-6l-7.5-6.1C30.9 38.2 27.6 39.5 24 39.5c-5.6 0-10.4-3.6-12.2-8.7l-8.1 6.3C7.2 42.7 14.6 48 24 48z"
|
||||
/>
|
||||
<path
|
||||
fill="#4A90E2"
|
||||
d="M48 24c0-1.6-.2-3.1-.5-4.6H24v9h13.7c-.6 3-2.2 5.5-4.5 7.3l7.5 6.1C45.6 37.4 48 31 48 24z"
|
||||
/>
|
||||
<path
|
||||
fill="#FBBC05"
|
||||
d="M11.8 30.8c-.6-1.7-1-3.5-1-5.5s.4-3.8 1-5.5l-8-6.3C1.8 16.2 0 20 0 24s1.8 7.8 4.7 10.7l7.1-3.9z"
|
||||
/>
|
||||
</svg>
|
||||
Sign in with Google
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
export default GoogleSignInButton;
|
||||
34
app/firebase/config.ts
Normal file
34
app/firebase/config.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import { initializeApp} from 'firebase/app'
|
||||
import { getAuth } from 'firebase/auth';
|
||||
|
||||
// const firebaseConfig = {
|
||||
// apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY_PK,
|
||||
// authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
|
||||
// projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
|
||||
// storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
|
||||
// messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
|
||||
// appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
|
||||
// measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID
|
||||
// };
|
||||
const firebaseConfig = {
|
||||
|
||||
apiKey: "AIzaSyCpATgMXv9Pu3coBwljh0uv9I9ciFkBJIA",
|
||||
|
||||
authDomain: "sologin-55bbd.firebaseapp.com",
|
||||
|
||||
projectId: "sologin-55bbd",
|
||||
|
||||
storageBucket: "sologin-55bbd.firebasestorage.app",
|
||||
|
||||
messagingSenderId: "652710461284",
|
||||
|
||||
appId: "1:652710461284:web:cb86f9afb033a5bcf54471",
|
||||
|
||||
measurementId: "G-Q6H1J4E92L"
|
||||
|
||||
};
|
||||
|
||||
const app = initializeApp(firebaseConfig);
|
||||
const auth = getAuth(app);
|
||||
|
||||
export {app,auth}
|
||||
139
app/login/page.tsx
Normal file
139
app/login/page.tsx
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
'use client';
|
||||
import React, { useState } from 'react';
|
||||
import { auth } from '@/app/firebase/config';
|
||||
import { signInWithEmailAndPassword, createUserWithEmailAndPassword } from 'firebase/auth';
|
||||
import GoogleSignInButton from '../firebase/components/GoogleSignInButton';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { LoginSologin, RegisterSologin } from '../sologin';
|
||||
|
||||
const AuthTabs = () => {
|
||||
const [activeTab, setActiveTab] = useState<'signin' | 'signup'>('signin');
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const router = useRouter();
|
||||
|
||||
const onAuthSuccess = () => {
|
||||
router.push('/');
|
||||
};
|
||||
|
||||
const handleAuth = async (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
try {
|
||||
if (activeTab === 'signin') {
|
||||
const userCredential = await signInWithEmailAndPassword(auth, email, password);
|
||||
console.log('User signed in:', userCredential.user);
|
||||
await LoginSologin(userCredential.user);
|
||||
} else {
|
||||
const userCredential = await createUserWithEmailAndPassword(auth, email, password);
|
||||
console.log('User signed up:', userCredential.user);
|
||||
await RegisterSologin(userCredential.user);
|
||||
}
|
||||
onAuthSuccess();
|
||||
setEmail('');
|
||||
setPassword('');
|
||||
setError(null);
|
||||
} catch (err: any) {
|
||||
const errorCode = err.code;
|
||||
switch (errorCode) {
|
||||
case 'auth/user-not-found':
|
||||
setError('User not found. Please check your email.');
|
||||
break;
|
||||
case 'auth/email-already-in-use':
|
||||
setError('This email is already registered. Try signing in.');
|
||||
break;
|
||||
case 'auth/wrong-password':
|
||||
setError('Incorrect email or password.');
|
||||
break;
|
||||
default:
|
||||
setError('An unexpected error occurred. Please try again.');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-900 flex items-center justify-center">
|
||||
<div className="bg-gray-800 p-8 rounded-lg shadow-lg w-full sm:w-96">
|
||||
<div className="flex border-b border-gray-600 mb-6">
|
||||
<button
|
||||
className={`flex-1 py-2 text-center ${
|
||||
activeTab === 'signin'
|
||||
? 'text-white border-b-2 border-blue-500'
|
||||
: 'text-gray-400 hover:text-white'
|
||||
}`}
|
||||
onClick={() => setActiveTab('signin')}
|
||||
>
|
||||
Sign In
|
||||
</button>
|
||||
<button
|
||||
className={`flex-1 py-2 text-center ${
|
||||
activeTab === 'signup'
|
||||
? 'text-white border-b-2 border-blue-500'
|
||||
: 'text-gray-400 hover:text-white'
|
||||
}`}
|
||||
onClick={() => setActiveTab('signup')}
|
||||
>
|
||||
Sign Up
|
||||
</button>
|
||||
</div>
|
||||
<form onSubmit={handleAuth}>
|
||||
<div className="mb-4">
|
||||
<label className="block text-sm text-gray-300 mb-2" htmlFor="email">
|
||||
Email Address
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
className="w-full p-3 bg-gray-700 text-white rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder="Enter your email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-6">
|
||||
<label className="block text-sm text-gray-300 mb-2" htmlFor="password">
|
||||
Password
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
className="w-full p-3 bg-gray-700 text-white rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder="Enter your password"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full py-3 bg-blue-600 text-white rounded-md hover:bg-blue-500 transition duration-300"
|
||||
>
|
||||
{activeTab === 'signin' ? 'Sign In' : 'Sign Up'}
|
||||
</button>
|
||||
</form>
|
||||
<div className='h-10'></div>
|
||||
|
||||
<GoogleSignInButton onLoginSuccess={onAuthSuccess}></GoogleSignInButton>
|
||||
</div>
|
||||
|
||||
{/* Error Dialog */}
|
||||
{error && (
|
||||
<div className="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50 z-50">
|
||||
<div className="bg-gray-800 p-6 rounded-lg shadow-lg">
|
||||
<h3 className="text-xl font-bold text-white mb-4">Error</h3>
|
||||
<p className="text-gray-300">{error}</p>
|
||||
<button
|
||||
className="mt-4 px-4 py-2 bg-red-600 text-white rounded-md hover:bg-red-500"
|
||||
onClick={() => setError(null)}
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AuthTabs;
|
||||
188
app/page.tsx
188
app/page.tsx
|
|
@ -1,101 +1,97 @@
|
|||
import Image from "next/image";
|
||||
'use client';
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { getAuth, onAuthStateChanged, User } from 'firebase/auth';
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
|
||||
import { app } from '@/app/firebase/config';
|
||||
import { SOLOGIN_API } from './shared';
|
||||
|
||||
const HomePage = () => {
|
||||
const [user, setUser] = useState<any | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const auth = getAuth(app);
|
||||
const [userPubkey, setUserPubkey] = useState();
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
|
||||
const getSologinUser = async (currentUser: User)=>{
|
||||
const url = `${SOLOGIN_API}getPubkey?email=${currentUser.uid}`;
|
||||
const userDataRes = await fetch(url);
|
||||
const userDataJson = await userDataRes.json();
|
||||
|
||||
return userDataJson;
|
||||
}
|
||||
|
||||
const SetUser = async(currentUser:User)=>{
|
||||
const sologinUser = await getSologinUser(currentUser);
|
||||
console.log(sologinUser);
|
||||
setUser({
|
||||
name: currentUser.displayName || 'Anonymous User',
|
||||
email: currentUser.email,
|
||||
id: currentUser.uid,
|
||||
tokenId: await currentUser.getIdToken(),
|
||||
pubkey: sologinUser.pub_key
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
const signout = async()=>{
|
||||
await auth.signOut();
|
||||
|
||||
};
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
const unsubscribe = onAuthStateChanged(auth, async (currentUser) => {
|
||||
if (currentUser) {
|
||||
SetUser(currentUser);
|
||||
} else {
|
||||
router.push('/signup'); // Redirect to signup if not logged in
|
||||
}
|
||||
setLoading(false);
|
||||
});
|
||||
|
||||
return () => unsubscribe(); // Cleanup subscription on unmount
|
||||
}, [auth, router]);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-gray-900 text-white">
|
||||
<p className="text-lg">Loading...</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!user) {
|
||||
return null; // Return null to avoid rendering during redirection
|
||||
}
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
|
||||
<main className="flex flex-col gap-8 row-start-2 items-center sm:items-start">
|
||||
<Image
|
||||
className="dark:invert"
|
||||
src="/next.svg"
|
||||
alt="Next.js logo"
|
||||
width={180}
|
||||
height={38}
|
||||
priority
|
||||
/>
|
||||
<ol className="list-inside list-decimal text-sm text-center sm:text-left font-[family-name:var(--font-geist-mono)]">
|
||||
<li className="mb-2">
|
||||
Get started by editing{" "}
|
||||
<code className="bg-black/[.05] dark:bg-white/[.06] px-1 py-0.5 rounded font-semibold">
|
||||
app/page.tsx
|
||||
</code>
|
||||
.
|
||||
</li>
|
||||
<li>Save and see your changes instantly.</li>
|
||||
</ol>
|
||||
<div className="min-h-screen bg-gray-900 text-white flex items-center justify-center">
|
||||
<div className="bg-gray-800 p-8 rounded-lg shadow-lg w-full sm:w-96">
|
||||
<h1 className="text-3xl font-bold mb-4">Welcome</h1>
|
||||
<p className="text-lg mb-2">
|
||||
<strong>Name:</strong> {user.name}
|
||||
</p>
|
||||
<p className="text-lg mb-2">
|
||||
<strong>Email:</strong> {user.email}
|
||||
</p>
|
||||
<p className="text-lg">
|
||||
<strong>ID:</strong> {user.id}
|
||||
</p>
|
||||
<p className="text-lg">
|
||||
<strong>PubKey:</strong> {user.pubkey}
|
||||
</p>
|
||||
<button className='bg-red-500 px-5 py-2 rounded' onClick={signout}> Signout </button>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="flex gap-4 items-center flex-col sm:flex-row">
|
||||
<a
|
||||
className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5"
|
||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
className="dark:invert"
|
||||
src="/vercel.svg"
|
||||
alt="Vercel logomark"
|
||||
width={20}
|
||||
height={20}
|
||||
/>
|
||||
Deploy now
|
||||
</a>
|
||||
<a
|
||||
className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:min-w-44"
|
||||
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Read our docs
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
<footer className="row-start-3 flex gap-6 flex-wrap items-center justify-center">
|
||||
<a
|
||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
||||
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
aria-hidden
|
||||
src="/file.svg"
|
||||
alt="File icon"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
Learn
|
||||
</a>
|
||||
<a
|
||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
||||
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
aria-hidden
|
||||
src="/window.svg"
|
||||
alt="Window icon"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
Examples
|
||||
</a>
|
||||
<a
|
||||
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
||||
href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
aria-hidden
|
||||
src="/globe.svg"
|
||||
alt="Globe icon"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
Go to nextjs.org →
|
||||
</a>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default HomePage;
|
||||
|
|
|
|||
1
app/shared.ts
Normal file
1
app/shared.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export const SOLOGIN_API = "http://vps.playpoolstudios.com:20017/";
|
||||
117
app/signin/page.tsx
Normal file
117
app/signin/page.tsx
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
'use client';
|
||||
import React, { useState } from 'react';
|
||||
import { app, auth } from '@/app/firebase/config';
|
||||
import { signInWithEmailAndPassword, getAuth } from 'firebase/auth';
|
||||
import GoogleSignInButton from '../firebase/components/GoogleSignInButton';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { LoginSologin } from '../sologin';
|
||||
|
||||
const SignIn = () => {
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const router = useRouter();
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
try {
|
||||
const userCredential = await signInWithEmailAndPassword(auth, email, password);
|
||||
console.log('User signed in:', userCredential.user);
|
||||
await LoginSologin(userCredential.user);
|
||||
onLoginSuccess();
|
||||
setEmail('');
|
||||
setPassword('');
|
||||
setError(null); // Clear errors on successful login
|
||||
} catch (err: any) {
|
||||
// Set the error message based on Firebase error codes
|
||||
switch (err.code) {
|
||||
case 'auth/user-not-found':
|
||||
setError('User not found. Please check your email and try again.');
|
||||
break;
|
||||
case 'auth/invalid-credential':
|
||||
setError('Incorrect password. Please try again.');
|
||||
break;
|
||||
case 'auth/network-request-failed':
|
||||
setError('Unable to connect. Please check your internet connection.');
|
||||
break;
|
||||
default:
|
||||
setError('An unexpected error occurred. Please try again.');
|
||||
console.error(err.code);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const onLoginSuccess = ()=>{
|
||||
router.push('/');
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-900 flex items-center justify-center">
|
||||
<div className="bg-gray-800 p-8 rounded-lg shadow-lg w-full sm:w-96">
|
||||
<h2 className="text-3xl font-bold text-white mb-6">Sign In</h2>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="mb-4">
|
||||
<label className="block text-sm text-gray-300 mb-2" htmlFor="email">
|
||||
Email Address
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
className="w-full p-3 bg-gray-700 text-white rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder="Enter your email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-6">
|
||||
<label className="block text-sm text-gray-300 mb-2" htmlFor="password">
|
||||
Password
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
className="w-full p-3 bg-gray-700 text-white rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder="Enter your password"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full py-3 bg-blue-600 text-white rounded-md hover:bg-blue-500 transition duration-300"
|
||||
>
|
||||
Sign In
|
||||
</button>
|
||||
</form>
|
||||
<p className="mt-4 text-center text-sm text-gray-400">
|
||||
Don't have an account?{' '}
|
||||
<a href="/signup" className="text-blue-400 hover:underline">
|
||||
Sign Up
|
||||
</a>
|
||||
</p>
|
||||
<GoogleSignInButton onLoginSuccess={onLoginSuccess}></GoogleSignInButton>
|
||||
</div>
|
||||
|
||||
{/* Error Dialog */}
|
||||
{error && (
|
||||
<div className="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50 z-50">
|
||||
<div className="bg-gray-800 p-6 rounded-lg shadow-lg">
|
||||
<h3 className="text-xl font-bold text-white mb-4">Error</h3>
|
||||
<p className="text-gray-300">{error}</p>
|
||||
<button
|
||||
className=" mt-4 px-4 py-2 bg-red-600 text-white rounded-md hover:bg-red-500"
|
||||
onClick={() => setError(null)}
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SignIn;
|
||||
122
app/signup/page.tsx
Normal file
122
app/signup/page.tsx
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
'use client'
|
||||
import React, { useState } from 'react';
|
||||
import {app, auth} from '@/app/firebase/config';
|
||||
import { createUserWithEmailAndPassword, getAuth } from 'firebase/auth';
|
||||
import { getApp } from 'firebase/app';
|
||||
import { SOLOGIN_API } from '../shared';
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
import { RegisterSologin } from '../sologin';
|
||||
|
||||
const SignUp = () => {
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const onLoginSuccess = ()=>{
|
||||
router.push('/');
|
||||
}
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
try{
|
||||
createUserWithEmailAndPassword(auth, email, password)
|
||||
.then(async(userCredential) => {
|
||||
// Signed up
|
||||
const user = userCredential.user;
|
||||
await RegisterSologin(userCredential.user);
|
||||
console.log(user);
|
||||
onLoginSuccess();
|
||||
|
||||
})
|
||||
.catch((error) => {
|
||||
const errorCode = error.code;
|
||||
|
||||
switch(errorCode){
|
||||
case 'auth/email-already-in-use':
|
||||
setError("This email address is already signed up. Forgot password?")
|
||||
break;
|
||||
|
||||
default:
|
||||
setError("Something went wrong");
|
||||
break;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
setEmail('');
|
||||
setPassword('');
|
||||
}catch(e){
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-900 flex items-center justify-center">
|
||||
<div className="bg-gray-800 p-8 rounded-lg shadow-lg w-full sm:w-96">
|
||||
<h2 className="text-3xl font-bold text-white mb-6">Sign Up</h2>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="mb-4">
|
||||
<label className="block text-sm text-gray-300 mb-2" htmlFor="email">
|
||||
Email Address
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
className="w-full p-3 bg-gray-700 text-white rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder="Enter your email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-6">
|
||||
<label className="block text-sm text-gray-300 mb-2" htmlFor="password">
|
||||
Password
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
className="w-full p-3 bg-gray-700 text-white rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
placeholder="Enter your password"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full py-3 bg-blue-600 text-white rounded-md hover:bg-blue-500 transition duration-300"
|
||||
>
|
||||
Sign Up
|
||||
</button>
|
||||
</form>
|
||||
<p className="mt-4 text-center text-sm text-gray-400">
|
||||
Already have an account?{' '}
|
||||
<a href="/signin" className="text-blue-400 hover:underline">
|
||||
Log In
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
{error && (
|
||||
<div className="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50 z-50">
|
||||
<div className="bg-gray-800 p-6 rounded-lg shadow-lg">
|
||||
<h3 className="text-xl font-bold text-white mb-4">Error</h3>
|
||||
<p className="text-gray-300">{error}</p>
|
||||
<button
|
||||
className=" mt-4 px-4 py-2 bg-red-600 text-white rounded-md hover:bg-red-500"
|
||||
onClick={() => setError(null)}
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
);
|
||||
};
|
||||
|
||||
export default SignUp;
|
||||
18
app/sologin.ts
Normal file
18
app/sologin.ts
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import { User } from "firebase/auth"
|
||||
import { SOLOGIN_API } from "./shared";
|
||||
|
||||
export const LoginSologin=async(currentUser:User)=>{
|
||||
const tokenId = await currentUser.getIdToken();
|
||||
const sologinLoginRes = await fetch(`${SOLOGIN_API}login?tokenId=${tokenId}`);
|
||||
|
||||
const resText = await sologinLoginRes.text();
|
||||
console.log(resText);
|
||||
}
|
||||
|
||||
export const RegisterSologin= async(currentUser:User)=>{
|
||||
const tokenId = await currentUser.getIdToken();
|
||||
const sologinRegisterRes = await fetch(`${SOLOGIN_API}register?tokenId=${tokenId}`);
|
||||
|
||||
const resText = await sologinRegisterRes.text();
|
||||
console.log(resText);
|
||||
}
|
||||
24
firebase-debug.log
Normal file
24
firebase-debug.log
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
[debug] [2024-11-19T17:18:05.272Z] ----------------------------------------------------------------------
|
||||
[debug] [2024-11-19T17:18:05.274Z] Command: C:\Program Files\nodejs\node.exe C:\Users\warlock\AppData\Roaming\npm\node_modules\firebase-tools\lib\bin\firebase.js init
|
||||
[debug] [2024-11-19T17:18:05.274Z] CLI Version: 13.25.0
|
||||
[debug] [2024-11-19T17:18:05.275Z] Platform: win32
|
||||
[debug] [2024-11-19T17:18:05.275Z] Node Version: v20.16.0
|
||||
[debug] [2024-11-19T17:18:05.275Z] Time: Tue Nov 19 2024 22:48:05 GMT+0530 (India Standard Time)
|
||||
[debug] [2024-11-19T17:18:05.275Z] ----------------------------------------------------------------------
|
||||
[debug]
|
||||
[debug] [2024-11-19T17:18:05.277Z] >>> [apiv2][query] GET https://firebase-public.firebaseio.com/cli.json [none]
|
||||
[debug] [2024-11-19T17:18:05.321Z] > command requires scopes: ["email","openid","https://www.googleapis.com/auth/cloudplatformprojects.readonly","https://www.googleapis.com/auth/firebase","https://www.googleapis.com/auth/cloud-platform"]
|
||||
[debug] [2024-11-19T17:18:05.321Z] > authorizing via signed-in user (sewmina7@gmail.com)
|
||||
[info]
|
||||
######## #### ######## ######## ######## ### ###### ########
|
||||
## ## ## ## ## ## ## ## ## ## ##
|
||||
###### ## ######## ###### ######## ######### ###### ######
|
||||
## ## ## ## ## ## ## ## ## ## ##
|
||||
## #### ## ## ######## ######## ## ## ###### ########
|
||||
|
||||
You're about to initialize a Firebase project in this directory:
|
||||
|
||||
I:\NodeJS\mhunt_auth_dash_sologin
|
||||
|
||||
[debug] [2024-11-19T17:18:05.852Z] <<< [apiv2][status] GET https://firebase-public.firebaseio.com/cli.json 200
|
||||
[debug] [2024-11-19T17:18:05.853Z] <<< [apiv2][body] GET https://firebase-public.firebaseio.com/cli.json {"cloudBuildErrorAfter":1594252800000,"cloudBuildWarnAfter":1590019200000,"defaultNode10After":1594252800000,"minVersion":"3.0.5","node8DeploysDisabledAfter":1613390400000,"node8RuntimeDisabledAfter":1615809600000,"node8WarnAfter":1600128000000}
|
||||
|
|
@ -1,7 +1,19 @@
|
|||
import type { NextConfig } from "next";
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
/* config options here */
|
||||
};
|
||||
|
||||
const nextConfig = {
|
||||
async headers() {
|
||||
return [
|
||||
{
|
||||
// matching all API routes
|
||||
source: "/api/:path*",
|
||||
headers: [
|
||||
{ key: "Access-Control-Allow-Credentials", value: "true" },
|
||||
{ key: "Access-Control-Allow-Origin", value: "vps.playpoolstudios.com" }, // replace this your actual origin
|
||||
{ key: "Access-Control-Allow-Methods", value: "GET,DELETE,PATCH,POST,PUT" },
|
||||
{ key: "Access-Control-Allow-Headers", value: "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version" },
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
export default nextConfig;
|
||||
|
|
|
|||
1152
package-lock.json
generated
1152
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
|
|
@ -9,18 +9,20 @@
|
|||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"firebase": "^11.0.2",
|
||||
"next": "15.0.3",
|
||||
"react": "19.0.0-rc-66855b96-20241106",
|
||||
"react-dom": "19.0.0-rc-66855b96-20241106",
|
||||
"next": "15.0.3"
|
||||
"react-dom": "19.0.0-rc-66855b96-20241106"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5",
|
||||
"@types/node": "^20",
|
||||
"@types/react": "^18",
|
||||
"@types/react-dom": "^18",
|
||||
"postcss": "^8",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "15.0.3"
|
||||
"eslint-config-next": "15.0.3",
|
||||
"postcss": "^8.4.49",
|
||||
"tailwindcss": "^3.4.15",
|
||||
"typescript": "^5"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
15
tailwind.config.js
Normal file
15
tailwind.config.js
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: [
|
||||
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
|
||||
// Or if using `src` directory:
|
||||
"./src/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user