Optimistically join groups
This commit is contained in:
parent
8daf1b2ba8
commit
27a544205f
|
@ -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(
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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'}
|
||||
|
|
Loading…
Reference in New Issue
Block a user