diff --git a/src/components/UI/LikeButton.tsx b/src/components/UI/LikeButton.tsx index d53744b..701368a 100644 --- a/src/components/UI/LikeButton.tsx +++ b/src/components/UI/LikeButton.tsx @@ -6,12 +6,13 @@ import React, { } from 'react'; import { SlLike } from 'react-icons/sl'; +import { VscLoading } from 'react-icons/vsc'; import '../../styles/UI/LikeButton.scss'; +import '../../styles/animations/loading-icon.scss'; import involvement from '../../services/involvementAPI/involvementAPI.ts'; -/* eslint-disable no-undef */ interface LikeButtonProps { itemId: string; } @@ -20,6 +21,8 @@ const LikeButton: React.FC = ({ itemId }) => { const [wasLiked, setWasLiked] = useState(false); const [likeCount, setLikeCount] = useState(0); const [error, setError] = useState(false); + const [loading, setLoading] = useState(true); + const maximumLoadingTime = 5000; const likeBtn = useRef(null); @@ -35,6 +38,15 @@ const LikeButton: React.FC = ({ itemId }) => { } }, [wasLiked, styleButton]); + // ! terminate the loading state after a certain time. + // ? this is to prevent the loading state from being stuck. + // * and show the user the like button again. + const setLoadingToFalse = useCallback(() => { + setTimeout(() => { + setLoading(false); + }, maximumLoadingTime); + }, []); + interface Like { // * disable camelcase since 'item_id' is the name of the property in the API response. // eslint-disable-next-line camelcase @@ -45,12 +57,23 @@ const LikeButton: React.FC = ({ itemId }) => { const updateLikeCount = useCallback(async () => { const likes: Like[] = (await involvement.getLikes()) as Like[]; + if (likes.length === 0) { + setError(true); + // ? at this point the loading spinner is still showing. + // * so terminate the loading state, to show the error message. + setLoadingToFalse(); + return; + } + const likedProject = likes.find((like) => like.item_id === itemId); if (likedProject) { setLikeCount(likedProject.likes); + // ? at this point the loading spinner is still showing because of the initial API request. + // * so terminate the loading state, to show the like button with the like count. + setLoadingToFalse(); } - }, [itemId]); + }, [itemId, setLoadingToFalse]); useEffect(() => { updateLikeCount(); @@ -64,26 +87,54 @@ const LikeButton: React.FC = ({ itemId }) => { setLikeCount((count) => count + 1); } + if (error) { + // ? at this point, there was an error already, so user will attempt to like again. + // * so trigger the loading state again. + setLoading(true); + // * after some time, terminate the loading state, to show like button again. + setLoadingToFalse(); + return; + } + const likePosted = await involvement.postLike(itemId); if (likePosted === 'error') { setError(true); + return; } + setLoading(false); // * after posting a like, update the like count. updateLikeCount(); }; + if (loading) { + return ( + + ); + } + return (