import React, { ReactNode, useEffect, useState } from 'react' import Router from 'next/router' import { AdjustmentsIcon, PencilAltIcon, ArrowSmRightIcon, } from '@heroicons/react/solid' import { XCircleIcon } from '@heroicons/react/outline' import clsx from 'clsx' import { toast, Toaster } from 'react-hot-toast' import { Page } from 'web/components/page' import { Col } from 'web/components/layout/col' import { ContractSearch, SORTS } from 'web/components/contract-search' import { User } from 'common/user' import { useTracking } from 'web/hooks/use-tracking' import { track } from 'web/lib/service/analytics' import { useSaveReferral } from 'web/hooks/use-save-referral' import { Sort } from 'web/components/contract-search' import { Group } from 'common/group' import { SiteLink } from 'web/components/site-link' import { usePrivateUser, useUser } from 'web/hooks/use-user' import { useMemberGroupIds, useMemberGroups, useTrendingGroups, } from 'web/hooks/use-group' import { Button } from 'web/components/button' import { Row } from 'web/components/layout/row' import { ProbChangeTable } from 'web/components/contract/prob-change-table' import { getGroup, groupPath, joinGroup, leaveGroup, } from 'web/lib/firebase/groups' import { usePortfolioHistory } from 'web/hooks/use-portfolio-history' import { formatMoney } from 'common/util/format' import { useProbChanges } from 'web/hooks/use-prob-changes' import { ProfitBadge } from 'web/components/bets-list' import { calculatePortfolioProfit } from 'common/calculate-metrics' import { hasCompletedStreakToday } from 'web/components/profile/betting-streak-modal' import { useContractsQuery } from 'web/hooks/use-contracts' import { ContractsGrid } from 'web/components/contract/contracts-grid' import { PillButton } from 'web/components/buttons/pill-button' import { filterDefined } from 'common/util/array' import { updateUser } from 'web/lib/firebase/users' import { isArray, keyBy } from 'lodash' import { usePrefetch } from 'web/hooks/use-prefetch' export default function Home() { const user = useUser() useTracking('view home') useSaveReferral() usePrefetch(user?.id) const cachedGroups = useMemberGroups(user?.id) ?? [] const groupIds = useMemberGroupIds(user) const [groups, setGroups] = useState(cachedGroups) useEffect(() => { if (groupIds) { Promise.all(groupIds.map((id) => getGroup(id))).then((groups) => setGroups(filterDefined(groups)) ) } }, [groupIds]) const { sections } = getHomeItems(groups, user?.homeSections ?? []) return ( {sections.map((section) => renderSection(section, user, groups))} ) } const HOME_SECTIONS = [ { label: 'Daily movers', id: 'daily-movers' }, { label: 'Trending', id: 'score' }, { label: 'New', id: 'newest' }, { label: 'New for you', id: 'new-for-you' }, ] export const getHomeItems = (groups: Group[], sections: string[]) => { // Accommodate old home sections. if (!isArray(sections)) sections = [] const items = [ ...HOME_SECTIONS, ...groups.map((g) => ({ label: g.name, id: g.id, })), ] const itemsById = keyBy(items, 'id') const sectionItems = filterDefined(sections.map((id) => itemsById[id])) // Add unmentioned items to the end. sectionItems.push(...items.filter((item) => !sectionItems.includes(item))) return { sections: sectionItems, itemsById, } } function renderSection( section: { id: string; label: string }, user: User | null | undefined, groups: Group[] ) { const { id, label } = section if (id === 'daily-movers') { return } if (id === 'new-for-you') return ( ) const sort = SORTS.find((sort) => sort.value === id) if (sort) return ( ) const group = groups.find((g) => g.id === id) if (group) return return null } function SectionHeader(props: { label: string href: string children?: ReactNode }) { const { label, href, children } = props return ( track('home click section header', { section: href })} > {label}{' '} {children} ) } function SearchSection(props: { label: string user: User | null | undefined | undefined sort: Sort pill?: string }) { const { label, user, sort, pill } = props return ( ) } function GroupSection(props: { group: Group user: User | null | undefined | undefined }) { const { group, user } = props const contracts = useContractsQuery('score', 4, { groupSlug: group.slug }) return ( ) } function DailyMoversSection(props: { userId: string | null | undefined }) { const { userId } = props const changes = useProbChanges(userId ?? '') return ( ) } function SearchRow() { return ( ) } function DailyStats(props: { user: User | null | undefined className?: string }) { const { user, className } = props const metrics = usePortfolioHistory(user?.id ?? '', 'daily') ?? [] const [first, last] = [metrics[0], metrics[metrics.length - 1]] const privateUser = usePrivateUser() const streaksHidden = privateUser?.notificationPreferences.betting_streaks.length === 0 let profit = 0 let profitPercent = 0 if (first && last) { profit = calculatePortfolioProfit(last) - calculatePortfolioProfit(first) profitPercent = profit / first.investmentValue } return (
Daily profit
{formatMoney(profit)}{' '} {!streaksHidden && (
Streak
🔥 {user?.currentBettingStreak ?? 0} )}
) } function TrendingGroupsSection(props: { user: User | null | undefined }) { const { user } = props const memberGroupIds = useMemberGroupIds(user) || [] const groups = useTrendingGroups().filter( (g) => !memberGroupIds.includes(g.id) ) const count = 25 const chosenGroups = groups.slice(0, count) return ( {chosenGroups.map((g) => ( { if (!user) return if (memberGroupIds.includes(g.id)) leaveGroup(g, user?.id) else { const homeSections = (user.homeSections ?? []) .filter((id) => id !== g.id) .concat(g.id) updateUser(user.id, { homeSections }) toast.promise(joinGroup(g, user.id), { loading: 'Following group...', success: `Followed ${g.name}`, error: "Couldn't follow group, try again?", }) track('home follow group', { group: g.slug }) } }} > {g.name} ))} ) } function CustomizeButton() { return ( ) }