From e6e99cc1fb1de3a815b4f3396abaf30f8388d9a7 Mon Sep 17 00:00:00 2001 From: Aaron <45613289+aaerhart@users.noreply.github.com> Date: Tue, 21 Jan 2025 12:08:36 -0500 Subject: [PATCH] feat: bill follow and unfollow functionality to testimony page (#1661) * feat: bill follow and unfollow functionality to testimony page * ran prettier * fix: remove unnecesary code * fix: run linter --------- Co-authored-by: Merritt Baggett --- components/bill/BillDetails.tsx | 131 +++++++++--------- components/layout.tsx | 25 ++-- .../TestimonyDetailPage/PolicyActions.tsx | 54 +++++++- .../TestimonyDetailPage.tsx | 11 ++ 4 files changed, 139 insertions(+), 82 deletions(-) diff --git a/components/bill/BillDetails.tsx b/components/bill/BillDetails.tsx index b1de4b77a..9c27a8e7f 100644 --- a/components/bill/BillDetails.tsx +++ b/components/bill/BillDetails.tsx @@ -37,86 +37,83 @@ export const BillDetails = ({ bill }: BillProps) => { const isPendingUpgrade = useAuth().claims?.role === "pendingUpgrade" const flags = useFlags() - const [followStatus, setFollowStatus] = useState({}) const { user } = useAuth() return ( <> - - {isPendingUpgrade && } - {!isCurrentCourt(bill.court) && ( - {t("bill.old_session", { billCourt: bill.court })} - )} + {isPendingUpgrade && } + {!isCurrentCourt(bill.court) && ( + {t("bill.old_session", { billCourt: bill.court })} + )} - - - - {t("back_to_bills")} - - - {bill.history.length > 0 ? ( - <> - - - - - - - - - - - {flags.notifications && user && ( - - )} - - - - ) : ( - - + + + + {t("back_to_bills")} + + + {bill.history.length > 0 ? ( + <> + + - - - {flags.notifications && user && ( - - )} - + + - )} - - - - - + + + {flags.notifications && user && ( + + )} + + + + ) : ( - - - - {flags.lobbyingTable && ( - - )} + + - - - - - {flags.billTracker && ( - - )} + + + {flags.notifications && user && ( + + )} + - - + )} + + + + + + + + + + {flags.lobbyingTable && ( + + )} + + + + + + {flags.billTracker && ( + + )} + + + ) } diff --git a/components/layout.tsx b/components/layout.tsx index 857673a18..6f3669e0c 100644 --- a/components/layout.tsx +++ b/components/layout.tsx @@ -6,6 +6,7 @@ import AuthModal from "./auth/AuthModal" import PageFooter from "./Footer/Footer" import { MainNavbar } from "./Navbar" import { TabContext, TabStatus } from "./shared/ProfileTabsContext" +import { FollowContext, OrgFollowStatus } from "./shared/FollowContext" export const PageContainer: FC> = ({ children @@ -36,6 +37,8 @@ export const Layout: React.FC> = ({ setIsClient(true) }, []) + const [followStatus, setFollowStatus] = useState({}) + return ( <> {isClient ? ( @@ -45,16 +48,18 @@ export const Layout: React.FC> = ({ - - - -
{children}
- -
+ + + + +
{children}
+ +
+
) : ( diff --git a/components/testimony/TestimonyDetailPage/PolicyActions.tsx b/components/testimony/TestimonyDetailPage/PolicyActions.tsx index 0ec7557b5..90d8c4d52 100644 --- a/components/testimony/TestimonyDetailPage/PolicyActions.tsx +++ b/components/testimony/TestimonyDetailPage/PolicyActions.tsx @@ -2,16 +2,22 @@ import { Card, ListItem, ListItemProps } from "components/Card" import { useFlags } from "components/featureFlags" import { formatBillId } from "components/formatting" import { formUrl } from "components/publish" -import { isNotNull } from "components/utils" -import { FC, ReactElement } from "react" +import { FC, ReactElement, useContext, useEffect } from "react" import { useCurrentTestimonyDetails } from "./testimonyDetailSlice" import { useTranslation } from "next-i18next" +import { useAuth } from "components/auth" +import { TopicQuery } from "components/shared/FollowingQueries" +import { StyledImage } from "components/ProfilePage/StyledProfileComponents" +import { FollowContext } from "components/shared/FollowContext" interface PolicyActionsProps { className?: string isUser?: boolean isReporting: boolean setReporting: (boolean: boolean) => void + topicName: string + followAction: () => Promise + unfollowAction: () => Promise } const PolicyActionItem: FC> = props => ( @@ -22,19 +28,57 @@ export const PolicyActions: FC> = ({ className, isUser, isReporting, - setReporting + setReporting, + topicName, + followAction, + unfollowAction }) => { const { bill } = useCurrentTestimonyDetails(), billLabel = formatBillId(bill.id) const { notifications } = useFlags() + const { user } = useAuth() + const uid = user?.uid + + const { followStatus, setFollowStatus } = useContext(FollowContext) + + useEffect(() => { + uid + ? TopicQuery(uid, topicName).then(result => { + setFollowStatus(prevOrgFollowGroup => { + return { ...prevOrgFollowGroup, [topicName]: Boolean(result) } + }) + }) + : null + }, [uid, topicName, setFollowStatus]) + + const FollowClick = async () => { + await followAction() + setFollowStatus({ ...followStatus, [topicName]: true }) + } + + const UnfollowClick = async () => { + await unfollowAction() + setFollowStatus({ ...followStatus, [topicName]: false }) + } + + const isFollowing = followStatus[topicName] + const text = isFollowing ? "Unfollow" : "Follow" + const checkmark = isFollowing ? ( + + ) : null + const handleClick = (event: React.MouseEvent) => { + event.preventDefault() + isFollowing ? UnfollowClick() : FollowClick() + } + const items: ReactElement[] = [] if (notifications) items.push( window.alert("TODO")} // TODO: add follow action here + onClick={e => handleClick(e)} key="follow" - billName={`Follow ${billLabel}`} + billName={`${text} ${billLabel}`} /> ) items.push( diff --git a/components/testimony/TestimonyDetailPage/TestimonyDetailPage.tsx b/components/testimony/TestimonyDetailPage/TestimonyDetailPage.tsx index 0e96e1c98..82a76d9f5 100644 --- a/components/testimony/TestimonyDetailPage/TestimonyDetailPage.tsx +++ b/components/testimony/TestimonyDetailPage/TestimonyDetailPage.tsx @@ -15,6 +15,7 @@ import { TestimonyDetail } from "./TestimonyDetail" import { VersionBanner } from "./TestimonyVersionBanner" import { useAuth } from "components/auth" import { useMediaQuery } from "usehooks-ts" +import { setFollow, setUnfollow } from "components/shared/FollowingQueries" export const TestimonyDetailPage: FC> = () => { const [isReporting, setIsReporting] = useState(false) @@ -22,12 +23,19 @@ export const TestimonyDetailPage: FC> = () => { const didReport = reportMutation.isError || reportMutation.isSuccess const isMobile = useMediaQuery("(max-width: 768px)") const { authorUid, revision } = useCurrentTestimonyDetails() + const { bill } = useCurrentTestimonyDetails() const { user } = useAuth() const isUser = user?.uid === authorUid const handleReporting = (boolean: boolean) => { setIsReporting(boolean) } const { t } = useTranslation("testimony", { keyPrefix: "reportModal" }) + const uid = user?.uid + const { id: billId, court: courtId } = bill + const topicName = `bill-${courtId}-${billId}` + const followAction = () => + setFollow(uid, topicName, bill, billId, courtId, undefined) + const unfollowAction = () => setUnfollow(uid, topicName) return ( <> @@ -49,6 +57,9 @@ export const TestimonyDetailPage: FC> = () => { isUser={isUser} isReporting={isReporting} setReporting={handleReporting} + topicName={topicName} + followAction={followAction} + unfollowAction={unfollowAction} /> )}