diff --git a/backend/src/controller/auth.js b/backend/src/controller/auth.js index acfd264..3d8b287 100644 --- a/backend/src/controller/auth.js +++ b/backend/src/controller/auth.js @@ -128,6 +128,9 @@ const signup = async (req, res) => { }); } }; + + + const varifyOtp = async (req, res) => { try { // console.log("Remaining = "+(req.rateLimit.remaining)); @@ -135,7 +138,7 @@ const varifyOtp = async (req, res) => { { return res.status(425).send({message:"Too Many requests, please try again after some minutes"}); } - const { userID, otp } = req.body; + const { userID, otp, email } = req.body; if (userID == "" || otp == "") { throw Error(" credetials cannot be empty"); } else { @@ -161,6 +164,10 @@ const varifyOtp = async (req, res) => { if (!validOtp) { return res.status(401).json({ msg: "Invalid Otp" }); } + + var token = jwt.sign({ userId:userID,email: email }, process.env.SECRET_KEY, { + expiresIn: 24 * 60 * 60, + }); const updateUser = await prisma.user.update({ where: { userID: userID, @@ -176,12 +183,18 @@ const varifyOtp = async (req, res) => { }, }); - return res.status(202).json({ msg: "User successfully Varified" }); + return res.cookie(updateUser.userID, token, { + path: "/", + expires: new Date(Date.now() + 1000 * 1 * 24 * 60 * 60), + httpOnly: true, + sameSite: "lax", + }).status(202).send(email); } } catch (error) { console.log(error); } }; + const resendOtp = async (req, res) => { console.log(req.body); try { diff --git a/frontend/index.html b/frontend/index.html index d1f6dcf..4a6f422 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -4,10 +4,26 @@ quIET - - - - + + + + - - - + + + - + + + + +
diff --git a/frontend/public/vite.svg b/frontend/public/vite.svg deleted file mode 100644 index e7b8dfb..0000000 --- a/frontend/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 1511da8..4c05695 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -50,6 +50,8 @@ import NotFound from './pages/NotFound' import Popular from './pages/Popular' import ForbiddenPage from './pages/ForbiddenPage' import loading from './redux/loading' +import About from './components/About' +import { hide } from './redux/welcome' @@ -65,10 +67,12 @@ function App() { const isLogin = useSelector((state) => state.login.value); const userInfo = useSelector(state => state.user.userInfo); const searchRef = useRef(null) + const welcomeRef = useRef(null) const posts = useSelector(state => state.post.posts) const location = useLocation(); const isSkelton = useSelector(state => state.skelton.value); const showSearch = useSelector(state => state.search.value) + const showWelcome= useSelector(state=> state.welcome.value) const navigate= useNavigate() @@ -88,22 +92,7 @@ function App() { - const getUserData = async (email) => { - setLoading(true); - try { - const res = await axios.get(`${baseAddress}u/${email}`, { withCredentials: true }); - if (res.status == 200) { - dispatch(setUserInfo(res.data.user)); - console.log(res); - - - } - } catch (error) { - console.log(error); - } - setLoading(false); - } @@ -129,11 +118,12 @@ function App() { try { const res = await axios.post(`${baseAddress}auth/refreshsignin`, { withCredentials: true }); if (res.status == 200) { + + await getUserData({email:res.data, dispatch}); toast("Loggin Session Restored", { icon: 'ℹ️', }) dispatch(login()); - getUserData(res.data); getUserNotification(); } } catch (error) { @@ -167,6 +157,9 @@ function App() { if (searchRef.current && !searchRef.current.contains(event.target)) { dispatch(setShowSearch(false)) } + if (welcomeRef.current && !welcomeRef.current.contains(event.target)) { + dispatch(hide()) + } }; @@ -266,8 +259,41 @@ function App() { )} + {showWelcome && <> +
+ + + + +
+ } + + + ) } -export default App \ No newline at end of file +export default App + + +export const getUserData=async({email, dispatch})=>{ + toast.dismiss() + toast.loading("Signing In") + + dispatch(setSkeltonLoader()) + + try { + const res= await axios.get(`${baseAddress}u/${email}`, {withCredentials:true}); + + if(res.status==200){ + console.log(res); + dispatch(setUserInfo(res.data.user)); + } + } catch (error) { + console.log(error); + } + + dispatch(setSkeltonLoader()) + toast.dismiss() +} \ No newline at end of file diff --git a/frontend/src/assets/Greencheck.jsx b/frontend/src/assets/Greencheck.jsx index 6b4c128..08fee83 100644 --- a/frontend/src/assets/Greencheck.jsx +++ b/frontend/src/assets/Greencheck.jsx @@ -1,6 +1,6 @@ const Greencheck = () => ( - + ) diff --git a/frontend/src/assets/LeetCodeLogo.jsx b/frontend/src/assets/LeetCodeLogo.jsx index 2f70ed2..dbfd942 100644 --- a/frontend/src/assets/LeetCodeLogo.jsx +++ b/frontend/src/assets/LeetCodeLogo.jsx @@ -2,7 +2,7 @@ import React from 'react' const LeetCodeLogo = () => { return ( - + ) } diff --git a/frontend/src/components/About.jsx b/frontend/src/components/About.jsx new file mode 100644 index 0000000..eb34a63 --- /dev/null +++ b/frontend/src/components/About.jsx @@ -0,0 +1,60 @@ +import React from 'react' +import { IoIosSend } from "react-icons/io"; +import { MdCancelPresentation } from "react-icons/md"; +import { useDispatch } from 'react-redux'; +import {hide} from '../redux/welcome' + +const About = () => { + const dispatch= useDispatch(); + return ( + <> +
+
dispatch(hide())} className=' absolute right-4 top-4 text-2xl'>
+
+ Welcome to quIET +
+
+
+ Welcome to quIET, a social media platform designed for those who value their privacy and the freedom to express themselves without fear of judgment. We’re thrilled to have you join our community where your thoughts, ideas, and experiences can be shared freely and anonymously. +
+
+
What is quIET?
+
+ quIET is an anonymous social media platform where users can interact, post comments, and engage in discussions without revealing their true identity as users often face the challenge of balancing their public image with their true thoughts and feelings. In this digital age, where personal data is often at risk, quIET provides a sanctuary where you can be yourself without the pressure of maintaining a public persona. Here, every user is assigned a randomly generated username, ensuring that your real name and email address remain completely private. +
+
+
+
Key Features
+
    +
  • Each user is given a unique, randomly generated username. Your real name and email address are never displayed, ensuring complete anonymity.
  • + +
  • + Discuss anything from college life and societal critiques to personal stories, or just engage in some light-hearted gossip and observations without the fear of judgment and burden of revealing your identity. +
  • + +
  • + Interact with others, comment on posts, and participate in discussions in a community that values privacy and authenticity. +
  • + +
+ + +
+ +
+
A Glimpse Into the quIET Experience
+
+ As a new user, you’ll find that quIET is not just another social media platform. It’s a space where the usual constraints of identity and reputation are lifted, allowing for more genuine and diverse conversations. Whether you’re here to share your thoughts on the latest trends, vent about college life, or engage in serious discussions about social issues, quIET welcomes you with open arms. +
+
+
+ + +
+ + ) +} + +export default About diff --git a/frontend/src/components/AddMemBox.jsx b/frontend/src/components/AddMemBox.jsx index 3c79775..da12c65 100644 --- a/frontend/src/components/AddMemBox.jsx +++ b/frontend/src/components/AddMemBox.jsx @@ -5,6 +5,7 @@ import SmoothLoader from "../assets/SmoothLoader"; import axios from "axios"; import baseAddress from "../utils/localhost"; import toast from "react-hot-toast"; +import dp from '../assets/dummydp.png' import { useDebounce } from '../hooks/useDebounce'; import { fetchUsers } from "./Search"; import { v4 as uuidv4 } from "uuid"; diff --git a/frontend/src/pages/Home.jsx b/frontend/src/pages/Home.jsx index a25ca3d..ee00f6f 100644 --- a/frontend/src/pages/Home.jsx +++ b/frontend/src/pages/Home.jsx @@ -94,7 +94,7 @@ const Home = () => { return ( -
+
{ const [userData, setUserData] = useState([]); @@ -15,15 +16,15 @@ const Overview = () => { const [hasMore, setHasMore] = useState(true); const { user } = useOutletContext(); const { username } = useParams(); - const dispatch = useDispatch() + const dispatch = useDispatch(); const isSkelton = useSelector(state => state.skelton.value); const [postOffset, setPostOffset] = useState(0); const [commentOffset, setCommentOffset] = useState(0); - const [isLoading, setisLoading] = useState(false) + const [isLoading, setIsLoading] = useState(false); const getUserOverview = async (reset = false) => { dispatch(setSkeltonLoader()); - setisLoading(true) + setIsLoading(true); try { if (reset) { @@ -34,8 +35,6 @@ const Overview = () => { const currentPage = reset ? 1 : page; - - const res1 = await axios.get(`${baseAddress}search/getusercomments`, { params: { userID: user.userID, @@ -47,9 +46,6 @@ const Overview = () => { withCredentials: true, }); - - - const res2 = await axios.get(`${baseAddress}search/getuserposts`, { params: { userID: user.userID, @@ -61,73 +57,79 @@ const Overview = () => { withCredentials: true, }); + if (res1.status === 200 && res2.status === 200) { + let res = [...res1.data, ...res2.data.posts] + .sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt)) + .slice(0, 10); - if (res1.status === 200 && res2.status == 200) { - - let res = [...res1.data, ...res2.data.posts].sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt)).slice(0,10); - + setUserData(prevUserData => [...prevUserData, ...res]); - setUserData([...userData, ...res]); let temp = res.filter(e => 'postId' in e); let co = temp.length; let po = res.length - co; - setPostOffset(postOffset + po); - setCommentOffset(commentOffset + co); - + setPostOffset(prevOffset => prevOffset + po); + setCommentOffset(prevOffset => prevOffset + co); if (res.length < 10) { setHasMore(false); } - } } catch (error) { console.log(error); } dispatch(setSkeltonLoader()); - setisLoading(false) - + setIsLoading(false); }; useEffect(() => { - if(page==1){ - window.scroll(0,0) + if (page === 1) { + window.scroll(0, 0); getUserOverview(true); - }else{ + } else { getUserOverview(); } }, [page]); - - const fetchMoreData = () => { if (isLoading || !hasMore) return; setPage(prevPage => prevPage + 1); }; - return (<> -
} - endMessage={

{`${userData.length == 0 ? "It looks like the user hasn't made any posts or comments yet." : "You've reached the end of the page!"}`}

} - > -
- {(isSkelton && userData.length === 0) ? <> : - ( - userData.map(e=><> - {'postId' in e? - - : - - } - ) - ) - } -
- + return ( + <> +
} + endMessage={

{`${userData.length === 0 ? "It looks like the user hasn't made any posts or comments yet." : "You've reached the end of the page!"}`}

} + > +
+ {isSkelton && userData.length === 0 ? null : + ( + userData.map((e) => ( + 'postId' in e + ? + : + )) + ) + } +
+ - ) -} + ); +}; -export default Overview +export default Overview; diff --git a/frontend/src/pages/Room.jsx b/frontend/src/pages/Room.jsx index eb4810d..2121085 100644 --- a/frontend/src/pages/Room.jsx +++ b/frontend/src/pages/Room.jsx @@ -3,7 +3,7 @@ import { useEffect, useRef, useState } from "react"; import baseAddress from "../utils/localhost"; import { Link, Navigate, useAsyncError, useLocation, useNavigate, useParams } from 'react-router-dom' import bg from '../assets/unnamed.png' -import NotUploaded from '../assets/NotUploaded.jpg' +import NotUploaded from '../assets/NotUploaded.jpg' import { MdFileUpload } from "react-icons/md"; import q from '../assets/q.svg' import { setRoomDetail, changeBgImg, changeDpImg } from "../redux/roomSlice"; @@ -38,21 +38,21 @@ import { MdDelete } from "react-icons/md"; const Room = function () { const location = useLocation(); const { title, CreatorId } = useParams(); - - const {data,isLoading,isError,error} = useGetRoomDetailsQuery(title) - const [joined,setJoined] = useState(false); + const { data, isLoading, isError, error } = useGetRoomDetailsQuery(title) + + const [joined, setJoined] = useState(false); const dispatch = useDispatch(); - + const userData = useSelector(state => state.user.userInfo); const room = useSelector(state => state.rooms.rooms); const roomDetail = useSelector(state => state.room.roomInfo); - + const [loader1, setLoader1] = useState(false); const [loader2, setLoader2] = useState(false); const [isLoading2, setisLoading2] = useState(false) const ref = useRef(null); - const dpref= useRef(null) + const dpref = useRef(null) const [showCP, setShowCP] = useState(false); const navigate = useNavigate(); const isSkelton = useSelector((state) => state.skelton.value); @@ -64,28 +64,27 @@ const Room = function () { const [showAddMem, setShowAddMem] = useState(false); const [privateRoom, setPrivateRoom] = useState(true); const dropdownRef = useRef(null); - const [isOpen,setisOpen] = useState(false); - function handleToggle(){ + const [isOpen, setisOpen] = useState(false); + function handleToggle() { setisOpen((isOpen) => !isOpen) } - async function deleteRoom(){ - setisOpen((isOpen)=>!isOpen); + async function deleteRoom() { + setisOpen((isOpen) => !isOpen); toast.loading("Processing..."); - try{ + try { const roomId = roomDetail.id; - const res = await axios.post(baseAddress+"rooms/leave/"+roomId); - + const res = await axios.post(baseAddress + "rooms/leave/" + roomId); + toast.dismiss(); toast.success(res?.data?.msg); const updatedRooms = [...room].filter(roomObject => roomObject.room.id !== roomId); dispatch(setRooms(updatedRooms)); refresh(); - if(isOwner)navigate('/'); + if (isOwner) navigate('/'); else setJoined(false); } - catch(e) - { + catch (e) { toast.dismiss(); toast.error(e?.response?.data?.msg); } @@ -100,7 +99,7 @@ const Room = function () { setisLoading2(true) const res = await axios.post(`${baseAddress}rooms/join`, { title, - Username:userData?.username + Username: userData?.username }) if (res.status == 200) { console.clear() @@ -110,7 +109,7 @@ const Room = function () { console.log(res?.data); console.log(room); toast.success(res?.data.msg); - + setJoined(true); } else { @@ -128,7 +127,7 @@ const Room = function () { const getPost = async () => { - + // setisLoading(true) console.log(`Fetching posts for page: ${page}`); if (!joined && privateRoom) { @@ -136,7 +135,7 @@ const Room = function () { dispatch(setHotPost([])) return; } - else{ + else { if (page == 1) { dispatch(clearHotPostsInfo()) } @@ -148,10 +147,10 @@ const Room = function () { limit: 10, }, }); - + if (res.status === 200) { const fetchedPosts = res.data.posts; - + if (fetchedPosts.length < 10) { setHasMore(false); } @@ -169,26 +168,26 @@ const Room = function () { }; - + // console.clear(); - + async function refresh() { dispatch(roomsApi.util.invalidateTags([{ type: 'Room', id: title }])); - if(joined || !privateRoom)getPost(); + if (joined || !privateRoom) getPost(); } - async function onStart(){ - if(isLoading)return; + async function onStart() { + if (isLoading) return; setisLoading2(true); dispatch(setRoomDetail(data?.room)); setPrivateRoom(data?.room?.privateRoom); console.log("Inside useeffect ") console.log(data); - console.log(isLoading2||isLoading) + console.log(isLoading2 || isLoading) setJoined(data?.joined); - if (joined || !privateRoom){ + if (joined || !privateRoom) { getPost(); - setPage(1); + setPage(1); setHasMore(true); } setisLoading2(false); @@ -198,19 +197,19 @@ const Room = function () { return () => { dispatch(clearHotPostsInfo()); } - }, [data,title]) + }, [data, title]) - useEffect(()=>{ - if (joined || !privateRoom){ + useEffect(() => { + if (joined || !privateRoom) { getPost(); - setPage(1); + setPage(1); setHasMore(true); } - },[joined,privateRoom]) + }, [joined, privateRoom]) - useEffect(()=>{ - if(joined || !privateRoom)getPost(); - },[page]) + useEffect(() => { + if (joined || !privateRoom) getPost(); + }, [page]) function onNewPost() { @@ -287,8 +286,8 @@ const Room = function () { {showCP && } {showAddMem && }
-
-
+
+
backgroudImage {(isOwner) && (loader1 ?
: )} -
- - {loader2?
:Image Not Uploaded} +
+ + {loader2 ?
: Image Not Uploaded} handleDpUpdate(e)} accept='image/*' ref={dpref} type="file" name="media" id="media" hidden /> {isOwner && ()}
-
- {title} +
+ {title}
- { + { joined ?
- - {isOwner && }
: <> - - }{!joined?<>: -
- - - {isOpen && ( -
-
    -
  • - -
  • -
- -
- )} -
} + }{!joined ? <> : +
+ + + {isOpen && ( +
+
    +
  • + +
  • +
+ +
+ )} +
}
-
-
+
+
- -
-{privateRoom&&!joined?: - } - endMessage={hotposts.length > 0 ?

{"You've reached the end of the page!"}

:

No posts available to display!

} - > - {/* */} - -
- ( refresh() )} className=' bg-[#eff1d3] rounded-full p-1'> - {isSkelton ? : } - -
-
- { (hotposts.length == 0 && isSkelton) ? ( - - ) : ( - hotposts.map((post) => ( - - ) - ) - )} -
-
-} +
+ {privateRoom && !joined ? : + } + endMessage={hotposts.length > 0 ?

{"You've reached the end of the page!"}

:

No posts available to display!

} + > + {/* */} + +
+ (refresh())} className=' bg-[#eff1d3] rounded-full p-1'> + {isSkelton ? : } + +
+ +
+ {(hotposts.length == 0 && isSkelton) ? ( + + ) : ( + hotposts.map((post) => ( + + ) + ) + )} +
+
+ }
) diff --git a/frontend/src/pages/Signin.jsx b/frontend/src/pages/Signin.jsx index 7b3ed76..425b9be 100644 --- a/frontend/src/pages/Signin.jsx +++ b/frontend/src/pages/Signin.jsx @@ -14,6 +14,7 @@ import toast from 'react-hot-toast'; import { setUserInfo } from '../redux/user'; import { setSkeltonLoader } from '../redux/skelton'; import baseAddress from "../utils/localhost"; +import { getUserData } from '../App'; @@ -34,21 +35,7 @@ const Signin = () => { const passref = useRef(); - const getUserData=async(email)=>{ - // dispatch(loading()) - dispatch(setSkeltonLoader()) - - try { - const res= await axios.get(`${baseAddress}u/${email}`, {withCredentials:true}); - if(res.status==200){ - dispatch(setUserInfo(res.data.user)); - } - } catch (error) { - console.log(error); - } - // dispatch(loading()) - dispatch(setSkeltonLoader()) - } + const sendRequest = async () => { @@ -60,17 +47,20 @@ const Signin = () => { if (res.status == 202) { toast.dismiss() Navigate("/") - await getUserData(res.data); + await getUserData({email:res.data, dispatch}); toast.dismiss() - toast.success("Logged In successfully !") + toast.success("Logged In succesfully!") dispatch(login()) } } else { const res = await axios.post(`${baseAddress}auth/signin`, { username: form.user, password: form.password }); + console.log(res); + if (res.status == 202) { + toast.dismiss() + await getUserData({email:res.data, dispatch}); Navigate("/") - await getUserData(res.data); toast.dismiss() toast.success("Logged In succesfully!") dispatch(login()) @@ -162,3 +152,6 @@ const Signin = () => { } export default Signin + + + diff --git a/frontend/src/pages/Signup.jsx b/frontend/src/pages/Signup.jsx index 3dba8bc..fc1cab2 100644 --- a/frontend/src/pages/Signup.jsx +++ b/frontend/src/pages/Signup.jsx @@ -14,6 +14,10 @@ import toast from 'react-hot-toast'; import { FiRefreshCcw } from "react-icons/fi"; import SmallLoader from '../components/SmallLoader'; import baseAddress from "../utils/localhost"; +import { login } from '../redux/login'; +import { getUserData } from '../App'; +import { show } from '../redux/welcome'; + @@ -37,8 +41,45 @@ const Signup = () => { const [eye, setEye] = useState(false) const [usrnmList, setUsrnmList] = useState([]); const passref = useRef(); + const [isLoading, setisLoading] = useState(false) + const [loading, setLoading] = useState(false) + + + const usernameRef = useRef(null); + + const handleClick = () => { + generateUsername(); + } + + const generateUsername = async () => { + setisLoading(true); + try { + const res = await axios.get(`${baseAddress}auth/generateusername`); + + setUsrnmList(res.data.usernames); + + } catch (error) { + + } + setisLoading(false) + } + + const handleSelect = (username) => { + usernameRef.current.value = username; + setForm({ ...form, username: username }); + + } + + + + useEffect(() => { + generateUsername(); + }, []) + + + + - useEffect(() => { let timer; if (timeLeft > 0) { @@ -55,7 +96,7 @@ const Signup = () => { setErrorPass(null) setOnSave(true) setForm({ ...form, [e.target.name]: e.target.value }); - + } const handleOtp = async (e) => { @@ -65,15 +106,19 @@ const Signup = () => { } const sendOtp = async () => { + setLoading(true) try { + toast.loading("Sending OTP") const res = await axios.post(`${baseAddress}auth/signup`, form); if (res.status == 202) { + toast.dismiss(); setVarifyOtpData({ ...varifyOtpData, userID: res.data.userID, email: res.data.email }); toast.success("Your OTP is on its way !"); setOtpsent(true); } } catch (error) { + toast.dismiss() if (error.response.status == 500) { toast.error("Some error occured! Try Again.") } else if (error.response.status == 400) { @@ -81,12 +126,13 @@ const Signup = () => { } console.log(error) } + setLoading(false) } const handleSubmit = async (e) => { e.preventDefault(); - + if ((form.username.length < 3)) { setOnSave(false) setErrorUsername("* username must contain more than 3 characters"); @@ -100,9 +146,8 @@ const Signup = () => { setErrorPass('* Password must include a-z,A-Z,0-9,symbols and min-length of 8') } else { - dispatch(loading()); + await sendOtp(); - dispatch(loading()); setdisable(true); setTimeLeft(60) @@ -138,14 +183,19 @@ const Signup = () => { } const varifyOtp = async () => { - dispatch(loading()) + setLoading(true) try { const res = await axios.post(`${baseAddress}auth/varifyotp`, varifyOtpData); + console.log(res); + if (res.status == 202) { - toast.success("Sign Up Successful!"); - Navigate("/signin"); + Navigate("/") + dispatch(show()) + await getUserData({ email: res.data, dispatch }); + toast.dismiss() + dispatch(login()) } } catch (error) { console.log(error); @@ -162,7 +212,7 @@ const Signup = () => { } - dispatch(loading()) + setLoading(false) } @@ -206,117 +256,81 @@ const Signup = () => { - - return ( - - ) -} -export default Signup - + return ( + <> +
+
-export const Layout = ({ form,setForm, passref, eye, handleChange, handleCloseEye, handleEye, handleSubmit, errorUsername, errorEmail, errorPass, onSave, otp, otpsent, resendOTP, handleOtp,usrnmList, setUsrnmList, varifyOtp, errorOtp, timeLeft, disable }) =>{ +
{ handleSubmit(e) }}> - const [isLoading, setisLoading] = useState(false); - const usernameRef= useRef(null); - const handleClick = ()=>{ - generateUsername(); - } - - const generateUsername = async()=>{ - setisLoading(true); - try { - const res = await axios.get(`${baseAddress}auth/generateusername`); - - setUsrnmList(res.data.usernames); - - } catch (error) { - - } - setisLoading(false) - } + {otpsent ? <>
+ + { handleOtp(e) }} type='text' name="otp" id="otp" placeholder='Enter OTP' /> +
{errorOtp}
+
+
+ +
- const handleSelect=(username)=>{ - usernameRef.current.value= username; - setForm({...form, username:username}); - - } - + : <>
- useEffect(() => { - generateUsername(); - }, []) +
+ + { handleChange(e) }} type="text" name="username" id="username" placeholder='Enter Username' readOnly /> +
{errorUsername}
-return ( - <> -
-
+
- { handleSubmit(e) }}> +
+ {Array.from(usrnmList).map(username => <> +
handleSelect(username)} className=' rounded-xl px-2 cursor-pointer bg-[#b1b390] text-gray-900'>{username}
+ + )} +
{isLoading ? : handleClick()} className=' font-semibold text-xl' />}
+
- {otpsent ? <>
- - { handleOtp(e) }} type='text' name="otp" id="otp" placeholder='Enter OTP' /> -
{errorOtp}
-
-
{ varifyOtp() }} className=' rounded-full bg-black text-white px-4 py-2 hover:bg-gray-800' >Varify OTP
- -
- : <>
-
- - { handleChange(e) }} type="text" name="username" id="username" placeholder='Enter Username' readOnly/> -
{errorUsername}
- +
+ + { handleChange(e) }} type="email" name="email" id="email" placeholder='Enter Email' /> +
{errorEmail}
+
+
+ + { handleChange(e) }} placeholder='Enter Password' type="password" name="password" id="password" /> +
{errorPass}
+ handleEye()} onMouseUp={() => handleCloseEye()} className=' cursor-pointer absolute right-2 top-[50%] translate-y-[-50%] '>{!eye ? : } +
+
+ {onSave ? : } +
Already an user? Sign In
-
- {Array.from(usrnmList).map(username=><> -
handleSelect(username)} className=' rounded-xl px-2 cursor-pointer bg-[#b1b390] text-gray-900'>{username}
- - )} -
{isLoading?:handleClick()} className=' font-semibold text-xl'/>}
-
+
} - + +
+
+ -
- - { handleChange(e) }} type="email" name="email" id="email" placeholder='Enter Email' /> -
{errorEmail}
-
-
- - { handleChange(e) }} placeholder='Enter Password' type="password" name="password" id="password" /> -
{errorPass}
- handleEye()} onMouseUp={() => handleCloseEye()} className=' cursor-pointer absolute right-2 top-[50%] translate-y-[-50%] '>{!eye ? : } -
-
-
- {onSave ? : } -
Already an user? Sign In
-
} + ) +} +export default Signup - -
-
- -) -} diff --git a/frontend/src/redux/store.js b/frontend/src/redux/store.js index 73b67f3..3ecda23 100644 --- a/frontend/src/redux/store.js +++ b/frontend/src/redux/store.js @@ -15,6 +15,7 @@ import roomReducer from './roomSlice' import userRoomsReducer from './userRooms' import PageReducer from './Page' import { roomsApi } from '../pages/RoomApis' +import welcomeStateReducer from './welcome' export const store = configureStore({ reducer: { @@ -33,6 +34,7 @@ export const store = configureStore({ room:roomReducer, rooms:userRoomsReducer, page:PageReducer, + welcome: welcomeStateReducer, roomsApi:roomsApi.reducer }, diff --git a/frontend/src/redux/welcome.js b/frontend/src/redux/welcome.js new file mode 100644 index 0000000..ae06aa7 --- /dev/null +++ b/frontend/src/redux/welcome.js @@ -0,0 +1,22 @@ +import { createSlice } from '@reduxjs/toolkit' + +const initialState = { + value: false, +} + +export const welcomeState = createSlice({ + name: 'welcome', + initialState, + reducers: { + show: (state) => { + state.value = true; + }, + hide: (state) => { + state.value = false; + }, + }, +}) + +export const { show, hide} = welcomeState.actions + +export default welcomeState.reducer \ No newline at end of file diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index ddb2dc3..b844f3c 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -30,12 +30,21 @@ export const theme = { '0%, 100%': { boxShadow: '0 0 5px #f9ff86, 0 0 10px #f9ff86, 0 0 20px #f9ff86' }, '50%': { boxShadow: '0 0 15px #f9ff86, 0 0 20px #f9ff86, 0 0 30px #f9ff86' }, }, + slideInFromBehind: { + '0%': { transform: 'scale(0.5) translateZ(-200px)', opacity: '0' }, + '100%': { transform: 'scale(1) translateZ(0)', opacity: '1' }, + }, }, transitionDuration: { '400': '400ms', // 2 seconds }, animation: { glow: 'glow 2s infinite', + slideInFromBehind: 'slideInFromBehind 0.8s ease-out forwards', + }, + fontFamily: { + roboto: ["Roboto", 'sans-serif'], + ubuntu:["Ubuntu", "sans-serif"] }, }, // colors:{