import { sortBy, debounce } from 'lodash'
import Link from 'next/link'
import { useEffect, useState } from 'react'
import { Fold } from 'common/fold'
import { CreateFoldButton } from 'web/components/folds/create-fold-button'
import { FollowFoldButton } from 'web/components/folds/follow-fold-button'
import { Col } from 'web/components/layout/col'
import { Row } from 'web/components/layout/row'
import { Page } from 'web/components/page'
import { TagsList } from 'web/components/tags-list'
import { Title } from 'web/components/title'
import { UserLink } from 'web/components/user-page'
import { useFolds, useFollowedFoldIds } from 'web/hooks/use-fold'
import { useUser } from 'web/hooks/use-user'
import { foldPath, listAllFolds } from 'web/lib/firebase/folds'
import { getUser, User } from 'web/lib/firebase/users'
export async function getStaticProps() {
const folds = await listAllFolds().catch((_) => [])
const curators = await Promise.all(
folds.map((fold) => getUser(fold.curatorId))
)
const curatorsDict = Object.fromEntries(
curators.map((curator) => [curator.id, curator])
)
return {
props: {
folds,
curatorsDict,
},
revalidate: 60, // regenerate after a minute
}
}
export default function Folds(props: {
folds: Fold[]
curatorsDict: { [k: string]: User }
}) {
const [curatorsDict, setCuratorsDict] = useState(props.curatorsDict)
const folds = useFolds() ?? props.folds
const user = useUser()
const followedFoldIds = useFollowedFoldIds(user) || []
useEffect(() => {
// Load User object for curator of new Folds.
const newFolds = folds.filter(({ curatorId }) => !curatorsDict[curatorId])
if (newFolds.length > 0) {
Promise.all(newFolds.map(({ curatorId }) => getUser(curatorId))).then(
(newUsers) => {
const newUsersDict = Object.fromEntries(
newUsers.map((user) => [user.id, user])
)
setCuratorsDict({ ...curatorsDict, ...newUsersDict })
}
)
}
}, [curatorsDict, folds])
const [query, setQuery] = useState('')
// Copied from contracts-list.tsx; extract if we copy this again
const queryWords = query.toLowerCase().split(' ')
function check(corpus: String) {
return queryWords.every((word) => corpus.toLowerCase().includes(word))
}
// List followed folds first, then folds with the highest follower count
const matches = sortBy(folds, [
(fold) => !followedFoldIds.includes(fold.id),
(fold) => -1 * fold.followCount,
]).filter(
(f) =>
check(f.name) ||
check(f.about || '') ||
check(curatorsDict[f.curatorId].username) ||
check(f.lowercaseTags.map((tag) => `#${tag}`).join(' '))
)
// Not strictly necessary, but makes the "hold delete" experience less laggy
const debouncedQuery = debounce(setQuery, 50)
return (