manifold/web/lib/firebase/folds.ts

127 lines
3.3 KiB
TypeScript
Raw Normal View History

2022-01-26 20:03:32 +00:00
import {
collection,
deleteDoc,
doc,
query,
setDoc,
updateDoc,
where,
} from 'firebase/firestore'
import { Fold } from '../../../common/fold'
import { Contract, contractCollection } from './contracts'
import { db } from './init'
2022-01-26 20:03:32 +00:00
import { User } from './users'
2022-01-24 05:47:20 +00:00
import { getValues, listenForValue, listenForValues } from './utils'
const foldCollection = collection(db, 'folds')
2022-01-22 17:39:31 +00:00
export function foldPath(
fold: Fold,
subpath?: 'edit' | 'markets' | 'leaderboards'
) {
return `/fold/${fold.slug}${subpath ? `/${subpath}` : ''}`
}
export function updateFold(fold: Fold, updates: Partial<Fold>) {
return updateDoc(doc(foldCollection, fold.id), updates)
}
2022-01-26 20:56:15 +00:00
export function deleteFold(fold: Fold) {
return deleteDoc(doc(foldCollection, fold.id))
}
export async function listAllFolds() {
return getValues<Fold>(foldCollection)
}
2022-01-24 05:47:20 +00:00
export function listenForFolds(setFolds: (folds: Fold[]) => void) {
return listenForValues(foldCollection, setFolds)
}
export async function getFoldBySlug(slug: string) {
const q = query(foldCollection, where('slug', '==', slug))
const folds = await getValues<Fold>(q)
return folds.length === 0 ? null : folds[0]
}
export async function getFoldContracts(fold: Fold) {
const {
tags,
contractIds,
excludedContractIds,
creatorIds,
excludedCreatorIds,
} = fold
const [tagsContracts, includedContracts] = await Promise.all([
// TODO: if tags.length > 10, execute multiple parallel queries
tags.length > 0
? getValues<Contract>(
query(
contractCollection,
where(
'lowercaseTags',
'array-contains-any',
tags.map((tag) => tag.toLowerCase())
)
)
)
: [],
// TODO: if contractIds.length > 10, execute multiple parallel queries
contractIds.length > 0
? getValues<Contract>(
query(contractCollection, where('id', 'in', contractIds))
)
: [],
])
const excludedContractsSet = new Set(excludedContractIds)
const creatorSet = creatorIds ? new Set(creatorIds) : undefined
const excludedCreatorSet = excludedCreatorIds
? new Set(excludedCreatorIds)
: undefined
const approvedContracts = tagsContracts.filter((contract) => {
const { id, creatorId } = contract
if (excludedContractsSet.has(id)) return false
if (creatorSet && !creatorSet.has(creatorId)) return false
if (excludedCreatorSet && excludedCreatorSet.has(creatorId)) return false
return true
})
return [...approvedContracts, ...includedContracts]
}
2022-01-23 06:51:19 +00:00
export function listenForFold(
foldId: string,
setFold: (fold: Fold | null) => void
) {
return listenForValue(doc(foldCollection, foldId), setFold)
}
2022-01-26 20:03:32 +00:00
export function followFold(fold: Fold, user: User) {
const followDoc = doc(foldCollection, fold.id, 'followers', user.id)
return setDoc(followDoc, { userId: user.id })
}
export function unfollowFold(fold: Fold, user: User) {
const followDoc = doc(foldCollection, fold.id, 'followers', user.id)
return deleteDoc(followDoc)
}
export function listenForFollow(
fold: Fold,
user: User,
setFollow: (following: boolean) => void
) {
const followDoc = doc(foldCollection, fold.id, 'followers', user.id)
return listenForValue(followDoc, (value) => {
setFollow(!!value)
})
}