Fix up several pages to load user data on the server (#722)
* Fix up several pages to load user data on the server * Add key prop to `EditUserField`
This commit is contained in:
parent
5649161348
commit
e7f1d3924b
|
@ -52,6 +52,11 @@ export async function getUser(userId: string) {
|
||||||
return (await getDoc(doc(users, userId))).data()!
|
return (await getDoc(doc(users, userId))).data()!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getPrivateUser(userId: string) {
|
||||||
|
/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */
|
||||||
|
return (await getDoc(doc(users, userId))).data()!
|
||||||
|
}
|
||||||
|
|
||||||
export async function getUserByUsername(username: string) {
|
export async function getUserByUsername(username: string) {
|
||||||
// Find a user whose username matches the given username, or null if no such user exists.
|
// Find a user whose username matches the given username, or null if no such user exists.
|
||||||
const q = query(users, where('username', '==', username), limit(1))
|
const q = query(users, where('username', '==', username), limit(1))
|
||||||
|
|
|
@ -4,7 +4,7 @@ import clsx from 'clsx'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import Textarea from 'react-expanding-textarea'
|
import Textarea from 'react-expanding-textarea'
|
||||||
import { Spacer } from 'web/components/layout/spacer'
|
import { Spacer } from 'web/components/layout/spacer'
|
||||||
import { useUser } from 'web/hooks/use-user'
|
import { getUser } from 'web/lib/firebase/users'
|
||||||
import { Contract, contractPath } from 'web/lib/firebase/contracts'
|
import { Contract, contractPath } from 'web/lib/firebase/contracts'
|
||||||
import { createMarket } from 'web/lib/firebase/api'
|
import { createMarket } from 'web/lib/firebase/api'
|
||||||
import { FIXED_ANTE } from 'common/antes'
|
import { FIXED_ANTE } from 'common/antes'
|
||||||
|
@ -33,7 +33,10 @@ import { Title } from 'web/components/title'
|
||||||
import { SEO } from 'web/components/SEO'
|
import { SEO } from 'web/components/SEO'
|
||||||
import { MultipleChoiceAnswers } from 'web/components/answers/multiple-choice-answers'
|
import { MultipleChoiceAnswers } from 'web/components/answers/multiple-choice-answers'
|
||||||
|
|
||||||
export const getServerSideProps = redirectIfLoggedOut('/')
|
export const getServerSideProps = redirectIfLoggedOut('/', async (_, creds) => {
|
||||||
|
const user = await getUser(creds.user.uid)
|
||||||
|
return { props: { user } }
|
||||||
|
})
|
||||||
|
|
||||||
type NewQuestionParams = {
|
type NewQuestionParams = {
|
||||||
groupId?: string
|
groupId?: string
|
||||||
|
@ -49,8 +52,9 @@ type NewQuestionParams = {
|
||||||
initValue?: string
|
initValue?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Create() {
|
export default function Create(props: { user: User }) {
|
||||||
useTracking('view create page')
|
useTracking('view create page')
|
||||||
|
const { user } = props
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const params = router.query as NewQuestionParams
|
const params = router.query as NewQuestionParams
|
||||||
// TODO: Not sure why Question is pulled out as its own component;
|
// TODO: Not sure why Question is pulled out as its own component;
|
||||||
|
@ -60,8 +64,7 @@ export default function Create() {
|
||||||
setQuestion(params.q ?? '')
|
setQuestion(params.q ?? '')
|
||||||
}, [params.q])
|
}, [params.q])
|
||||||
|
|
||||||
const creator = useUser()
|
if (!router.isReady) return <div />
|
||||||
if (!router.isReady || !creator) return <div />
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Page>
|
||||||
|
@ -93,7 +96,7 @@ export default function Create() {
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<Spacer h={6} />
|
<Spacer h={6} />
|
||||||
<NewContract question={question} params={params} creator={creator} />
|
<NewContract question={question} params={params} creator={user} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Page>
|
</Page>
|
||||||
|
@ -102,7 +105,7 @@ export default function Create() {
|
||||||
|
|
||||||
// Allow user to create a new contract
|
// Allow user to create a new contract
|
||||||
export function NewContract(props: {
|
export function NewContract(props: {
|
||||||
creator?: User | null
|
creator: User
|
||||||
question: string
|
question: string
|
||||||
params?: NewQuestionParams
|
params?: NewQuestionParams
|
||||||
}) {
|
}) {
|
||||||
|
@ -120,14 +123,14 @@ export function NewContract(props: {
|
||||||
const [answers, setAnswers] = useState<string[]>([]) // for multiple choice
|
const [answers, setAnswers] = useState<string[]>([]) // for multiple choice
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (groupId && creator)
|
if (groupId)
|
||||||
getGroup(groupId).then((group) => {
|
getGroup(groupId).then((group) => {
|
||||||
if (group && canModifyGroupContracts(group, creator.id)) {
|
if (group && canModifyGroupContracts(group, creator.id)) {
|
||||||
setSelectedGroup(group)
|
setSelectedGroup(group)
|
||||||
setShowGroupSelector(false)
|
setShowGroupSelector(false)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}, [creator, groupId])
|
}, [creator.id, groupId])
|
||||||
const [ante, _setAnte] = useState(FIXED_ANTE)
|
const [ante, _setAnte] = useState(FIXED_ANTE)
|
||||||
|
|
||||||
// If params.closeTime is set, extract out the specified date and time
|
// If params.closeTime is set, extract out the specified date and time
|
||||||
|
@ -152,7 +155,7 @@ export function NewContract(props: {
|
||||||
? dayjs(`${closeDate}T${closeHoursMinutes}`).valueOf()
|
? dayjs(`${closeDate}T${closeHoursMinutes}`).valueOf()
|
||||||
: undefined
|
: undefined
|
||||||
|
|
||||||
const balance = creator?.balance || 0
|
const balance = creator.balance || 0
|
||||||
|
|
||||||
const min = minString ? parseFloat(minString) : undefined
|
const min = minString ? parseFloat(minString) : undefined
|
||||||
const max = maxString ? parseFloat(maxString) : undefined
|
const max = maxString ? parseFloat(maxString) : undefined
|
||||||
|
@ -214,7 +217,7 @@ export function NewContract(props: {
|
||||||
|
|
||||||
async function submit() {
|
async function submit() {
|
||||||
// TODO: Tell users why their contract is invalid
|
// TODO: Tell users why their contract is invalid
|
||||||
if (!creator || !isValid) return
|
if (!isValid) return
|
||||||
setIsSubmitting(true)
|
setIsSubmitting(true)
|
||||||
try {
|
try {
|
||||||
const result = await createMarket(
|
const result = await createMarket(
|
||||||
|
@ -249,8 +252,6 @@ export function NewContract(props: {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!creator) return <></>
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<label className="label">
|
<label className="label">
|
||||||
|
|
|
@ -11,10 +11,11 @@ import { Page } from 'web/components/page'
|
||||||
import { SEO } from 'web/components/SEO'
|
import { SEO } from 'web/components/SEO'
|
||||||
import { Title } from 'web/components/title'
|
import { Title } from 'web/components/title'
|
||||||
import { Subtitle } from 'web/components/subtitle'
|
import { Subtitle } from 'web/components/subtitle'
|
||||||
import { useUser } from 'web/hooks/use-user'
|
import { getUser } from 'web/lib/firebase/users'
|
||||||
import { useUserManalinks } from 'web/lib/firebase/manalinks'
|
import { useUserManalinks } from 'web/lib/firebase/manalinks'
|
||||||
import { useUserById } from 'web/hooks/use-user'
|
import { useUserById } from 'web/hooks/use-user'
|
||||||
import { ManalinkTxn } from 'common/txn'
|
import { ManalinkTxn } from 'common/txn'
|
||||||
|
import { User } from 'common/user'
|
||||||
import { Avatar } from 'web/components/avatar'
|
import { Avatar } from 'web/components/avatar'
|
||||||
import { RelativeTimestamp } from 'web/components/relative-timestamp'
|
import { RelativeTimestamp } from 'web/components/relative-timestamp'
|
||||||
import { UserLink } from 'web/components/user-page'
|
import { UserLink } from 'web/components/user-page'
|
||||||
|
@ -27,15 +28,19 @@ import { Manalink } from 'common/manalink'
|
||||||
import { REFERRAL_AMOUNT } from 'common/user'
|
import { REFERRAL_AMOUNT } from 'common/user'
|
||||||
|
|
||||||
const LINKS_PER_PAGE = 24
|
const LINKS_PER_PAGE = 24
|
||||||
export const getServerSideProps = redirectIfLoggedOut('/')
|
|
||||||
|
export const getServerSideProps = redirectIfLoggedOut('/', async (_, creds) => {
|
||||||
|
const user = await getUser(creds.user.uid)
|
||||||
|
return { props: { user } }
|
||||||
|
})
|
||||||
|
|
||||||
export function getManalinkUrl(slug: string) {
|
export function getManalinkUrl(slug: string) {
|
||||||
return `${location.protocol}//${location.host}/link/${slug}`
|
return `${location.protocol}//${location.host}/link/${slug}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function LinkPage() {
|
export default function LinkPage(props: { user: User }) {
|
||||||
const user = useUser()
|
const { user } = props
|
||||||
const links = useUserManalinks(user?.id ?? '')
|
const links = useUserManalinks(user.id ?? '')
|
||||||
// const manalinkTxns = useManalinkTxns(user?.id ?? '')
|
// const manalinkTxns = useManalinkTxns(user?.id ?? '')
|
||||||
const [highlightedSlug, setHighlightedSlug] = useState('')
|
const [highlightedSlug, setHighlightedSlug] = useState('')
|
||||||
const unclaimedLinks = links.filter(
|
const unclaimedLinks = links.filter(
|
||||||
|
@ -44,10 +49,6 @@ export default function LinkPage() {
|
||||||
(l.expiresTime == null || l.expiresTime > Date.now())
|
(l.expiresTime == null || l.expiresTime > Date.now())
|
||||||
)
|
)
|
||||||
|
|
||||||
if (user == null) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Page>
|
||||||
<SEO
|
<SEO
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { Tabs } from 'web/components/layout/tabs'
|
import { Tabs } from 'web/components/layout/tabs'
|
||||||
import { usePrivateUser } from 'web/hooks/use-user'
|
|
||||||
import React, { useEffect, useMemo, useState } from 'react'
|
import React, { useEffect, useMemo, useState } from 'react'
|
||||||
import { Notification, notification_source_types } from 'common/notification'
|
import { Notification, notification_source_types } from 'common/notification'
|
||||||
import { Avatar, EmptyAvatar } from 'web/components/avatar'
|
import { Avatar, EmptyAvatar } from 'web/components/avatar'
|
||||||
|
@ -13,9 +12,8 @@ import {
|
||||||
MANIFOLD_AVATAR_URL,
|
MANIFOLD_AVATAR_URL,
|
||||||
MANIFOLD_USERNAME,
|
MANIFOLD_USERNAME,
|
||||||
PrivateUser,
|
PrivateUser,
|
||||||
User,
|
|
||||||
} from 'common/user'
|
} from 'common/user'
|
||||||
import { getUser } from 'web/lib/firebase/users'
|
import { getPrivateUser } from 'web/lib/firebase/users'
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
import { RelativeTimestamp } from 'web/components/relative-timestamp'
|
import { RelativeTimestamp } from 'web/components/relative-timestamp'
|
||||||
import { Linkify } from 'web/components/linkify'
|
import { Linkify } from 'web/components/linkify'
|
||||||
|
@ -35,7 +33,6 @@ import { formatMoney } from 'common/util/format'
|
||||||
import { groupPath } from 'web/lib/firebase/groups'
|
import { groupPath } from 'web/lib/firebase/groups'
|
||||||
import { UNIQUE_BETTOR_BONUS_AMOUNT } from 'common/numeric-constants'
|
import { UNIQUE_BETTOR_BONUS_AMOUNT } from 'common/numeric-constants'
|
||||||
import { groupBy, sum, uniq } from 'lodash'
|
import { groupBy, sum, uniq } from 'lodash'
|
||||||
import Custom404 from 'web/pages/404'
|
|
||||||
import { track } from '@amplitude/analytics-browser'
|
import { track } from '@amplitude/analytics-browser'
|
||||||
import { Pagination } from 'web/components/pagination'
|
import { Pagination } from 'web/components/pagination'
|
||||||
import { useWindowSize } from 'web/hooks/use-window-size'
|
import { useWindowSize } from 'web/hooks/use-window-size'
|
||||||
|
@ -49,13 +46,12 @@ const MULTIPLE_USERS_KEY = 'multipleUsers'
|
||||||
const HIGHLIGHT_CLASS = 'bg-indigo-50'
|
const HIGHLIGHT_CLASS = 'bg-indigo-50'
|
||||||
|
|
||||||
export const getServerSideProps = redirectIfLoggedOut('/', async (_, creds) => {
|
export const getServerSideProps = redirectIfLoggedOut('/', async (_, creds) => {
|
||||||
const user = await getUser(creds.user.uid)
|
const privateUser = await getPrivateUser(creds.user.uid)
|
||||||
return { props: { user } }
|
return { props: { privateUser } }
|
||||||
})
|
})
|
||||||
|
|
||||||
export default function Notifications(props: { user: User }) {
|
export default function Notifications(props: { privateUser: PrivateUser }) {
|
||||||
const { user } = props
|
const { privateUser } = props
|
||||||
const privateUser = usePrivateUser(user?.id)
|
|
||||||
const local = safeLocalStorage()
|
const local = safeLocalStorage()
|
||||||
let localNotifications = [] as Notification[]
|
let localNotifications = [] as Notification[]
|
||||||
const localSavedNotificationGroups = local?.getItem('notification-groups')
|
const localSavedNotificationGroups = local?.getItem('notification-groups')
|
||||||
|
@ -67,7 +63,6 @@ export default function Notifications(props: { user: User }) {
|
||||||
.flat()
|
.flat()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!user) return <Custom404 />
|
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Page>
|
||||||
<div className={'px-2 pt-4 sm:px-4 lg:pt-0'}>
|
<div className={'px-2 pt-4 sm:px-4 lg:pt-0'}>
|
||||||
|
@ -81,17 +76,11 @@ export default function Notifications(props: { user: User }) {
|
||||||
tabs={[
|
tabs={[
|
||||||
{
|
{
|
||||||
title: 'Notifications',
|
title: 'Notifications',
|
||||||
content: privateUser ? (
|
content: (
|
||||||
<NotificationsList
|
<NotificationsList
|
||||||
privateUser={privateUser}
|
privateUser={privateUser}
|
||||||
cachedNotifications={localNotifications}
|
cachedNotifications={localNotifications}
|
||||||
/>
|
/>
|
||||||
) : (
|
|
||||||
<div className={'min-h-[100vh]'}>
|
|
||||||
<RenderNotificationGroups
|
|
||||||
notificationGroups={localNotificationGroups}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,25 +1,35 @@
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { RefreshIcon } from '@heroicons/react/outline'
|
import { RefreshIcon } from '@heroicons/react/outline'
|
||||||
|
|
||||||
import { AddFundsButton } from 'web/components/add-funds-button'
|
import { AddFundsButton } from 'web/components/add-funds-button'
|
||||||
import { Page } from 'web/components/page'
|
import { Page } from 'web/components/page'
|
||||||
import { SEO } from 'web/components/SEO'
|
import { SEO } from 'web/components/SEO'
|
||||||
import { Title } from 'web/components/title'
|
import { Title } from 'web/components/title'
|
||||||
import { usePrivateUser, useUser } from 'web/hooks/use-user'
|
|
||||||
import { formatMoney } from 'common/util/format'
|
import { formatMoney } from 'common/util/format'
|
||||||
import { cleanDisplayName, cleanUsername } from 'common/util/clean-username'
|
import { cleanDisplayName, cleanUsername } from 'common/util/clean-username'
|
||||||
import { changeUserInfo } from 'web/lib/firebase/api'
|
import { changeUserInfo } from 'web/lib/firebase/api'
|
||||||
import { uploadImage } from 'web/lib/firebase/storage'
|
import { uploadImage } from 'web/lib/firebase/storage'
|
||||||
import { Col } from 'web/components/layout/col'
|
import { Col } from 'web/components/layout/col'
|
||||||
import { Row } from 'web/components/layout/row'
|
import { Row } from 'web/components/layout/row'
|
||||||
import { User } from 'common/user'
|
import { User, PrivateUser } from 'common/user'
|
||||||
import { updateUser, updatePrivateUser } from 'web/lib/firebase/users'
|
import {
|
||||||
|
getUser,
|
||||||
|
getPrivateUser,
|
||||||
|
updateUser,
|
||||||
|
updatePrivateUser,
|
||||||
|
} from 'web/lib/firebase/users'
|
||||||
import { defaultBannerUrl } from 'web/components/user-page'
|
import { defaultBannerUrl } from 'web/components/user-page'
|
||||||
import { SiteLink } from 'web/components/site-link'
|
import { SiteLink } from 'web/components/site-link'
|
||||||
import Textarea from 'react-expanding-textarea'
|
import Textarea from 'react-expanding-textarea'
|
||||||
import { redirectIfLoggedOut } from 'web/lib/firebase/server-auth'
|
import { redirectIfLoggedOut } from 'web/lib/firebase/server-auth'
|
||||||
|
|
||||||
export const getServerSideProps = redirectIfLoggedOut('/')
|
export const getServerSideProps = redirectIfLoggedOut('/', async (_, creds) => {
|
||||||
|
const [user, privateUser] = await Promise.all([
|
||||||
|
getUser(creds.user.uid),
|
||||||
|
getPrivateUser(creds.user.uid),
|
||||||
|
])
|
||||||
|
return { props: { user, privateUser } }
|
||||||
|
})
|
||||||
|
|
||||||
function EditUserField(props: {
|
function EditUserField(props: {
|
||||||
user: User
|
user: User
|
||||||
|
@ -58,64 +68,45 @@ function EditUserField(props: {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ProfilePage() {
|
export default function ProfilePage(props: {
|
||||||
const user = useUser()
|
user: User
|
||||||
const privateUser = usePrivateUser(user?.id)
|
privateUser: PrivateUser
|
||||||
|
}) {
|
||||||
const [avatarUrl, setAvatarUrl] = useState(user?.avatarUrl || '')
|
const { user, privateUser } = props
|
||||||
|
const [avatarUrl, setAvatarUrl] = useState(user.avatarUrl || '')
|
||||||
const [avatarLoading, setAvatarLoading] = useState(false)
|
const [avatarLoading, setAvatarLoading] = useState(false)
|
||||||
const [name, setName] = useState(user?.name || '')
|
const [name, setName] = useState(user.name)
|
||||||
const [username, setUsername] = useState(user?.username || '')
|
const [username, setUsername] = useState(user.username)
|
||||||
const [apiKey, setApiKey] = useState(privateUser?.apiKey || '')
|
const [apiKey, setApiKey] = useState(privateUser.apiKey || '')
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (user) {
|
|
||||||
setAvatarUrl(user.avatarUrl || '')
|
|
||||||
setName(user.name || '')
|
|
||||||
setUsername(user.username || '')
|
|
||||||
}
|
|
||||||
}, [user])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (privateUser) {
|
|
||||||
setApiKey(privateUser.apiKey || '')
|
|
||||||
}
|
|
||||||
}, [privateUser])
|
|
||||||
|
|
||||||
const updateDisplayName = async () => {
|
const updateDisplayName = async () => {
|
||||||
const newName = cleanDisplayName(name)
|
const newName = cleanDisplayName(name)
|
||||||
|
|
||||||
if (newName) {
|
if (newName) {
|
||||||
setName(newName)
|
setName(newName)
|
||||||
await changeUserInfo({ name: newName }).catch((_) =>
|
await changeUserInfo({ name: newName }).catch((_) => setName(user.name))
|
||||||
setName(user?.name || '')
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
setName(user?.name || '')
|
setName(user.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateUsername = async () => {
|
const updateUsername = async () => {
|
||||||
const newUsername = cleanUsername(username)
|
const newUsername = cleanUsername(username)
|
||||||
|
|
||||||
if (newUsername) {
|
if (newUsername) {
|
||||||
setUsername(newUsername)
|
setUsername(newUsername)
|
||||||
await changeUserInfo({ username: newUsername }).catch((_) =>
|
await changeUserInfo({ username: newUsername }).catch((_) =>
|
||||||
setUsername(user?.username || '')
|
setUsername(user.username)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
setUsername(user?.username || '')
|
setUsername(user.username)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateApiKey = async (e: React.MouseEvent) => {
|
const updateApiKey = async (e: React.MouseEvent) => {
|
||||||
const newApiKey = crypto.randomUUID()
|
const newApiKey = crypto.randomUUID()
|
||||||
if (user?.id != null) {
|
setApiKey(newApiKey)
|
||||||
setApiKey(newApiKey)
|
await updatePrivateUser(user.id, { apiKey: newApiKey }).catch(() => {
|
||||||
await updatePrivateUser(user.id, { apiKey: newApiKey }).catch(() => {
|
setApiKey(privateUser.apiKey || '')
|
||||||
setApiKey(privateUser?.apiKey || '')
|
})
|
||||||
})
|
|
||||||
}
|
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +115,7 @@ export default function ProfilePage() {
|
||||||
|
|
||||||
setAvatarLoading(true)
|
setAvatarLoading(true)
|
||||||
|
|
||||||
await uploadImage(user?.username || 'default', file)
|
await uploadImage(user.username, file)
|
||||||
.then(async (url) => {
|
.then(async (url) => {
|
||||||
await changeUserInfo({ avatarUrl: url })
|
await changeUserInfo({ avatarUrl: url })
|
||||||
setAvatarUrl(url)
|
setAvatarUrl(url)
|
||||||
|
@ -132,14 +123,10 @@ export default function ProfilePage() {
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
setAvatarLoading(false)
|
setAvatarLoading(false)
|
||||||
setAvatarUrl(user?.avatarUrl || '')
|
setAvatarUrl(user.avatarUrl || '')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user == null) {
|
|
||||||
return <></>
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Page>
|
||||||
<SEO title="Profile" description="User profile settings" url="/profile" />
|
<SEO title="Profile" description="User profile settings" url="/profile" />
|
||||||
|
@ -147,7 +134,7 @@ export default function ProfilePage() {
|
||||||
<Col className="max-w-lg rounded bg-white p-6 shadow-md sm:mx-auto">
|
<Col className="max-w-lg rounded bg-white p-6 shadow-md sm:mx-auto">
|
||||||
<Row className="justify-between">
|
<Row className="justify-between">
|
||||||
<Title className="!mt-0" text="Edit Profile" />
|
<Title className="!mt-0" text="Edit Profile" />
|
||||||
<SiteLink className="btn btn-primary" href={`/${user?.username}`}>
|
<SiteLink className="btn btn-primary" href={`/${user.username}`}>
|
||||||
Done
|
Done
|
||||||
</SiteLink>
|
</SiteLink>
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -192,54 +179,53 @@ export default function ProfilePage() {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{user && (
|
{/* TODO: Allow users with M$ 2000 of assets to set custom banners */}
|
||||||
<>
|
{/* <EditUserField
|
||||||
{/* TODO: Allow users with M$ 2000 of assets to set custom banners */}
|
|
||||||
{/* <EditUserField
|
|
||||||
user={user}
|
user={user}
|
||||||
field="bannerUrl"
|
field="bannerUrl"
|
||||||
label="Banner Url"
|
label="Banner Url"
|
||||||
isEditing={isEditing}
|
isEditing={isEditing}
|
||||||
/> */}
|
/> */}
|
||||||
<label className="label">
|
<label className="label">
|
||||||
Banner image{' '}
|
Banner image{' '}
|
||||||
<span className="text-sm text-gray-400">
|
<span className="text-sm text-gray-400">Not editable for now</span>
|
||||||
Not editable for now
|
</label>
|
||||||
</span>
|
<div
|
||||||
</label>
|
className="h-32 w-full bg-cover bg-center sm:h-40"
|
||||||
<div
|
style={{
|
||||||
className="h-32 w-full bg-cover bg-center sm:h-40"
|
backgroundImage: `url(${
|
||||||
style={{
|
user.bannerUrl || defaultBannerUrl(user.id)
|
||||||
backgroundImage: `url(${
|
})`,
|
||||||
user.bannerUrl || defaultBannerUrl(user.id)
|
}}
|
||||||
})`,
|
/>
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{(
|
{(
|
||||||
[
|
[
|
||||||
['bio', 'Bio'],
|
['bio', 'Bio'],
|
||||||
['website', 'Website URL'],
|
['website', 'Website URL'],
|
||||||
['twitterHandle', 'Twitter'],
|
['twitterHandle', 'Twitter'],
|
||||||
['discordHandle', 'Discord'],
|
['discordHandle', 'Discord'],
|
||||||
] as const
|
] as const
|
||||||
).map(([field, label]) => (
|
).map(([field, label]) => (
|
||||||
<EditUserField user={user} field={field} label={label} />
|
<EditUserField
|
||||||
))}
|
key={field}
|
||||||
</>
|
user={user}
|
||||||
)}
|
field={field}
|
||||||
|
label={label}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="label">Email</label>
|
<label className="label">Email</label>
|
||||||
<div className="ml-1 text-gray-500">
|
<div className="ml-1 text-gray-500">
|
||||||
{privateUser?.email ?? '\u00a0'}
|
{privateUser.email ?? '\u00a0'}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="label">Balance</label>
|
<label className="label">Balance</label>
|
||||||
<Row className="ml-1 items-start gap-4 text-gray-500">
|
<Row className="ml-1 items-start gap-4 text-gray-500">
|
||||||
{formatMoney(user?.balance || 0)}
|
{formatMoney(user.balance)}
|
||||||
<AddFundsButton />
|
<AddFundsButton />
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user