Skip to content

Commit

Permalink
refactor: search context (#397)
Browse files Browse the repository at this point in the history
* refactor: search context

* chore: remove unused code and move filter fn outside component

* chore: add missing dependency

---------

Co-authored-by: Antonio <[email protected]>
  • Loading branch information
franciscotobar and antomor authored Nov 23, 2024
1 parent 0ef5f7e commit e341a2f
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,17 @@ export const isActive = (stateFlags?: BuilderStateFlags) => {
return activeFlags.some(flag => stateFlags?.[flag])
}

export type BuilderWithStatus = Builder & { builderStatus: 'active' | 'inProgress' }
const filterFunction = (builder: Builder, status: string) => {
if (status === 'all') return true
if (status === 'active') return isActive(builder.stateFlags)
if (status === 'inProgress') return !isActive(builder.stateFlags)
return false
}

export const ActiveBuildersContent = () => {
const { data: builders, isLoading, error } = useGetBuildersByState(undefined, true)
useHandleErrors({ error, title: 'Error loading builders' })

const buildersWithStatus = builders.map(builder => {
const builderStatus = isActive(builder.stateFlags) ? 'active' : 'inProgress'
return {
...builder,
builderStatus,
}
})

const status = [
{ label: 'All', value: 'all' },
{ label: 'Active', value: 'active' },
Expand All @@ -33,7 +30,7 @@ export const ActiveBuildersContent = () => {

return (
<>
<SearchContextProvider builders={buildersWithStatus}>
<SearchContextProvider builders={builders} filterFunction={filterFunction}>
<Search status={status} />
{withSpinner(ActiveBuildersGrid)({ isLoading })}
</SearchContextProvider>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { FC } from 'react'
import { ActiveBuildersGridItem, BuilderWithStatus } from '@/app/collective-rewards/active-builders'
import { ActiveBuildersGridItem } from '@/app/collective-rewards/active-builders'
import { useSearchContext } from '@/app/collective-rewards/shared'
import { Builder } from '@/app/collective-rewards/types'

export const ActiveBuildersGrid: FC = () => {
const { getValues } = useSearchContext()
const items = getValues<BuilderWithStatus>()
const { data: items } = useSearchContext<Builder>()

return (
<div className="grid grid-cols-3 gap-6">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import { Badge } from '@/components/Badge'
import { Popover } from '@/components/Popover'
import { Paragraph, Span, Typography } from '@/components/Typography'
import { useRouter } from 'next/navigation'
import { FC, ReactNode } from 'react'
import { FC, HtmlHTMLAttributes, ReactNode } from 'react'
import { Jdenticon } from '@/components/Header/Jdenticon'
import { shortAddress } from '@/lib/utils'
import { isAddress, Address } from 'viem'
import { crStatusColorClasses } from '@/app/collective-rewards/utils'
import { BuilderWithStatus } from '@/app/collective-rewards/active-builders'
import { Builder, BuilderState } from '@/app/collective-rewards/types'
import { isActive } from '@/app/collective-rewards/active-builders'

type ActiveBuildersGridItemProps = BuilderWithStatus
type ActiveBuildersGridItemProps = Builder

const Card = ({ header, body }: { header: ReactNode; body: ReactNode }) => {
return (
Expand All @@ -26,15 +26,21 @@ const builderStatusMap = {
inProgress: 'In Progress',
}

const crStatusColorClasses: Record<BuilderState, HtmlHTMLAttributes<HTMLSpanElement>['className']> = {
active: 'bg-[#DBFEE5] text-secondary',
inProgress: 'bg-[#4B5CF0] color-text-primary',
} as const

// TODO: this content can be moved to a different component and become a generic card
export const ActiveBuildersGridItem: FC<ActiveBuildersGridItemProps> = ({
address,
builderName,
builderStatus,
stateFlags,
proposal: { id: proposalId, date: joiningDate, name: proposalName },
}) => {
const router = useRouter()
const shortenAddress = shortAddress(address as Address)
const builderState = isActive(stateFlags) ? 'active' : 'inProgress'
const Header = (
<div className="flex flex-row w-full items-center gap-x-3 min-h-11">
<Jdenticon className="rounded-md bg-white" value={address} size="32" />
Expand All @@ -61,14 +67,14 @@ export const ActiveBuildersGridItem: FC<ActiveBuildersGridItemProps> = ({
/>
</Typography>
</Popover>
{builderStatus === 'active' && (
{builderState === 'active' && (
<Paragraph className="text-sm font-light"> Joined {joiningDate}</Paragraph>
)}
</div>
<div className="flex justify-center items-center">
<Badge
content={builderStatusMap[builderStatus]}
className={`${crStatusColorClasses[builderStatus]} py-1 px-2`}
content={builderStatusMap[builderState]}
className={`${crStatusColorClasses[builderState]} py-1 px-2`}
/>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { BuildersRewards } from '@/app/collective-rewards/rewards'
import { TableBody, TableCore, TableHead, TableRow } from '@/components/Table'
import { useBasicPaginationUi } from '@/shared/hooks/usePaginationUi'
import { FC, useContext, useEffect, useMemo, useState } from 'react'
import { FC, useMemo, useState } from 'react'
import {
ISortConfig,
TableHeader,
Expand All @@ -13,8 +13,6 @@ import {
TotalAllocationCell,
useSearchContext,
} from '@/app/collective-rewards/shared'
import { PaginatedDataContext } from '../context/PaginatedDataContext'
import { Pagination } from '../shared/components/Pagination'

enum RewardsColumnKeyEnum {
builder = 'builder',
Expand Down Expand Up @@ -42,8 +40,7 @@ const tableHeaders: TableHeader[] = [
]

export const BuildersLeaderBoardTable: FC = () => {
const { getValues } = useSearchContext()
const rewardsData = getValues<BuildersRewards>()
const { data: rewardsData } = useSearchContext<BuildersRewards>()

const [sortConfig, setSortConfig] = useState<ISortConfig>({
key: RewardsColumnKeyEnum.totalAllocationPercentage,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
RifSvg,
RbtcSvg,
} from '@/app/collective-rewards/rewards'
import { useBuilderContext } from '@/app/collective-rewards/user'
import { useGaugesGetFunction } from '@/app/collective-rewards//shared'
import { Address } from 'viem'
import { usePricesContext } from '@/shared/context/PricesContext'
Expand Down Expand Up @@ -73,8 +72,8 @@ export const useGetBackerRewards = (
const rbtcPrice = prices[rbtc.symbol]?.price ?? 0

const data = buildersV2.map(({ address, builderName, gauge, stateFlags }) => {
const builderTotalAllocation = totalAllocation[gauge]
const backerAllocationOf = allocationOf[gauge]
const builderTotalAllocation = totalAllocation[gauge] ?? 0n
const backerAllocationOf = allocationOf[gauge] ?? 0n
const totalAllocationPercentage = builderTotalAllocation
? (backerAllocationOf * 100n) / builderTotalAllocation
: 0n
Expand Down
47 changes: 30 additions & 17 deletions src/app/collective-rewards/shared/context/SearchContext.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
import { createContext, Dispatch, FC, ReactNode, SetStateAction, useContext, useMemo, useState } from 'react'
import {
Context,
createContext,
Dispatch,
ReactNode,
SetStateAction,
useContext,
useMemo,
useState,
} from 'react'

type StateWithUpdate<T> = {
value: T
onChange: Dispatch<SetStateAction<T>>
}

type SearchContextValue = {
getValues: <T>() => T[]
type SearchContextValue<Type> = {
data: Type[]
search: StateWithUpdate<string>
filterBy: StateWithUpdate<string>
}

export const SearchContext = createContext<SearchContextValue>({
getValues: () => [],
type SearchValue = { builderName: string; address: string }
export const SearchContext = createContext<SearchContextValue<SearchValue>>({
data: [],
search: {
value: '',
onChange: () => {},
Expand All @@ -23,14 +33,18 @@ export const SearchContext = createContext<SearchContextValue>({
},
})

type SearchValue = { builderName: string; address: string; builderStatus?: string }
type SearchProviderProps = {
type SearchProviderProps<T> = {
children: ReactNode
builders: SearchValue[]
builders: T[]
filterFunction?: (param: T, status: string) => boolean
}

const lowerCaseCompare = (a: string, b: string) => a?.toLowerCase().includes(b?.toLowerCase())
export const SearchContextProvider: FC<SearchProviderProps> = ({ children, builders }) => {
export const SearchContextProvider = <T extends SearchValue>({
children,
builders,
filterFunction,
}: SearchProviderProps<T>) => {
const [search, setSearch] = useState('')
const [filterBy, setFilterBy] = useState('all')

Expand All @@ -46,22 +60,21 @@ export const SearchContextProvider: FC<SearchProviderProps> = ({ children, build
)
}

if (filterBy !== 'all') {
filteredBuilders = filteredBuilders.filter(builder => builder.builderStatus === filterBy)
if (filterBy !== 'all' && filterFunction) {
filteredBuilders = filteredBuilders.filter(builder => filterFunction(builder, filterBy))
}

return filteredBuilders
}, [builders, search, filterBy])
}, [builders, search, filterBy, filterFunction])

const getValues = <T,>() => data as T[]

const valueOfContext: SearchContextValue = {
getValues,
const valueOfContext: SearchContextValue<T> = {
data,
search: { value: search, onChange: setSearch },
filterBy: { value: filterBy, onChange: setFilterBy },
}

return <SearchContext.Provider value={valueOfContext}>{children}</SearchContext.Provider>
}

export const useSearchContext = () => useContext(SearchContext)
export const useSearchContext = <T extends SearchValue>() =>
useContext(SearchContext as unknown as Context<SearchContextValue<T>>)
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { BuilderState, BuilderStateFlags } from '@/app/collective-rewards/types'
import { useHandleErrors } from '@/app/collective-rewards/utils'

type StatusBadgeProps = {
builderStatus?: BuilderState
builderState?: BuilderState
}

const BuilderRegistrationButton = () => {
Expand All @@ -24,7 +24,7 @@ const BuilderRegistrationButton = () => {
)
}

const StatusBadge: FC<StatusBadgeProps> = ({ builderStatus }) => {
const StatusBadge: FC<StatusBadgeProps> = ({ builderState }) => {
const InProgressComponent = (
<Badge content="In Progress" className="bg-[#4B5CF0] color-text-primary py-2 px-1" />
)
Expand All @@ -38,7 +38,7 @@ const StatusBadge: FC<StatusBadgeProps> = ({ builderStatus }) => {
inProgress: InProgressComponent,
active: WhitelistedComponent,
undefined: BuilderRegistrationButton,
}[builderStatus as BuilderState]
}[builderState as BuilderState]
}

const getBuilderState = (builderStateFlags?: BuilderStateFlags): BuilderState => {
Expand All @@ -51,7 +51,7 @@ export const BecomeABuilderHandler = ({ address }: { address: Address }) => {
const { getBuilderByAddress, isLoading: builderLoading, error: builderLoadingError } = useBuilderContext()

const builder = getBuilderByAddress(address)
const builderStatus = getBuilderState(builder?.stateFlags)
const builderState = getBuilderState(builder?.stateFlags)

useHandleErrors({ error: builderLoadingError, title: `Error loading builder with address ${address}` })

Expand All @@ -63,7 +63,7 @@ export const BecomeABuilderHandler = ({ address }: { address: Address }) => {
return <BuilderRegistrationButton />
}

return <StatusBadge builderStatus={builderStatus} />
return <StatusBadge builderState={builderState} />
}

export const BecomeABuilderButton = ({ address }: { address: Address }) => {
Expand Down
13 changes: 0 additions & 13 deletions src/app/collective-rewards/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,6 @@
import { HtmlHTMLAttributes } from 'react'
import { BuilderState } from '../types'

export * from './applyPrecision'
export * from './getBuilderGauge'
export * from './getBuilderState'
export * from './getCoinbaseAddress'
export * from './getMostAdvancedProposal'
export * from './handleErrors'

export const crStatusLabels: Record<BuilderState, string> = {
active: 'Active',
inProgress: 'In Progress',
} as const

export const crStatusColorClasses: Record<BuilderState, HtmlHTMLAttributes<HTMLSpanElement>['className']> = {
active: 'bg-[#DBFEE5] text-secondary',
inProgress: 'bg-[#4B5CF0] color-text-primary',
} as const

0 comments on commit e341a2f

Please sign in to comment.