Optimistically join groups

This commit is contained in:
Ian Philips 2022-07-14 11:09:28 -06:00
parent 8daf1b2ba8
commit 27a544205f
3 changed files with 36 additions and 32 deletions

View File

@ -1,6 +1,6 @@
import clsx from 'clsx'
import { User } from 'common/user'
import { useState } from 'react'
import { useEffect, useState } from 'react'
import { useUser } from 'web/hooks/use-user'
import { withTracking } from 'web/lib/service/analytics'
import { Row } from 'web/components/layout/row'
@ -9,9 +9,10 @@ import { TextButton } from 'web/components/text-button'
import { Group } from 'common/group'
import { Modal } from 'web/components/layout/modal'
import { Col } from 'web/components/layout/col'
import { addUserToGroup, leaveGroup } from 'web/lib/firebase/groups'
import { joinGroup, leaveGroup } from 'web/lib/firebase/groups'
import { firebaseLogin } from 'web/lib/firebase/users'
import { GroupLink } from 'web/pages/groups'
import toast from 'react-hot-toast'
export function GroupsButton(props: { user: User }) {
const { user } = props
@ -88,22 +89,34 @@ export function JoinOrLeaveGroupButton(props: {
}) {
const { group, small, className } = props
const currentUser = useUser()
const isFollowing = currentUser
? group.memberIds.includes(currentUser.id)
: false
const [isMember, setIsMember] = useState<boolean>(false)
useEffect(() => {
if (currentUser && group.memberIds.includes(currentUser.id)) {
setIsMember(group.memberIds.includes(currentUser.id))
}
}, [currentUser, group])
const onJoinGroup = () => {
if (!currentUser) return
addUserToGroup(group, currentUser.id)
setIsMember(true)
joinGroup(group, currentUser.id).catch(() => {
setIsMember(false)
toast.error('Failed to join group')
})
}
const onLeaveGroup = () => {
if (!currentUser) return
leaveGroup(group, currentUser.id)
setIsMember(false)
leaveGroup(group, currentUser.id).catch(() => {
setIsMember(true)
toast.error('Failed to leave group')
})
}
const smallStyle =
'btn !btn-xs border-2 border-gray-500 bg-white normal-case text-gray-500 hover:border-gray-500 hover:bg-white hover:text-gray-500'
if (!currentUser || isFollowing === undefined) {
if (!currentUser || isMember === undefined) {
if (!group.anyoneCanJoin)
return <div className={clsx(className, 'text-gray-500')}>Closed</div>
return (
@ -116,7 +129,7 @@ export function JoinOrLeaveGroupButton(props: {
)
}
if (isFollowing) {
if (isMember) {
return (
<button
className={clsx(

View File

@ -87,32 +87,23 @@ export async function addUserToGroupViaSlug(groupSlug: string, userId: string) {
console.error(`Group not found: ${groupSlug}`)
return
}
return await addUserToGroup(group, userId)
return await joinGroup(group, userId)
}
export async function addUserToGroup(
group: Group,
userId: string
): Promise<Group> {
export async function joinGroup(group: Group, userId: string): Promise<void> {
const { memberIds } = group
if (memberIds.includes(userId)) {
return group
}
if (memberIds.includes(userId)) return // already a member
const newMemberIds = [...memberIds, userId]
const newGroup = { ...group, memberIds: newMemberIds }
await updateGroup(newGroup, { memberIds: uniq(newMemberIds) })
return newGroup
return await updateGroup(group, { memberIds: uniq(newMemberIds) })
}
export async function leaveGroup(group: Group, userId: string): Promise<Group> {
export async function leaveGroup(group: Group, userId: string): Promise<void> {
const { memberIds } = group
if (!memberIds.includes(userId)) {
return group
}
if (!memberIds.includes(userId)) return // not a member
const newMemberIds = memberIds.filter((id) => id !== userId)
const newGroup = { ...group, memberIds: newMemberIds }
await updateGroup(newGroup, { memberIds: uniq(newMemberIds) })
return newGroup
return await updateGroup(group, { memberIds: uniq(newMemberIds) })
}
export async function addContractToGroup(group: Group, contract: Contract) {

View File

@ -8,7 +8,7 @@ import {
groupPath,
getGroupBySlug,
updateGroup,
addUserToGroup,
joinGroup,
addContractToGroup,
} from 'web/lib/firebase/groups'
import { Row } from 'web/components/layout/row'
@ -604,19 +604,19 @@ function JoinGroupButton(props: {
user: User | null | undefined
}) {
const { group, user } = props
function joinGroup() {
function addUserToGroup() {
if (user && !group.memberIds.includes(user.id)) {
toast.promise(addUserToGroup(group, user.id), {
toast.promise(joinGroup(group, user.id), {
loading: 'Joining group...',
success: 'Joined group!',
error: "Couldn't join group",
error: "Couldn't join group, try again?",
})
}
}
return (
<div>
<button
onClick={user ? joinGroup : firebaseLogin}
onClick={user ? addUserToGroup : firebaseLogin}
className={'btn-md btn-outline btn whitespace-nowrap normal-case'}
>
{user ? 'Join group' : 'Login to join group'}