diff --git a/package.json b/package.json index 8b15eeb..47892cf 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,9 @@ }, "dependencies": { "@emailjs/browser": "^4.3.3", + "@fortawesome/free-solid-svg-icons": "^6.5.2", + "@fortawesome/react-fontawesome": "^0.2.2", + "@hookform/resolvers": "^3.6.0", "@react-three/drei": "^9.106.0", "@react-three/fiber": "^8.16.6", "@tsparticles/all": "^3.4.0", @@ -24,7 +27,8 @@ "react-router-dom": "^6.23.1", "react-scroll": "^1.9.0", "three": "^0.164.1", - "typed.js": "^2.1.0" + "typed.js": "^2.1.0", + "zod": "^3.23.8" }, "devDependencies": { "@types/react": "^18.2.66", diff --git a/src/components/Navbar/Navbar.jsx b/src/components/Navbar/Navbar.jsx index 986c998..a6e6510 100644 --- a/src/components/Navbar/Navbar.jsx +++ b/src/components/Navbar/Navbar.jsx @@ -121,6 +121,9 @@ function Navbar() {
  • ("rem-default " + (isActive ? ' active' : ''))} to="/about">About us
  • +
  • + ("rem-default " + (isActive ? ' active' : ''))} to="/login">AstroAccess +
  • {renderContactLink()} diff --git a/src/main.jsx b/src/main.jsx index ee0b24b..1d1cd6d 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -4,11 +4,13 @@ import { createBrowserRouter, createRoutesFromElements, RouterProvider, Route } import './index.css' import App from './App.jsx' import Home from "./pages/Home/Home.jsx" +import Login from './pages/Login/page.jsx' import MarsRover from './pages/MarsRover/MarsRover.jsx' import NasaProjects from "./pages/NasaProjects/NasaProjects.jsx" import About from "./pages/About/About.jsx" import NotFoundPage from "./pages/404 Page/NotfoundPage.jsx" + const router = createBrowserRouter( createRoutesFromElements( }> @@ -16,6 +18,7 @@ const router = createBrowserRouter( } /> } /> } /> + } /> } /> ) diff --git a/src/pages/Login/page.jsx b/src/pages/Login/page.jsx new file mode 100644 index 0000000..c51f2f4 --- /dev/null +++ b/src/pages/Login/page.jsx @@ -0,0 +1,432 @@ +"use client"; + +import React, { useState } from 'react'; +import * as z from "zod"; +import { useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons'; + +// Define the form schema using zod +const formSchema = z.object({ + name: z.string().nonempty("*Name is required"), + email: z.string().email("*Invalid email address"), + password: z.string().min(6, "*Password should be at least 6 characters"), +}); + +// Contact form component +export default function SignInSignUp() { + const [type, setType] = useState('signIn'); + const [isSubmitted, setIsSubmitted] = useState(false); + const [isVisible, setIsVisible] = useState(false); + + const signInForm = useForm({ + resolver: zodResolver(formSchema), + defaultValues: { + email: "", + password: "" + } + }); + + const signUpForm = useForm({ + resolver: zodResolver(formSchema), + defaultValues: { + name: "", + email: "", + password: "" + } + }); + + // Handle form submission + const handleSignInSubmit = (values) => { + console.log("Sign In:", values); + // Handle form submission (e.g., send data to the server) + setIsSubmitted(true); + signInForm.reset(); + setTimeout(() => setIsSubmitted(false), 3000); // Hide notification after 3 seconds + }; + + const handleSignUpSubmit = (values) => { + console.log("Sign Up:", values); + // Handle form submission (e.g., send data to the server) + setIsSubmitted(true); + signUpForm.reset(); + setTimeout(() => setIsSubmitted(false), 3000); // Hide notification after 3 seconds + }; + + const handleOnClick = (text) => { + if (text !== type) { + setType(text); + } + }; + + const togglePasswordVisibility = () => { + setIsVisible(!isVisible); + }; + + const containerClass = `container ${type === 'signUp' ? 'right-panel-active' : ''}`; + + return React.createElement('div', { className: 'App' }, + React.createElement('style', null, ` + @import url('https://fonts.googleapis.com/css?family=Montserrat:400,800'); + @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css'); + + + body { + background: rgb(11, 3, 71);; + justify-content: center; + align-items: center; + flex-direction: column; + font-family: 'Montserrat', sans-serif; + } +h1 { + font-weight: bold; + margin: 0; + font-size: 23px; + background: linear-gradient(90deg, #8a2be2, #d896ff); /* Adjust the colors to match your gradient */ + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; +} + + h2 { + text-align: center; + background: linear-gradient(90deg, #8a2be2, #d896ff); /* Adjust the colors to match your gradient */ + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + } + + p { + font-size: 14px; + font-weight: 100; + line-height: 20px; + letter-spacing: 0.5px; + margin: 20px 0 30px; + background: linear-gradient(90deg, #8a2be2, #d896ff); /* Adjust the colors to match your gradient */ + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + } + + span { + font-size: 14px; + color: #9000ff; + } + + a { + color:#9000ff ; + font-size: 14px; + text-decoration: none; + margin: 15px 0; + } + + button { + border-radius: 20px; + border: 2px solid yellow; + background-color: #9000ff; + color: #ffffff; + font-size: 12px; + font-weight: bold; + padding: 12px 45px; + letter-spacing: 1px; + text-transform: uppercase; + transition: transform 80ms ease-in; + } + button:hover { + transform: scale(1.1); + } + + button:active { + transform: scale(0.95); + } + + button:focus { + outline: none; + } + + button.ghost { + background-color: transparent; + border-color: #9000ff; + } + + form { + background-color: #ffffff; + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + padding: 0 50px; + height: 100%; + text-align: center; + border: solid 2px #9000ff; + } + + input { + background-color: #eee; + border: dotted 2px #9000ff; + padding: 6px 6px; + margin: 6px 0; + width: 100%; + background: linear-gradient(90deg, #8a2be2, #d896ff); /* Adjust the colors to match your gradient */ + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + } + + .container { + background-color: #fff; + border-radius: 10px; + border: solid 2px #9000ff; + box-shadow: 10px 14px 28px #9000ff, 10px 10px 10px #9000ff; + position: absolute; + overflow: hidden; + margin-top:7% ; + margin-left:9%; + height: 580px; + width: 1250px; + max-width: 100%; + min-height: 480px; + } + + .form-container { + position: absolute; + top: 0; + height: 100%; + transition: all 0.6s ease-in-out; + border: solid 2px #9000ff; + } + + .eye-button { + position: absolute; + right: -19px; + top: 9px; + background: none; + border: none; + cursor: pointer; + color: #9000ff; + } + + .sign-in-container { + left: 0; + width: 50%; + z-index: 2; + border: solid 2px #9000ff; + } + + .container.right-panel-active .sign-in-container { + transform: translateX(100%); + } + + .sign-up-container { + left: 0; + width: 50%; + opacity: 0; + z-index: 1; + } + + .container.right-panel-active .sign-up-container { + transform: translateX(100%); + opacity: 1; + z-index: 5; + animation: show 0.6s; + } + + @keyframes show { + 0% { + opacity: 0; + transform: translateX(200%); + } + 100% { + opacity: 1; + transform: translateX(0); + } + } + + .overlay-container { + position: absolute; + top: 0; + left: 50%; + width: 50%; + height: 100%; + overflow: hidden; + transition: transform 0.6s ease-in-out; + z-index: 100; + } + + .container.right-panel-active .overlay-container { + transform: translateX(-100%); + } + + .overlay { + background: #ff416c; + background: -webkit-linear-gradient(to right, #03001D, #03001D); + background: linear-gradient(to right, #03001D, #03001D); + background-repeat: no-repeat; + background-size: cover; + background-position: 0 0; + color: #ffffff; + position: relative; + left: -100%; + height: 100%; + width: 200%; + transform: translateX(0); + transition: transform 0.6s ease-in-out; + } + + .container.right-panel-active .overlay { + transform: translateX(50%); + } + + .overlay-panel { + position: absolute; + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + padding: 0 40px; + text-align: center; + top: 0; + height: 100%; + width: 50%; + transform: translateX(0); + transition: transform 0.6s ease-in-out; + } + + .overlay-left { + transform: translateX(-20%); + } + + .container.right-panel-active .overlay-left { + transform: translateX(0); + } + + .overlay-right { + right: 0; + transform: translateX(0); + } + + .container.right-panel-active .overlay-right { + transform: translateX(20%); + } + + /* Styling for social icons */ + .social-container { + display: flex; + justify-content: center; + margin-top: 20px; + } + + .social-container .social { + display: flex; + align-items: center; + justify-content: center; + height: 50px; + width: 50px; + border-radius: 50%; + background-color: #9000ff; + margin: 0 10px; + font-size: 20px; + color: white; + transition: transform 0.3s ease; + } + + .social-container .social:hover { + transform: scale(1.1); + } + `), + React.createElement('div', { className: containerClass, id: 'container' }, + React.createElement('div', { className: 'form-container sign-up-container' }, + React.createElement('form', { onSubmit: signUpForm.handleSubmit(handleSignUpSubmit) }, + React.createElement('h1', null, 'Create Account'), + React.createElement('div', { className: 'social-container' }, + React.createElement('a', { href: 'https://www.facebook.com', className: 'social' }, + React.createElement('i', { className: 'fab fa-facebook-f' }) + ), + React.createElement('a', { href: 'https://www.google.com', className: 'social' }, + React.createElement('i', { className: 'fab fa-google-plus-g' }) + ), + React.createElement('a', { href: 'https://www.linkedin.com', className: 'social' }, + React.createElement('i', { className: 'fab fa-linkedin-in' }) + ), + React.createElement('a', { href: 'https://www.twitter.com', className: 'social' }, + React.createElement('i', { className: 'fab fa-twitter' }) + ) + ), + React.createElement('br', null), + React.createElement('span', null, 'Join Cosmoxplore by creating your account or register with your email'), + React.createElement('input', { type: 'text', placeholder: 'Name', ...signUpForm.register("name") }), + signUpForm.formState.errors.name && ( + React.createElement('p', { className: 'text- #9000ff' }, signUpForm.formState.errors.name?.message) + ), + React.createElement('input', { type: 'email', placeholder: 'Email', ...signUpForm.register("email") }), + signUpForm.formState.errors.email && ( + React.createElement('p', { className: 'text- #9000ff' }, signUpForm.formState.errors.email?.message) + ), + React.createElement('div', { style: { position: 'relative', width: '100%' } }, + React.createElement('input', { type: isVisible ? "text" : "password", placeholder: 'Password', ...signUpForm.register("password") }), + React.createElement('button', { type: 'button', className: 'eye-button', onClick: togglePasswordVisibility }, + React.createElement(FontAwesomeIcon, { icon: isVisible ? faEyeSlash : faEye }) + ) + ), + signUpForm.formState.errors.password && ( + React.createElement('p', { className: 'text- #9000ff' }, signUpForm.formState.errors.password?.message) + ), + React.createElement('button', { type: 'submit' }, 'Sign Up') + ) + ), + React.createElement('div', { className: 'form-container sign-in-container' }, + React.createElement('form', { onSubmit: signInForm.handleSubmit(handleSignInSubmit) }, + React.createElement('h1', null, 'Access your Cosmoxplore account'), + React.createElement('div', { className: 'social-container' }, + React.createElement('a', { href: 'https://www.facebook.com', className: 'social' }, + React.createElement('i', { className: 'fab fa-facebook-f' }) + ), + React.createElement('a', { href: 'https://www.google.com', className: 'social' }, + React.createElement('i', { className: 'fab fa-google-plus-g' }) + ), + React.createElement('a', { href: 'https://www.linkedin.com', className: 'social' }, + React.createElement('i', { className: 'fab fa-linkedin-in' }) + ), + React.createElement('a', { href: 'https://www.twitter.com', className: 'social' }, + React.createElement('i', { className: 'fab fa-twitter' }) + ) + ), + React.createElement('br', null), + React.createElement('span', null, 'Join Cosmoxplore by creating your account or continue with your profile'), + React.createElement('input', { type: 'email', placeholder: 'Email', ...signInForm.register("email") }), + signInForm.formState.errors.email && ( + React.createElement('p', { className: 'text- #9000ff' }, signInForm.formState.errors.email?.message) + ), + React.createElement('div', { style: { position: 'relative', width: '100%' } }, + React.createElement('input', { type: isVisible ? "text" : "password", placeholder: 'Password', ...signInForm.register("password") }), + React.createElement('button', { type: 'button', className: 'eye-button', onClick: togglePasswordVisibility }, + React.createElement(FontAwesomeIcon, { icon: isVisible ? faEyeSlash : faEye }) + ) + ), + signInForm.formState.errors.password && ( + React.createElement('p', { className: 'text- #9000ff' }, signInForm.formState.errors.password?.message) + ), + React.createElement('span', null, + React.createElement('a', { href: 'https://cosmoxplore.vercel.app/' }, 'Forgot your password?') + ), + React.createElement('br', null), + React.createElement('button', { type: 'submit' }, 'Sign In') + ) + ), + React.createElement('div', { className: 'overlay-container' }, + React.createElement('div', { className: 'overlay' }, + React.createElement('div', { className: 'overlay-panel overlay-left' }, + React.createElement('h1', null, 'Welcome back! Dive into your Cosmoxplore journey'), + React.createElement('p', null, 'We are glad you are here! Connect with us by logging in with your personal details to explore Cosmoxplore'), + React.createElement('button', { className: 'ghost', onClick: () => handleOnClick('signIn') }, 'Sign In') + ), + React.createElement('div', { className: 'overlay-panel overlay-right' }, + React.createElement('h1', null, 'Explore the universe with Cosmoxplore'), + React.createElement('p', null, 'Cosmoxplore: Unveiling the mysteries of the cosmos'), + React.createElement('button', { className: 'ghost', onClick: () => handleOnClick('signUp') }, 'Sign Up') + ) + ) + ) + ), + isSubmitted && ( + React.createElement('p', { className: 'mt-4 text-Blue-1000' }, 'Form submitted successfully!') + ) + ); +} \ No newline at end of file