Skip to content

Commit

Permalink
wip: move roles to columns
Browse files Browse the repository at this point in the history
  • Loading branch information
dovalid committed Dec 13, 2023
1 parent adb8f64 commit eadb255
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { PopoverHeader } from "@chakra-ui/react"
import { POPOVER_HEADER_STYLES } from "components/[guild]/Requirements/components/RequiementAccessIndicator"
import { Check, X } from "phosphor-react"
import { CrmRole } from "../useMembers"
import CrmRoleAccessIndicatorUI from "./components/CrmRoleAccessIndicatorUI"

type Props = {
memberRole: CrmRole
}

const CrmRoleAccessIndicator = ({ memberRole }: Props) => {
if (!memberRole)
return (
<CrmRoleAccessIndicatorUI colorScheme={"gray"} icon={X}>
<PopoverHeader {...POPOVER_HEADER_STYLES}>Role not satisfied</PopoverHeader>
</CrmRoleAccessIndicatorUI>
)

return (
<CrmRoleAccessIndicatorUI
colorScheme={"green"}
icon={Check}
amount={memberRole.amount}
>
<PopoverHeader {...POPOVER_HEADER_STYLES}>Role satisfied</PopoverHeader>
</CrmRoleAccessIndicatorUI>
)
}

export default CrmRoleAccessIndicator
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {
Center,
Icon,
Popover,
PopoverArrow,
PopoverContent,
PopoverTrigger,
Portal,
Tag,
Text,
} from "@chakra-ui/react"
import { FC, PropsWithChildren } from "react"

type Props = {
colorScheme: string
icon: FC
amount?: number
}

const CrmRoleAccessIndicatorUI = ({
colorScheme,
icon,
amount,
children,
}: PropsWithChildren<Props>) => (
<Center>
<Popover placement="left" trigger="hover" closeDelay={100}>
<PopoverTrigger>
<Tag colorScheme={colorScheme} px="1.5">
<Icon as={icon} boxSize={3} />
{amount && <Text ml={1.5}>{amount.toFixed(2)}</Text>}
</Tag>
</PopoverTrigger>
<Portal>
<PopoverContent width="unset" maxW={{ base: "2xs", md: "xs" }}>
{children}
<PopoverArrow />
</PopoverContent>
</Portal>
</Popover>
</Center>
)

export default CrmRoleAccessIndicatorUI
3 changes: 3 additions & 0 deletions src/components/[guild]/crm/CrmRoleAccessIndicator/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import CrmRoleAccessIndicator from "./CrmRoleAccessIndicator"

export default CrmRoleAccessIndicator
55 changes: 50 additions & 5 deletions src/components/[guild]/crm/CustomizeViewModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import {
useColorModeValue,
} from "@chakra-ui/react"
import { Column, Table } from "@tanstack/react-table"
import SimpleRoleTag from "components/analytics/MembersChart/components/SimpleRoleTag"
import { Modal } from "components/common/Modal"
import { Reorder } from "framer-motion"
import { DotsSixVertical } from "phosphor-react"
import { useState } from "react"
import { useEffect, useState } from "react"
import useGuild from "../hooks/useGuild"
import { Member } from "./useMembers"

