diff --git a/README.md b/README.md index 8bf8b0d..b768e3b 100644 --- a/README.md +++ b/README.md @@ -35,3 +35,4 @@ npm install -g serve npm run build serve -s build ``` + diff --git a/src/components/AuthContext.jsx b/src/components/AuthContext.jsx index 5ca9be0..6fdfc6e 100644 --- a/src/components/AuthContext.jsx +++ b/src/components/AuthContext.jsx @@ -8,6 +8,7 @@ export const AuthProvider = ({ children }) => { const logout = () => { setToken(null); localStorage.removeItem("token"); + localStorage.removeItem("currentUser"); }; const isLogged = () => { diff --git a/src/components/KasulaNavbar.jsx b/src/components/KasulaNavbar.jsx index 0b7f7ec..de6fd8b 100644 --- a/src/components/KasulaNavbar.jsx +++ b/src/components/KasulaNavbar.jsx @@ -1,6 +1,6 @@ //React import React, { useState, useEffect } from "react"; -import { Link } from "react-router-dom"; +import { Link, useNavigate } from "react-router-dom"; import { useAuth } from "./AuthContext"; import "../css/common.css"; @@ -27,6 +27,7 @@ import chef from "../assets/chef.png"; function KasulaNavbar() { const { token, logout, isLogged } = useAuth(); + const navigate = useNavigate(); const [user, setUser] = useState({}); const [showModal, setShowModal] = useState(false); const [showPostRecipe, setShowPostRecipe] = useState(false); @@ -68,13 +69,13 @@ function KasulaNavbar() { const handleClosePostRecipeSuccessfulModal = () => { setShowPostRecipe(false); - //window.location.reload(); }; const handleLogout = () => { localStorage.setItem("logged", "false"); // This will update the localStorage handleCloseModal(); // This will close the modal logout(); // This will remove the token from the localStorage + window.location.reload(); }; const CustomToggle = React.forwardRef(({ onClick }, ref) => ( diff --git a/src/components/PostRecipe.jsx b/src/components/PostRecipe.jsx index ba64552..bba13b9 100644 --- a/src/components/PostRecipe.jsx +++ b/src/components/PostRecipe.jsx @@ -28,7 +28,7 @@ import { Table, } from "react-bootstrap"; -const RecipePost = ({ onClose }) => { +const RecipePost = ({onClose, edit, id}) => { const { token } = useAuth(); const Unit = { @@ -76,6 +76,42 @@ const RecipePost = ({ onClose }) => { } }, [localStorage.getItem("logged"), navigate]); + useEffect(() => { + if(edit){ + fetchRecipeData(); + } + }, []); + + const fetchRecipeData = async () => { + try { + const response = await fetch(`${process.env.REACT_APP_API_URL}/recipe/${id}`, { + method: 'GET', + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json', + }, + }); + + if (!response.ok) { + throw new Error('Error fetching recipe data'); + } + + const data = await response.json(); + + setRecipeName(data.name); + setIngredients(data.ingredients); + setPreparation(data.instructions); + setTime(data.cooking_time); + setEnergy(data.energy); + setDifficulty(data.difficulty); + setImagePreviewUrl(data.main_image) + + } catch (error) { + console.error('Error:', error); + } + }; + + const renderStars = (amount) => { let stars = []; for (let i = 1; i <= 5; i++) { @@ -228,34 +264,61 @@ const RecipePost = ({ onClose }) => { formData.append("recipe", JSON.stringify(recipeData)); if (image) { formData.append("files", image); - console.log(formData); + } - - - try { - const response = await fetch(process.env.REACT_APP_API_URL + "/recipe/", { - method: "POST", - headers: { - Authorization: `Bearer ${token}`, - }, - body: formData, - }); - - const data = await response.json(); - - if (response.ok) { - setSubmitMessage("Recipe posted successfully", data); - setPostRecipeSuccess(true); - //onClose(); - } else { - setSubmitMessage("Error posting recipe: " + JSON.stringify(data)); + console.log(formData["recipe"]); + if(edit){ + try { + const response = await fetch(process.env.REACT_APP_API_URL + "/recipe/" + id, { + method: "PUT", + headers: { + Authorization: `Bearer ${token}`, + }, + body: formData, + }); + + const data = await response.json(); + + if (response.ok) { + setSubmitMessage("Updated correctly!", data); + setPostRecipeSuccess(true); + //onClose(); + } else { + setSubmitMessage("Error updating recipe: " + JSON.stringify(data)); + } + } catch (error) { + setSubmitMessage(JSON.stringify(error)); + setPostRecipeSuccess(false); + } finally { + setShowPostRecipeConfirmation(true); + } + }else{ + try { + const response = await fetch(process.env.REACT_APP_API_URL + "/recipe/", { + method: "POST", + headers: { + Authorization: `Bearer ${token}`, + }, + body: formData, + }); + + const data = await response.json(); + + if (response.ok) { + setSubmitMessage("Posted correctly!", data); + setPostRecipeSuccess(true); + //onClose(); + } else { + setSubmitMessage("Error posting recipe: " + JSON.stringify(data)); + } + } catch (error) { + setSubmitMessage(JSON.stringify(error)); + setPostRecipeSuccess(false); + } finally { + setShowPostRecipeConfirmation(true); } - } catch (error) { - setSubmitMessage(JSON.stringify(error)); - setPostRecipeSuccess(false); - } finally { - setShowPostRecipeConfirmation(true); } + }; const handleImageUpload = (event) => { @@ -268,7 +331,7 @@ const RecipePost = ({ onClose }) => { const handlePostRecipeConfirmationClose = () => { setShowPostRecipeConfirmation(false); if (postSuccess) { - navigate("/"); + onClose(); } }; @@ -661,7 +724,7 @@ const RecipePost = ({ onClose }) => { variant={postSuccess ? "success" : "secondary"} onClick={handlePostRecipeConfirmationClose} > - {postSuccess ? "Go to recipes" : "Close"} + {postSuccess ? "Okay" : "Close"} diff --git a/src/components/RecipeDetail.jsx b/src/components/RecipeDetail.jsx index b19f4a1..ebd686f 100644 --- a/src/components/RecipeDetail.jsx +++ b/src/components/RecipeDetail.jsx @@ -36,7 +36,8 @@ import AddRecipeToCollection from "./AddRecipeToCollection"; function RecipeDetail() { const { token, isLogged } = useAuth(); - const [username, setUsername] = useState(localStorage.getItem("currentUser")); + const [myUserId, setMyUserId] = useState(''); + const [myUserName, setMyUserName] = useState(localStorage.getItem("currentUser")); const [userId, setUserId] = useState(''); const [userName, setUserName] = useState(''); const [userImage, setUserImage] = useState(''); @@ -46,6 +47,13 @@ function RecipeDetail() { const [recipe, setRecipe] = useState({ images: [] }); const [showReviews, setShowReviews] = useState(false); const [isLiked, setIsLiked] = useState(false); + const [adminMode, setadminMode] = useState(false); + const [showUnfollowModal, setShowUnfollowModal] = useState(false); + const [showLoginRedirectModal, setShowLoginRedirectModal] = useState(false); + const [confirmationMessage, setConfirmationMessage] = useState(""); + const [showConfirmation, setShowConfirmation] = useState(false); + const [isFollowing, setIsFollowing] = useState(null); + const [userFollowers, setUserFollowers] = useState([]); const [imageModal, setImageModal] = useState({ show: false, @@ -74,10 +82,18 @@ function RecipeDetail() { useEffect(() => { getRecipe(); if (isLogged()) { - getIsLiked(username); + getIsLiked(userName); } }, [id, reloadReviews]); + useEffect(() => { + if(myUserName == userName){ + setadminMode(true); + }else{ + setIsFollowing(userFollowers.includes(myUserName)); + } + }, [userName, userFollowers]); + const getRecipe = () => { fetch(process.env.REACT_APP_API_URL + `/recipe/${id}`) .then((response) => response.json()) @@ -106,12 +122,16 @@ function RecipeDetail() { setUserId(data.user_id); setUserName(data.username); setUserImage(data.profile_picture || ''); + setUserFollowers(data.followers || []); } catch (error) { console.error('Error fetching user data:', error); } }; - const handleNavigate = (userId) => { + const handleNavigate = (event, userId) => { + if (event) { + event.stopPropagation(); + } navigate(`/UserProfile/${userId}`); }; @@ -207,6 +227,68 @@ function RecipeDetail() { )); + const handleFollow = async () => { + if (!isLogged()) { + setShowLoginRedirectModal(true); + return; + } + + try { + const response = await fetch(process.env.REACT_APP_API_URL + `/user/follow/${userName}`, { + method: 'POST', + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json' + }, + }); + + if (response.ok) { + setConfirmationMessage(`You're now following ${userName}.`); + setIsFollowing(true); + setToastData({ + message: `You're now following ${userName}.`, + variant: 'success', + show: true, + }); + } else { + throw new Error('There was an error following the user.'); + } + } catch (error) { + console.error('Error following user:', error); + setConfirmationMessage(error.toString()); + setShowConfirmation(true); + } + }; + + const handleUnfollow = async () => { + try { + const response = await fetch(process.env.REACT_APP_API_URL + `/user/unfollow/${userName}`, { + method: 'POST', + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json' + }, + }); + + if (response.ok) { + setConfirmationMessage("You have unfollowed the user."); + setIsFollowing(false) + setToastData({ + message: `You' have unfollowed ${userName}.`, + variant: 'secondary', + show: true, + }); + } else { + throw new Error('There was an error unfollowing the user.'); + } + } catch (error) { + console.error('Error unfollowing user:', error); + setConfirmationMessage(error.toString()); + setShowConfirmation(true); + } + setShowUnfollowModal(false); + }; + return (

