feat(LOY-53): CurrentRewards - replace show more functionality with pagination

This commit is contained in:
Chuma McPhoy
2024-12-02 21:11:53 +01:00
parent 9e42cf0f37
commit 28d4d752e9
11 changed files with 124 additions and 167 deletions
@@ -6,9 +6,9 @@ import { useState } from "react"
import { trpc } from "@/lib/trpc/client"
import LoadingSpinner from "@/components/LoadingSpinner"
import Pagination from "@/components/MyPages/Pagination"
import ClientTable from "./ClientTable"
import Pagination from "./Pagination"
import { Transactions } from "@/types/components/myPages/myPage/earnAndBurn"
@@ -1,72 +0,0 @@
import { ChevronRightIcon } from "@/components/Icons"
import styles from "./pagination.module.css"
import {
PaginationButtonProps,
PaginationProps,
} from "@/types/components/myPages/myPage/earnAndBurn"
function PaginationButton({
children,
isActive,
handleClick,
disabled,
}: React.PropsWithChildren<PaginationButtonProps>) {
return (
<button
type={"button"}
disabled={disabled}
onClick={handleClick}
className={`${styles.paginationButton} ${isActive ? styles.paginationButtonActive : ""}`}
>
{children}
</button>
)
}
export default function Pagination({
pageCount,
isFetching,
handlePageChange,
currentPage,
}: PaginationProps) {
const isOnFirstPage = currentPage === 1
const isOnLastPage = currentPage === pageCount
return (
<div className={styles.pagination}>
<PaginationButton
disabled={isFetching || isOnFirstPage}
handleClick={() => {
handlePageChange(currentPage - 1)
}}
>
<ChevronRightIcon
className={styles.chevronLeft}
height={20}
width={20}
/>
</PaginationButton>
{[...Array(pageCount)].map((_, idx) => (
<PaginationButton
isActive={currentPage === idx + 1}
disabled={isFetching || currentPage === idx + 1}
key={idx}
handleClick={() => {
handlePageChange(idx + 1)
}}
>
{idx + 1}
</PaginationButton>
))}
<PaginationButton
disabled={isFetching || isOnLastPage}
handleClick={() => {
handlePageChange(currentPage + 1)
}}
>
<ChevronRightIcon height={20} width={20} />
</PaginationButton>
</div>
)
}
@@ -1,40 +0,0 @@
.pagination {
display: flex;
justify-content: left;
padding: var(--Spacing-x2);
background-color: var(--Base-Surface-Primary-light-Normal);
border-radius: var(--Corner-radius-Rounded);
margin: auto;
gap: var(--Spacing-x5);
max-width: 100%;
overflow-x: auto;
}
.paginationButton {
background-color: transparent;
border: none;
cursor: pointer;
height: 32px;
width: 32px;
font-size: var(--typography-Body-Bold-fontSize);
font-weight: var(--typography-Body-Bold-fontWeight);
padding: 0;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.paginationButton[disabled] {
cursor: not-allowed;
}
.chevronLeft {
transform: rotate(180deg);
height: 100%;
}
.paginationButtonActive {
color: var(--WHITE);
background-color: var(--Base-Text-Accent);
border-radius: var(--Corner-radius-Rounded);
}
@@ -1,14 +1,11 @@
"use client"
import { trpc } from "@/lib/trpc/client"
import { Reward } from "@/server/routers/contentstack/reward/output"
import { useState } from "react"
import Image from "@/components/Image"
import LoadingSpinner from "@/components/LoadingSpinner"
import Pagination from "@/components/MyPages/Pagination"
import Grids from "@/components/TempDesignSystem/Grids"
import ShowMoreButton from "@/components/TempDesignSystem/ShowMoreButton"
import Title from "@/components/TempDesignSystem/Text/Title"
import useLang from "@/hooks/useLang"
import Redeem from "./Redeem"
@@ -17,46 +14,21 @@ import styles from "./current.module.css"
import type { CurrentRewardsClientProps } from "@/types/components/myPages/myPage/accountPage"
export default function ClientCurrentRewards({
initialCurrentRewards,
rewards,
pageSize,
showRedeem,
}: CurrentRewardsClientProps) {
const lang = useLang()
const { data, isFetching, fetchNextPage, hasNextPage, isLoading } =
trpc.contentstack.rewards.current.useInfiniteQuery(
{
limit: 3,
lang,
},
{
getNextPageParam: (lastPage) => lastPage?.nextCursor,
initialData: {
pageParams: [undefined, 1],
pages: [initialCurrentRewards],
},
}
)
function loadMoreData() {
if (hasNextPage) {
fetchNextPage()
}
}
const filteredRewards = data?.pages.filter((page) => page?.rewards) ?? []
const rewards = filteredRewards
.flatMap((page) => page?.rewards)
.filter((reward): reward is Reward => !!reward)
const [currentPage, setCurrentPage] = useState(1)
if (isLoading) {
return <LoadingSpinner />
}
if (!rewards.length) {
return null
}
const totalPages = Math.ceil(rewards.length / pageSize)
const startIndex = (currentPage - 1) * pageSize
const endIndex = startIndex + pageSize
const currentRewards = rewards.slice(startIndex, endIndex)
return (
<div>
<div className={styles.container}>
<Grids.Stackable>
{rewards.map((reward, idx) => (
{currentRewards.map((reward, idx) => (
<article className={styles.card} key={`${reward.reward_id}-${idx}`}>
<div className={styles.content}>
<Image
@@ -82,12 +54,11 @@ export default function ClientCurrentRewards({
</article>
))}
</Grids.Stackable>
{hasNextPage &&
(isFetching ? (
<LoadingSpinner />
) : (
<ShowMoreButton loadMoreData={loadMoreData} />
))}
<Pagination
pageCount={totalPages}
currentPage={currentPage}
handlePageChange={setCurrentPage}
/>
</div>
)
}
@@ -123,3 +123,9 @@
display: flex;
align-items: center;
}
.container {
display: flex;
flex-direction: column;
gap: var(--Spacing-x4);
}
@@ -14,12 +14,9 @@ export default async function CurrentRewardsBlock({
subtitle,
link,
}: AccountPageComponentProps) {
const initialCurrentRewards =
await serverClient().contentstack.rewards.current({
limit: 3,
})
const rewardsResponse = await serverClient().contentstack.rewards.current()
if (!initialCurrentRewards) {
if (!rewardsResponse?.rewards.length) {
return null
}
@@ -27,7 +24,8 @@ export default async function CurrentRewardsBlock({
<SectionContainer>
<SectionHeader title={title} link={link} preamble={subtitle} />
<ClientCurrentRewards
initialCurrentRewards={initialCurrentRewards}
rewards={rewardsResponse.rewards}
pageSize={6}
showRedeem={env.USE_NEW_REWARDS_ENDPOINT}
/>
<SectionLink link={link} variant="mobile" />