Skip to content

Commit

Permalink
fix(RoleRequirements): properly display "Some secret requirements" (#…
Browse files Browse the repository at this point in the history
…1416)

* fix(RoleRequirements): properly display "Some hidden requirements"

* fix: show only one "Some hidden requirements" UI in the virtual list

* fix: rename `hiddenRequirements` to `notShownRequirements`
  • Loading branch information
BrickheadJohnny authored Jul 29, 2024
1 parent e6e354b commit 88602f7
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 43 deletions.
79 changes: 53 additions & 26 deletions src/components/[guild]/Requirements/RoleRequirements.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import {
Box,
Collapse,
Icon,
SlideFade,
VStack,
useColorModeValue,
} from "@chakra-ui/react"
import { Logic } from "@guildxyz/types"
import { Question } from "@phosphor-icons/react"
import React, {
Fragment,
memo,
Expand All @@ -15,13 +16,14 @@ import React, {
useRef,
} from "react"
import { VariableSizeList } from "react-window"
import { Requirement, Role } from "types"
import { Role } from "types"
import LogicDivider from "../LogicDivider"
import { RoleCardCollapseProps } from "../RoleCard"
import useRequirements from "../hooks/useRequirements"
import AnyOfHeader from "./components/AnyOfHeader"
import ExpandRequirementsButton from "./components/ExpandRequirementsButton"
import { RequirementSkeleton } from "./components/Requirement"
import HiddenRequirementAccessIndicator from "./components/HiddenRequirementAccessIndicator"
import RequirementComponent, { RequirementSkeleton } from "./components/Requirement"
import RequirementDisplayComponent from "./components/RequirementDisplayComponent"

type Props = {
Expand All @@ -40,17 +42,12 @@ const RoleRequirements = ({
descriptionRef,
initialRequirementsRef,
}: Props) => {
const { data, isLoading } = useRequirements(role?.id)
const { data: requirements, isLoading } = useRequirements(role?.id)

const requirements =
role.hiddenRequirements || data?.length === 0
? [...(data ?? []), { roleId: role.id, visibility: "HIDDEN" } as Requirement]
: data

const isVirtualList = requirements?.length > VIRTUAL_LIST_REQUIREMENT_LIMIT
const isVirtualList = (requirements?.length ?? 0) > VIRTUAL_LIST_REQUIREMENT_LIMIT
const sliceIndex = (requirements?.length ?? 0) - 3
const shownRequirements = (requirements ?? []).slice(0, 3)
const hiddenRequirements =
const notShownRequirements =
sliceIndex > 0 ? (requirements ?? []).slice(-sliceIndex) : []

const shadowColor = useColorModeValue(
Expand All @@ -72,13 +69,10 @@ const RoleRequirements = ({
{role.logic === "ANY_OF" && <AnyOfHeader anyOfNum={role.anyOfNum} />}
<VStack ref={initialRequirementsRef} spacing={0} w="full" p={5} pt={0}>
{/* Checking !data here too, so we don't show a loading state when we have data from the public request, but the authenticated request is still loading */}
{isLoading && !data ? (
{isLoading && !requirements ? (
<RoleRequirementsSkeleton />
) : isVirtualList ? (
<VirtualRequirements
{...{ isExpanded, requirements, descriptionRef }}
logic={role.logic}
/>
<VirtualRequirements {...{ isExpanded, descriptionRef }} role={role} />
) : (
<>
<VStack ref={initialRequirementsRef} spacing={0} w="full">
Expand All @@ -95,30 +89,46 @@ const RoleRequirements = ({
)}
</SlideFade>
))}
{(role.hiddenRequirements || requirements?.length === 0) &&
!notShownRequirements.length && (
<>
{shownRequirements.length > 0 && (
<LogicDivider logic={role.logic} />
)}
<SomeSecretRequirements roleId={role.id} />
</>
)}
</VStack>
<Collapse
in={isExpanded}
animateOpacity={false}
style={{ width: "100%" }}
>
{hiddenRequirements.map((requirement, i) => (
{notShownRequirements.map((requirement, i) => (
<React.Fragment key={i}>
{i === 0 && <LogicDivider logic={role.logic} />}
<RequirementDisplayComponent requirement={requirement} />
{i < hiddenRequirements.length - 1 && (
{i < notShownRequirements.length - 1 && (
<LogicDivider logic={role.logic} />
)}
</React.Fragment>
))}

{role.hiddenRequirements && (
<>
<LogicDivider logic={role.logic} />
<SomeSecretRequirements roleId={role.id} />
</>
)}
</Collapse>
</>
)}

{hiddenRequirements.length > 0 && onToggleExpanded && (
{notShownRequirements.length > 0 && onToggleExpanded && (
<>
<ExpandRequirementsButton
logic={role.logic}
hiddenRequirements={hiddenRequirements.length}
notShownRequirements={notShownRequirements.length}
isRequirementsExpanded={isExpanded}
onToggleExpanded={onToggleExpanded}
/>
Expand All @@ -144,15 +154,15 @@ const RoleRequirements = ({
const VirtualRequirements = memo(
({
isExpanded,
requirements,
logic,
role,
descriptionRef,
}: {
isExpanded: boolean
requirements: Requirement[]
logic: Logic
role: Role
descriptionRef?: MutableRefObject<HTMLDivElement>
}) => {
const { data: requirements } = useRequirements(role.id)

const listRef = useRef(null)
const rowHeights = useRef<Record<number, number>>({})
const expandedHeight = useMemo(() => {
Expand Down Expand Up @@ -183,11 +193,19 @@ const VirtualRequirements = memo(
}
}, [rowRef, index])

if (!requirements?.length) return <RoleRequirementsSkeleton />

return (
<Box style={style}>
<Box ref={rowRef} paddingRight={PARENT_PADDING}>
<RequirementDisplayComponent requirement={requirements[index]} />
{index < requirements?.length - 1 && <LogicDivider logic={logic} />}
{index < requirements.length - 1 && <LogicDivider logic={role.logic} />}
{index === requirements.length - 1 && role.hiddenRequirements && (
<>
<LogicDivider logic={role.logic} />
<SomeSecretRequirements roleId={role.id} />
</>
)}
</Box>
</Box>
)
Expand All @@ -199,7 +217,7 @@ const VirtualRequirements = memo(
ref={listRef}
width={`calc(100% + ${PARENT_PADDING})`}
height={isExpanded ? expandedHeight : 275}
itemCount={requirements.length}
itemCount={role.requirements.length}
itemSize={(i) => Math.max(rowHeights.current[i] ?? 0, 106)}
className="custom-scrollbar"
style={{
Expand All @@ -216,6 +234,15 @@ const VirtualRequirements = memo(
}
)

const SomeSecretRequirements = ({ roleId }: { roleId: number }) => (
<RequirementComponent
image={<Icon as={Question} boxSize={5} />}
rightElement={<HiddenRequirementAccessIndicator roleId={roleId} />}
>
Some secret requirements
</RequirementComponent>
)

const RoleRequirementsSkeleton = () => (
<>
{[...Array(3)].map((_, i) => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import Button from "components/common/Button"

type Props = {
logic: Logic
hiddenRequirements: number
notShownRequirements: number
isRequirementsExpanded: boolean
onToggleExpanded: (event: React.MouseEvent<HTMLElement>) => void
}

const ExpandRequirementsButton = ({
logic,
hiddenRequirements,
notShownRequirements,
isRequirementsExpanded,
onToggleExpanded,
}: Props): JSX.Element => {
Expand Down Expand Up @@ -47,7 +47,7 @@ const ExpandRequirementsButton = ({
>
{isRequirementsExpanded
? "Collapse"
: `${formattedLogic[logic]} ${hiddenRequirements} more`}
: `${formattedLogic[logic]} ${notShownRequirements} more`}
</Button>
</Flex>
<Divider
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { usePostHogContext } from "@/components/Providers/PostHogProvider"
import { Icon } from "@chakra-ui/react"
import { Question, Warning } from "@phosphor-icons/react"
import { Warning } from "@phosphor-icons/react"
import DataBlock from "components/common/DataBlock"
import { PropsWithChildren } from "react"
import { ErrorBoundary } from "react-error-boundary"
import { REQUIREMENT_DISPLAY_COMPONENTS } from "requirements/requirementDisplayComponents"
import { Requirement as RequirementType, Rest } from "types"
import { CHAIN_CONFIG } from "wagmiConfig/chains"
import HiddenRequirementAccessIndicator from "./HiddenRequirementAccessIndicator"
import Requirement from "./Requirement"
import RequirementAccessIndicator from "./RequirementAccessIndicator"
import { RequirementProvider, useRequirementContext } from "./RequirementContext"
Expand All @@ -22,18 +21,6 @@ const RequirementDisplayComponent = ({
rightElement = <RequirementAccessIndicator />,
...rest
}: Props) => {
if (requirement.visibility === "HIDDEN")
return (
<Requirement
image={<Icon as={Question} boxSize={5} />}
rightElement={
<HiddenRequirementAccessIndicator roleId={requirement.roleId} />
}
>
Some secret requirements
</Requirement>
)

const RequirementComponent = REQUIREMENT_DISPLAY_COMPONENTS[requirement.type]

if (!!requirement.chain && !CHAIN_CONFIG[requirement.chain])
Expand Down

0 comments on commit 88602f7

Please sign in to comment.