type Props = {
Expand All @@ -35,6 +37,10 @@ const CustomizeViewModal = ({ isOpen, onClose, table }: Props) => {
const columns = table.getAllColumns()
const [localOrder, setLocalOrder] = useState(() => transformToLocalOrder(table))

useEffect(() => {
setLocalOrder(transformToLocalOrder(table))
}, [columns])

const setTableOrder = () => {
const newOrder = transformToTableOrder(localOrder)
/**
Expand All @@ -47,7 +53,7 @@ const CustomizeViewModal = ({ isOpen, onClose, table }: Props) => {
}

return (
<Modal {...{ isOpen, onClose }}>
<Modal {...{ isOpen, onClose }} /* colorScheme={"dark"} */>
<ModalOverlay />
<ModalContent>
<ModalHeader>Customize shown columns</ModalHeader>
Expand All @@ -65,7 +71,14 @@ const CustomizeViewModal = ({ isOpen, onClose, table }: Props) => {
onDragEnd={setTableOrder}
style={{ position: "relative" }} // needed for the auto-applied zIndex to work
>
<ColumnSelector column={columns.find((col) => col.id === colId)} />
{colId.startsWith("role_") ? (
<RoleColumnSelector
column={columns.find((col) => col.id === colId)}
roleId={parseInt(colId.split("_")[1])}
/>
) : (
<ColumnSelector column={columns.find((col) => col.id === colId)} />
)}
</Reorder.Item>
))}
</Reorder.Group>
Expand All @@ -87,6 +100,7 @@ const ColumnSelector = ({ column, isDisabled }: SelectorProps) => {
mb="2"
bg={bg}
borderRadius="xl"
boxShadow={"xs"}
cursor={!isDisabled && "grab"}
>
<HStack justifyContent={"space-between"}>
Expand Down Expand Up @@ -135,10 +149,41 @@ const ColumnSelector = ({ column, isDisabled }: SelectorProps) => {
)
}

type RoleSelectorProps = { column: Column<Member>; roleId: number }

const RoleColumnSelector = ({ column, roleId }: RoleSelectorProps) => {
const bg = useColorModeValue("white", "#343437")
const { roles } = useGuild()

const role = roles.find((r) => r.id === roleId)

return (
<Box
py="3"
px="4"
mb="2"
bg={bg}
borderRadius="xl"
cursor={"grab"}
boxShadow={"xs"}
>
<HStack justifyContent={"space-between"}>
<Checkbox
isChecked={column.getIsVisible()}
onChange={column.getToggleVisibilityHandler()}
>
<SimpleRoleTag roleData={role} />
</Checkbox>
<DotsSixVertical />
</HStack>
</Box>
)
}

const transformToLocalOrder = (table) => {
const columnOrder = table.getState().columnOrder
const res = [...table.getState().columnOrder]
const columnIds = table.getAllLeafColumns().map((col) => col.id)
const res = columnOrder.length ? columnOrder : columnIds
columnIds.forEach((colId) => !res.includes(colId) && res.push(colId))

// remove 'select' and 'identity'
res.splice(0, 2)
Expand Down
32 changes: 31 additions & 1 deletion src/components/[guild]/crm/RoleTags.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ import {
} from "@chakra-ui/react"
import { Column } from "@tanstack/react-table"
import Button from "components/common/Button"
import { Funnel } from "phosphor-react"
import { useAtom } from "jotai"
import { shownRoleColumnsAtom } from "pages/[guild]/members"
import { ArrowFatRight, Funnel, X } from "phosphor-react"
import { Visibility } from "types"
import pluralize from "utils/pluralize"
import ClickableTagPopover from "../activity/ActivityLogAction/components/ClickableTagPopover"
Expand Down Expand Up @@ -176,6 +178,7 @@ export const ClickableCrmRoleTag = ({
<FilterByCrmRole {...{ roleId, column, onFilter }} />
<ViewRole roleId={roleId} page="activity" />
<ViewRole roleId={roleId} />
<MoveRoleToColumn roleId={roleId} />
</>
}
>
Expand Down Expand Up @@ -206,4 +209,31 @@ const FilterByCrmRole = ({ roleId, column, onFilter }) => {
)
}

const MoveRoleToColumn = ({ roleId }) => {
const [shownRoleColumns, setShownRoleColumnsAtom] = useAtom(shownRoleColumnsAtom)

const isAlreadyColumn = shownRoleColumns.includes(roleId)

const onClick = () => {
setShownRoleColumnsAtom((prevValue) =>
isAlreadyColumn
? prevValue.filter((id) => id !== roleId)
: [...prevValue, roleId]
)
}

return (
<Button
variant="ghost"
leftIcon={isAlreadyColumn ? <X /> : <ArrowFatRight />}
size="sm"
borderRadius={0}
onClick={onClick}
justifyContent="start"
>
{isAlreadyColumn ? "Remove column" : "Move to column"}
</Button>
)
}

export default RoleTags
23 changes: 21 additions & 2 deletions src/pages/[guild]/members.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import CrmTableWrapper from "components/[guild]/crm/CRMTable/CrmTableWrapper"
import CrmTbody from "components/[guild]/crm/CRMTable/CrmTbody"
import CrmThead from "components/[guild]/crm/CRMTable/CrmThead"
import CrmMenu from "components/[guild]/crm/CrmMenu"
import CrmRoleAccessIndicator from "components/[guild]/crm/CrmRoleAccessIndicator"
import FilterByRoles from "components/[guild]/crm/FilterByRoles"
import Identities from "components/[guild]/crm/Identities"
import IdentitiesExpansionToggle from "components/[guild]/crm/IdentitiesExpansionToggle"
Expand All @@ -22,10 +23,11 @@ import {
parseFiltersFromQuery,
parseSortingFromQuery,
} from "components/[guild]/crm/transformTableStateToAndFromQuery"
import useMembers, { Member } from "components/[guild]/crm/useMembers"
import useMembers, { CrmRole, Member } from "components/[guild]/crm/useMembers"
import useGuild from "components/[guild]/hooks/useGuild"
import GuildLogo from "components/common/GuildLogo"
import Layout from "components/common/Layout"
import { atom, useAtom } from "jotai"
import Head from "next/head"
import { useRouter } from "next/router"
import ErrorPage from "pages/_error"
Expand Down Expand Up @@ -124,9 +126,26 @@ const columns = [
}),
]

export const shownRoleColumnsAtom = atom([])

const GuildPage = (): JSX.Element => {
const { textColor, localThemeColor, localBackgroundImage } = useThemeContext()
const { name, roles, imageUrl } = useGuild()
const [shownRoleColumns] = useAtom(shownRoleColumnsAtom)

const roleColumns = useMemo(
() =>
shownRoleColumns.map((roleId) => ({
accessorKey: `role_${roleId}`,
accessorFn: (row) =>
Object.values(row.roles)
.flat()
.find((role: CrmRole) => role.roleId === roleId),
header: () => roles.find((role) => role.id === roleId)?.name,
cell: (info) => <CrmRoleAccessIndicator memberRole={info.getValue()} />,
})),
[shownRoleColumns]
)

const router = useRouter()
const [columnFilters, setColumnFilters] = useState(() =>
Expand Down Expand Up @@ -166,7 +185,7 @@ const GuildPage = (): JSX.Element => {

const table = useReactTable({
data: useMemo(() => data ?? [], [data]),
columns,
columns: useMemo(() => [...columns, ...roleColumns], [roleColumns]),
state: {
columnFilters,
sorting,
Expand Down

0 comments on commit eadb255

Please sign in to comment.