Skip to content

Commit 4a31bcd

Browse files
add profile details
1 parent 8ed052d commit 4a31bcd

File tree

22 files changed

+329
-28
lines changed

22 files changed

+329
-28
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { useState } from "react";
2+
import { useSelector } from "react-redux";
3+
import Input from "./Input";
4+
import SavePersonalInformation from "./SavePersonalInformation";
5+
6+
const data = [
7+
{ placeholder: "governate", value: "governate" },
8+
{ placeholder: "university", value: "university" },
9+
{ placeholder: "faculty", value: "faculty" },
10+
{ placeholder: "birthDate", value: "birthDate",type:'date'},
11+
{ placeholder: "emailProfile", value: "emailProfile", type:'emai' },
12+
{ placeholder: "phoneNumber", value: "phoneNumber" },
13+
{ placeholder: "projects", value: "projects" },
14+
{ placeholder: "progLanguages", value: "progLanguages" },
15+
{ placeholder: "cvUrl", value: "cvUrl" },
16+
{ placeholder: "githubUrl", value: "githubUrl" },
17+
{ placeholder: "linkedinUrl", value: "linkedinUrl" },
18+
{ placeholder: "behanceUrl", value: "behanceUrl" },
19+
{ placeholder: "twitterUrl", value: "twitterUrl" },
20+
{ placeholder: "facebookUrl", value: "facebookUrl" }
21+
];
22+
23+
const initialFormData = {
24+
governate: '',
25+
university: '',
26+
faculty: '',
27+
birthDate: '',
28+
emailProfile: '',
29+
phoneNumber: '',
30+
projects: '',
31+
progLanguages: '',
32+
cvUrl: '',
33+
githubUrl: '',
34+
linkedinUrl: '',
35+
behanceUrl: '',
36+
twitterUrl: '',
37+
facebookUrl: '',
38+
};
39+
40+
function EditPersonalInformation() {
41+
const [formData,setFormData]=useState(initialFormData)
42+
const user=useSelector(state=>state.auth).user
43+
if(user)
44+
return (
45+
<form className="flex flex-col w-full items-center overflow-y-auto pt-20">
46+
{data.map(input=><Input value={input.value} type={input.type} key={input.placeholder} formData={formData} setFormData={setFormData}
47+
placeholder={input.placeholder}/>)}
48+
<SavePersonalInformation userId={user.id} formData={formData} />
49+
</form>
50+
)
51+
}
52+
53+
export default EditPersonalInformation
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/* eslint-disable react/prop-types */
2+
function Input({placeholder,value,setFormData,formData,type}) {
3+
const changeHandler =(e)=>{
4+
setFormData({...formData,[value]:e.target.value})
5+
}
6+
console.log(type)
7+
8+
return (
9+
<input type={!type?'text':type} lang="en" placeholder={placeholder} onChange={changeHandler} value={formData[value]} className={`w-[350px] max-w-full pl-8 rounded-2xl mb-5
10+
shadow-[0px_6px_20px_0px_rgba(218,_218,_218,_0.3)] outline-none py-5 transition-all duration-300 bg-white text-sm h-[60px] `}/>
11+
)
12+
}
13+
14+
export default Input
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/* eslint-disable react/prop-types */
2+
import useFetch from "../../../CustomHooks/useFetch"
3+
import { postOptions } from "../../../options"
4+
import ReactLoading from 'react-loading';
5+
6+
function SavePersonalInformation({userId,formData}) {
7+
const {fetchApi:editPersonalInformation,loading}=useFetch(`http://localhost:8000/api/profile/edit-info/${userId}`,postOptions)
8+
const saveHandler=async(e)=>{
9+
console.log(formData)
10+
const formatData = new FormData();
11+
for (const key in formData) {
12+
console.log(key,formData[key])
13+
formatData.append(`${key}`, formData[key]);
14+
}
15+
const res=await editPersonalInformation(formatData)
16+
console.log(res)
17+
18+
}
19+
return (<>
20+
{!loading?
21+
<button className="btn w-fit px-20 py-4 text-lg font-medium mx-auto mt-8" onClick={saveHandler}>Save</button>:
22+
<div className="element-center center-element mx-auto w-[60px]"> <ReactLoading
23+
className="mx-auto"
24+
type="spin"
25+
color="#D9C6A4"
26+
height={40}
27+
width={40}
28+
/></div>
29+
30+
}
31+
</>
32+
)
33+
}
34+
35+
export default SavePersonalInformation

