import { debounce, sortBy } from 'lodash'
import Link from 'next/link'
import React, { useEffect, useState } from 'react'
import { Group } from 'common/group'
import { CreateGroupButton } from 'web/components/groups/create-group-button'
import { Col } from 'web/components/layout/col'
import { Row } from 'web/components/layout/row'
import { Page } from 'web/components/page'
import { Title } from 'web/components/title'
import { useGroups, useMemberGroupIds } from 'web/hooks/use-group'
import { groupPath, listAllGroups } from 'web/lib/firebase/groups'
import { getUser, getUserAndPrivateUser, User } from 'web/lib/firebase/users'
import { Tabs } from 'web/components/layout/tabs'
import { SiteLink } from 'web/components/site-link'
import clsx from 'clsx'
import { Avatar } from 'web/components/avatar'
import { JoinOrLeaveGroupButton } from 'web/components/groups/groups-button'
import { searchInAny } from 'common/util/parse'
import { SEO } from 'web/components/SEO'
import { GetServerSideProps } from 'next'
import { authenticateOnServer } from 'web/lib/firebase/server-auth'
import { useUser } from 'web/hooks/use-user'
export const getServerSideProps: GetServerSideProps = async (ctx) => {
const creds = await authenticateOnServer(ctx)
const auth = creds ? await getUserAndPrivateUser(creds.uid) : null
const groups = await listAllGroups().catch((_) => [])
const creators = await Promise.all(
groups.map((group) => getUser(group.creatorId))
)
const creatorsDict = Object.fromEntries(
creators.map((creator) => [creator.id, creator])
)
return { props: { auth, groups, creatorsDict } }
}
export default function Groups(props: {
auth: { user: User } | null
groups: Group[]
creatorsDict: { [k: string]: User }
}) {
//TODO: do we really need the creatorsDict?
const [creatorsDict, setCreatorsDict] = useState(props.creatorsDict)
const serverUser = props.auth?.user
const groups = useGroups() ?? props.groups
const user = useUser() ?? serverUser
const memberGroupIds = useMemberGroupIds(user) || []
useEffect(() => {
// Load User object for creator of new Groups.
const newGroups = groups.filter(({ creatorId }) => !creatorsDict[creatorId])
if (newGroups.length > 0) {
Promise.all(newGroups.map(({ creatorId }) => getUser(creatorId))).then(
(newUsers) => {
const newUsersDict = Object.fromEntries(
newUsers.map((user) => [user.id, user])
)
setCreatorsDict({ ...creatorsDict, ...newUsersDict })
}
)
}
}, [creatorsDict, groups])
const [query, setQuery] = useState('')
// List groups with the highest question count, then highest member count
// TODO use find-active-contracts to sort by?
const matches = sortBy(groups, []).filter((g) =>
searchInAny(
query,
g.name,
g.about || '',
creatorsDict[g.creatorId].username
)
)
const matchesOrderedByRecentActivity = sortBy(groups, [
(group) =>
-1 * (group.mostRecentContractAddedTime ?? group.mostRecentActivityTime),
]).filter((g) =>
searchInAny(
query,
g.name,
g.about || '',
creatorsDict[g.creatorId].username
)
)
// Not strictly necessary, but makes the "hold delete" experience less laggy
const debouncedQuery = debounce(setQuery, 50)
return (