Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat share profile #160

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion backend/controllers/userController.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,21 @@ exports.UploadPhoto=catchAsync(async(req,res,next)=>{
// exports.AvailableUsersToCreateGroup=catchAsync(async(req,res)=>{


// })
// })

exports.getUserById=catchAsync(async(req,res)=>{

try {
const users = await User.findById(req.params.id);
if (!users) {
return res.status(404).json({ message: 'Item not found' });
}
res.status(200).json({
status:'success',
users
})
} catch (err) {
console.error(err);
res.status(500).json({ message: 'Server error' });
}
})
2 changes: 1 addition & 1 deletion backend/routes/userRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ router.post('/login',authController.login);
router.post('/ispresent',authController.isUserPresent)
router.post('/protect',authController.protect,authController.send);
router.post('/uploadPhoto',authController.protect,userController.uploadUserPhoto,userController.UploadPhoto)

router.get('/:id',authController.protect,userController.getUserById)

module.exports=router;
5 changes: 5 additions & 0 deletions frontend/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import Settings from './pages/Settings';

import Root,{loader as loadingAction} from './pages/Root';
import Search from './pages/Search';
import Profile from './pages/Profile';


const router = createBrowserRouter([
Expand Down Expand Up @@ -54,6 +55,10 @@ const router = createBrowserRouter([
{
path:"search",
element:<Search></Search>
},
{
path:":id",
element:<Profile></Profile>
}
]

Expand Down
67 changes: 67 additions & 0 deletions frontend/src/components/SettingsComponents/ShareProfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React, { useState } from "react";
import ShareIcon from "@mui/icons-material/Share";
import CloseIcon from "@mui/icons-material/Close";
import { Modal } from "@mui/material";
import { useLocation } from "react-router-dom";
import ContentCopyIcon from "@mui/icons-material/ContentCopy";
import { toast } from "react-toastify";

export default function ShareProfile({ id }) {
const [showModal, setShowModal] = useState(false);
const location = useLocation();

const copyToClipboard = async () => {
console.log(window.location.origin);
toast.info("Copied!", {
position: "top-center",
autoClose: 2500,
hideProgressBar: false,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
progress: undefined,
});
return await window.navigator.clipboard.writeText(
`${window.location.origin}/home/${id}`
);
};

return (
<>
<button
onClick={() => setShowModal(true)}
className="flex sm:gap-2 text-sm sm:text-xl font-medium items-center justify-center bg-[#202142] hover:bg-[#202162] text-white cursor-pointer border-[#000000] px-4 py-2 max-[1024px]:px-2 max-[1024px]:py-1 rounded-md font-Roboto tracking-tight"
>
<ShareIcon fontSize="small" />
<p className="hidden sm:inline text-lg">Share Profile</p>
</button>

<Modal
open={showModal}
onClose={() => setShowModal(false)}
className="flex items-center justify-center"
>
<div className="flex gap-4 flex-col p-5 rounded-xl text-white items-center bg-[#202142] justify-start">
<div className="flex items-center justify-between w-full">
<h1 className="text-lg sm:text-xl">Share Profile</h1>
<button onClick={() => setShowModal(false)} className="">
<CloseIcon />
</button>
</div>
<div className="flex w-full items-center justify-start gap-4">
<div className="border hidden sm:inline text-gray-400 border-gray-500 bg-[#16173485] p-4 rounded-lg">
<h1>{`${window.location.origin}/home/${id}`}</h1>
</div>
<button
className="flex gap-4 border border-gray-500 p-2 rounded-lg sm:rounded-none sm:p-0 sm:border-none"
onClick={() => copyToClipboard()}
>
<p className="sm:hidden">Click to copy!</p>
<ContentCopyIcon />
</button>
</div>
</div>
</Modal>
</>
);
}
74 changes: 74 additions & 0 deletions frontend/src/pages/Profile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React, { useEffect, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import LoadingPage from "./LoadingPage";
import { Avatar } from "@mui/material";
import SendIcon from "@mui/icons-material/Send";
import { useDispatch, useSelector } from "react-redux";
import { AddUser } from "../services/Actions/Chat/action";

export default function Profile() {
const { id } = useParams();
const [userData, setUserData] = useState(null);
const dispatch=useDispatch();
const state=useSelector((state)=>state.chat.AllChats);
const navigate = useNavigate()

useEffect(() => {
const getData = async () => {
const cookie = localStorage.getItem("jwt");
const response = await fetch(
`${process.env.REACT_APP_API_URL}/api/v1/users/${id}`,
{
headers: {
"Content-type": "application/json",
Authorization: `Bearer ${cookie}`,
},
}
);
const data = await response.json();

setUserData(data.users);
};
getData();
}, [id]);

const accessChatHandler = (values) => {
const isPresent = state.find((data) => {
return data.email === values.email;
});
dispatch(AddUser(values, state));
setTimeout(() => {
navigate("/home/message", { replace: true });
}, 2000);
};

if (userData === null) return <LoadingPage></LoadingPage>;

return (
<div className="flex w-full flex-col items-center justify-start">
<div className="flex sm:gap-8 text-center flex-col sm:pt-10">
<Avatar
referrerPolicy="no-referrer"
alt="User-pic"
sx={{ width: 150, height: 150 }}
src={userData.pic}
/>
<h1 className="text-lg sm:text-xl font-semibold">{userData.name}</h1>
</div>
<div className="flex flex-col items-start justify-start p-5">
<div className="flex gap-1">
<p>Email :</p>
<h1 className=" font-medium">{userData.email}</h1>
</div>
<div className="flex gap-1">
<p>Gender :</p>
<h1 className=" font-medium">{userData.gender}</h1>
</div>
</div>
<button onClick={()=>accessChatHandler(userData)} className="bg-[#202142] flex items-center justify-center gap-2 p-2 px-4 text-white rounded-lg">
<p>Start Messaging</p>
<SendIcon className="-rotate-45 animate-pulse w-4" />
</button>
</div>
);
}
3 changes: 2 additions & 1 deletion frontend/src/pages/Search.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ export default function Search() {
}

const searchHandler=async(value)=>{

SetisLoading(true);
const cookie=localStorage.getItem('jwt');
const response=await fetch(`${process.env.REACT_APP_API_URL}/api/v1/users?search=${value}`,{
Expand All @@ -72,6 +71,8 @@ export default function Search() {

const accessChatHandler=(values)=>{

console.log(values)

const isPresent=state.find((data)=>{
return data.email===values.email
});
Expand Down
31 changes: 15 additions & 16 deletions frontend/src/pages/Settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,18 @@ import React from "react";
import Profile from "../components/SettingsComponents/Profile";
import InputName from "../components/SettingsComponents/InputName";
import InputEmail from "../components/SettingsComponents/InputEmail";
import { useState,useEffect} from "react";
import {setUser} from '../services/Actions/User/actions'
import { useDispatch } from 'react-redux';
import { useState, useEffect } from "react";
import { setUser } from "../services/Actions/User/actions";
import { useDispatch } from "react-redux";
import { ToastContainer, toast } from "react-toastify";
import InfoIcon from '@mui/icons-material/Info';
import InfoIcon from "@mui/icons-material/Info";
import ShareProfile from "../components/SettingsComponents/ShareProfile";

export default function Settings() {

const dispatch=useDispatch();
const dispatch = useDispatch();
const storedData = JSON.parse(localStorage.getItem("info"));
const [name, setName] = useState(storedData.name);
const [email, setEmail] = useState(storedData.email);

const resetData = () => {
setName(storedData.name);
setEmail(storedData.email);
Expand Down Expand Up @@ -63,13 +62,10 @@ export default function Settings() {
}
);
const data = await response.json();
if (data.status === "success")
{
if (data.status === "success") {
notify("success");
dispatch(setUser(data.updatedUser));
}

else notify("error");
} else notify("error");
};
updateData();
};
Expand All @@ -80,12 +76,15 @@ export default function Settings() {
<div className="border-[1px] border-[#f5f5f5]">
<ToastContainer></ToastContainer>
<div className="px-[5%] py-[2%]">
<div className="font-Poppins max-[1024px]:text-xl font-semibold text-2xl">
Public profile
<div className="flex relative items-center justify-between font-Poppins max-[1024px]:text-xl font-semibold text-2xl">
<h1>Public profile</h1>
<ShareProfile id={storedData._id} />
</div>
<div className="flex items-center mt-2">
<InfoIcon fontSize='10' color="info"></InfoIcon>
<div className="font-Poppins text-xs">To update your profile picture, select an image and upload it.</div>
<InfoIcon fontSize="10" color="info"></InfoIcon>
<div className="font-Poppins text-xs">
To update your profile picture, select an image and upload it.
</div>
</div>
<Profile></Profile>
<div className="mt-[3%] flex flex-col gap-8">
Expand Down