+
+
{user?.name}
+
{user ? formatMoney(Math.floor(user.balance)) : ' '}
-
+
)
}
diff --git a/web/components/nav/sidebar.tsx b/web/components/nav/sidebar.tsx
new file mode 100644
index 00000000..cb7055df
--- /dev/null
+++ b/web/components/nav/sidebar.tsx
@@ -0,0 +1,140 @@
+import {
+ HomeIcon,
+ UserGroupIcon,
+ SearchIcon,
+ BookOpenIcon,
+ DotsHorizontalIcon,
+} from '@heroicons/react/outline'
+import clsx from 'clsx'
+import _ from 'lodash'
+import Link from 'next/link'
+import { useRouter } from 'next/router'
+import { useFollowedFolds } from '../../hooks/use-fold'
+import { useUser } from '../../hooks/use-user'
+import { firebaseLogin } from '../../lib/firebase/users'
+import { ManifoldLogo } from './manifold-logo'
+import { MenuButton } from './menu'
+import { getNavigationOptions, ProfileSummary } from './profile-menu'
+
+const navigation = [
+ { name: 'Home', href: '/home', icon: HomeIcon },
+ { name: 'Markets', href: '/markets', icon: SearchIcon },
+ { name: 'About', href: 'https://docs.manifold.markets', icon: BookOpenIcon },
+]
+
+type Item = {
+ name: string
+ href: string
+ icon: React.ComponentType<{ className?: string }>
+}
+
+function SidebarItem(props: { item: Item; currentPage: string }) {
+ const { item, currentPage } = props
+ return (
+
+
+
+ {item.name}
+
+
+ )
+}
+
+function MoreButton() {
+ return (
+
+
+ More
+
+ )
+}
+
+export default function Sidebar() {
+ const router = useRouter()
+ const currentPage = router.pathname
+
+ const user = useUser()
+ let folds = useFollowedFolds(user) || []
+ folds = _.sortBy(folds, 'followCount').reverse()
+
+ return (
+
+ )
+}
diff --git a/web/components/page.tsx b/web/components/page.tsx
index 95ff4270..61ce4a47 100644
--- a/web/components/page.tsx
+++ b/web/components/page.tsx
@@ -1,27 +1,43 @@
import clsx from 'clsx'
-import { NavBar } from './nav/nav-bar'
+import { BottomNavBar } from './nav/nav-bar'
+import Sidebar from './nav/sidebar'
export function Page(props: {
- wide?: boolean
margin?: boolean
assertUser?: 'signed-in' | 'signed-out'
+ rightSidebar?: React.ReactNode
children?: any
}) {
- const { wide, margin, assertUser, children } = props
+ const { margin, assertUser, children, rightSidebar } = props
return (
-
-
- {children}
+
+ {assertUser !== 'signed-out' && }
+
+
+ {children}
+
+ {/* If right sidebar is hidden, place its content at the bottom of the page. */}
+ {rightSidebar}
+
+
+
+
)
}
diff --git a/web/components/resolution-panel.tsx b/web/components/resolution-panel.tsx
index b22a45e4..2469c8f1 100644
--- a/web/components/resolution-panel.tsx
+++ b/web/components/resolution-panel.tsx
@@ -72,7 +72,7 @@ export function ResolutionPanel(props: {
return (
-
+
Outcome
diff --git a/web/hooks/use-find-active-contracts.ts b/web/hooks/use-find-active-contracts.ts
index ba80a899..66573728 100644
--- a/web/hooks/use-find-active-contracts.ts
+++ b/web/hooks/use-find-active-contracts.ts
@@ -10,7 +10,7 @@ import { Comment, getRecentComments } from '../lib/firebase/comments'
import { Contract, getActiveContracts } from '../lib/firebase/contracts'
import { listAllFolds } from '../lib/firebase/folds'
import { useInactiveContracts } from './use-contracts'
-import { useFollowedFolds } from './use-fold'
+import { useFollowedFoldIds } from './use-fold'
import { useSeenContracts } from './use-seen-contracts'
import { useUserBetContracts } from './use-user-bets'
@@ -48,7 +48,7 @@ export const useFilterYourContracts = (
folds: Fold[],
contracts: Contract[]
) => {
- const followedFoldIds = useFollowedFolds(user)
+ const followedFoldIds = useFollowedFoldIds(user)
const followedFolds = filterDefined(
(followedFoldIds ?? []).map((id) => folds.find((fold) => fold.id === id))
diff --git a/web/hooks/use-fold.ts b/web/hooks/use-fold.ts
index e7eb737f..ffb19615 100644
--- a/web/hooks/use-fold.ts
+++ b/web/hooks/use-fold.ts
@@ -1,7 +1,9 @@
+import _ from 'lodash'
import { useEffect, useState } from 'react'
import { Fold } from '../../common/fold'
import { User } from '../../common/user'
import {
+ listAllFolds,
listenForFold,
listenForFolds,
listenForFoldsWithTags,
@@ -49,8 +51,8 @@ export const useFollowingFold = (fold: Fold, user: User | null | undefined) => {
return following
}
-// Note: We cache FollowedFolds in localstorage to speed up the initial load
-export const useFollowedFolds = (user: User | null | undefined) => {
+// Note: We cache followedFoldIds in localstorage to speed up the initial load
+export const useFollowedFoldIds = (user: User | null | undefined) => {
const [followedFoldIds, setFollowedFoldIds] = useState
(
undefined
)
@@ -72,3 +74,38 @@ export const useFollowedFolds = (user: User | null | undefined) => {
return followedFoldIds
}
+
+// We also cache followedFolds directly in JSON.
+// TODO: Extract out localStorage caches to a utility
+export const useFollowedFolds = (user: User | null | undefined) => {
+ const [followedFolds, setFollowedFolds] = useState()
+ const ids = useFollowedFoldIds(user)
+
+ useEffect(() => {
+ if (user && ids) {
+ const key = `followed-full-folds-${user.id}`
+ const followedFoldJson = localStorage.getItem(key)
+ if (followedFoldJson) {
+ setFollowedFolds(JSON.parse(followedFoldJson))
+ // Exit early if ids and followedFoldIds have all the same elements.
+ if (
+ _.isEqual(
+ _.sortBy(ids),
+ _.sortBy(JSON.parse(followedFoldJson).map((f: Fold) => f.id))
+ )
+ ) {
+ return
+ }
+ }
+
+ // Otherwise, fetch the full contents of all folds
+ listAllFolds().then((folds) => {
+ const followedFolds = folds.filter((fold) => ids.includes(fold.id))
+ setFollowedFolds(followedFolds)
+ localStorage.setItem(key, JSON.stringify(followedFolds))
+ })
+ }
+ }, [user, ids])
+
+ return followedFolds
+}
diff --git a/web/pages/[username]/[contractSlug].tsx b/web/pages/[username]/[contractSlug].tsx
index 1c321abc..ee0ef26a 100644
--- a/web/pages/[username]/[contractSlug].tsx
+++ b/web/pages/[username]/[contractSlug].tsx
@@ -121,8 +121,17 @@ export default function ContractPage(props: {
const ogCardProps = getOpenGraphProps(contract)
+ const rightSidebar = hasSidePanel ? (
+
+ {allowTrade && (
+
+ )}
+ {allowResolve && }
+
+ ) : null
+
return (
-
+
{ogCardProps && (
- )}
-
- >
- )}
)
diff --git a/web/pages/admin.tsx b/web/pages/admin.tsx
index 637e2801..e71e1cf1 100644
--- a/web/pages/admin.tsx
+++ b/web/pages/admin.tsx
@@ -205,7 +205,7 @@ function ContractsTable() {
export default function Admin() {
return useAdmin() ? (
-