src/Components/Profile/EditProfile/SaveEditForm.jsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { postOptions } from "../../../options"
66
import ReactLoading from 'react-loading';
77
import { useDispatch } from "react-redux";
88
import { editUser } from "../../../store/user/userSlice";
9-
import { imgLink } from "../../../api";
109

1110
function SaveEditForm({data,user}) {
1211
const {fetchApi:saveProfileForm,loading}=useFetch(`http://localhost:8000/api/profile/edit-profile/${user.id}`,postOptions)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { useSelector } from "react-redux"
2+
3+
const id=JSON.parse(localStorage.getItem('user')).id
4+
function InviteTeams() {
5+
const
6+
return (
7+
<div>InviteTeams</div>
8+
)
9+
}
10+
11+
export default InviteTeams
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/* eslint-disable react/prop-types */
2+
3+
function About({user}) {
4+
return (
5+
<div className="bg-white pt-4 w-full">
6+
<span className="border-t-[rgba(251,249,247,1)] border-t-[11px] absolute left-0 w-full"></span>
7+
<h4 className="text-base pt-5 font-semibold">About</h4>
8+
<p className="pt-3 text-base">{user.bio?user.bio:'no bio'}</p>
9+
</div>
10+
11+
12+
)
13+
}
14+
15+
export default About
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/* eslint-disable react/prop-types */
2+
import GitHubIcon from '../../../assets/images/profile/contacts/github.svg';
3+
import BehanceIcon from '../../../assets/images/profile/contacts/behance.svg';
4+
import LinkedinIcon from '../../../assets/images/profile/contacts/linkedin.svg';
5+
import TwitterIcon from '../../../assets/images/profile/contacts/twitter.svg';
6+
import FacebookIcon from '../../../assets/images/profile/contacts/facebook.svg';
7+
8+
function Contacts({ githubUrl, linkedinUrl, behanceUrl, facebookUrl, twitterUrl }) {
9+
const contactLinks = [
10+
{ name: 'GitHub', url: githubUrl, icon: GitHubIcon },
11+
{ name: 'LinkedIn', url: linkedinUrl, icon: LinkedinIcon },
12+
{ name: 'Behance', url: behanceUrl, icon: BehanceIcon },
13+
{ name: 'Facebook', url: facebookUrl, icon: FacebookIcon },
14+
{ name: 'Twitter', url: twitterUrl, icon: TwitterIcon },
15+
].filter(item => item.url.length > 6);
16+
17+
return (
18+
<div className='pt-4'>
19+
<span className="border-t-[rgba(251,249,247,1)] border-t-[11px] absolute left-0 w-full"></span>
20+
<h2 className='pt-5'>Contacts</h2>
21+
<ul className='flex gap-3 mt-3'>
22+
{contactLinks.map((link, index) => (
23+
<li key={index}>
24+
<a href={link.url} target="_blank" rel="noopener noreferrer"><img src={link.icon} /></a>
25+
</li>
26+
))}
27+
</ul>
28+
</div>
29+
);
30+
}
31+
32+
export default Contacts;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/* eslint-disable react/prop-types */
2+
3+
function Follower({userImg,userName}) {
4+
return (
5+
<div className="bg-white w-14 text-center">
6+
<img src={userImg} alt='follower image' className="w-14 h-14 m-0 !mr-0"/>
7+
<h6 className="text-[6px]">{userName}</h6>
8+
9+
</div>
10+
)
11+
}
12+
13+
export default Follower
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { useState } from "react"
2+
import { useEffect } from "react"
3+
import { getFriendsFakeData } from "../../../../Functions/getFriendsFakeData"
4+
import Follower from "./Follower"
5+
6+
export default function Followers() {
7+
const [followers,setFollowers]=useState([])
8+
useEffect(()=>{
9+
const generatedFollowers=getFriendsFakeData(6)
10+
setFollowers(generatedFollowers)
11+
},[])
12+
return (
13+
<div className="bg-white pt-4 w-full">
14+
<span className="border-t-[rgba(251,249,247,1)] border-t-[11px] absolute left-0 w-full"></span>
15+
<div className="flex justify-between pt-5">
16+
<h4 className="text-base font-semibold">Followers</h4>
17+
<button className="font-bold text-[rgba(140,122,88,1)] text-[16px]">View All</button>
18+
</div>
19+
<div className="flex justify-between pt-5">
20+
{followers.map(follower=><Follower userName={follower.userName} userImg={follower.userImg} key={follower.id}/>)}
21+
</div>
22+
</div>
23+
)
24+
}
Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,33 @@
1+
/* eslint-disable react/prop-types */
12
import inviteIcon from '../../../../assets/images/profile/add-friend 1.svg'
23
import editPersonalInformation from '../../../../assets/images/profile/writing-notepad-svgrepo-com 1.svg'
34
import ProfileOptions from './ProfileOptions'
45
import ProfileNumbers from './ProfileNumbers'
6+
import {Link} from 'react-router-dom'
7+
import Followers from '../Followers/Followers'
8+
import About from '../About'
9+
import Posts from '../ProfilePosts'
10+
import Contacts from '../Contacts'
511

6-
function ProfileHeadeDetails() {
12+
function ProfileHeaderDetails({user}) {
13+
714
return (
815
<>
9-
<div className='bg-white shadow-[0px_6px_20px_0px_rgba(218,218,218,0.3)] h-96 -top-[90px] w-[488px]
16+
<div className='bg-white shadow-[0px_6px_20px_0px_rgba(218,218,218,0.3)] -top-[90px] w-[488px]
1017
rounded-2xl relative px-5 py-5'>
1118
<div className='flex justify-between items-start w-full'>
12-
<button><img src={inviteIcon}/></button>
13-
<button><img src={editPersonalInformation}/></button>
19+
<Link to='/profile/invite'><button><img src={inviteIcon}/></button></Link>
20+
<Link to='/profile/edit/personalinformation'><button><img src={editPersonalInformation}/></button></Link>
1421
</div>
1522
<div className='pt-16'>
16-
<h3 className='font-bold text-center text-lg pb-[6px]'>Emilia William</h3>
17-
<p className='text-[rgba(184,184,184,1)] text-center text-sm mb-4'>UI/UX designer</p>
23+
<h3 className='font-bold text-center text-lg pb-[6px]'>{user.name}</h3>
24+
<p className='text-[rgba(184,184,184,1)] text-center text-sm mb-4'>{user.track?user.track:null}</p>
1825
<ProfileOptions/>
19-
<ProfileNumbers/>
26+
<ProfileNumbers/>
27+
<Contacts {...user}/>
28+
<About user={user}/>
29+
<Followers/>
30+
<Posts user={user}/>
2031
</div>
2132

2233

@@ -27,4 +38,4 @@ function ProfileHeadeDetails() {
2738
)
2839
}
2940

30-
export default ProfileHeadeDetails
41+
export default ProfileHeaderDetails

src/Components/Profile/UserProfile/ProfileHeader/ProfileHeader.jsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1+
/* eslint-disable react/prop-types */
12
import headerbg from '../../../../assets/images/profile/Vector 1.svg'
2-
import profileImg from '../../../../assets/images/profile/Ellipse 30.svg'
3-
import ProfileHeadeDetails from './ProfileHeadeDetails'
3+
import profileImg from '../../../../assets/images/profile/no-profile-picture.svg'
4+
import { imgLink } from '../../../../api'
45

5-
function ProfileHeader() {
6+
function ProfileHeader({user}) {
7+
if(user)
68
return (
79
<>
8-
<div className='relative w-[488px] '>
10+
<div className='relative w-[488px] '>
911
<img src={headerbg} alt='header' className='w-full'/>
10-
<img src={profileImg} alt='profile image' className='absolute bottom-0 z-10 left-1/2 -translate-x-1/2' />
12+
<img src={user.imageUrl?`${imgLink}/${user.imageUrl}`:profileImg} alt='profile image' className=' border-4 border-white shadow-md absolute bottom-0 z-10 left-1/2 -translate-x-1/2 w-[180px] h-[180px] rounded-full' />
1113

1214
</div>
13-
<ProfileHeadeDetails/>
1415

1516
</>
1617
)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* eslint-disable react/prop-types */
2+
import { useSelector } from "react-redux"
3+
import { imgLink } from "../../../api";
4+
5+
function Posts({user}) {
6+
const posts=useSelector(state=>state.posts).posts;
7+
const userPosts=posts?posts.filter(post=>post.user_id==user.id):[]
8+
9+
10+
return (
11+
<div className="bg-white pt-4 w-full">
12+
<span className="border-t-[rgba(251,249,247,1)] border-t-[11px] absolute left-0 w-full"></span>
13+
<h4 className="text-base font-semibold pt-5">Posts</h4>
14+
{ userPosts.length?
15+
userPosts.map((post)=><img className="w-[86px] h-[78px]" key={post.id} src={`${imgLink}/${post.image_path}`}/>):
16+
<p className="py-2 text-base font-medium">No Posts</p>
17+
}
18+
</div>
19+
)
20+
}
21+
22+
export default Posts

src/Components/Profile/UserProfile/UserProfile.jsx

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,35 @@
1+
import { api } from "../../../api"
2+
import { getOptions } from "../../../options"
3+
import ProfileHeaderDetails from "./ProfileHeader/ProfileHeadeDetails"
14
import ProfileHeader from "./ProfileHeader/ProfileHeader"
2-
5+
import {useSelector} from 'react-redux'
6+
import { useEffect } from "react"
7+
import { useState } from "react"
8+
import useFetch from "../../../CustomHooks/useFetch"
9+
const id=JSON.parse(localStorage.getItem('user')).id
310
function UserProfile() {
11+
const user=useSelector(state=>state.auth.user)
12+
console.log(id)
13+
const {fetchApi:getUser}=useFetch(`${api}/users/show/${id}`,getOptions,true)
14+
const [currentUser,setCurrentUser]=useState(null)
15+
useEffect(()=>{
16+
const fetchData=async()=>{
17+
const res=await getUser()
18+
if(res.ok){
19+
setCurrentUser(res.data.user)
20+
21+
}
22+
}
23+
if(user){
24+
fetchData()
25+
}
26+
27+
},[user])
28+
if(currentUser)
429
return (
5-
<div className="w-1/3">
6-
<ProfileHeader/>
30+
<div className="w-1/3 h-[calc(100vh_-_99px)] overflow-y-auto custom-scrollbar w-[496px]">
31+
<ProfileHeader user={currentUser}/>
32+
<ProfileHeaderDetails user={currentUser}/>
733
</div>
834
)
935
}

src/Components/Teams/CreateTeamForm/CreateTeamInput.jsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { useState } from "react"
21

32
function CreateTeamInput({placeholder,value,setTeamForm,teamForm}) {
43
const changeHandler =(e)=>{

src/Pages/Profile/Profile.jsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,20 @@ import RequireAuth from '../../Protected/RequireAuth'
33
import {Outlet} from 'react-router-dom'
44
import { useDispatch } from 'react-redux'
55
import { logOut } from '../../store/user/logOutAction'
6+
import { useEffect } from 'react'
7+
import { fetchPosts } from '../../store/posts/fetchPosts'
68
function Profile() {
79
const dispatch=useDispatch()
10+
useEffect(()=>{
11+
dispatch(fetchPosts())
12+
},[])
813

914
return (
1015
<RequireAuth>
11-
<div className='flex'>
16+
<div className='flex h-[calc(100vh_-_99px)]'>
1217
<ProfileSideBar></ProfileSideBar>
1318
<Outlet/>
14-
<button onClick={()=>dispatch(logOut())}>logoout</button>
19+
{/* <button onClick={()=>dispatch(logOut())}>logoout</button> */}
1520

1621
</div>
1722
</RequireAuth>
Lines changed: 11 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)