Skip to content

Commit

Permalink
pagination and safer context return
Browse files Browse the repository at this point in the history
  • Loading branch information
jurajpiar committed Nov 21, 2024
1 parent 6b037a2 commit 2896f36
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,8 @@ import { AddressOrAlias } from '@/components/Address'
import { Badge } from '@/components/Badge'
import { Jdenticon } from '@/components/Header/Jdenticon'
import { Paragraph, Typography } from '@/components/Typography'
import {
BuilderInfo,
BuilderStatus,
BuilderStatusActive,
BuilderStatusShown,
} from '@/app/collective-rewards/types'
import { BuilderInfo, BuilderStatusActive, BuilderStatusShown } from '@/app/collective-rewards/types'
import { crStatusColorClasses } from '@/app/collective-rewards/user'
import { Address } from 'viem'
import { FC } from 'react'

export type BuilderAllocationHeaderProps = Pick<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ export const AllocationsContextProvider: FC<{ children: ReactNode }> = ({ childr
}
}, [allAllocations, builders, totalAllocation, votingPower, isContextLoading, selections])

const data: AllocationsContextValue = {
const state: AllocationsContextValue = {
selections,
allocations,
backer,
Expand All @@ -208,7 +208,7 @@ export const AllocationsContextProvider: FC<{ children: ReactNode }> = ({ childr
<AllocationsContext.Provider
value={{
initialState,
state: data,
state,
actions,
}}
>
Expand Down
36 changes: 28 additions & 8 deletions src/app/collective-rewards/context/PaginatedDataContext.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,39 @@
import { Context, createContext, FC, useContext, useEffect, useState } from 'react'
import { Context, createContext, FC, useContext, useEffect, useMemo, useState } from 'react'

type PaginationConfig<T> = {
data: T[]
pageSize: number
currentPage: number
}

type PaginatedData<T extends Object = {}> = PaginationConfig<T> & {
type State<T extends Object = {}> = PaginationConfig<T> & {
pageCount: number
}

type Actions<T extends Object = {}> = {
getDataIndex: (index: number) => number
getPage: (page?: number) => T[]
updateData: (data: T[]) => void
updatePageSize: (pageSize: number) => void
updateCurrentPage: (currentPage: number) => void
}

export const PaginatedDataContext = createContext<PaginatedData<any>>({
type PageContext<T extends Object = {}> = State<T> & Actions<T>

export const PaginatedDataContext = createContext<PageContext<any>>({
data: [],
pageSize: 0,
currentPage: 0,
pageCount: 0,
getDataIndex: () => 0,
getPage: () => [],
updateData: () => {},
updatePageSize: () => {},
updateCurrentPage: () => {},
})

export const usePaginatedDataContext = <T extends Object = {}>() => {
const context = useContext<PaginatedData<T>>(PaginatedDataContext)
const context = useContext<PageContext<T>>(PaginatedDataContext)
if (!context) {
throw new Error('usePaginatedDataContext must be used within a PaginatedDataContextProvider')
}
Expand All @@ -41,17 +50,28 @@ export const PaginatedDataContextProvider: FC<PaginatedDataContextProviderProps>
const [pageSize, setPageSize] = useState(config.pageSize)
const [currentPage, setCurrentPage] = useState(config.currentPage)

const contextMethods = {
const state = {
data,
pageSize,
currentPage,
pageCount: useMemo(() => Math.ceil(data.length / pageSize), [data, pageSize]),
}
const actions = {
getDataIndex: (pagedIndex: number) => pagedIndex + pageSize * currentPage,
getPage: (page?: number) => {
const pageIndex = page ?? currentPage
const start = pageIndex * pageSize
const end = start + pageSize

return data.slice(start, end)
},
updateData: (newData: typeof data) => setData(newData),
updatePageSize: (newPageSize: number) => setPageSize(newPageSize),
updateCurrentPage: (newCurrentPage: number) => setCurrentPage(newCurrentPage),
}

return (
<PaginatedDataContext.Provider value={{ data, pageSize, currentPage, ...contextMethods }}>
{children}
</PaginatedDataContext.Provider>
<PaginatedDataContext.Provider value={{ ...state, ...actions }}>{children}</PaginatedDataContext.Provider>
)
}

Expand Down
33 changes: 33 additions & 0 deletions src/app/collective-rewards/shared/components/Pagination.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { FC, useContext } from 'react'
import { PaginatedDataContext } from '@/app/collective-rewards/context/PaginatedDataContext'
import { PaginationButton } from './PaginationButton'
import { ChevronLeft, ChevronRight } from 'lucide-react'

export const Pagination: FC = () => {
const { currentPage, pageCount, updateCurrentPage } = useContext(PaginatedDataContext)

return (
<div className="flex gap-x-1 items-center justify-center">
<PaginationButton
text={<ChevronLeft />}
onClick={() => updateCurrentPage(currentPage - 1)}
disabled={currentPage === 0}
/>
{Array(pageCount)
.fill(1)
.map((_, pageNumber) => (
<PaginationButton
key={pageNumber}
onClick={() => updateCurrentPage(pageNumber)}
text={pageNumber + 1}
isActive={pageNumber === currentPage}
/>
))}
<PaginationButton
text={<ChevronRight />}
onClick={() => updateCurrentPage(currentPage + 1)}
disabled={currentPage === pageCount - 1}
/>
</div>
)
}
13 changes: 13 additions & 0 deletions src/app/collective-rewards/shared/components/PaginationButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Button } from '@/components/Button'
import { FC, ReactNode } from 'react'

export const PaginationButton: FC<{
text: ReactNode
onClick: () => void
disabled?: boolean
isActive?: boolean
}> = ({ text, onClick, disabled, isActive }) => (
<Button onClick={onClick} disabled={disabled} variant={isActive ? 'pagination-active' : 'pagination'}>
{text}
</Button>
)
3 changes: 2 additions & 1 deletion src/app/collective-rewards/shared/components/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './Table'
export * from './Pagination'
export * from './PaginationButton'

0 comments on commit 2896f36

Please sign in to comment.