Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
243 changes: 121 additions & 122 deletions frontend/src/components/follow/FollowCard.js
Original file line number Diff line number Diff line change
@@ -1,139 +1,138 @@
import React, { useState, useEffect } from 'react'
import { Button, Badge } from 'react-bootstrap'
import { json, useNavigate } from 'react-router-dom'
import PfpResolver from '../PfpResolver'
import ClickableEnsAndAddress from '../ClickableEnsAndAddress'
import { apiPostFollow, apiPostUnfollow, apiGetProfile } from '../../api'
import './follow-custom.css'

import React, { useState, useContext } from "react";
import { Button, Badge } from "react-bootstrap";
import { useNavigate } from "react-router-dom";
import { ProfileContext } from "../../contexts/ProfileContext";
import PfpResolver from "../PfpResolver";
import ClickableEnsAndAddress from "../ClickableEnsAndAddress";
import { apiPostFollow, apiPostUnfollow } from "../../api";
import "./follow-custom.css";

function FollowCard(props) {
// State
const [buttonMsg, setButtonMsg] = useState("Following");
const [readMore, setReadMore] = useState(false);

const navigate = useNavigate()
const [buttonMsg, setButtonMsg] = useState('Following')
const [profileData, setProfileData] = useState({})
const [profileDataLoading, setProfileDataLoading] = useState(false)
const [readMore, setReadMore] = useState(false)

const handleFollow = async () => {
const resp = await apiPostFollow(props.address)
if (resp.ok) {
setButtonMsg('Following')
setProfileData({
...profileData,
numFollowers: profileData["numFollowers"] + 1,
followedByMe: true
});
}
}
// Const
const { profileData, setProfileData } = useContext(ProfileContext);
const navigate = useNavigate();

const handleUnfollow = async () => {
const resp = await apiPostUnfollow(props.address)
if (resp.ok) {
setButtonMsg('Follow')
setProfileData({
...profileData,
numFollowers: profileData["numFollowers"] - 1,
followedByMe: false
});
} else if (!resp.ok) {
console.error(resp.error)
}
const handleFollow = async () => {
const resp = await apiPostFollow(props.address);
if (resp.ok) {
setButtonMsg("Following");
setProfileData({
...profileData,
numFollowers: profileData["numFollowers"] + 1,
followedByMe: true,
});
}
};

const fetchProfile = async () => {
setProfileDataLoading(true);
const resp = await apiGetProfile(props.address)
if (resp.ok) {
var data = await resp.json();
setProfileData(data);
setProfileDataLoading(false);
}
else {
console.error(resp);
setProfileDataLoading(false);
}
const handleUnfollow = async () => {
const resp = await apiPostUnfollow(props.address);
if (resp.ok) {
setButtonMsg("Follow");
setProfileData({
...profileData,
numFollowers: profileData["numFollowers"] - 1,
followedByMe: false,
});
} else if (!resp.ok) {
console.error(resp.error);
}
};

const navigateProfile = () => {
navigate(`/${props.address}/profile`)
}
const navigateProfile = () => {
navigate(`/${props.address}/profile`);
};

// Hover On and Off Button Text Change
const handleHoverOn = () => {
if(buttonMsg === 'Follow') return
setButtonMsg('Unfollow')
}
const handleHoverOff = () => {
if(buttonMsg === 'Follow') return
setButtonMsg('Following')
}
// Hover On and Off Button Text Change
const handleHoverOn = () => {
if (buttonMsg === "Follow") return;
setButtonMsg("Unfollow");
};
const handleHoverOff = () => {
if (buttonMsg === "Follow") return;
setButtonMsg("Following");
};

// Button Logic
const handleButtonDisplayed = () => {
if(profileData.followedByMe === true) {
return <Button
className='outline-primary'
onClick={handleUnfollow}
onMouseEnter={handleHoverOn}
onMouseLeave={handleHoverOff}
>{buttonMsg}</Button>
} else {
return <Button onClick={handleFollow} className='btn-primary'>Follow</Button>
}
// Button Logic
const handleButtonDisplayed = () => {
if (props.followedByMe === true) {
return (
<Button
className="outline-primary"
onClick={handleUnfollow}
onMouseEnter={handleHoverOn}
onMouseLeave={handleHoverOff}
>
{buttonMsg}
</Button>
);
} else {
return (
<Button onClick={handleFollow} className="btn-primary">
Follow
</Button>
);
}
};

// shorten bio
const abbrBio = (bio) => {
if(bio.length > 200) {
if(readMore === false) {
return <div>
{bio.substr(0,200) + '...'}
<span className="link-style" onClick={() => setReadMore(true)}> read more</span>
</div>
} else if (readMore === true) {
return <div>
{bio}
</div>
}
} else return bio
}

// Fetch profile data
useEffect(() => {

fetchProfile()

}, [])
// shorten bio
const abbrBio = (bio) => {
if (bio.length > 200) {
if (readMore === false) {
return (
<div>
{bio.substr(0, 200) + "..."}
<span className="link-style" onClick={() => setReadMore(true)}>
{" "}
read more
</span>
</div>
);
} else if (readMore === true) {
return <div>{bio}</div>;
}
} else return bio;
};

return (
<div className="d-flex flex-sm-row flex-column align-items-sm-center py-sm-3 py-1 px-sm-2 px-lg-5 light-hover">
<PfpResolver
address={props.address}
imgUrl={props.imgUrl}
height="90px"
width="90px"
fontSize="0.9rem"
onClick={navigateProfile}
className="pointer d-flex justify-content-center mt-2"
/>
<div className='flex-grow-1 ps-sm-4'>
<div className='follow-body'>
<div className='d-flex flex-column'>
<ClickableEnsAndAddress address={props.address} className='fs-5 primary-color-hover pointer' onClick={navigateProfile}/>
<Badge className='text-dark bg-light align-self-sm-start align-self-center'>{props.numFollowers} {props.numFollowers === 1 ? 'follower' : 'followers'} </Badge>
</div>
<div className='align-self-center follow-btn'>
{handleButtonDisplayed()}
</div>
</div>
<div className=''>
{props.bio && <p className='fs-6 pt-1 px-sm-0 px-3 bio'>{abbrBio(props.bio)}</p>}
</div>
</div>
<div className="d-flex flex-sm-row flex-column align-items-sm-center py-sm-3 py-1 px-sm-2 px-lg-5 light-hover">
<PfpResolver
address={props.address}
imgUrl={props.imgUrl}
height="90px"
width="90px"
fontSize="0.9rem"
onClick={navigateProfile}
className="pointer d-flex justify-content-center mt-2"
/>
<div className="flex-grow-1 ps-sm-4">
<div className="follow-body">
<div className="d-flex flex-column">
<ClickableEnsAndAddress
address={props.address}
className="fs-5 primary-color-hover pointer"
onClick={navigateProfile}
/>
<Badge className="text-dark bg-light align-self-sm-start align-self-center">
{props.numFollowers}{" "}
{props.numFollowers === 1 ? "follower" : "followers"}{" "}
</Badge>
</div>
<div className="align-self-center follow-btn">
{handleButtonDisplayed()}
</div>
</div>
<div className="">
{props.bio && (
<p className="fs-6 pt-1 px-sm-0 px-3 bio">{abbrBio(props.bio)}</p>
)}
</div>

)
</div>
</div>
);
}

export default FollowCard
export default FollowCard;
65 changes: 43 additions & 22 deletions frontend/src/components/follow/FollowNav.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,51 @@
import React, { useEffect } from 'react'
import { useNavigate, useLocation } from 'react-router-dom'
import EnsAndAddress from '../EnsAndAddress'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faArrowLeft } from '@fortawesome/free-solid-svg-icons'
import ClickableEnsAndAddress from '../ClickableEnsAndAddress';
import React, { useContext } from "react";
import { useNavigate } from "react-router-dom";
import { ProfileContext } from "../../contexts/ProfileContext";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faArrowLeft } from "@fortawesome/free-solid-svg-icons";
import ClickableEnsAndAddress from "../ClickableEnsAndAddress";
import PfpResolver from "../PfpResolver";

