Skip to content

Commit 9aafef5

Browse files
author
chaoyi09
committed
feat: add pagination to Edit Profile page sections
1 parent 1928689 commit 9aafef5

File tree

5 files changed

+111
-30
lines changed

5 files changed

+111
-30
lines changed

components/EditProfilePage/EditProfilePage.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,9 @@ export function EditProfileForm({
134134
content: (
135135
<TestimoniesTab
136136
publishedTestimonies={publishedTestimonies.items.result ?? []}
137-
draftTestimonies={draftTestimonies.result ?? []}
137+
publishedTestimoniesPagination={publishedTestimonies.pagination}
138+
draftTestimonies={draftTestimonies.items.result ?? []}
139+
draftTestimoniesPagination={draftTestimonies.pagination}
138140
/>
139141
)
140142
},

components/EditProfilePage/FollowingTab.tsx

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { collection, getDocs, query, where } from "firebase/firestore"
2-
import { getFunctions } from "firebase/functions"
32
import { useTranslation } from "next-i18next"
43
import { useCallback, useEffect, useMemo, useState } from "react"
54
import { useAuth } from "../auth"
@@ -10,6 +9,7 @@ import UnfollowItem, { UnfollowModalConfig } from "./UnfollowModal"
109
import { FollowedItem } from "./FollowingTabComponents"
1110
import { BillElement, UserElement } from "./FollowingTabComponents"
1211
import { deleteItem } from "components/shared/FollowingQueries"
12+
import { PaginationButtons } from "../table"
1313

1414
export function FollowingTab({ className }: { className?: string }) {
1515
const { user } = useAuth()
@@ -29,6 +29,10 @@ export function FollowingTab({ className }: { className?: string }) {
2929
const [billsFollowing, setBillsFollowing] = useState<BillElement[]>([])
3030
const [usersFollowing, setUsersFollowing] = useState<UserElement[]>([])
3131

32+
const [currentBillsPage, setCurrentBillsPage] = useState(1)
33+
const [currentUsersPage, setCurrentUsersPage] = useState(1)
34+
const itemsPerPage = 10
35+
3236
const billsFollowingQuery = useCallback(async () => {
3337
if (!subscriptionRef) return // handle the case where subscriptionRef is null
3438
const billList: BillElement[] = []
@@ -42,14 +46,12 @@ export function FollowingTab({ className }: { className?: string }) {
4246
// doc.data() is never undefined for query doc snapshots
4347
billList.push(doc.data().billLookup)
4448
})
45-
if (billsFollowing.length === 0 && billList.length != 0) {
46-
setBillsFollowing(billList)
47-
}
48-
}, [subscriptionRef, uid, billsFollowing])
49+
setBillsFollowing(billList)
50+
}, [subscriptionRef, uid])
4951

5052
useEffect(() => {
5153
uid ? billsFollowingQuery() : null
52-
})
54+
}, [uid, billsFollowingQuery])
5355

