Merge remote-tracking branch 'origin/master'
continuous-integration/drone/push Build encountered an error Details

# Conflicts:
#	Site Web/client/src/components/AjoutLien.js
#	Site Web/client/src/components/Post/NouveauDisplayPosts.js
#	Site Web/client/src/pages/Profil.js
#	Site Web/client/src/pages/Trends.js
master
Bastien OLLIER 3 years ago
commit 02ccfd329b

@ -7,7 +7,22 @@ export const getPosts = (num) => {
return axios
.get(`${process.env.REACT_APP_API_URL}api/post/`)
.then((res) => {
const array = res.data.slice(0, num);
let array = res.data.slice(0, num);
dispatch(setPostData(array));
})
.catch((err) => console.log(err))
}
}
export const getPostsDisc = (num) => {
return (dispatch) => {
return axios
.get(`${process.env.REACT_APP_API_URL}api/post/`)
.then((res) => {
console.log("test");
let array = res.data.sort((a, b) => b.likers.length - a.likers.length);
array = array.slice(0, num);
console.log(array);
dispatch(setPostData(array));
})
.catch((err) => console.log(err))

@ -20,7 +20,7 @@ export const uploadPicture = (data, id) => {
.then((res) => {
return axios
.get(`${process.env.REACT_APP_API_URL}api/user/${id}`)
.then((res) => {
.then((res) => {
dispatch(setUserDataImg(res.data.picture));
})
})

@ -19,7 +19,7 @@ const AjoutLien = () => {
dispatch(getPosts());
cancelPost();
setDisplayAdd(false);
//window.location.reload();
window.location.reload();
}else {
alert("Veuillez compléter tous les champs.")
}

@ -14,7 +14,7 @@ const ConfigurationDuCompte =()=>{
return(
<div>
<h2 className='ligneHorizontal'>Modifucation information du compte</h2>
<h2 className='ligneHorizontal'>Modification des information du compte</h2>
<form className="ModifucationInformationDuCompte">

@ -1,8 +1,10 @@
import React, { useState } from 'react';
import { useSelector } from 'react-redux';
import { useSelector, useDispatch } from 'react-redux';
import PP from "../../assets/img/unknown.png";
import PLUS from "../../assets/img/plus.png";
import { NavLink } from "react-router-dom";
import axios from "axios";
import { uploadPicture } from '../../actions/user.actions';
@ -10,47 +12,81 @@ const ConfigurationDuProfil = ()=>{
const userData = useSelector((state) => state.user.user);
const [pseudo, setPseudo] = useState('');
const [nomUtilisateur, setNomUtilisateur] = useState('');
const [pseudo, setPseudo] = useState(userData.pseudo);
const[userPicture, setUserPicture] = useState(userData.picture)
const [tmpImage, setTmpImage] =useState('')
const [displayAdd, setDisplayAdd] = useState(false);
/*const [updateImage, setUpdateImage]= useState(false);
const setimageDeProfile=()=>{
if(updateImage=true){
useState("");
const dispatch = useDispatch();
const handleValidationPopup =(e)=>{
setUserPicture(tmpImage);
setDisplayAdd(false);
}
else{
setDisplayAdd(false);
}
}*/
var handleLoadFile=(e)=>{
}
const handleLoadFile=(e)=>{
var image = document.getElementById("output");
image.src = URL.createObjectURL(e.target.files[0]);
setTmpImage(image.src);
};
const handleUpdate = async (e) => {
console.log(userPicture)
e.preventDefault();
const data = new FormData();
data.append("pseudo", pseudo);
data.append("userId", userData._id);
data.append("file",userPicture);
dispatch(uploadPicture(data,userData._id));
//const pseudoError = document.querySelector(".pseudo.error");
/* const pictureError =document.querySelector(".picture.error");
await axios({
method: "post",
url: `${process.env.REACT_APP_API_URL}api/user/upload`,
data: {
// pseudo,
userPicture,
}
,
})
.then((res) => {
console.log(res);
if (res.data.errors) {
//pseudoError.innerHTML = res.data.errors.pseudo;
pictureError.innerHTML = res.data.errors.picture;
}
})
.catch((err) => console.log(err));*/
};
var a=PP;
return(
<div className='modificationDuProfilBackgroud'>
<h2 className='ligneHorizontal' >Modifucation du Profil</h2>
<h2 className='ligneHorizontal' >Modification des informations du Profil</h2>
<form action='' onSubmit={handleUpdate} >
<div className='modificationDuProfil' >
<>
<button className='imageDeProfilConfigurationPlus imageDeProfil' >
<img src={PLUS} className="plusButton "/>
<img src={a} className="imageDeProfilConfiguration imageDeProfil" onClick={() => setDisplayAdd(true)}/>
<img src={userPicture} className="imageDeProfilConfiguration imageDeProfil" onClick={() => setDisplayAdd(true)}/>
</button>
<div className='picture error'></div>
</>
<div className='modificationDuProfilText alignementText'>
<span>Pseudo: </span>
<span>Nom d'utilisateur:</span>
</div>
<div>
<div className='modificationDuProfilText'>
<input className='inputConfiguration'
type="nomUtilisateur"
name="nomUtilisateur"
id="nomUtilisateur"
onChange={(e) => setNomUtilisateur (e.target.value)}
value={nomUtilisateur}
/>
<input className='inputConfiguration'
type="pseudo"
name="pseudo"
@ -58,18 +94,20 @@ const ConfigurationDuProfil = ()=>{
value={pseudo}
onChange={(e) => setPseudo (e.target.value)}
/>
{/* <div className='pseudo error'></div>*/}
</div>
<button className='buttonValidationChangements'>Valider</button>
<button type='submit' className='buttonValidationChangements' id='update' value='update' >Valider</button>
</div>
</div>
</form>
<h2 className='ligneHorizontal' >Acces au dossiers personnel</h2>
<div className='accesDossiersPerso'>
<div className='accesDossiersPersoValidation'>
<input type="checkbox" name='cocher' />
<label for="cocher" class='textAccesDossiersPerso'>Cocher si oui</label>
<label for="cocher" className='textAccesDossiersPerso'>Cocher si oui</label>
</div>
</div>
@ -78,27 +116,43 @@ const ConfigurationDuProfil = ()=>{
<div className='popup-modificationProfil'>
<div className="modal">
<div className='imagesPopup'>
<img src={PP} className="imageDeProfilConfigurationPlus imageDeProfil"/>
<div className="imageDeProfilConfigurationPlus imageDeProfil profile-pic" >
<div className='imageModifSpace'>
<img src={userPicture} className=" imageDeProfil "/>
</div>
<div className='profile-pic '>
<label className="-label" for="file">
<span class="camera"></span>
<span className="camera"></span>
<span>Changer</span>
</label>
<input type="file" id="file" onChange={handleLoadFile}/>
<img src={PLUS} id="output" />
<input type="file" id="file" name='file' accept=".jpg, .jpeg, .png" onChange={handleLoadFile}/> {/* onChange={(e)=> setTmpImage(e.target.files[0].name)} */}
<img src={PLUS} className="imageDeProfil"id="output" />
</div>
</div >
<div className='buttonPopup'>
<button onClick={() => setDisplayAdd(false)/*&&setUpdateImage(true)*/}>Retour</button>
<button /*onClick={} */>Valider</button>
<button onClick={()=>setDisplayAdd(false)}>Retour</button>
<button onClick={handleValidationPopup} >Valider</button>
</div>
</div>
</div>
)}
</div>
)
}
export default ConfigurationDuProfil;

@ -6,17 +6,22 @@ const PolitiqueDeConfidentialite =()=>{
return(
<div className='PolitiqueDeConfidentialiteText'>
<p> Cette politique de confidentialité sapplique au site : Designed By GG.
La présente politique de confidentialité a pour but dexposer aux utilisateurs du site :
La manière dont sont collectées et traitées leurs données à caractère
personnel. Doivent être considérées comme données personnelles toutes les données étant susceptibles didentifier un utilisateur. Il sagit notamment du prénom et du nom, de lâge, de ladresse postale, ladresse mail, la localisation de lutilisateur ou encore son adresse IP ;
Quels sont les droits des utilisateurs concernant ces données ;
Qui est responsable du traitement des données à caractère personnes
collectées et traitées ;
A qui ces données sont transmises ;
Eventuellement, la politique du site en matière de fichiers cookies
</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur sodales ligula in libero. Sed dignissim lacinia nunc. </p>
<p>Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem at dolor. Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel nunc egestas porttitor. Morbi lectus risus, iaculis vel, suscipit quis, luctus non, massa. Fusce ac turpis quis ligula lacinia aliquet. Mauris ipsum. Nulla metus metus, ullamcorper vel, tincidunt sed, euismod in, nibh. Quisque volutpat condimentum velit. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. </p>
<p>Nam nec ante. Sed lacinia, urna non tincidunt mattis, tortor neque adipiscing diam, a cursus ipsum ante quis turpis. Nulla facilisi. Ut fringilla. Suspendisse potenti. Nunc feugiat mi a tellus consequat imperdiet. Vestibulum sapien. Proin quam. Etiam ultrices. Suspendisse in justo eu magna luctus suscipit. Sed lectus. Integer euismod lacus luctus magna. Quisque cursus, metus vitae pharetra auctor, sem massa mattis sem, at interdum magna augue eget diam. </p>
<p>Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Morbi lacinia molestie dui. Praesent blandit dolor. Sed non quam. In vel mi sit amet augue congue elementum. Morbi in ipsum sit amet pede facilisis laoreet. Donec lacus nunc, viverra nec, blandit vel, egestas et, augue. Vestibulum tincidunt malesuada tellus. Ut ultrices ultrices enim. Curabitur sit amet mauris. Morbi in dui quis est pulvinar ullamcorper. Nulla facilisi. Integer lacinia sollicitudin massa. Cras metus. </p>
<p>Sed aliquet risus a tortor. Integer id quam. Morbi mi. Quisque nisl felis, venenatis tristique, dignissim in, ultrices sit amet, augue. Proin sodales libero eget ante. Nulla quam. Aenean laoreet. Vestibulum nisi lectus, commodo ac, facilisis ac, ultricies eu, pede. Ut orci risus, accumsan porttitor, cursus quis, aliquet eget, justo. Sed pretium blandit orci. Ut eu diam at pede suscipit sodales. Aenean lectus elit, fermentum non, convallis id, sagittis at, neque. </p>
<p>Nullam mauris orci, aliquet et, iaculis et, viverra vitae, ligula. Nulla ut felis in purus aliquam imperdiet. Maecenas aliquet mollis lectus. Vivamus consectetuer risus et tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum. </p>
<p>Praesent mauris. Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur sodales ligula in libero. Sed dignissim lacinia nunc. Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem at dolor. Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel nunc egestas porttitor. </p>
<p>Morbi lectus risus, iaculis vel, suscipit quis, luctus non, massa. Fusce ac turpis quis ligula lacinia aliquet. Mauris ipsum. Nulla metus metus, ullamcorper vel, tincidunt sed, euismod in, nibh. Quisque volutpat condimentum velit. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nam nec ante. Sed lacinia, urna non tincidunt mattis, tortor neque adipiscing diam, a cursus ipsum ante quis turpis. Nulla facilisi. Ut fringilla. Suspendisse potenti. </p>
</div>
)
}

@ -84,7 +84,7 @@ const Inscription = () => {
id="email"
onChange={(e) => setEmail(e.target.value)}
value={email}/>
<div className='password error'></div>
<div className='email error'></div>
</div>
<br />
<div className="inputbox">

@ -1,6 +1,6 @@
import React, { useContext, useEffect, useState } from 'react';
import { useDispatch } from 'react-redux';
import { deleteComment } from '../../actions/post.actions';
import { deleteComment, editComment } from '../../actions/post.actions';
import { UidContext } from '../AppContext';
@ -14,46 +14,48 @@ const ActionComment = ( { commentaire , postId}) => {
const handleEdit = (e) => {
e.preventDefault();
if(message){
//dispatch();
dispatch(editComment(postId, commentaire._id, message));
setMessage('');
setEdit(false);
}
};
const handleDelete = () => {
//dispatch(deleteComment(postId, commentaire._id))
dispatch(deleteComment(postId, commentaire._id));
};
useEffect(() => {
const verifCreateur = () => {
if(uid === commentaire.commenterId){
if(uid === commentaire.commentId){
setCreateur(true);
}
}
console.log(commentaire);
verifCreateur();
console.log(createur);
}, [uid, commentaire.commenterId]);
return (
<div>
<div className="edit-comment">
{createur && edit === false && (
<span onClick={() => setEdit(!edit)}>
<img src="" alt="editer"/>
<i className='fas fa-edit'></i>
</span>
)}
{createur && edit && (
<form action="" onSubmit={handleEdit}
className="edit-form">
className="edit-comment-form">
<label htmlFor='text' onClick={() => setEdit(!edit)}>Modifier le commentaire</label>
<input type="text" name="text" onChange={(e) => setMessage(e.target.value)} defaultValue={commentaire.text}/>
<div>
<br/>
<div className="btn">
<span onClick={() => {
if(window.confirm("Etes-vous sur de supprimer ce commentaire ?")){
handleDelete();
}
}}>
<img src="" alt="Icon supprimer"/>
<i className="fas fa-trash-alt"></i>
</span>
</div>
<input type="submit" value="Modifier"/>

@ -21,36 +21,68 @@ const Comment = ({ post }) => {
}
};
return (
<div>
{post.comments.map((comment) => {
return (
<div className={comment.commenterId === userData._id ? "comment-friend" : "comment-user"} key={comment._id}>
<img id="PhotoProfile" alt="ppCommentaire" src={
!isEmpty(usersData[0]) &&
usersData.map((user) => {
if (user._id === comment.commenterId) return user.picture;
else return null;
}).join('')
}/>
<p>{comment.commenterPseudo}</p>
{comment.commenterPseudo !== userData._id && (
<FollowHandler idToFollow={comment.commenterId} type={'suggest'}/>)}
<span></span>
{timestampParser(comment.timestamp)}
<p>{comment.text}</p>
<ActionComment commentaire={comment} postId={post._Id} />
return (
<div className="comments-container">
{post.comments.map((comment) => {
return (
<div
className={
comment.commenterId === userData._id
? "comment-container client"
: "comment-container"
}
key={comment._id}
>
<div className="left-part">
<img
src={
!isEmpty(usersData[0]) &&
usersData
.map((user) => {
if (user._id === comment.commenterId) return user.picture;
else return null;
})
.join("")
}
alt="commenter-pic"
/>
</div>
<div className="right-part">
<div className="comment-header">
<div className="pseudo">
<h3>{comment.commenterPseudo}</h3>
{comment.commenterId !== userData._id && (
<FollowHandler
idToFollow={comment.commenterId}
type={"suggest"}
/>
)}
</div>
);
})}
{userData._id && (
<form action="" onSubmit={handleComment} className="form-comment">
<input type="text" name="text" onChange={(e) => setMessage(e.target.value)} value={message} placeholder="Ajoutez un commentaire" />
<input type="submit" value="Partager"/>
</form>
)}
<span>{timestampParser(comment.timestamp)}</span>
</div>
<p>{comment.text}</p>
<ActionComment commentaire={comment} postId={post._id} />
</div>
</div>
);
})}
{userData._id && (
<form action="" onSubmit={handleComment} className="comment-form">
<input
type="text"
name="text"
onChange={(e) => setMessage(e.target.value)}
value={message}
placeholder="Laisser un commentaire"
/>
<br />
<input type="submit" value="Envoyer" />
</form>
)}
</div>
);
);
};
export default Comment;

@ -0,0 +1,32 @@
import { current } from '@reduxjs/toolkit';
import React, { useEffect, useState, useContext } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { getPosts } from '../../../actions/post.actions';
import { isEmpty } from "../../Utils";
import Post from '../PostNouvelleAffichage';
import { UidContext } from '../../AppContext';
const DiplayPostDossier = () => {
const postsData = useSelector((state) => state.post.post);
const uid = useContext(UidContext);
const dispatch = useDispatch();
useEffect(() => {
dispatch(getPosts());
},[dispatch])
return (
<div>
<ul>
{!isEmpty(postsData[0]) &&
postsData.map((post) => {
if(post.postedId === uid){
return <Post post={post} key={post._id}/>
}
})}
</ul>
</div>
);
};
export default DiplayPostDossier;

@ -0,0 +1,33 @@
import { current } from '@reduxjs/toolkit';
import React, { useEffect, useState, useContext } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { getPosts } from '../../../actions/post.actions';
import { isEmpty } from "../../Utils";
import Post from '../PostNouvelleAffichage';
import { UidContext } from '../../AppContext';
const DisplayPostLikeProfil = () => {
const postsData = useSelector((state) => state.post.post);
const uid = useContext(UidContext);
const dispatch = useDispatch();
useEffect(() => {
dispatch(getPosts());
},[dispatch])
return (
<div>
<ul>
{!isEmpty(postsData[0]) &&
postsData.filter(post => post.likers.includes(uid))
.map((post) => {
return <Post post={post} key={post._id}/>
})
}
</ul>
</div>
);
};
export default DisplayPostLikeProfil;

@ -0,0 +1,31 @@
import { current } from '@reduxjs/toolkit';
import React, { useEffect, useState, useContext } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { getPosts } from '../../../actions/post.actions';
import { isEmpty } from "../../Utils";
import Post from '../PostNouvelleAffichage';
import { UidContext } from '../../AppContext';
const NouveauDisplayPosts = () => {
const postsData = useSelector((state) => state.post.post);
const uid = useContext(UidContext);
const dispatch = useDispatch();
useEffect(() => {
dispatch(getPosts());
},[dispatch])
return (
<div>
<ul>
{!isEmpty(postsData[0]) &&
postsData.map((post) => {
if(post.postedId === uid){
return <Post post={post} key={post._id}/>
}
})}
</ul>
</div>
);
};
export default NouveauDisplayPosts;

@ -1,10 +1,10 @@
import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { getPosts } from '../../actions/post.actions';
import { getPosts, getPostsDisc } from '../../actions/post.actions';
import { isEmpty } from "../Utils";
import Post from './Post';
const DisplayPosts = () => {
const DisplayPosts = ( {type} ) => {
const [loadPost, setLoadPost] = useState(true);
const [count , setCount] = useState(5);
const dispatch = useDispatch();
@ -17,8 +17,16 @@ const DisplayPosts = () => {
}
useEffect(() => {
while(postsData== null){
}
if (loadPost) {
dispatch(getPosts(count));
if(type === "discover"){
dispatch(getPostsDisc(count));
}
else{
dispatch(getPosts(count));
}
setLoadPost(false);
setCount(count + 5);
}

@ -1,11 +1,11 @@
import axios from 'axios';
import React, { useEffect, useState } from 'react';
import React, { Component, useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import FollowHandler from '../UserProfil/FollowHandler';
import { dateParser, isEmpty } from '../Utils';
import ButtonLike from './ButtonLike';
import Comment from './Comment';
import Commentaire from '../../assets/img/commentaire.png';
const LinkPreview = ({ link }) => {
const [preview, setPreview] = useState({ image: '', title: '', description: '' });
@ -23,16 +23,19 @@ const LinkPreview = ({ link }) => {
}, [link]);
if(preview.image === "") {
return (<div><a href={link}>{link}</a></div>);
return (<div className='alignementLien'><a className="LienPostHome" href={link}>{link}</a></div>);
}
else {
return (
<div>
<>
<div className='alignementLien'>
<a href={link}>
<img id="imageLien" src={preview.image} alt={preview.title}/>
<img id="imageLien" className="LienPostHome" src={preview.image} alt={preview.title}/>
</a>
<p>{preview.description}</p>
</div>
<p>{preview.description}</p>
</>
);
}
};
@ -48,7 +51,7 @@ const Post = ( { post } ) => {
useEffect(() => {
!isEmpty(usersData[0]) && setIsLoading(false)
!isEmpty(usersData[0]) && !isEmpty(userData) && setIsLoading(false)
})
return (
@ -76,8 +79,8 @@ const Post = ( { post } ) => {
}).join('')
}
</h6>
{/* {post.postedId !== userData._id &&
(<FollowHandler idToFollow={post.postedId} type={'suggest'}/>)} */}
{post.postedId !== userData._id &&
(<FollowHandler idToFollow={post.postedId} type={'suggest'}/>)}
</div>
<div>{dateParser(post.createdAt)}</div>
</div>
@ -94,7 +97,7 @@ const Post = ( { post } ) => {
<div>{post.likers.length}</div>
</div>
<div id="commentaire">
<img src="commentaire.png" onClick={() => setComments(!comments)}/>
<img src={Commentaire} onClick={() => setComments(!comments)}/>
<div>{post.comments.length}</div>
</div>
</div>

@ -40,7 +40,6 @@ const LinkPreview = ({ link }) => {
const PostNouvelleAffichage = ( { post } ) => {
const [isLoading, setIsLoading] = useState(true);
const usersData = useSelector((state) => state.users.users);
const userData = useSelector((state) => state.user.user);
const [updated,setUpdate] = useState(false);
const [message, setMessage] = useState(null);
const [comments, setComments] = useState(false);
@ -51,10 +50,11 @@ const PostNouvelleAffichage = ( { post } ) => {
})
return (
<li className='conteneur_postes' key={post._id}>
<li className='PostesProfilConteneur' key={post._id}>
{isLoading ? (
<i className='fas fa-spinner fa-spin'></i>
):(
<>
<div className="unPosteNouvelleAffichage">
<div className="dateDePublicationDuPost">
<div>{dateParser(post.createdAt)}</div>
@ -71,11 +71,12 @@ const PostNouvelleAffichage = ( { post } ) => {
</div>
<div id="commentaire">
<img src="commentaire.png" onClick={() => setComments(!comments)}/>
<div>{post.comments.length}</div>
<div >{post.comments.length}</div>
</div>
</div>
{comments && <Comment post={post} />}
</div>
{comments && <Comment className="CommentaireProfil" post={post} />}
</>
) }
</li>
);

@ -10,24 +10,26 @@ const FollowHandler = ( { idToFollow , type } ) => {
const [isFollowed, setIsFollowed] = useState(false);
const dispatch = useDispatch();
const handleFollow = () => {
const handleFollow = (e) => {
axios.patch(`${process.env.REACT_APP_API_URL}api/user/follow/` + userData._id, {params: {idToFollow: idToFollow}} )
axios.patch(`${process.env.REACT_APP_API_URL}api/user/follow/` + userData._id, {idToFollow: idToFollow})
.then((res) => {
//dispatch(setUserToFollowData({payload: {idToFollow}}));
})
.catch((err) => console.log(err));
setIsFollowed(false);
setIsFollowed(true);
e.preventDefault();
};
const handleUnFollow = () => {
const handleUnFollow = (e) => {
axios.patch(`${process.env.REACT_APP_API_URL}api/user/unfollow/` + userData._id, {params: {idToFollow: idToFollow}} )
axios.patch(`${process.env.REACT_APP_API_URL}api/user/unfollow/` + userData._id, {idToUnFollow: idToFollow})
.then((res) => {
// dispatch(setUserToUnFollowData({payload: {idToFollow}}));
})
.catch((err) => console.log(err));
setIsFollowed(false);
e.preventDefault();
};

@ -1,4 +1,4 @@
import NouveauDisplayPosts from "../../Post/NouveauDisplayPosts";
import DiplayPostDossier from "../../Post/DisplayPost/DiplayPostDossier";
@ -8,7 +8,7 @@ const DossiersPersonnels=()=>{
return(
<div className='dossierPersonnel'>
pppp
<DiplayPostDossier/>
</div>
)

@ -1,4 +1,4 @@
import NouveauDisplayPosts from "../../Post/NouveauDisplayPosts";
import DisplayPostLikeProfil from "../../Post/DisplayPost/DisplayPostLikeProfil";
@ -10,7 +10,7 @@ const PostLikes=()=>{
return(
<div className='postPersonnel'>
<NouveauDisplayPosts/>
<DisplayPostLikeProfil/>
</div>
)

@ -1,4 +1,4 @@
import NouveauDisplayPosts from "../../Post/NouveauDisplayPosts";
import NouveauDisplayPosts from "../../Post/DisplayPost/NouveauDisplayPosts";
@ -8,8 +8,7 @@ const PostPersonnels=()=>{
return(
<div className='postPersonnel'>
oooo
<NouveauDisplayPosts/>
<NouveauDisplayPosts/>
</div>
)
}

@ -4,76 +4,95 @@ import { isEmpty } from '../Utils';
import FollowHandler from './FollowHandler';
const SuggestFriends = () => {
// const userData = useSelector((state) => state.user.user);
// const usersData = useSelector((state) => state.users.users);
// const [chargement,setChargement] = useState(true);
// const [change, setChange] = useState(true);
// const [friends, setFriends] = useState([]);
const userData = useSelector((state) => state.user.user);
const usersData = useSelector((state) => state.users.users);
const [chargement,setChargement] = useState(true);
const [change, setChange] = useState(true);
const [friends, setFriends] = useState([]);
useEffect(() => {
const stateFriend = () => {
let array = [];
usersData.map((user) => {
if(user._id !== userData._id && user.followers.includes(userData._id)){
return array.push(user._id);
}
})
//mettre dans un ordre aléatoire
array.sort(() => 0.5 - Math.random());
if(window.innerHeight > 780){
array.length = 5;
}
if(window.innerHeight > 720){
array.length = 4;
}
if(window.innerHeight > 660){
array.length = 3;
}
if(window.innerHeight > 600){
array.length = 2;
}
if(window.innerHeight > 540){
array.length = 1;
}else {
array.length = 0;
}
setFriends(array);
}
const stateTopFollowers = () => {
let array = [];
let obj = JSON.parse(JSON.stringify(usersData));
obj.sort((a, b) => b.followers.length - a.followers.length);
obj.map((user) => {
if(user._id !== userData._id && !user.followers.includes(userData._id)){
return array.push(user._id);
}
})
console.log(array);
array = array.splice(0, 5);
setFriends(array);
}
// useEffect(() => {
// const stateFriend = () => {
// let array = [];
// usersData.map((user) => {
// if(user._id !== userData._id && user.followers.includes(userData._id)){
// return array.push(user._id);
// }
// })
// //mettre dans un ordre aléatoire
// array.sort(() => 0.5 - Math.random());
// if(window.innerHeight > 780){
// array.length = 5;
// }
// if(window.innerHeight > 720){
// array.length = 4;
// }
// if(window.innerHeight > 660){
// array.length = 3;
// }
// if(window.innerHeight > 600){
// array.length = 2;
// }
// if(window.innerHeight > 540){
// array.length = 1;
// }else {
// array.length = 0;
// }
// setFriends(array);
// }
if(change && !isEmpty(usersData[0]) && userData!=null){
if(userData.followers.length === 0){
stateTopFollowers();
}else{
stateFriend();
}
setChargement(false);
setChange(false);
}
}, [userData, usersData, change])
// if(change && !isEmpty(usersData[0]) && !isEmpty(userData._id)){
// stateFriend();
// setChargement(false);
// setChange(false);
// }
// }, [userData, usersData, change])
return (
<div className="recoDiv">
<div className="reco">
<span>Vous pourriez suivre</span>
<hr/>
{chargement ? (
<i className='fas fa-spinner fa-pulse'></i>
) : (
<div className="ListReco" >
{friends && friends.map((user) => {
for(let i = 0; i < usersData.length; i++){
if(user === usersData[i]._id){
return (
<div className="UtiReco" key={user}>
<img src={usersData[i].picture} alt="img"/>
<p>{usersData[i].pseudo}</p>
<FollowHandler idToFollow={usersData[i]._id} type={"card"}/>
</div>
);
}
}
})}
// return (
// <div>
// <p>Suggestions</p>
// {chargement ? (
// <i className='fas fa-spinner fa-pulse'></i>
// ) : (
// <ul>
// {friends && friends.map((user) => {
// for(let i = 0; i < usersData.length; i++){
// if(user === usersData[i]._id){
// return (
// <li className='suggest-friend-card' key={user}>
// <img src={usersData[i].picture} alt="img"/>
// <p>{usersData[i].pseudo}</p>
// <FollowHandler idToFollow={usersData[i]._id} type={"card"}/>
// </li>
// );
// }
// }
// })}
// </ul>
// )}
// </div>
//);
</div>
)}
</div>
</div>
);
};
export default SuggestFriends;

@ -9,7 +9,7 @@ const Configuration = () => {
const [ConfigurationCompte, setConfigurationDuCompte] = useState(false);
const [ConfigurationProfil, setConfigurationDuProfil] = useState(true);
const [PolitiqueConfidentialite, setPolitiqueDeConfidentialite] =useState(false)
const [PolitiqueConfidentialite, setPolitiqueDeConfidentialite] =useState(false);
const handleModals = (e) => {
if (e.target.id === "ConfigurationDuProfil") {

@ -9,7 +9,7 @@ const Discover = () => {
<Navbar />
<main >
<div className='postInMain'>
<DisplayPosts/>
<DisplayPosts type={"discover"}/>
</div>
<div className="RightBar">
<AjoutLien/>

@ -12,7 +12,7 @@ const Home = () => {
<Navbar />
<main >
<div className='postInMain'>
<DisplayPosts/>
<DisplayPosts type={"home"}/>
</div>
<div className="RightBar">
<AjoutLien/>

@ -22,6 +22,7 @@ export const userSlice = createSlice({
(id) => id !== action.payload.idToUnfollow
),};
},
},
});

@ -8,6 +8,8 @@ $color-5: #AABBCC;
$color-6: #5499c7 ;
$color-7: #19104f ;
$color-8: #FAFAFA;
$color-9: #645b5b;
$color-10:#dddddd;
// $color-1: #4cbfa6;
@ -32,7 +34,10 @@ body{
.imageDeProfil{
object-fit: cover;
background-size: cover;
width: 180px;
height: 180px;
clip-path:circle(50%);
}

@ -8,16 +8,18 @@
cursor: pointer;
}
.popup-profil-container {
z-index: 100;
width: 100%;
top: 0;
left: 0;
height: 100%;
position: fixed;
animation: popup 1s forwards;
.popup-ajout-container {
position: fixed;
animation: popup 1s forwards;
z-index: 100;
left: 50%;
@keyframes popup {
from{
backdrop-filter: none;
}
to {
backdrop-filter: blur(2px);
}
@ -49,6 +51,7 @@
top: 25px;
right: 25px;
transition: 0.1s;
cursor: pointer;
&:hover {
@ -57,23 +60,12 @@
}
ul {
min-width: 250px;
max-width: 300px;
margin: 20px 0 0;
max-height: 500px;
overflow-y: scroll;
overflow-x: hidden;
min-height: 200px;
&::-webkit-scrollbar {
width: 2px;
}
&::-webkit-scrollbar-track {
background: $color-4;
}
&::-webkit-scrollbar-thumb {
background: $color-1;
}
&::-webkit-scrollbar-thumb:hover {
background: #555;
}
li {
display: grid;

@ -16,14 +16,15 @@
flex-direction: column;
padding-left:5%;
font-size: medium;
span{
}
margin-bottom: 4%;
}
span{
}
margin-bottom: 4%;
}
.plusButton{
@ -38,9 +39,10 @@ span{
.imageDeProfilConfigurationPlus {
position: relative;
width: 15%;
max-width: 180px;
min-width: 130px;
max-width: 200px;
min-width: 150px;
border: none;
}
@ -119,8 +121,8 @@ input{
transform: scaleY(0);
transform-origin: center;
animation: modal .5s forwards;
max-width: 360px;
min-width: 320px;
max-width: 650px;
min-width: 500px;
border: 2px solid $color-4;
border-bottom-right-radius: 50px;
@ -130,42 +132,33 @@ input{
}
}
&:hover {
transform: scale(1.07);
}
}
&::-webkit-scrollbar {
width: 2px;
}
&::-webkit-scrollbar-track {
background: $color-4;
}
&::-webkit-scrollbar-thumb {
background: $color-1;
}
&::-webkit-scrollbar-thumb:hover {
background: #555;
}
.imagesPopup{
display: flex;
justify-content: space-between;
flex-direction: row;
.imageModifSpace{
margin-right: 18%;
img{
max-width: initial;
}
}
.profile-pic {
position: relative;
width: 100%;
color: transparent;
transition: all .3s ease;
@include object-center;
position: relative;
transition: all .3s ease;
input{
display:none;
}
img{
position: absolute;
object-fit: cover;
z-index: 0;
}
.-label {

@ -1,31 +1,35 @@
.PolitiqueDeConfidentialiteText{
margin-top: 2%;
display: flex;
justify-content: center;
flex-direction: column;
margin-top: 0.2%;
margin-left: 5%;
text-indent: 1%;
text-align: justify;
display: flex;
justify-content: center;
background-color: $color-8;
border: 0.2px solid $color-5;
max-width:85% ;
min-width: 380px;
height: 550px;
overflow-y: scroll;
scrollbar-width: thin;
scrollbar-gutter: stable both-edges;
p{
animation-duration: 2s;
animation-duration: 1s;
animation-name: slide;
margin: 1.5%;
@keyframes slide {
from {
margin-top: 100%;
width: 50%;
width: 80%;
}
to {
margin-top: 0%;
width: 100%;
}
}

@ -1,4 +1,4 @@
.conteneur_postes{
.PostesProfilConteneur{
display: flex;
flex-direction: column;
.unPosteNouvelleAffichage{
@ -9,15 +9,20 @@
background: $color-8;
border: 0.3px solid $color-5;
margin: 0.2% 1%;
padding: 1%;
padding: 1% 3%;
border-radius: 10px;
.dateDePublicationDuPost{
flex: 0.5 0.8 20%;
flex: 0 0 22%;
}
.LienDunPosteNouvelleAffichage{
display: flex;
justify-content: space-around;
justify-content: space-between;
flex-flow: row wrap;
flex: 0.9 0 60%;
margin-left: 3%;
p{
margin-left: 5%;
}
}
.informationDunPosteNouvelleAffichage{
@ -25,21 +30,28 @@
flex-direction: row;
justify-content: space-between;
padding-left: 10%;
flex: 0.5 0.8 auto;
flex: 0.5 0.4 auto;
}
}
.CommentaireProfil{
background: $color-8;
border: 0.3px solid $color-5;
}
}
.PreviewPostNouvelleAffichage{
min-width: 100px;
width: 80%;
max-height: 48px;
}
.postPersonnel .dossierPersonnel{
display: flex;
display: flex;
flex-direction: column;
width: 100;
}
}
width: 100%;
}

@ -53,7 +53,6 @@
height:40px;
border-radius: 20px;
border: 2px solid #555;
margin-bottom: 8%;
}
#NomProfile{
@ -77,5 +76,191 @@
align-items:center;
}
.alignementLien{
display: flex;
flex-direction: row;
justify-content: center;
background-color: $color-10;
.LienPostHome{
min-height:100px ;
height: 100%;
max-height: 300px;
}
}
.comment-container.client {
background: $color-4;
border: none;
border-radius: 20px 20px 6px 20px;
}
.comment-container {
display: grid;
grid-template-columns: 50px 1fr;
border: 1px solid $color-2;
padding: 15px;
margin: 5px 0;
border-radius: 20px 20px 20px 6px;
img {
height: 40px;
width: 40px;
border-radius: 14px;
box-shadow: 1px 1px 3px rgba(51, 51, 51, 0.192);
object-fit: cover;
}
.comment-header {
display: flex;
justify-content: space-between;
.pseudo {
display: flex;
span {
transform: translate(6px, 4px);
cursor: pointer;
img {
box-shadow: none;
height: 15px;
width: 15px;
}
}
}
span {
font-size: 0.9rem;
font-style: italic;
}
}
p {
margin-top: 8px;
}
.edit-comment {
color: $color-2;
img {
float: right;
margin-left: 10px;
cursor: pointer;
transition: 0.15s;
box-shadow: none;
height: 20px;
width: 20px;
&:hover {
transform: scale(1.1);
}
}
.edit-comment-form {
margin-top: 14px;
label {
background: white;
color: $color-1;
padding: 6px 12px 5px;
border-radius: 20px 20px 20px 6px;
cursor: pointer;
transition: 0.2s;
display: inline-block;
&:hover {
transform: scale(1.05);
}
}
input[type="text"] {
margin: 4px 0;
background: white;
font-size: 1.15rem;
padding: 16px;
width: 100%;
border-radius: 6px 20px 6px 20px;
}
.btn {
display: flex;
align-items: center;
float: right;
span {
background: white;
padding: 10px 5px;
border-radius: 50px;
margin-right: 6px;
transition: 0.2s;
cursor: pointer;
&:hover {
background: $color-2;
}
img {
transform: translate(-5px, 0);
}
}
input[type="submit"] {
background: $color-2;
width: inherit;
transition: 0.2s;
&:hover {
width: inherit;
background: $color-1;
}
}
}
}
}
}
.comment-form {
margin-top: 6px;
input[type="text"] {
width: 100%;
background: $color-4;
border-radius: 20px 20px 6px 20px;
padding: 20px;
font-size: 1.4rem;
&:focus {
box-shadow: 0 0 2px rgba(51, 51, 51, 0.5);
}
}
input[type="submit"] {
margin-top: 4px;
padding: 12px 16px;
width: 120px;
background: $color-2;
border-radius: 20px 6px 20px 20px;
transition: 0.2s;
float: right;
&:hover {
background: $color-1;
letter-spacing: 2px;
width: 130px;
}
}
button {
float: right;
background: $color-1;
transition: 0.2s;
&:hover {
background: $color-2;
}
}
}
.like-container {
span {
font-size: 1.02rem;
position: absolute;
transform: translate(8px, -1px);
}
}
.fa-share-alt {
transform: translate(0, 2px);
}

@ -39,7 +39,7 @@
input:focus{
background-color:$color-3;
}
margin-left: 1%;
margin-left: 6%;
}
.ligneHorizontal{

@ -162,6 +162,7 @@
padding-top: 2%;
padding-bottom: 2%;
list-style: none;
}
.navItemProfil {
@ -317,9 +318,10 @@ margin-top: 1%;
}
.menuContent{
background-color: #8c8c8e;
border: 0.3px solid $color-5;
background-color: $color-9;
border-radius: 10px;
margin: 0% 0% 0% 2.5%;
border-radius: 25px;
width: 95%;
height: 85%;
}
@ -339,10 +341,12 @@ padding-top: 3%;
}
.listContent {
/* display: flex;
justify-content: center; */
padding-left: 2.5%;
padding-top: 2.5%;
padding-left: 1%;
padding-top: 1%;
overflow-y: scroll;
scrollbar-width: thin;
scrollbar-gutter: stable both-edges;
}
.basDePage {

@ -1,11 +1,11 @@
#listeNotif{
margin: 2%;
margin-left: 8%;
margin-left: 20%;
padding:1%;
border-color: $color-5;
border-style:solid;
border-width: 0.3px;
min-width: 410px;
width: 84%;
width: 60%;
background: $color-8;
}

@ -177,8 +177,8 @@ module.exports.commentPost = async (req, res) => {
{
$push: {
comments: {
commenterId: req.body.commenterId,
commenterPseudo: req.body.commenterPseudo,
commentId: req.body.commenterId,
commentPseudo: req.body.commenterPseudo,
text: req.body.text,
timestamp: new Date().getTime(),
},

@ -6,23 +6,30 @@ const { uploadErrors } = require('../utils/errors.utils');
module.exports.uploadProfil = async (req, res) => {
try {
console.log(req.body.file);
try {
console.log(req.body.file);
if (
req.file.detectedMimeType != "image/jpg" &&
req.file.detectedMimeType != "image/png" &&
req.file.detectedMimeType != "image/jpeg"
req.body.file.detectedMimeType != "image/jpg" &&
req.body.file.detectedMimeType != "image/png" &&
req.body.file.detectedMimeType != "image/jpeg"
)
throw Error("invalid file");
if (req.file.size > 500000) throw Error("max size");
} catch (err) {
const errors = uploadErrors(err);
return res.status(201).json({ errors });
}
const fileName = req.body.name + ".jpg";
throw Error("Invalid file format. Only jpg, jpeg, png formats are allowed.");
if (req.body.file.size > 500000) throw Error("File size exceeded the maximum limit of 500KB.");
if(req.body.file.size === 0) throw Error("Empty file");
} catch (err) {
console.log("File upload failed.")
console.log(err)
return res.status(400).json({ message: err.message });
}
const fileName = req.body.file.name + ".jpg";
await pipeline(
req.file.stream,
req.body.file.stream,
fs.createWriteStream(
`${__dirname}/../client/public/uploads/profil/${fileName}`
)
@ -30,7 +37,7 @@ module.exports.uploadProfil = async (req, res) => {
try {
await UserModel.findByIdAndUpdate(
req.body.userId,
req.body.file.userId,
{ $set: { picture: "./uploads/profil/" + fileName } },
{ new: true, upsert: true, setDefaultsOnInsert: true })
.then((data) => res.send(data))

@ -48,6 +48,24 @@ module.exports.updateUser = async (req, res) => {
}
};
// module.exports.compteUpdate = async (req,res)=>{
// const{email, password}=req.body
// try{
// await UserModel.findOneAndUpdate{
// {_id: req.params.id}
// {set:{
// email: req.body.email
// }}
// }
// }
// }
module.exports.deleteUser = async (req, res) => {
if (!ObjectID.isValid(req.params.id))
return res.status(400).send("ID unknown : " + req.params.id);
@ -64,7 +82,6 @@ module.exports.follow = async (req, res) => {
if (!ObjectID.isValid(req.params.id) || !ObjectID.isValid(req.body.idToFollow)) {
return res.status(400).send("ID unknown : " + req.params.id);
}
try {
const user = await UserModel.findByIdAndUpdate(
req.params.id,
@ -84,68 +101,17 @@ module.exports.follow = async (req, res) => {
}
};
// module.exports.follow = async (req, res) => {
// if (
// !ObjectID.isValid(req.params.id) ||
// !ObjectID.isValid(req.body.idToFollow)
// )
// return res.status(400).send("ID unknown : " + req.params.id);
// try {
// // add to the follower list
// await UserModel.findByIdAndUpdate(
// req.params.id,
// { $addToSet: { following: req.body.idToFollow }, },
// { new: true , upsert: true },
// (err, docs) => {
// if (!err) return res.send(docs);
// else return res.status(200).send(err);
// }
// )
// // ajouter à la liste des followers
// await UserModel.findByIdAndUpdate(
// req.body.idToFollow,
// { $addToSet: { followers: req.params.id }, },
// { new: true , upsert: true},
// (err, docs) => {
// if (!err) return res.send(docs);
// else return res.status(200).send(err);
// }
// );
// } catch (err) {
// return res.status(400).send(err);
// }
// };
module.exports.unfollow = async (req, res) => {
if (
!ObjectID.isValid(req.params.id) ||
!ObjectID.isValid(req.body.idToUnfollow)
)
return res.status(400).send("ID unknown : " + req.params.id);
console.log(req.body.idToUnFollow);
if (!ObjectID.isValid(req.params.id) || !ObjectID.isValid(req.body.idToUnFollow)) {
return res.status(400).send("Invalid user ID: " + req.params.id);
}
try {
await userModel.findByIdAndUpdate(
req.params.id,
{ $pull: { following: req.body.idToUnfollow ,} },
{ new: true , upsert: true },
(err, docs) => {
if (err) return res.status(400).send(err);
}
);
// Retirer de la liste des followers
await userModel.findByIdAndUpdate(
req.body.idToUnfollow,
{ $pull: { followers: req.params.id } },
{ new: true , upsert: true},
(err, docs) => {
if (!err) return res.send(docs);
else return res.status(400).send(err);
}
);
await UserModel.findOneAndUpdate({ _id: req.params.id }, { $pull: { following: req.body.idToUnFollow } }, { new: true });
await UserModel.findOneAndUpdate({ _id: req.body.idToUnFollow }, { $pull: { followers: req.params.id } }, { new: true });
res.send({ message: 'unfollow successfull' });
} catch (err) {
return res.status(401).send(err);
return res.status(400).send(err);
}
}

@ -51,7 +51,7 @@ const userSchema = new mongoose.Schema(
},
picture: {
type: String,
default: "/random-user.png"
default: "./random-user.png"
},
bio :{
type: String,

File diff suppressed because it is too large Load Diff

@ -12,10 +12,11 @@ router.post('/login', authController.signIn);
//retirer le token (cookie)
router.get('/logout', authController.logout);
// user
router.get('/', userController.getAllUsers);
router.get('/:id', userController.userInfo);
//put pour faire des updates
router.put("/:id", userController.updateUser);
router.put('/:id', userController.updateUser);
router.delete('/:id', userController.deleteUser);
router.patch('/follow/:id', userController.follow);

@ -32,24 +32,17 @@ module.exports.signInErrors = (err) => {
}
module.exports.uploadErrors = (err) => {
let errors = { format: '', maxSize: ""};
let errors = { format: '', maxSize: "",empty:""};
if (err.message.includes('invalid file'))
errors.format = "Format incompatabile";
if (err.message.includes('max size'))
errors.maxSize = "Le fichier dépasse 500ko";
if(err.message.includes('empty file'))
errors.empty ="Le fichier est vide";
return errors
}
module.exports.uploadErrors = (err) => {
let errors = { format: '', maxSize: ""};
if (err.message.includes('invalid file'))
errors.format = "Format incompatible";
if (err.message.includes('max size'))
errors.maxSize = "Le fichier dépasse 500ko";
return errors;
}
Loading…
Cancel
Save