function FollowNav(props) {
const navigate = useNavigate()
// const
const navigate = useNavigate();
const { profileData } = useContext(ProfileContext);

const navigateProfile = () => {
navigate(`/${props.address}/profile`)
}
navigate(`/${props.address}/profile`);
};

return (
<>
<div className='d-flex py-3 px-sm-5 border-bottom justify-content-center align-items-center'>
<div className='px-2'>
<FontAwesomeIcon icon={faArrowLeft} onClick={navigateProfile} className="fa-lg arrow pointer" />
</div>
<div className='px-1'>
<span><ClickableEnsAndAddress address={props.address} onClick={navigateProfile} className='pointer fs-4 primary-color-hover'/></span>
</div>
</div>
</>
)
<>
<div className="d-flex py-3 px-sm-5 justify-content-center align-items-center">
<div className="">
<FontAwesomeIcon
icon={faArrowLeft}
onClick={navigateProfile}
className="fa-lg arrow pointer"
/>
</div>
<div className="">
<PfpResolver
address={props.address}
imgUrl={profileData["image"]}
height="90px"
width="90px"
fontSize="0.9rem"
onClick={navigateProfile}
className="pointer d-flex justify-content-center"
/>
<span>
<ClickableEnsAndAddress
address={props.address}
onClick={navigateProfile}
className="pointer fs-4 primary-color-hover"
/>
</span>
</div>
</div>
</>
);
}

export default FollowNav

export default FollowNav;
Loading