Skip to content

Commit 021dc95

Browse files
committed
vibe-coded first go
1 parent b6e19b9 commit 021dc95

File tree

3 files changed

+112
-3
lines changed

3 files changed

+112
-3
lines changed

components/EditProfilePage/EditProfilePage.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@ import { TestimoniesTab } from "./TestimoniesTab"
2727
import { useFlags } from "components/featureFlags"
2828
import LoginPage from "components/Login/login"
2929
import { PendingUpgradeBanner } from "components/PendingUpgradeBanner"
30+
import { FollowersTab } from "./FollowersTab"
3031

31-
const tabTitle = ["about-you", "testimonies", "following"] as const
32+
const tabTitle = ["about-you", "testimonies", "following", "followers"] as const
3233
export type TabTitles = (typeof tabTitle)[number]
3334

3435
export default function EditProfile({
@@ -145,6 +146,11 @@ export function EditProfileForm({
145146
title: t("tabs.following"),
146147
eventKey: "following",
147148
content: <FollowingTab className="mt-3 mb-4" />
149+
},
150+
{
151+
title: t("followersWithCount", { count: 1 }),
152+
eventKey: "followers",
153+
content: <FollowersTab className="mt-3 mb-4" />
148154
}
149155
]
150156

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { useTranslation } from "next-i18next"
2+
import { useEffect, useMemo, useState } from "react"
3+
import { useAuth } from "../auth"
4+
import { Stack } from "../bootstrap"
5+
import { firestore } from "../firebase"
6+
import {
7+
collection,
8+
collectionGroup,
9+
getDocs,
10+
query,
11+
where,
12+
addDoc
13+
} from "firebase/firestore"
14+
import { FollowedItem, UserElement } from "./FollowingTabComponents"
15+
import { UnfollowModalConfig } from "./UnfollowModal"
16+
17+
export const FollowersTab = ({ className }: { className?: string }) => {
18+
const { user } = useAuth()
19+
const uid = user?.uid
20+
21+
// NEW: build a query over the collection group
22+
const followersQuery = useMemo(
23+
() =>
24+
uid
25+
? query(
26+
collectionGroup(firestore, "activeTopicSubscriptions"),
27+
where("uid", "==", uid), // they follow *me*
28+
where("type", "==", "testimony") // user-to-user follows only
29+
)
30+
: null,
31+
[uid]
32+
)
33+
34+
// query for people *I* follow so we can decide button state
35+
const myFollowsQuery = useMemo(
36+
() =>
37+
uid
38+
? query(
39+
collection(firestore, `/users/${uid}/activeTopicSubscriptions/`),
40+
where("uid", "==", uid),
41+
where("type", "==", "testimony")
42+
)
43+
: null,
44+
[uid]
45+
)
46+
const [iFollowSet, setIFollowSet] = useState<Set<string>>(new Set())
47+
48+
const [followers, setFollowers] = useState<UserElement[]>([])
49+
50+
useEffect(() => {
51+
if (!followersQuery) return
52+
;(async () => {
53+
const qs = await getDocs(followersQuery)
54+
const list: UserElement[] = []
55+
qs.forEach(doc => list.push(doc.data().userLookup)) // same field used elsewhere
56+
setFollowers(list)
57+
})()
58+
}, [followersQuery])
59+
60+
useEffect(() => {
61+
if (!myFollowsQuery) return
62+
;(async () => {
63+
const qs = await getDocs(myFollowsQuery)
64+
const ids = new Set<string>()
65+
qs.forEach(doc => ids.add(doc.data().userLookup.uid))
66+
setIFollowSet(ids)
67+
})()
68+
}, [myFollowsQuery])
69+
70+
const [unfollow, setUnfollow] = useState<UnfollowModalConfig | null>(null)
71+
72+
const { t } = useTranslation("editProfile")
73+
74+
return (
75+
<Stack>
76+
<h2 className={className ? `pb-3 ${className}` : "pb-3"}>
77+
{t("follow.orgs")}
78+
</h2>
79+
{followers.map(element => (
80+
<FollowedItem
81+
key={element.profileId}
82+
element={element}
83+
alreadyFollowing={iFollowSet.has(element.profileId)}
84+
setFollow={async (targetUid: string) => {
85+
if (!uid || iFollowSet.has(targetUid)) return
86+
await addDoc(
87+
collection(firestore, `/users/${uid}/activeTopicSubscriptions/`),
88+
{
89+
uid,
90+
type: "testimony",
91+
userLookup: { uid: targetUid }
92+
}
93+
)
94+
setIFollowSet(new Set([...iFollowSet, targetUid]))
95+
}}
96+
setUnfollow={setUnfollow}
97+
type="org"
98+
/>
99+
))}
100+
</Stack>
101+
)
102+
}

public/locales/en/editProfile.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"enabled": "Enabled",
99
"disable": "Disable",
1010
"disabled": "Disabled",
11+
"followersWithCount": "Followers ({{count}})",
1112
"viewMyProfile": "View My Profile",
1213
"viewOrgProfile": "View My Organization",
1314
"saveChanges": "Save Personal Information",
@@ -38,7 +39,7 @@
3839
"weekly": "Weekly",
3940
"monthly": "Monthly"
4041
},
41-
"emailIconAlt":"open envelope with letter, toggles update frequency options",
42+
"emailIconAlt": "open envelope with letter, toggles update frequency options",
4243
"legislator": {
4344
"representative": "Representative",
4445
"searchRepresentative": "Search your representative",
@@ -100,4 +101,4 @@
100101
"admin": "Your profile is currently public. Others can view your profile page. Admin accounts cannot set their profile to private.",
101102
"default": "The publicity of your profile is unknown. Please contact the admin for more information."
102103
}
103-
}
104+
}

0 commit comments

Comments
 (0)