5456
const orgsFollowingQuery = useCallback(async () => {
5557
if (!subscriptionRef) return // handle the case where subscriptionRef is null
@@ -104,6 +106,21 @@ export function FollowingTab({ className }: { className?: string }) {
104106
setUnfollow(null)
105107
}
106108

109+
const getPaginatedBills = () => {
110+
const startIndex = (currentBillsPage - 1) * itemsPerPage
111+
const endIndex = startIndex + itemsPerPage
112+
return billsFollowing.slice(startIndex, endIndex)
113+
}
114+
115+
const getPaginatedUsers = () => {
116+
const startIndex = (currentUsersPage - 1) * itemsPerPage
117+
const endIndex = startIndex + itemsPerPage
118+
return usersFollowing.slice(startIndex, endIndex)
119+
}
120+
121+
const totalBillsPages = Math.ceil(billsFollowing.length / itemsPerPage)
122+
const totalUsersPages = Math.ceil(usersFollowing.length / itemsPerPage)
123+
107124
const { t } = useTranslation("editProfile")
108125

109126
return (
@@ -112,7 +129,7 @@ export function FollowingTab({ className }: { className?: string }) {
112129
<div className={`mx-4 mt-3 d-flex flex-column gap-3`}>
113130
<Stack>
114131
<h2>{t("follow.bills")}</h2>
115-
{billsFollowing.map((element: BillElement, index: number) => (
132+
{getPaginatedBills().map((element: BillElement, index: number) => (
116133
<FollowedItem
117134
key={index}
118135
index={index}
@@ -121,14 +138,26 @@ export function FollowingTab({ className }: { className?: string }) {
121138
type={"bill"}
122139
/>
123140
))}
141+
{billsFollowing.length > 0 && (
142+
<PaginationButtons
143+
pagination={{
144+
currentPage: currentBillsPage,
145+
hasNextPage: currentBillsPage < totalBillsPages,
146+
hasPreviousPage: currentBillsPage > 1,
147+
nextPage: () => setCurrentBillsPage(prev => prev + 1),
148+
previousPage: () => setCurrentBillsPage(prev => prev - 1),
149+
itemsPerPage
150+
}}
151+
/>
152+
)}
124153
</Stack>
125154
</div>
126155
</TitledSectionCard>
127156
<TitledSectionCard className={`${className}`}>
128157
<div className={`mx-4 mt-3 d-flex flex-column gap-3`}>
129158
<Stack>
130159
<h2 className="pb-3">{t("follow.orgs")}</h2>
131-
{usersFollowing.map((element: UserElement, index: number) => (
160+
{getPaginatedUsers().map((element: UserElement, index: number) => (
132161
<FollowedItem
133162
key={index}
134163
index={index}
@@ -137,6 +166,18 @@ export function FollowingTab({ className }: { className?: string }) {
137166
type={"org"}
138167
/>
139168
))}
169+
{usersFollowing.length > 0 && (
170+
<PaginationButtons
171+
pagination={{
172+
currentPage: currentUsersPage,
173+
hasNextPage: currentUsersPage < totalUsersPages,
174+
hasPreviousPage: currentUsersPage > 1,
175+
nextPage: () => setCurrentUsersPage(prev => prev + 1),
176+
previousPage: () => setCurrentUsersPage(prev => prev - 1),
177+
itemsPerPage
178+
}}
179+
/>
180+
)}
140181
</Stack>
141182
</div>
142183
</TitledSectionCard>

components/EditProfilePage/TestimoniesTab.tsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,21 @@ import { TitledSectionCard } from "../shared"
44
import { TestimonyItem } from "components/TestimonyCard/TestimonyItem"
55
import { SortTestimonyDropDown } from "components/TestimonyCard/SortTestimonyDropDown"
66
import { TestimonyFAQ } from "./TestimonyFAQ"
7-
import { Testimony } from "../db"
7+
import { Testimony, DraftTestimony, Pagination } from "../db"
88
import { useTranslation } from "next-i18next"
9+
import { PaginationButtons } from "../table"
910

1011
export const TestimoniesTab = ({
1112
publishedTestimonies,
13+
publishedTestimoniesPagination,
1214
draftTestimonies,
15+
draftTestimoniesPagination,
1316
className
1417
}: {
1518
publishedTestimonies: Testimony[]
16-
draftTestimonies: Testimony[]
19+
publishedTestimoniesPagination?: Pagination
20+
draftTestimonies: DraftTestimony[]
21+
draftTestimoniesPagination?: Pagination
1722
className?: string
1823
}) => {
1924
const [orderBy, setOrderBy] = useState<string>()
@@ -58,17 +63,23 @@ export const TestimoniesTab = ({
5863
onProfilePage={true}
5964
/>
6065
))}
66+
{publishedTestimoniesPagination && (
67+
<PaginationButtons pagination={publishedTestimoniesPagination} />
68+
)}
6169
</TitledSectionCard>
6270
<TitledSectionCard className="mt-3 mb-4">
6371
<h2>{t("testimonies.draft")}</h2>
6472
{draftTestimonies.map(t => (
6573
<TestimonyItem
66-
key={t.authorUid + t.billId + t.publishedAt}
67-
testimony={t}
74+
key={t.billId + t.court + t.position}
75+
testimony={t as any}
6876
isUser={true}
6977
onProfilePage={true}
7078
/>
7179
))}
80+
{draftTestimoniesPagination && (
81+
<PaginationButtons pagination={draftTestimoniesPagination} />
82+
)}
7283
</TitledSectionCard>
7384
</Col>
7485
<Col>
Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,56 @@
1-
import { getDocs, collection } from "firebase/firestore"
1+
import {
2+
getDocs,
3+
collection,
4+
limit,
5+
startAfter,
6+
orderBy
7+
} from "firebase/firestore"
28
import { firestore } from "../../firebase"
39
import { nullableQuery } from "../common"
4-
import { Testimony } from "./types"
5-
import { useAsync } from "react-async-hook"
10+
import { DraftTestimony } from "./types"
11+
import { createTableHook } from "../createTableHook"
12+
13+
type Refinement = {
14+
uid: string
15+
}
16+
17+
const initialRefinement = (uid: string): Refinement => ({
18+
uid
19+
})
20+
21+
const useTable = createTableHook<DraftTestimony, Refinement, unknown>({
22+
getPageKey: i => i.billId,
23+
getItems: listTestimony,
24+
name: "draft testimony"
25+
})
626

727
export type UseDraftTestimonyListing = ReturnType<
828
typeof useDraftTestimonyListing
929
>
1030
export function useDraftTestimonyListing({ uid }: { uid: string }) {
11-
const items = useAsync(
12-
() => {
13-
return listTestimony(uid)
14-
},
15-
[uid],
16-
{
17-
onSuccess: data => data
18-
}
31+
const { pagination, items, refine, refinement } = useTable(
32+
initialRefinement(uid)
1933
)
2034

21-
return items
35+
return {
36+
pagination,
37+
items,
38+
refine
39+
}
2240
}
2341

24-
async function listTestimony(uid: string): Promise<Testimony[]> {
42+
async function listTestimony(
43+
refinement: Refinement,
44+
limitCount: number,
45+
startAfterKey: unknown | null
46+
): Promise<DraftTestimony[]> {
2547
const result = await getDocs(
26-
nullableQuery(collection(firestore, `/users/${uid}/draftTestimony`))
48+
nullableQuery(
49+
collection(firestore, `/users/${refinement.uid}/draftTestimony`),
50+
orderBy("billId"), // Draft doesn't have publishedAt, use billId instead
51+
limit(limitCount),
52+
startAfterKey !== null && startAfter(startAfterKey)
53+
)
2754
)
28-
return result.docs.map(d => d.data() as Testimony)
55+
return result.docs.map(d => d.data() as DraftTestimony)
2956
}

public/locales/en/editProfile.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
"error": "An error occured. Please refresh the page."
2424
},
2525
"follow": {
26-
"bills": "Bills You Follow",
27-
"orgs": "Users You Follow",
26+
"bills": "Bills I Follow",
27+
"orgs": "Users I Follow",
2828
"unfollow": "Unfollow"
2929
},
3030
"confirmation": {

0 commit comments

Comments
 (0)