diff --git a/website/components/CommentCard/CommentCard.js b/website/components/CommentCard/CommentCard.js index b3a577b..578a721 100644 --- a/website/components/CommentCard/CommentCard.js +++ b/website/components/CommentCard/CommentCard.js @@ -11,6 +11,7 @@ const CommentCard = forwardRef((props, ref) => { const { isAuth, user } = useContext(UserContext); const deleteCommentById = async () => { + props.manageComment.setLoadingComments(true); if (isAuth && user.token != undefined) { try { 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 }); } catch {} } + props.manageComment.setLoadingComments(false); } return ( diff --git a/website/components/FunctionComments/FunctionComments.js b/website/components/FunctionComments/FunctionComments.js index 6296e77..b98f8f5 100644 --- a/website/components/FunctionComments/FunctionComments.js +++ b/website/components/FunctionComments/FunctionComments.js @@ -17,6 +17,14 @@ const FunctionComments = ({ functionId }) => { const [isLoadingComments, setLoadingComments] = useState(true); 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 const observer = useRef(); 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 inputStateNew = { ...inputState }; inputStateNew[event.target.name] = event.target.value; @@ -102,9 +102,9 @@ const FunctionComments = ({ functionId }) => { {commentsData.rows.map((comment, index) => { // Si c'est le dernier élément if (commentsData.rows.length === index + 1) { - return ; + return ; } - return ; + return ; })} diff --git a/website/components/FunctionComponentTop.js b/website/components/FunctionComponentTop.js index a8a1497..9ece2a2 100644 --- a/website/components/FunctionComponentTop.js +++ b/website/components/FunctionComponentTop.js @@ -1,21 +1,65 @@ +import { useState, useEffect, useContext } from 'react'; 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) => ( -
-
-
- {props.title} -

{props.title}

-

{props.description}

-
- - {props.categorie.name} - -

{props.publicationDate}

+const FunctionComponentTop = (props) => { + + const { isAuth, user } = useContext(UserContext); + const [isFavorite, setIsFavorite] = useState(false); + + useEffect(() => { + if (isAuth && user.token != undefined) { + fetchFavorite(); + } + }, [isAuth]); + + 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 ( +
+
+
+ + {(isAuth) && + + } + + {props.title} +

{props.title}

+

{props.description}

+
+ + {props.categorie.name} + +

{props.publicationDate}

+
-
-); + ); +} export default FunctionComponentTop; \ No newline at end of file diff --git a/website/contexts/FunctionTabsContext.js b/website/contexts/FunctionTabsContext.js index c12b30a..f080886 100644 --- a/website/contexts/FunctionTabsContext.js +++ b/website/contexts/FunctionTabsContext.js @@ -4,7 +4,7 @@ export const FunctionTabsContext = createContext(); function FunctionTabsContextProvider(props) { - const [slideIndex, setSlideIndex] = useState(2); + const [slideIndex, setSlideIndex] = useState(0); return ( diff --git a/website/package-lock.json b/website/package-lock.json index c172428..193bbf6 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -1408,6 +1408,14 @@ "@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": { "version": "5.13.0", "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.13.0.tgz", diff --git a/website/package.json b/website/package.json index 4e36188..ea68c48 100644 --- a/website/package.json +++ b/website/package.json @@ -9,6 +9,7 @@ }, "dependencies": { "@fortawesome/fontawesome-svg-core": "^1.2.28", + "@fortawesome/free-regular-svg-icons": "^5.13.0", "@fortawesome/free-solid-svg-icons": "^5.13.0", "@fortawesome/react-fontawesome": "^0.1.9", "@zeit/next-css": "^1.0.1", diff --git a/website/pages/functions/index.js b/website/pages/functions/index.js index 36ca75e..5f6cb04 100644 --- a/website/pages/functions/index.js +++ b/website/pages/functions/index.js @@ -20,6 +20,26 @@ const Functions = () => { const [isLoadingFunctions, setLoadingFunctions] = useState(true); 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 const observer = useRef(); const lastFunctionCardRef = useCallback((node) => { @@ -41,26 +61,6 @@ const Functions = () => { 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 inputSearchNew = { ...inputSearch }; diff --git a/website/public/css/pages/FunctionComponent.css b/website/public/css/pages/FunctionComponent.css index 1c45d55..67d17c8 100644 --- a/website/public/css/pages/FunctionComponent.css +++ b/website/public/css/pages/FunctionComponent.css @@ -18,4 +18,17 @@ } .FunctionComponent__slide { 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; } \ No newline at end of file