UNPKG

leumas-private-shared

Version:

Private React JSX Package For Leumas Shared Components, Headers, Footers, Asides, Login Pages, API Key Manager and much more. Styles and everything reusable to avoid DRY code across all of our subdomains

272 lines (244 loc) 12.2 kB
import { useState } from 'react'; import axios from 'axios'; import { Link, useNavigate } from 'react-router-dom'; import { FaCircleCheck } from "react-icons/fa6"; import useSignIn from 'react-auth-kit/hooks/useSignIn'; import { FaCheckCircle } from 'react-icons/fa'; import useAuthUser from 'react-auth-kit/hooks/useAuthUser'; import { Helmet } from 'react-helmet'; import { useTheme } from "../../Theme/ThemeContext"; import InfinityBackgroundComponent from '../../Components/Backgrounds/Infinity'; // Import the new background component import React from 'react'; function Login({ setMode }) { const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const signIn = useSignIn(); const navigate = useNavigate(); const auth = useAuthUser(); const isLoggedIn = auth !== null; const { theme } = useTheme(); const handleGoogleSuccess = async (response) => { console.log('Google response:', response); const token = response.credential; try { const res = await axios.post(`${import.meta.env.VITE_REACT_APP_LEUMAS_LOGIN_ENDPOINT}/login/google`, { token }); const { token: appToken, expiresIn, authUserState } = res.data; if (signIn({ auth: { token: appToken, type: 'Bearer', expiresIn: expiresIn, authState: res.data.authUserState, }, expiresIn: expiresIn, authState: res.data.authUserState, userState: authUserState })) { navigate('/dashboard'); window.location.href = '/dashboard'; } else { console.error('Sign-in failed'); } navigate("/dashboard"); } catch (error) { console.error('Error during Google Sign In:', error); } }; const handleGoogleFailure = (error) => { if (error.error === 'popup_closed_by_user') { console.log("Popup was closed before completing the sign-in process."); } else { console.error('Google Sign In Failed:', error); } }; const navigateToUserDashboard = () => { navigate("/dashboard"); window.location.href = '/dashboard'; }; const handleLogin = async (e) => { e.preventDefault(); if (!username || !password) { setError('Please enter both username and password.'); return; } setIsLoading(true); setError(null); try { console.log("Fetching from Wordpress "); const wpResponse = await axios.post(`https://leumas.tech/wp-json/jwt-auth/v1/token`, { username: username, password: password, }); const membershipId = wpResponse.data.user_membership_level?.id || 0; const membershipName = wpResponse.data.user_membership_level?.name || "Free"; const { token, user_display_name, user_email, user_nicename } = wpResponse.data; console.log("Fetching From Backend"); const backendResponse = await axios.post(`${import.meta.env.VITE_REACT_APP_LEUMAS_LOGIN_ENDPOINT}/login`, { token, user_display_name, user_email, user_nicename, membershipId, membershipName, windowLocation: window.location.href }); console.log("Backend Response : ", backendResponse) const backendToken = backendResponse.data.token; // Use backendToken for MongoDB const expiresIn = backendResponse.data.expiresIn; const authUserState = { ...backendResponse.data.authUserState, membershipId, membershipName, token, backendToken // Store the backend token in authUserState }; if (signIn({ auth: { token: token, // Keep the original token type: 'Bearer', expiresIn: expiresIn, authState: authUserState, }, expiresIn: expiresIn, authState: authUserState, userState: authUserState })) { // navigate('/'); // window.location.href = '/'; } } catch (error) { console.log("Error ", error); setError(error.response?.data.message || 'An error occurred.'); } finally { setIsLoading(false); } }; return ( <> <Helmet> <title>Login | Bulk Forge - Mass AI Asset Generation</title> <meta name="description" content="Login to Bulk Forge to start mass producing assets with AI. Access your dashboard for code generation, image creation with DALL·E, and more." /> <meta name="keywords" content="Bulk Forge login, AI asset generation, code generation, DALL·E image creation, mass produce AI, AI tools" /> <meta name="robots" content="index, follow" /> <meta name="author" content="Leumas Tech" /> <meta property="og:title" content="Login | Bulk Forge - Mass AI Asset Generation" /> <meta property="og:description" content="Access Bulk Forge to efficiently produce assets with AI, including code and DALL·E generated images." /> <meta property="og:type" content="website" /> <meta property="og:url" content="https://bulkForge.leumas.tech/login" /> <meta property="og:image" content="https://res.cloudinary.com/dx25lltre/image/upload/v1707176122/Leumas/2_t6ap9y.svg" /> <meta property="og:site_name" content="Bulk Forge" /> <meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:title" content="Login | Bulk Forge - Mass AI Asset Generation" /> <meta name="twitter:description" content="Access Bulk Forge to start creating assets with AI for code generation and image creation with DALL·E." /> <meta name="twitter:image" content="https://res.cloudinary.com/dx25lltre/image/upload/v1707176122/Leumas/2_t6ap9y.svg" /> <link rel="canonical" href="https://bulkForge.leumas.tech/login" /> <meta httpEquiv="content-language" content="en" /> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /> <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" /> <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" /> <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" /> <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5" /> <meta name="msapplication-TileColor" content="#2b5797" /> <meta name="theme-color" content="#ffffff" /> </Helmet> <InfinityBackgroundComponent> {isLoggedIn === false ? ( <div className="flex flex-col md:flex-row items-stretch bg-transparent p-4 md:p-8 "> <div className={`hidden md:flex w-1/2 flex-col gap-4 mx-auto rounded-lg shadow-3xl p-2 text-blue-400`}> <div className='flex gap-2 items-center justify-start'> <img src={`https://res.cloudinary.com/dx25lltre/image/upload/v1707176122/Leumas/2_t6ap9y.svg`} className='h-12' /> <h1 className='text-2xl md:text-3xl font-bold'>Leumas Tech</h1> </div> <div className='space-y-2 p-2 max-w-[450px] '> <div className='flex items-center gap-2'> <FaCircleCheck className='text-blue-500' /> <h2 className='text-lg font-semibold'>All Tools, One Account</h2> </div> <p className='text-xs ml-4 text-start'>Access 30+ tools instantly with a single sign-up.</p> </div> <div className='space-y-2 p-2 max-w-[450px]'> <div className='flex items-center gap-2'> <FaCircleCheck className='text-blue-500' /> <h2 className='text-lg font-semibold'>Seamless Tool Transitions</h2> </div> <p className='text-xs ml-4 text-start'>Enjoy smooth workflows across all platforms.</p> </div> <div className='space-y-2 p-2 max-w-[450px]'> <div className='flex items-center gap-2'> <FaCircleCheck className='text-blue-500' /> <h2 className='text-lg font-semibold'>AI-Powered Efficiency</h2> </div> <p className='text-xs ml-4 text-start'>Unlock the power of AI to streamline tasks and enhance productivity across all LeumasAI applications.</p> </div> <div className='text-center border rounded-lg p-2 mt-2 bg-blue-600 flex flex-col gap-2'> <p className='mt-2'>You must create an account on Leumas.Tech before entering our Tools</p> <p><strong>Note: </strong>If you signup with your social please navigate to your Dashboard on Leumas.Tech to find your login credentials</p> </div> </div> <div className={`w-full md:w-1/2 p-6 rounded-lg shadow-xl max-h-[500px] mx-auto ${theme === 'dark' ? 'bg-black' : 'bg-white'}`}> <h1 className="text-xl md:text-2xl font-semibold mb-6 text-start">Login</h1> {error && ( <div className="bg-red-100 text-red-700 p-3 mb-6 rounded-lg"> {error} </div> )} <form onSubmit={handleLogin} className="space-y-6"> <div> <label htmlFor="username" className="block text-sm md:text-base font-medium mb-2 text-start"> Username </label> <input type="text" id="username" value={username} onChange={(e) => setUsername(e.target.value)} className="w-full p-3 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 bg-transparent" /> </div> <div> <label htmlFor="password" className="block text-sm md:text-base font-medium mb-2 text-start"> Password </label> <input type="password" id="password" value={password} onChange={(e) => setPassword(e.target.value)} className="w-full p-3 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 bg-transparent " /> </div> <button type="submit" className={`w-full p-3 text-base font-semibold text-white rounded-lg ${ isLoading ? 'bg-gray-400 cursor-not-allowed' : 'bg-blue-600 hover:bg-blue-700' }`} disabled={isLoading} > {isLoading ? 'Logging in...' : 'Login'} </button> </form> <div className="mt-4 text-center"> <Link to="https://leumas.tech/signup" className="text-sm md:text-base text-blue-600 hover:text-blue-700"> Don't have an account? Sign up. </Link> </div> </div> </div> ) : ( <div className="flex items-center justify-center min-h-screen"> <div className="text-center"> <FaCheckCircle className="text-green-500 text-6xl mx-auto" /> <p className="text-xl mt-4">You are already logged in {auth?.id}</p> <button onClick={navigateToUserDashboard} className="mt-4 bg-blue-500 hover:bg-blue-600 text-white py-2 px-4 rounded-lg"> Go to Dashboard </button> </div> </div> )} </InfinityBackgroundComponent> </> ); } export default Login;