import { track } from '@amplitude/analytics-browser'
import {
ArrowSmRightIcon,
PlusCircleIcon,
XCircleIcon,
} from '@heroicons/react/outline'
import PencilIcon from '@heroicons/react/solid/PencilIcon'
import { Contract } from 'common/contract'
import { Group } from 'common/group'
import { Post } from 'common/post'
import { useEffect, useState } from 'react'
import { ReactNode } from 'react'
import { getPost } from 'web/lib/firebase/posts'
import { ContractSearch } from '../contract-search'
import { ContractCard } from '../contract/contract-card'
import Masonry from 'react-masonry-css'
import { Col } from '../layout/col'
import { Row } from '../layout/row'
import { SiteLink } from '../site-link'
import { GroupOverviewPost } from './group-overview-post'
import { getContractFromId } from 'web/lib/firebase/contracts'
import { groupPath, updateGroup } from 'web/lib/firebase/groups'
import { PinnedSelectModal } from '../pinned-select-modal'
import { Button } from '../button'
import { User } from 'common/user'
import { UserLink } from '../user-link'
import { EditGroupButton } from './edit-group-button'
import { JoinOrLeaveGroupButton } from './groups-button'
import { Linkify } from '../linkify'
import { ChoicesToggleGroup } from '../choices-toggle-group'
import { CopyLinkButton } from '../copy-link-button'
import { REFERRAL_AMOUNT } from 'common/economy'
import toast from 'react-hot-toast'
import { ENV_CONFIG } from 'common/envs/constants'
import { PostCard, PostCardList } from '../post-card'
import { LoadingIndicator } from '../loading-indicator'
import { useUser } from 'web/hooks/use-user'
import { CreatePost } from '../create-post'
import { Modal } from '../layout/modal'
const MAX_TRENDING_POSTS = 6
export function GroupOverview(props: {
group: Group
isEditable: boolean
posts: Post[]
aboutPost: Post | null
creator: User
user: User | null | undefined
memberIds: string[]
}) {
const { group, isEditable, posts, aboutPost, creator, user, memberIds } =
props
return (
{(group.aboutPostId != null || isEditable) && (
<>
>
)}
)
}
export function GroupPosts(props: { posts: Post[]; group: Group }) {
const { posts, group } = props
const [showCreatePost, setShowCreatePost] = useState(false)
const user = useUser()
const createPost = (
)
const postList = (
{user && (
)}
{posts.length === 0 && (
No posts yet
)}
)
return showCreatePost ? createPost : postList
}
function GroupOverviewPinned(props: {
group: Group
posts: Post[]
isEditable: boolean
}) {
const { group, posts, isEditable } = props
const [pinned, setPinned] = useState([])
useEffect(() => {
async function getPinned() {
if (group.pinnedItems == null) {
updateGroup(group, { pinnedItems: [] })
} else {
const itemComponents = await Promise.all(
group.pinnedItems.map(async (element) => {
if (element.type === 'post') {
const post = await getPost(element.itemId)
if (post) {
return
}
} else if (element.type === 'contract') {
const contract = await getContractFromId(element.itemId)
if (contract) {
return
}
}
})
)
setPinned(
itemComponents.filter(
(element) => element != undefined
) as JSX.Element[]
)
}
}
getPinned()
}, [group, group.pinnedItems])
async function onSubmit(selectedItems: { itemId: string; type: string }[]) {
await updateGroup(group, {
pinnedItems: [
...group.pinnedItems,
...(selectedItems as { itemId: string; type: 'contract' | 'post' }[]),
],
})
}
function onDeleteClicked(index: number) {
const newPinned = group.pinnedItems.filter((item) => {
return item.itemId !== group.pinnedItems[index].itemId
})
updateGroup(group, { pinnedItems: newPinned })
}
return isEditable || (group.pinnedItems && group.pinnedItems.length > 0) ? (
) : (
)
}
export function PinnedItems(props: {
posts: Post[]
isEditable: boolean
pinned: JSX.Element[]
onDeleteClicked: (index: number) => void
onSubmit: (selectedItems: { itemId: string; type: string }[]) => void
group?: Group
modalMessage: string
}) {
const {
isEditable,
pinned,
onDeleteClicked,
onSubmit,
posts,
group,
modalMessage,
} = props
const [editMode, setEditMode] = useState(false)
const [open, setOpen] = useState(false)
return pinned.length > 0 || isEditable ? (
{isEditable && (
)}
{pinned.length == 0 && !editMode && (
No pinned items yet. Click the edit button to add some!
)}
{pinned.map((element, index) => (
{element}
{editMode && onDeleteClicked(index)} />}
))}
{editMode && pinned.length < 6 && (
)}
{modalMessage}
}
onSubmit={onSubmit}
/>
) : (
<>>
)
}
function SectionHeader(props: {
label: string
href?: string
children?: ReactNode
}) {
const { label, href, children } = props
const content = (
<>
{label}{' '}
>
)
return (
{href ? (
track('group click section header', { section: href })}
>
{content}
) : (
{content}
)}
{children}
)
}
export function GroupAbout(props: {
group: Group
creator: User
user: User | null | undefined
isEditable: boolean
memberIds: string[]
}) {
const { group, creator, isEditable, user, memberIds } = props
const anyoneCanJoinChoices: { [key: string]: string } = {
Closed: 'false',
Open: 'true',
}
const [anyoneCanJoin, setAnyoneCanJoin] = useState(group.anyoneCanJoin)
function updateAnyoneCanJoin(newVal: boolean) {
if (group.anyoneCanJoin == newVal || !isEditable) return
setAnyoneCanJoin(newVal)
toast.promise(updateGroup(group, { ...group, anyoneCanJoin: newVal }), {
loading: 'Updating group...',
success: 'Updated group!',
error: "Couldn't update group",
})
}
const postFix = user ? '?referrer=' + user.username : ''
const shareUrl = `https://${ENV_CONFIG.domain}${groupPath(
group.slug
)}${postFix}`
const isMember = user ? memberIds.includes(user.id) : false
return (
<>
{isEditable ? (
) : (
user && (
)
)}
Membership
{user && user.id === creator.id ? (
updateAnyoneCanJoin(choice.toString() === 'true')
}
toggleClassName={'h-10'}
className={'ml-2'}
/>
) : (
{anyoneCanJoin ? 'Open to all' : 'Closed (by invite only)'}
)}
{anyoneCanJoin && user && (
Invite
Invite a friend to this group and get M${REFERRAL_AMOUNT} if they
sign up!
)}
>
)
}
function CrossIcon(props: { onClick: () => void }) {
const { onClick } = props
return (
)
}