{recipe.name}

- -
handleNavigate(recipe.user_id)}> - - - {'Author:'} - - - - - - {userName} - - -
-

More information

@@ -315,7 +378,41 @@ function RecipeDetail() { - + +
handleNavigate(null, recipe.user_id)}> + + + + + +

{userName}

+ + + {!adminMode && ( + + )} + +
+
+ +
{toastData.message} + + setShowUnfollowModal(false)}> + + Unfollow User + + Do you want to unfollow this user? + + + + + + + setShowLoginRedirectModal(false)}> + + Required log in + + You need to log in to follow this user. + + + + + + ); } diff --git a/src/components/UserFeed.jsx b/src/components/UserFeed.jsx index 04ea2f9..608bd73 100644 --- a/src/components/UserFeed.jsx +++ b/src/components/UserFeed.jsx @@ -1,68 +1,126 @@ -//React import React, { useState, useEffect } from "react"; +import { useNavigate } from "react-router-dom"; import { useAuth } from "./AuthContext"; import RecipeList from "./RecipeList"; import RecipeBrowser from "./RecipeBrowser"; - -//Bootstrap -import { Container, Spinner } from "react-bootstrap"; +import { Container, Spinner, ButtonGroup, Button, Modal, Row, Col } from "react-bootstrap"; function UserFeed() { - const { isLogged } = useAuth(); + const {token, isLogged } = useAuth(); + const navigate = useNavigate(); const numRecipes = isLogged() ? 24 : 9; + const [recipes, setRecipes] = useState([]); + const [loading, setLoading] = useState(true); + const [feedType, setFeedType] = useState(localStorage.getItem('feedType') || 'foryou'); + const [showLoginRedirectModal, setShowLoginRedirectModal] = useState(false); + const [myFollowing, setMyFollowing] = useState(0); + const hasFollowings = myFollowing.length > 0; + const loggedOutFilters = { sortBy: "average_rating", sortAscending: false, }; - const [page, setPage] = useState(0); const [filters, setFilters] = useState(isLogged() ? (JSON.parse(localStorage.getItem("filters"))) : loggedOutFilters); const [recipeName, setRecipeName] = useState(null); - const [recipes, setRecipes] = useState([]); - const [loading, setLoading] = useState(false); + const [page, setPage] = useState(0); const [finished, setFinished] = useState(isLogged() ? false : true); - useEffect(() => { - getRecipes(filters, recipeName, page, numRecipes, true); - }, []); - useEffect(() => { if (!isLogged()) { setFinished(true); setPage(0); setFilters(loggedOutFilters); setRecipeName(null); - getRecipes(loggedOutFilters, null, 0, 9, true); + console.error("hola") + getRecipesLogout(loggedOutFilters, null, 0, 9, true, feedType); } + fetchMyUserData() }, [isLogged]); - const getRecipes = ( filters, recipeName, page, numRecipes, reset ) => { - if (loading) return; + useEffect(() => { + getRecipes(filters, recipeName, page, numRecipes, true, feedType); + }, [feedType]); + + const fetchMyUserData = async () => { + try { + const response = await fetch(process.env.REACT_APP_API_URL + '/user/me', { + method: 'GET', + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json' + }, + }); + if (!response.ok) { + throw new Error('Failed to fetch user data'); + } + const data = await response.json(); + setMyFollowing(data.following) + } catch (error) { + console.error('Error fetching user data:', error); + } + }; + + const getRecipesLogout = async (filters, recipeName, page, numRecipes, reset, feedType) => { setLoading(true); - fetch(buildRequestUrl(filters, recipeName, page, numRecipes)) - .then((response) => { - if (!response.ok) { - if (response.status === 400) { - setPage(page - 1); - setFinished(true); - } - } - return response.json(); - }) - .then((data) => { - if (reset) { - setRecipes(data); - } else { - setRecipes(recipes.concat(data)); + let url = buildRequestUrl(filters, recipeName, page, numRecipes, feedType); + try { + const response = await fetch(url, { + method: 'GET', + }); + if (!response.ok) { + if (response.status === 400) { + setPage(page - 1); + setFinished(true); } - setLoading(false); - }) - .catch((error) => { - console.error("Error al obtener recetas:", error); - setLoading(false); + throw new Error('Failed to fetch recipes'); + } + const data = await response.json(); + console.log(data) + if (reset) { + setRecipes(data) + } else { + setRecipes(recipes.concat(data)); + } + } catch (error) { + console.error('Error fetching recipes:', error); + } finally { + setLoading(false); + } + }; + + const getRecipes = async (filters, recipeName, page, numRecipes, reset, feedType) => { + setLoading(true); + let url = buildRequestUrl(filters, recipeName, page, numRecipes, feedType); + try { + const response = await fetch(url, { + method: 'GET', + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json' + }, }); - } + if (!response.ok) { + if (response.status === 400) { + setPage(page - 1); + setFinished(true); + } + throw new Error('Failed to fetch recipes'); + } + const data = await response.json(); + console.log(data) + if (reset) { + setRecipes(data) + } else { + setRecipes(recipes.concat(data)); + } + } catch (error) { + console.error('Error fetching recipes:', error); + } finally { + setLoading(false); + } + }; - const buildRequestUrl = (filters, recipeName, page, numRecipes) => { + const buildRequestUrl = (filters, recipeName, page, numRecipes, feedType) => { let url = process.env.REACT_APP_API_URL + "/recipe/" + (filters || recipeName || page || numRecipes ? "magic?" : ""); if (filters) { url += (filters.sortBy === 'none') ? '' : `sort_by=${filters.sortBy}&`; @@ -77,41 +135,116 @@ function UserFeed() { } if (page !== null && numRecipes !== null) { url += `start=${page * numRecipes}&`; - url += `size=${numRecipes}`; + url += `size=${numRecipes}&`; } - console.log(url); + url += `feedType=${feedType}`; + console.error(url) return url; - } + }; + + const handleTabChange = (tab) => { + setPage(0); + setFeedType(tab); + setFinished(false); + if(isLogged()){ + setRecipes([]); + } + localStorage.setItem('feedType', tab); + if (!isLogged() && tab === "following") { + setShowLoginRedirectModal(true); + setFeedType('foryou'); + return; + } + getRecipes(filters, recipeName, 0, numRecipes, true, tab); + }; return ( - + + + + + + + + + + + + {isLogged() && ( - { - setPage(0); - setFinished(false); - setFilters(filters); - setRecipeName(recipeName); - getRecipes(filters, recipeName, 0, numRecipes, true); + { + setPage(0); + setFinished(false); + setFilters(newFilters); + setRecipeName(newRecipeName); + getRecipes(newFilters, newRecipeName, 0, numRecipes, true, feedType); }}/> )} - {loading && recipes.length === 0 ? ( - - - - ) : ( - { - setPage(page + 1); - getRecipes(filters, recipeName, page + 1, numRecipes, false); - }} recipes={recipes} finished={finished}/> - )} + + { + feedType === 'foryou' || (feedType === "following" && hasFollowings) ? ( + loading && recipes.length === 0 ? ( + + + + ) : ( + isLogged && ( + { + setPage(page + 1); + if (feedType === "foryou") { + getRecipes(filters, recipeName, page+1, numRecipes, false, 'foryou'); + } else { + getRecipes(filters, recipeName, page+1, numRecipes, false, 'following'); + } + }} + finished={finished} + /> + ) + ) + ) : ( +
+ You still don't follow anyone! +
+ ) + } + {!isLogged() && (
This is as far as you can go. Please, login or register to see more recipes.
)} + + + setShowLoginRedirectModal(false)}> + + Required log in + + You need to log in to view the recipes of the people you follow. + + + + +
); - } -export default UserFeed; +export default UserFeed; \ No newline at end of file diff --git a/src/components/UserProfile.jsx b/src/components/UserProfile.jsx index ecb1c5a..221cef1 100644 --- a/src/components/UserProfile.jsx +++ b/src/components/UserProfile.jsx @@ -19,6 +19,9 @@ import { Container, Row, Col, Card, Button, Form, Image, Modal, Dropdown, ListGr import "../css/common.css"; import "../css/UserProfile.css"; +//Components +import PostRecipe from "./PostRecipe"; + const UserProfile = () => { const { token, logout, isLogged } = useAuth(); const navigate = useNavigate(); @@ -26,6 +29,7 @@ const UserProfile = () => { const { userId } = useParams(); + const [updateCount, setUpdateCount] = useState(0); const [myUserId, setMyUserId] = useState(''); const [myUserName, setMyUserName] = useState(''); const [userName, setUserName] = useState(''); @@ -33,6 +37,7 @@ const UserProfile = () => { const [userBio, setUserBio] = useState(''); const [userFollowers, setUserFollowers] = useState([]); const [userFollowing, setUserFollowing] = useState([]); + const [myFollowing, setMyFollowing] = useState([]); const [userNameAux, setUserNameAux] = useState(''); const [userMailAux, setUserMailAux] = useState(''); const [userBioAux, setUserBioAux] = useState(''); @@ -49,12 +54,14 @@ const UserProfile = () => { const [isFollowing, setIsFollowing] = useState(null); const [followerDetails, setFollowerDetails] = useState([]); const [followingDetails, setFollowingDetails] = useState([]); + const [suggestedUsers, setSuggestedUsers] = useState([]); const [adminMode, setadminMode] = useState(false); const [editMode, setEditMode] = useState(false); const [showConfirmation, setShowConfirmation] = useState(false); const [showDropdown, setShowDropdown] = useState(false); + const [showEditRecipe, setShowEditRecipe] = useState(false); const [showDropdown2, setShowDropdown2] = useState(false); const [showRemoveQuestion, setRemoveQuestion] = useState(false); const [showRemoveRecipeModal, setShowRemoveRecipeModal] = useState(false); @@ -107,11 +114,16 @@ const UserProfile = () => { const data = await response.json(); setMyUserId(data._id) setMyUserName(data.username) + setMyFollowing(data.following) } catch (error) { console.error('Error fetching user data:', error); } }; + const isFollowed = (follower) => { + return myFollowing.includes(follower.username); + }; + const fetchUserData = async () => { try { const response = await fetch(process.env.REACT_APP_API_URL + '/user/' + userId, { @@ -154,13 +166,34 @@ const UserProfile = () => { setUserDetails(userDetails); }; + const fetchSuggestedUsers = async () => { + try { + const response = await fetch(process.env.REACT_APP_API_URL + `/user/new/discover`, { + method: 'GET', + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json' + }, + }); + if (!response.ok) { + throw new Error('Failed to fetch suggested users'); + } + const data = await response.json(); + setSuggestedUsers(data); + } catch (error) { + console.error('Error fetching suggested users:', error); + } + }; + useEffect(() => { - if (isLogged) { + if (token!=null) { fetchMyUserData(); + fetchSuggestedUsers(); } - }, [token, navigate]); + }, [token]); useEffect(() => { + if(myUserId == userId){ setadminMode(true); } @@ -171,10 +204,11 @@ const UserProfile = () => { if (userName) { getRecipes(); } - }, [userName]); + }, [userName, updateCount]); useEffect(() => { fetchUserDetails(userFollowers, setFollowerDetails); + console.error(followerDetails) }, [userFollowers]); useEffect(() => { @@ -191,6 +225,16 @@ const UserProfile = () => { setEditMode(false); }; + const handleCloseEditRecipeModal = () => { + setShowEditRecipe(false); + setUpdateCount(prevCount => prevCount + 1); + }; + + const handleCloseEditRecipeSuccessfulModal = () => { + setShowEditRecipe(false); + setUpdateCount(prevCount => prevCount + 1); + }; + const handleShowRemoveRecipeModal = () => { setShowRemoveRecipeModal(true); }; @@ -239,15 +283,16 @@ const UserProfile = () => { setUserName(updatedData.username); setUserMail(updatedData.email); setUserBio(updatedData.bio || ''); + setOperationSuccess(true) setConfirmationMessage("Profile updated successfully"); } catch (error) { console.error('Error updating user data:', error); - setConfirmationMessage("Failed to update profile"); + setOperationSuccess(false) + setConfirmationMessage("Oops! Something went wrong."); } setShowConfirmation(true); - setOperationSuccess(true) setEditMode(false); }; @@ -277,14 +322,14 @@ const UserProfile = () => { }); if (!response.ok) { - throw new Error('Failed to update user data'); + throw new Error('Oops! Something went wrong.'); } const data = await response.json(); setConfirmationMessage("Profile updated successfully"); } catch (error) { console.error('Error updating user data:', error); - setConfirmationMessage("Failed to update profile"); + setConfirmationMessage("Oops! Something went wrong."); } setShowConfirmation(true); } @@ -484,11 +529,51 @@ const UserProfile = () => { useEffect(() => { setIsFollowing(userFollowers.includes(myUserName)); - console.error(userFollowers) }, [userFollowers]); + const checkIfFollowed = (username) => { + return userFollowing.includes(username); + }; + + const handleFollowUnfollow = async (username, isCurrentlyFollowed) => { + const url = process.env.REACT_APP_API_URL + `/user/${isCurrentlyFollowed ? 'unfollow' : 'follow'}/${username}`; + const method = 'POST'; + + try { + const response = await fetch(url, { + method, + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json' + }, + }); + + if (!response.ok) { + throw new Error(`Failed to ${isCurrentlyFollowed ? 'unfollow' : 'follow'} user`); + } + + setMyFollowing(prevFollowing => { + return isCurrentlyFollowed + ? prevFollowing.filter(user => user !== username) + : [...prevFollowing, username]; + }); + + if(myUserName===userName){ + setUserFollowing(prevFollowing => { + return isCurrentlyFollowed + ? prevFollowing.filter(user => user !== username) + : [...prevFollowing, username]; + }) + } + } catch (error) { + console.error('Error:', error); + } + }; + + + const handleFollow = async () => { - if (isLogged) { + if (token==null) { setShowLoginRedirectModal(true); return; } @@ -643,7 +728,7 @@ const UserProfile = () => {
@@ -675,10 +760,10 @@ const UserProfile = () => { setShowRemoveRecipeModal(false)}> - + Remove recipe - + @@ -690,7 +775,7 @@ const UserProfile = () => { - + @@ -701,11 +786,11 @@ const UserProfile = () => { show={showConfirmation} onHide={handleConfirmationClose} > - + Profile Update - {confirmationMessage} - + {confirmationMessage} + @@ -754,7 +839,7 @@ const UserProfile = () => { - + @@ -769,11 +854,11 @@ const UserProfile = () => { - + {operationSuccess ? 'Success' : 'Error'} - {confirmationMessage} - + {confirmationMessage} + @@ -781,12 +866,12 @@ const UserProfile = () => { - + Followers - + {followerDetails.length > 0 ? ( followerDetails.map((follower, index) => ( @@ -800,9 +885,23 @@ const UserProfile = () => { style={{ width: '30px', marginRight: '10px' }} /> - + {follower.username} + + {(token !== null) && (follower.username !== myUserName) && ( + + )} + + @@ -816,43 +915,87 @@ const UserProfile = () => { - + Following - - {followingDetails.length > 0 ? ( - followingDetails.map((follower, index) => ( - - handleNavigate(follower._id)}> + + {userFollowing.length > 0 ? ( + followingDetails.map((following, index) => ( + + handleNavigate(following._id)}> - + - - {follower.username} + + {following.username} + + + {(token !== null) && (following.username !== myUserName) && ( + + )} - )) + )) + ) : ( + adminMode ? ( + <> +

You're not following anyone. Discover creators that match your taste!

+ {suggestedUsers.length > 0 ? ( + suggestedUsers.slice(0, 5).map((user, index) => ( + + handleNavigate(user._id)}> + + + + + + + {user.username} + + + + + + )) + ) : ( +

Loading...

+ )} + + ) : ( -

There are no users to display.

- )} +

You are not following anyone yet.

+ ) + )}
setShowUnfollowModal(false)}> - + Unfollow User - Do you want to unfollow this user? - + Do you want to unfollow this user? + @@ -867,7 +1010,7 @@ const UserProfile = () => { Required log in You need to log in to follow this user. - + @@ -877,6 +1020,23 @@ const UserProfile = () => { + + + Edit Recipe + + + + + +
);