frontend: Ajouter/Retirer une fonction des favoris
This commit is contained in:
parent
0ac2fbf3ab
commit
02058fc2fb
@ -11,6 +11,7 @@ const CommentCard = forwardRef((props, ref) => {
|
|||||||
const { isAuth, user } = useContext(UserContext);
|
const { isAuth, user } = useContext(UserContext);
|
||||||
|
|
||||||
const deleteCommentById = async () => {
|
const deleteCommentById = async () => {
|
||||||
|
props.manageComment.setLoadingComments(true);
|
||||||
if (isAuth && user.token != undefined) {
|
if (isAuth && user.token != undefined) {
|
||||||
try {
|
try {
|
||||||
await api.delete(`/comments?commentId=${props.id}`, { headers: { 'Authorization': user.token } });
|
await api.delete(`/comments?commentId=${props.id}`, { headers: { 'Authorization': user.token } });
|
||||||
@ -20,6 +21,7 @@ const CommentCard = forwardRef((props, ref) => {
|
|||||||
props.manageComment.setCommentsData({ hasMore: props.manageComment.commentsData.hasMore, rows: newCommentsData.rows });
|
props.manageComment.setCommentsData({ hasMore: props.manageComment.commentsData.hasMore, rows: newCommentsData.rows });
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
|
props.manageComment.setLoadingComments(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -17,6 +17,14 @@ const FunctionComments = ({ functionId }) => {
|
|||||||
const [isLoadingComments, setLoadingComments] = useState(true);
|
const [isLoadingComments, setLoadingComments] = useState(true);
|
||||||
const [pageComments, setPageComments] = useState(1);
|
const [pageComments, setPageComments] = useState(1);
|
||||||
|
|
||||||
|
// Récupère les commentaires si la page change
|
||||||
|
useEffect(() => {
|
||||||
|
getCommentsData().then((data) => setCommentsData({
|
||||||
|
hasMore: data.hasMore,
|
||||||
|
rows: [...commentsData.rows, ...data.rows]
|
||||||
|
}));
|
||||||
|
}, [pageComments]);
|
||||||
|
|
||||||
// Permet la pagination au scroll
|
// Permet la pagination au scroll
|
||||||
const observer = useRef();
|
const observer = useRef();
|
||||||
const lastCommentCardRef = useCallback((node) => {
|
const lastCommentCardRef = useCallback((node) => {
|
||||||
@ -39,14 +47,6 @@ const FunctionComments = ({ functionId }) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Récupère les commentaires si la page change
|
|
||||||
useEffect(() => {
|
|
||||||
getCommentsData().then((data) => setCommentsData({
|
|
||||||
hasMore: data.hasMore,
|
|
||||||
rows: [...commentsData.rows, ...data.rows]
|
|
||||||
}));
|
|
||||||
}, [pageComments]);
|
|
||||||
|
|
||||||
const handleChange = (event) => {
|
const handleChange = (event) => {
|
||||||
const inputStateNew = { ...inputState };
|
const inputStateNew = { ...inputState };
|
||||||
inputStateNew[event.target.name] = event.target.value;
|
inputStateNew[event.target.name] = event.target.value;
|
||||||
@ -102,9 +102,9 @@ const FunctionComments = ({ functionId }) => {
|
|||||||
{commentsData.rows.map((comment, index) => {
|
{commentsData.rows.map((comment, index) => {
|
||||||
// Si c'est le dernier élément
|
// Si c'est le dernier élément
|
||||||
if (commentsData.rows.length === index + 1) {
|
if (commentsData.rows.length === index + 1) {
|
||||||
return <CommentCard key={comment.id} ref={lastCommentCardRef} { ...comment } manageComment={{ setCommentsData, commentsData }} />;
|
return <CommentCard key={comment.id} ref={lastCommentCardRef} { ...comment } manageComment={{ setCommentsData, commentsData, setLoadingComments }} />;
|
||||||
}
|
}
|
||||||
return <CommentCard key={comment.id} { ...comment } manageComment={{ setCommentsData, commentsData }} />;
|
return <CommentCard key={comment.id} { ...comment } manageComment={{ setCommentsData, commentsData, setLoadingComments }} />;
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,21 +1,65 @@
|
|||||||
|
import { useState, useEffect, useContext } from 'react';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
import { faStar } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import { faStar as farStar } from '@fortawesome/free-regular-svg-icons';
|
||||||
|
import { UserContext } from '../contexts/UserContext';
|
||||||
|
import api from '../utils/api';
|
||||||
|
import './FunctionCard/FunctionCard.css';
|
||||||
|
|
||||||
const FunctionComponentTop = (props) => (
|
const FunctionComponentTop = (props) => {
|
||||||
<div className="container-fluid">
|
|
||||||
<div className="row justify-content-center text-center">
|
const { isAuth, user } = useContext(UserContext);
|
||||||
<div className="FunctionComponent__top col-24">
|
const [isFavorite, setIsFavorite] = useState(false);
|
||||||
<img style={{ width: '150px' }} src={props.API_URL + props.image} alt={props.title} />
|
|
||||||
<h1 className="FunctionComponent__title title-important">{props.title}</h1>
|
useEffect(() => {
|
||||||
<p className="FunctionComponent__description">{props.description}</p>
|
if (isAuth && user.token != undefined) {
|
||||||
<div className="FunctionCard__info">
|
fetchFavorite();
|
||||||
<Link href={`/functions?categoryId=${props.categorieId}`}>
|
}
|
||||||
<a className="FunctionCard__category" style={{ backgroundColor: props.categorie.color, color: 'inherit' }}>{props.categorie.name}</a>
|
}, [isAuth]);
|
||||||
</Link>
|
|
||||||
<p className="FunctionCard__publication-date">{props.publicationDate}</p>
|
const fetchFavorite = async () => {
|
||||||
|
try {
|
||||||
|
const favoriteResponse = await api.get(`/favorites/${props.id}`, { headers: { 'Authorization': user.token } });
|
||||||
|
setIsFavorite(favoriteResponse.data.isFavorite);
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleFavorite = async () => {
|
||||||
|
if (isAuth && user.token != undefined) {
|
||||||
|
try {
|
||||||
|
if (isFavorite) {
|
||||||
|
const response = await api.delete(`/favorites/${props.id}`, { headers: { 'Authorization': user.token } });
|
||||||
|
if (response.status === 200) return setIsFavorite(false);
|
||||||
|
}
|
||||||
|
const response = await api.post(`/favorites/${props.id}`, {}, { headers: { 'Authorization': user.token } });
|
||||||
|
if (response.status === 201) return setIsFavorite(true);
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="container-fluid">
|
||||||
|
<div className="row justify-content-center text-center">
|
||||||
|
<div className="FunctionComponent__top col-24">
|
||||||
|
|
||||||
|
{(isAuth) &&
|
||||||
|
<FontAwesomeIcon onClick={toggleFavorite} { ...(isFavorite) ? { icon: faStar } : { icon: farStar } } title={(isFavorite) ? "Retirer la fonction des favoris" : "Ajouter la fonction aux favoris"} className="FunctionComponent__star-favorite" />
|
||||||
|
}
|
||||||
|
|
||||||
|
<img className="FunctionComponent__image" src={props.API_URL + props.image} alt={props.title} />
|
||||||
|
<h1 className="FunctionComponent__title title-important">{props.title}</h1>
|
||||||
|
<p className="FunctionComponent__description">{props.description}</p>
|
||||||
|
<div className="FunctionCard__info">
|
||||||
|
<Link href={`/functions?categoryId=${props.categorieId}`}>
|
||||||
|
<a className="FunctionCard__category" style={{ backgroundColor: props.categorie.color, color: 'inherit' }}>{props.categorie.name}</a>
|
||||||
|
</Link>
|
||||||
|
<p className="FunctionCard__publication-date">{props.publicationDate}</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
);
|
||||||
);
|
}
|
||||||
|
|
||||||
export default FunctionComponentTop;
|
export default FunctionComponentTop;
|
@ -4,7 +4,7 @@ export const FunctionTabsContext = createContext();
|
|||||||
|
|
||||||
function FunctionTabsContextProvider(props) {
|
function FunctionTabsContextProvider(props) {
|
||||||
|
|
||||||
const [slideIndex, setSlideIndex] = useState(2);
|
const [slideIndex, setSlideIndex] = useState(0);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FunctionTabsContext.Provider value={{ slideIndex, setSlideIndex }}>
|
<FunctionTabsContext.Provider value={{ slideIndex, setSlideIndex }}>
|
||||||
|
8
website/package-lock.json
generated
8
website/package-lock.json
generated
@ -1408,6 +1408,14 @@
|
|||||||
"@fortawesome/fontawesome-common-types": "^0.2.28"
|
"@fortawesome/fontawesome-common-types": "^0.2.28"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@fortawesome/free-regular-svg-icons": {
|
||||||
|
"version": "5.13.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.13.0.tgz",
|
||||||
|
"integrity": "sha512-70FAyiS5j+ANYD4dh9NGowTorNDnyvQHHpCM7FpnF7GxtDjBUCKdrFqCPzesEIpNDFNd+La3vex+jDk4nnUfpA==",
|
||||||
|
"requires": {
|
||||||
|
"@fortawesome/fontawesome-common-types": "^0.2.28"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@fortawesome/free-solid-svg-icons": {
|
"@fortawesome/free-solid-svg-icons": {
|
||||||
"version": "5.13.0",
|
"version": "5.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.13.0.tgz",
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-svg-core": "^1.2.28",
|
"@fortawesome/fontawesome-svg-core": "^1.2.28",
|
||||||
|
"@fortawesome/free-regular-svg-icons": "^5.13.0",
|
||||||
"@fortawesome/free-solid-svg-icons": "^5.13.0",
|
"@fortawesome/free-solid-svg-icons": "^5.13.0",
|
||||||
"@fortawesome/react-fontawesome": "^0.1.9",
|
"@fortawesome/react-fontawesome": "^0.1.9",
|
||||||
"@zeit/next-css": "^1.0.1",
|
"@zeit/next-css": "^1.0.1",
|
||||||
|
@ -20,6 +20,26 @@ const Functions = () => {
|
|||||||
const [isLoadingFunctions, setLoadingFunctions] = useState(true);
|
const [isLoadingFunctions, setLoadingFunctions] = useState(true);
|
||||||
const [pageFunctions, setPageFunctions] = useState(1);
|
const [pageFunctions, setPageFunctions] = useState(1);
|
||||||
|
|
||||||
|
// Récupère la catégorie avec la query categoryId
|
||||||
|
useEffect(() => {
|
||||||
|
if (categoryId) {
|
||||||
|
handleChange({ target: { name: "selectedCategory", value: categoryId } });
|
||||||
|
}
|
||||||
|
}, [categoryId]);
|
||||||
|
|
||||||
|
// Récupère les fonctions si la page change
|
||||||
|
useEffect(() => {
|
||||||
|
getFunctionsData().then((data) => setFunctionsData({
|
||||||
|
hasMore: data.hasMore,
|
||||||
|
rows: [...functionsData.rows, ...data.rows]
|
||||||
|
}));
|
||||||
|
}, [pageFunctions]);
|
||||||
|
|
||||||
|
// Récupère les fonctions si la catégorie/recherche change
|
||||||
|
useEffect(() => {
|
||||||
|
getFunctionsData().then((data) => setFunctionsData(data));
|
||||||
|
}, [inputSearch.selectedCategory, inputSearch.search]);
|
||||||
|
|
||||||
// Permet la pagination au scroll
|
// Permet la pagination au scroll
|
||||||
const observer = useRef();
|
const observer = useRef();
|
||||||
const lastFunctionCardRef = useCallback((node) => {
|
const lastFunctionCardRef = useCallback((node) => {
|
||||||
@ -41,26 +61,6 @@ const Functions = () => {
|
|||||||
next(result.data);
|
next(result.data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Récupère la catégorie avec la query categoryId
|
|
||||||
useEffect(() => {
|
|
||||||
if (categoryId) {
|
|
||||||
handleChange({ target: { name: "selectedCategory", value: categoryId } });
|
|
||||||
}
|
|
||||||
}, [categoryId]);
|
|
||||||
|
|
||||||
// Récupère les fonctions si la page change
|
|
||||||
useEffect(() => {
|
|
||||||
getFunctionsData().then((data) => setFunctionsData({
|
|
||||||
hasMore: data.hasMore,
|
|
||||||
rows: [...functionsData.rows, ...data.rows]
|
|
||||||
}));
|
|
||||||
}, [pageFunctions]);
|
|
||||||
|
|
||||||
// Récupère les fonctions si la catégorie/recherche change
|
|
||||||
useEffect(() => {
|
|
||||||
getFunctionsData().then((data) => setFunctionsData(data));
|
|
||||||
}, [inputSearch.selectedCategory, inputSearch.search]);
|
|
||||||
|
|
||||||
const handleChange = (event) => {
|
const handleChange = (event) => {
|
||||||
const inputSearchNew = { ...inputSearch };
|
const inputSearchNew = { ...inputSearch };
|
||||||
|
@ -18,4 +18,17 @@
|
|||||||
}
|
}
|
||||||
.FunctionComponent__slide {
|
.FunctionComponent__slide {
|
||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
.FunctionComponent__image {
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
.FunctionComponent__star-favorite {
|
||||||
|
color: var(--important);
|
||||||
|
width: 2em !important;
|
||||||
|
height: 2em !important;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 15px;
|
||||||
|
margin-right: 15px;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
Reference in New Issue
Block a user