group selector dialog (#888)
* group selector dialog * cache groups to prevent ui jumping * welcome dialog display logic * show fewer groups, more filtering
This commit is contained in:
parent
dd2b09830e
commit
f7164ddd7d
|
@ -6,9 +6,10 @@ export function PillButton(props: {
|
|||
onSelect: () => void
|
||||
color?: string
|
||||
xs?: boolean
|
||||
className?: string
|
||||
children: ReactNode
|
||||
}) {
|
||||
const { children, selected, onSelect, color, xs } = props
|
||||
const { children, selected, onSelect, color, xs, className } = props
|
||||
|
||||
return (
|
||||
<button
|
||||
|
@ -17,7 +18,8 @@ export function PillButton(props: {
|
|||
xs ? 'text-xs' : '',
|
||||
selected
|
||||
? ['text-white', color ?? 'bg-greyscale-6']
|
||||
: 'bg-greyscale-2 hover:bg-greyscale-3'
|
||||
: 'bg-greyscale-2 hover:bg-greyscale-3',
|
||||
className
|
||||
)}
|
||||
onClick={onSelect}
|
||||
>
|
||||
|
|
89
web/components/onboarding/group-selector-dialog.tsx
Normal file
89
web/components/onboarding/group-selector-dialog.tsx
Normal file
|
@ -0,0 +1,89 @@
|
|||
import { sortBy } from 'lodash'
|
||||
import React, { useRef } from 'react'
|
||||
|
||||
import { Col } from 'web/components/layout/col'
|
||||
import { Title } from 'web/components/title'
|
||||
import { useGroups, useMemberGroupIds } from 'web/hooks/use-group'
|
||||
import { joinGroup, leaveGroup } from 'web/lib/firebase/groups'
|
||||
import { useUser } from 'web/hooks/use-user'
|
||||
import { Modal } from 'web/components/layout/modal'
|
||||
import { PillButton } from 'web/components/buttons/pill-button'
|
||||
import { Button } from 'web/components/button'
|
||||
import { Group } from 'common/group'
|
||||
|
||||
export default function GroupSelectorDialog(props: {
|
||||
open: boolean
|
||||
setOpen: (open: boolean) => void
|
||||
}) {
|
||||
const { open, setOpen } = props
|
||||
|
||||
const groups = useGroups()
|
||||
const user = useUser()
|
||||
const memberGroupIds = useMemberGroupIds(user) || []
|
||||
const cachedGroups = useRef<Group[]>()
|
||||
|
||||
if (groups && !cachedGroups.current) {
|
||||
cachedGroups.current = groups
|
||||
}
|
||||
|
||||
const excludedGroups = [
|
||||
'features',
|
||||
'personal',
|
||||
'private',
|
||||
'nomic',
|
||||
'proofnik',
|
||||
'free money',
|
||||
'motivation',
|
||||
'sf events',
|
||||
'please resolve',
|
||||
'short-term',
|
||||
'washifold',
|
||||
]
|
||||
|
||||
const displayedGroups = sortBy(cachedGroups.current ?? [], [
|
||||
(group) => -1 * group.totalMembers,
|
||||
(group) => -1 * group.totalContracts,
|
||||
])
|
||||
.filter((group) => group.anyoneCanJoin)
|
||||
.filter((group) =>
|
||||
excludedGroups.every((name) => !group.name.toLowerCase().includes(name))
|
||||
)
|
||||
.filter(
|
||||
(group) =>
|
||||
(group.mostRecentContractAddedTime ?? 0) >
|
||||
Date.now() - 1000 * 60 * 60 * 24 * 7
|
||||
)
|
||||
.slice(0, 30)
|
||||
|
||||
return (
|
||||
<Modal open={open} setOpen={setOpen}>
|
||||
<Col className="h-[32rem] rounded-md bg-white px-8 py-6 text-sm font-light md:h-[40rem] md:text-lg">
|
||||
<Title text="What interests you?" />
|
||||
<p className="mb-4">
|
||||
Choose among the categories below to personalize your Manifold
|
||||
experience.
|
||||
</p>
|
||||
|
||||
<div className="scrollbar-hide items-start gap-2 overflow-x-auto">
|
||||
{user &&
|
||||
displayedGroups.map((group) => (
|
||||
<PillButton
|
||||
selected={memberGroupIds.includes(group.id)}
|
||||
onSelect={() =>
|
||||
memberGroupIds.includes(group.id)
|
||||
? leaveGroup(group, user.id)
|
||||
: joinGroup(group, user.id)
|
||||
}
|
||||
className="mr-1 mb-2 max-w-[12rem] truncate"
|
||||
>
|
||||
{group.name}
|
||||
</PillButton>
|
||||
))}
|
||||
</div>
|
||||
</Col>
|
||||
<Col>
|
||||
<Button onClick={() => setOpen(false)}>Done</Button>
|
||||
</Col>
|
||||
</Modal>
|
||||
)
|
||||
}
|
|
@ -7,6 +7,7 @@ import { Col } from '../layout/col'
|
|||
import { Modal } from '../layout/modal'
|
||||
import { Row } from '../layout/row'
|
||||
import { Title } from '../title'
|
||||
import GroupSelectorDialog from './group-selector-dialog'
|
||||
|
||||
export default function Welcome() {
|
||||
const user = useUser()
|
||||
|
@ -32,17 +33,26 @@ export default function Welcome() {
|
|||
}
|
||||
}
|
||||
|
||||
if (!user || !user.shouldShowWelcome) {
|
||||
return <></>
|
||||
} else
|
||||
return (
|
||||
<Modal
|
||||
open={open}
|
||||
setOpen={(newOpen) => {
|
||||
const [groupSelectorOpen, setGroupSelectorOpen] = useState(false)
|
||||
|
||||
if (!user || (!user.shouldShowWelcome && !groupSelectorOpen)) return <></>
|
||||
|
||||
const toggleOpen = (isOpen: boolean) => {
|
||||
setUserHasSeenWelcome()
|
||||
setOpen(newOpen)
|
||||
}}
|
||||
>
|
||||
setOpen(isOpen)
|
||||
|
||||
if (!isOpen) {
|
||||
setGroupSelectorOpen(true)
|
||||
}
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<GroupSelectorDialog
|
||||
open={groupSelectorOpen}
|
||||
setOpen={() => setGroupSelectorOpen(false)}
|
||||
/>
|
||||
|
||||
<Modal open={open} setOpen={toggleOpen}>
|
||||
<Col className="h-[32rem] place-content-between rounded-md bg-white px-8 py-6 text-sm font-light md:h-[40rem] md:text-lg">
|
||||
{page === 0 && <Page0 />}
|
||||
{page === 1 && <Page1 />}
|
||||
|
@ -68,16 +78,14 @@ export default function Welcome() {
|
|||
</Row>
|
||||
<u
|
||||
className="self-center text-xs text-gray-500"
|
||||
onClick={() => {
|
||||
setOpen(false)
|
||||
setUserHasSeenWelcome()
|
||||
}}
|
||||
onClick={() => toggleOpen(false)}
|
||||
>
|
||||
I got the gist, exit welcome
|
||||
</u>
|
||||
</Col>
|
||||
</Col>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user