Enrich contract resolved notification
This commit is contained in:
parent
b903183fff
commit
7628713c4b
|
@ -2,3 +2,8 @@ export type Follow = {
|
||||||
userId: string
|
userId: string
|
||||||
timestamp: number
|
timestamp: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ContractFollow = {
|
||||||
|
id: string // user id
|
||||||
|
createdTime: number
|
||||||
|
}
|
||||||
|
|
|
@ -248,3 +248,9 @@ export type BetFillData = {
|
||||||
probability: number
|
probability: number
|
||||||
fillAmount: number
|
fillAmount: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ContractResolutionData = {
|
||||||
|
outcome: string
|
||||||
|
userPayout: number
|
||||||
|
userInvestment: number
|
||||||
|
}
|
||||||
|
|
|
@ -218,6 +218,7 @@ const notificationReasonToSubscriptionType: Partial<
|
||||||
|
|
||||||
export const getNotificationDestinationsForUser = (
|
export const getNotificationDestinationsForUser = (
|
||||||
privateUser: PrivateUser,
|
privateUser: PrivateUser,
|
||||||
|
// TODO: accept reasons array from most to least important and work backwards
|
||||||
reason: notification_reason_types | notification_preference
|
reason: notification_reason_types | notification_preference
|
||||||
) => {
|
) => {
|
||||||
const notificationSettings = privateUser.notificationPreferences
|
const notificationSettings = privateUser.notificationPreferences
|
||||||
|
|
|
@ -2,6 +2,7 @@ import * as admin from 'firebase-admin'
|
||||||
import {
|
import {
|
||||||
BetFillData,
|
BetFillData,
|
||||||
BettingStreakData,
|
BettingStreakData,
|
||||||
|
ContractResolutionData,
|
||||||
Notification,
|
Notification,
|
||||||
notification_reason_types,
|
notification_reason_types,
|
||||||
} from '../../common/notification'
|
} from '../../common/notification'
|
||||||
|
@ -28,6 +29,7 @@ import {
|
||||||
} from './emails'
|
} from './emails'
|
||||||
import { filterDefined } from '../../common/util/array'
|
import { filterDefined } from '../../common/util/array'
|
||||||
import { getNotificationDestinationsForUser } from '../../common/user-notification-preferences'
|
import { getNotificationDestinationsForUser } from '../../common/user-notification-preferences'
|
||||||
|
import { ContractFollow } from '../../common/follow'
|
||||||
const firestore = admin.firestore()
|
const firestore = admin.firestore()
|
||||||
|
|
||||||
type recipients_to_reason_texts = {
|
type recipients_to_reason_texts = {
|
||||||
|
@ -159,7 +161,7 @@ export type replied_users_info = {
|
||||||
export const createCommentOrAnswerOrUpdatedContractNotification = async (
|
export const createCommentOrAnswerOrUpdatedContractNotification = async (
|
||||||
sourceId: string,
|
sourceId: string,
|
||||||
sourceType: 'comment' | 'answer' | 'contract',
|
sourceType: 'comment' | 'answer' | 'contract',
|
||||||
sourceUpdateType: 'created' | 'updated' | 'resolved',
|
sourceUpdateType: 'created' | 'updated',
|
||||||
sourceUser: User,
|
sourceUser: User,
|
||||||
idempotencyKey: string,
|
idempotencyKey: string,
|
||||||
sourceText: string,
|
sourceText: string,
|
||||||
|
@ -167,17 +169,6 @@ export const createCommentOrAnswerOrUpdatedContractNotification = async (
|
||||||
miscData?: {
|
miscData?: {
|
||||||
repliedUsersInfo: replied_users_info
|
repliedUsersInfo: replied_users_info
|
||||||
taggedUserIds: string[]
|
taggedUserIds: string[]
|
||||||
},
|
|
||||||
resolutionData?: {
|
|
||||||
bets: Bet[]
|
|
||||||
userInvestments: { [userId: string]: number }
|
|
||||||
userPayouts: { [userId: string]: number }
|
|
||||||
creator: User
|
|
||||||
creatorPayout: number
|
|
||||||
contract: Contract
|
|
||||||
outcome: string
|
|
||||||
resolutionProbability?: number
|
|
||||||
resolutions?: { [outcome: string]: number }
|
|
||||||
}
|
}
|
||||||
) => {
|
) => {
|
||||||
const { repliedUsersInfo, taggedUserIds } = miscData ?? {}
|
const { repliedUsersInfo, taggedUserIds } = miscData ?? {}
|
||||||
|
@ -230,11 +221,7 @@ export const createCommentOrAnswerOrUpdatedContractNotification = async (
|
||||||
userId: string,
|
userId: string,
|
||||||
reason: notification_reason_types
|
reason: notification_reason_types
|
||||||
) => {
|
) => {
|
||||||
if (
|
if (!stillFollowingContract(userId) || sourceUser.id == userId) return
|
||||||
!stillFollowingContract(sourceContract.creatorId) ||
|
|
||||||
sourceUser.id == userId
|
|
||||||
)
|
|
||||||
return
|
|
||||||
const privateUser = await getPrivateUser(userId)
|
const privateUser = await getPrivateUser(userId)
|
||||||
if (!privateUser) return
|
if (!privateUser) return
|
||||||
const { sendToBrowser, sendToEmail } = getNotificationDestinationsForUser(
|
const { sendToBrowser, sendToEmail } = getNotificationDestinationsForUser(
|
||||||
|
@ -276,24 +263,6 @@ export const createCommentOrAnswerOrUpdatedContractNotification = async (
|
||||||
sourceUser.avatarUrl
|
sourceUser.avatarUrl
|
||||||
)
|
)
|
||||||
emailRecipientIdsList.push(userId)
|
emailRecipientIdsList.push(userId)
|
||||||
} else if (
|
|
||||||
sourceType === 'contract' &&
|
|
||||||
sourceUpdateType === 'resolved' &&
|
|
||||||
resolutionData
|
|
||||||
) {
|
|
||||||
await sendMarketResolutionEmail(
|
|
||||||
reason,
|
|
||||||
privateUser,
|
|
||||||
resolutionData.userInvestments[userId] ?? 0,
|
|
||||||
resolutionData.userPayouts[userId] ?? 0,
|
|
||||||
sourceUser,
|
|
||||||
resolutionData.creatorPayout,
|
|
||||||
sourceContract,
|
|
||||||
resolutionData.outcome,
|
|
||||||
resolutionData.resolutionProbability,
|
|
||||||
resolutionData.resolutions
|
|
||||||
)
|
|
||||||
emailRecipientIdsList.push(userId)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,6 +416,8 @@ export const createCommentOrAnswerOrUpdatedContractNotification = async (
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: store all possible reasons why the user might be getting the notification and choose the most lenient that they
|
||||||
|
// have enabled so they will unsubscribe from the least important notifications
|
||||||
await notifyRepliedUser()
|
await notifyRepliedUser()
|
||||||
await notifyTaggedUsers()
|
await notifyTaggedUsers()
|
||||||
await notifyContractCreator()
|
await notifyContractCreator()
|
||||||
|
@ -943,3 +914,130 @@ export const createNewContractNotification = async (
|
||||||
await sendNotificationsIfSettingsAllow(mentionedUserId, 'tagged_user')
|
await sendNotificationsIfSettingsAllow(mentionedUserId, 'tagged_user')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const createContractResolvedNotifications = async (
|
||||||
|
contract: Contract,
|
||||||
|
creator: User,
|
||||||
|
outcome: string,
|
||||||
|
probabilityInt: number | undefined,
|
||||||
|
resolutionValue: number | undefined,
|
||||||
|
resolutionData: {
|
||||||
|
bets: Bet[]
|
||||||
|
userInvestments: { [userId: string]: number }
|
||||||
|
userPayouts: { [userId: string]: number }
|
||||||
|
creator: User
|
||||||
|
creatorPayout: number
|
||||||
|
contract: Contract
|
||||||
|
outcome: string
|
||||||
|
resolutionProbability?: number
|
||||||
|
resolutions?: { [outcome: string]: number }
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
let resolutionText = outcome ?? contract.question
|
||||||
|
if (
|
||||||
|
contract.outcomeType === 'FREE_RESPONSE' ||
|
||||||
|
contract.outcomeType === 'MULTIPLE_CHOICE'
|
||||||
|
) {
|
||||||
|
const answerText = contract.answers.find(
|
||||||
|
(answer) => answer.id === outcome
|
||||||
|
)?.text
|
||||||
|
if (answerText) resolutionText = answerText
|
||||||
|
} else if (contract.outcomeType === 'BINARY') {
|
||||||
|
if (resolutionText === 'MKT' && probabilityInt)
|
||||||
|
resolutionText = `${probabilityInt}%`
|
||||||
|
else if (resolutionText === 'MKT') resolutionText = 'PROB'
|
||||||
|
} else if (contract.outcomeType === 'PSEUDO_NUMERIC') {
|
||||||
|
if (resolutionText === 'MKT' && resolutionValue)
|
||||||
|
resolutionText = `${resolutionValue}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const idempotencyKey = contract.id + '-resolved'
|
||||||
|
const createBrowserNotification = async (
|
||||||
|
userId: string,
|
||||||
|
reason: notification_reason_types
|
||||||
|
) => {
|
||||||
|
const notificationRef = firestore
|
||||||
|
.collection(`/users/${userId}/notifications`)
|
||||||
|
.doc(idempotencyKey)
|
||||||
|
const notification: Notification = {
|
||||||
|
id: idempotencyKey,
|
||||||
|
userId,
|
||||||
|
reason,
|
||||||
|
createdTime: Date.now(),
|
||||||
|
isSeen: false,
|
||||||
|
sourceId: contract.id,
|
||||||
|
sourceType: 'contract',
|
||||||
|
sourceUpdateType: 'resolved',
|
||||||
|
sourceContractId: contract.id,
|
||||||
|
sourceUserName: creator.name,
|
||||||
|
sourceUserUsername: creator.username,
|
||||||
|
sourceUserAvatarUrl: creator.avatarUrl,
|
||||||
|
sourceText: resolutionText,
|
||||||
|
sourceContractCreatorUsername: contract.creatorUsername,
|
||||||
|
sourceContractTitle: contract.question,
|
||||||
|
sourceContractSlug: contract.slug,
|
||||||
|
sourceSlug: contract.slug,
|
||||||
|
sourceTitle: contract.question,
|
||||||
|
data: {
|
||||||
|
outcome,
|
||||||
|
userInvestment: resolutionData.userInvestments[userId] ?? 0,
|
||||||
|
userPayout: resolutionData.userPayouts[userId] ?? 0,
|
||||||
|
} as ContractResolutionData,
|
||||||
|
}
|
||||||
|
return await notificationRef.set(removeUndefinedProps(notification))
|
||||||
|
}
|
||||||
|
|
||||||
|
const sendNotificationsIfSettingsPermit = async (
|
||||||
|
userId: string,
|
||||||
|
reason: notification_reason_types
|
||||||
|
) => {
|
||||||
|
if (!stillFollowingContract(userId) || creator.id == userId) return
|
||||||
|
const privateUser = await getPrivateUser(userId)
|
||||||
|
if (!privateUser) return
|
||||||
|
const { sendToBrowser, sendToEmail } = getNotificationDestinationsForUser(
|
||||||
|
privateUser,
|
||||||
|
reason
|
||||||
|
)
|
||||||
|
|
||||||
|
// Browser notifications
|
||||||
|
if (sendToBrowser) {
|
||||||
|
await createBrowserNotification(userId, reason)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emails notifications
|
||||||
|
if (sendToEmail)
|
||||||
|
await sendMarketResolutionEmail(
|
||||||
|
reason,
|
||||||
|
privateUser,
|
||||||
|
resolutionData.userInvestments[userId] ?? 0,
|
||||||
|
resolutionData.userPayouts[userId] ?? 0,
|
||||||
|
creator,
|
||||||
|
resolutionData.creatorPayout,
|
||||||
|
contract,
|
||||||
|
resolutionData.outcome,
|
||||||
|
resolutionData.resolutionProbability,
|
||||||
|
resolutionData.resolutions
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const contractFollowersIds = (
|
||||||
|
await getValues<ContractFollow>(
|
||||||
|
firestore.collection(`contracts/${contract.id}/follows`)
|
||||||
|
)
|
||||||
|
).map((follow) => follow.id)
|
||||||
|
|
||||||
|
const stillFollowingContract = (userId: string) => {
|
||||||
|
return contractFollowersIds.includes(userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
contractFollowersIds.map((id) =>
|
||||||
|
sendNotificationsIfSettingsPermit(
|
||||||
|
id,
|
||||||
|
resolutionData.userInvestments[id]
|
||||||
|
? 'resolution_on_contract_with_users_shares_in'
|
||||||
|
: 'resolution_on_contract_you_follow'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ import { removeUndefinedProps } from '../../common/util/object'
|
||||||
import { LiquidityProvision } from '../../common/liquidity-provision'
|
import { LiquidityProvision } from '../../common/liquidity-provision'
|
||||||
import { APIError, newEndpoint, validate } from './api'
|
import { APIError, newEndpoint, validate } from './api'
|
||||||
import { getContractBetMetrics } from '../../common/calculate'
|
import { getContractBetMetrics } from '../../common/calculate'
|
||||||
import { createCommentOrAnswerOrUpdatedContractNotification } from './create-notification'
|
import { createContractResolvedNotifications } from './create-notification'
|
||||||
import { CancelUniqueBettorBonusTxn, Txn } from '../../common/txn'
|
import { CancelUniqueBettorBonusTxn, Txn } from '../../common/txn'
|
||||||
import { runTxn, TxnData } from './transact'
|
import { runTxn, TxnData } from './transact'
|
||||||
import {
|
import {
|
||||||
|
@ -177,33 +177,13 @@ export const resolvemarket = newEndpoint(opts, async (req, auth) => {
|
||||||
groupBy(bets, (bet) => bet.userId),
|
groupBy(bets, (bet) => bet.userId),
|
||||||
(bets) => getContractBetMetrics(contract, bets).invested
|
(bets) => getContractBetMetrics(contract, bets).invested
|
||||||
)
|
)
|
||||||
let resolutionText = outcome ?? contract.question
|
|
||||||
if (
|
|
||||||
contract.outcomeType === 'FREE_RESPONSE' ||
|
|
||||||
contract.outcomeType === 'MULTIPLE_CHOICE'
|
|
||||||
) {
|
|
||||||
const answerText = contract.answers.find(
|
|
||||||
(answer) => answer.id === outcome
|
|
||||||
)?.text
|
|
||||||
if (answerText) resolutionText = answerText
|
|
||||||
} else if (contract.outcomeType === 'BINARY') {
|
|
||||||
if (resolutionText === 'MKT' && probabilityInt)
|
|
||||||
resolutionText = `${probabilityInt}%`
|
|
||||||
else if (resolutionText === 'MKT') resolutionText = 'PROB'
|
|
||||||
} else if (contract.outcomeType === 'PSEUDO_NUMERIC') {
|
|
||||||
if (resolutionText === 'MKT' && value) resolutionText = `${value}`
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: this actually may be too slow to complete with a ton of users to notify?
|
await createContractResolvedNotifications(
|
||||||
await createCommentOrAnswerOrUpdatedContractNotification(
|
|
||||||
contract.id,
|
|
||||||
'contract',
|
|
||||||
'resolved',
|
|
||||||
creator,
|
|
||||||
contract.id + '-resolution',
|
|
||||||
resolutionText,
|
|
||||||
contract,
|
contract,
|
||||||
undefined,
|
creator,
|
||||||
|
outcome,
|
||||||
|
probabilityInt,
|
||||||
|
value,
|
||||||
{
|
{
|
||||||
bets,
|
bets,
|
||||||
userInvestments,
|
userInvestments,
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { chunk } from 'lodash'
|
||||||
import { Contract } from '../../common/contract'
|
import { Contract } from '../../common/contract'
|
||||||
import { PrivateUser, User } from '../../common/user'
|
import { PrivateUser, User } from '../../common/user'
|
||||||
import { Group } from '../../common/group'
|
import { Group } from '../../common/group'
|
||||||
import { Post } from 'common/post'
|
import { Post } from '../../common/post'
|
||||||
|
|
||||||
export const log = (...args: unknown[]) => {
|
export const log = (...args: unknown[]) => {
|
||||||
console.log(`[${new Date().toISOString()}]`, ...args)
|
console.log(`[${new Date().toISOString()}]`, ...args)
|
||||||
|
|
|
@ -3,6 +3,7 @@ import React, { useEffect, useMemo, useState } from 'react'
|
||||||
import Router, { useRouter } from 'next/router'
|
import Router, { useRouter } from 'next/router'
|
||||||
import {
|
import {
|
||||||
BetFillData,
|
BetFillData,
|
||||||
|
ContractResolutionData,
|
||||||
Notification,
|
Notification,
|
||||||
notification_source_types,
|
notification_source_types,
|
||||||
} from 'common/notification'
|
} from 'common/notification'
|
||||||
|
@ -706,7 +707,7 @@ function NotificationItem(props: {
|
||||||
isChildOfGroup?: boolean
|
isChildOfGroup?: boolean
|
||||||
}) {
|
}) {
|
||||||
const { notification, justSummary, isChildOfGroup } = props
|
const { notification, justSummary, isChildOfGroup } = props
|
||||||
const { sourceType, reason } = notification
|
const { sourceType, reason, sourceUpdateType } = notification
|
||||||
|
|
||||||
const [highlighted] = useState(!notification.isSeen)
|
const [highlighted] = useState(!notification.isSeen)
|
||||||
|
|
||||||
|
@ -724,6 +725,15 @@ function NotificationItem(props: {
|
||||||
justSummary={justSummary}
|
justSummary={justSummary}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
} else if (sourceType === 'contract' && sourceUpdateType === 'resolved') {
|
||||||
|
return (
|
||||||
|
<ContractResolvedNotification
|
||||||
|
notification={notification}
|
||||||
|
isChildOfGroup={isChildOfGroup}
|
||||||
|
highlighted={highlighted}
|
||||||
|
justSummary={justSummary}
|
||||||
|
/>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
// TODO Add new notification components here
|
// TODO Add new notification components here
|
||||||
|
|
||||||
|
@ -810,7 +820,8 @@ function NotificationFrame(props: {
|
||||||
sourceText,
|
sourceText,
|
||||||
} = notification
|
} = notification
|
||||||
const questionNeedsResolution = sourceUpdateType == 'closed'
|
const questionNeedsResolution = sourceUpdateType == 'closed'
|
||||||
|
const { width } = useWindowSize()
|
||||||
|
const isMobile = (width ?? 0) < 600
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(
|
className={clsx(
|
||||||
|
@ -860,7 +871,7 @@ function NotificationFrame(props: {
|
||||||
name={sourceUserName || ''}
|
name={sourceUserName || ''}
|
||||||
username={sourceUserUsername || ''}
|
username={sourceUserUsername || ''}
|
||||||
className={'relative mr-1 flex-shrink-0'}
|
className={'relative mr-1 flex-shrink-0'}
|
||||||
short={true}
|
short={isMobile}
|
||||||
/>
|
/>
|
||||||
{subtitle}
|
{subtitle}
|
||||||
{isChildOfGroup ? (
|
{isChildOfGroup ? (
|
||||||
|
@ -945,6 +956,83 @@ function BetFillNotification(props: {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ContractResolvedNotification(props: {
|
||||||
|
notification: Notification
|
||||||
|
highlighted: boolean
|
||||||
|
justSummary: boolean
|
||||||
|
isChildOfGroup?: boolean
|
||||||
|
}) {
|
||||||
|
const { notification, isChildOfGroup, highlighted, justSummary } = props
|
||||||
|
const { sourceText, data } = notification
|
||||||
|
const { userInvestment, userPayout } = (data as ContractResolutionData) ?? {}
|
||||||
|
const subtitle = 'resolved the market'
|
||||||
|
const resolutionDescription = () => {
|
||||||
|
if (!sourceText) return <div />
|
||||||
|
if (sourceText === 'YES' || sourceText == 'NO') {
|
||||||
|
return <BinaryOutcomeLabel outcome={sourceText as any} />
|
||||||
|
}
|
||||||
|
if (sourceText.includes('%'))
|
||||||
|
return <ProbPercentLabel prob={parseFloat(sourceText.replace('%', ''))} />
|
||||||
|
if (sourceText === 'CANCEL') return <CancelLabel />
|
||||||
|
if (sourceText === 'MKT' || sourceText === 'PROB') return <MultiLabel />
|
||||||
|
|
||||||
|
// Numeric market
|
||||||
|
if (parseFloat(sourceText))
|
||||||
|
return <NumericValueLabel value={parseFloat(sourceText)} />
|
||||||
|
|
||||||
|
// Free response market
|
||||||
|
return (
|
||||||
|
<div className={'line-clamp-1 text-blue-400'}>
|
||||||
|
<Linkify text={sourceText} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const description =
|
||||||
|
userInvestment && userPayout ? (
|
||||||
|
<Row className={'gap-1 '}>
|
||||||
|
{resolutionDescription()}
|
||||||
|
Invested:
|
||||||
|
<span className={'text-primary'}>{formatMoney(userInvestment)} </span>
|
||||||
|
Payout:
|
||||||
|
<span
|
||||||
|
className={clsx(
|
||||||
|
userPayout > 0 ? 'text-primary' : 'text-red-500',
|
||||||
|
'truncate'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{formatMoney(userPayout)}
|
||||||
|
{` (${userPayout > 0 ? '+' : '-'}${Math.round(
|
||||||
|
((userPayout - userInvestment) / userInvestment) * 100
|
||||||
|
)}%)`}
|
||||||
|
</span>
|
||||||
|
</Row>
|
||||||
|
) : (
|
||||||
|
<span>{resolutionDescription()}</span>
|
||||||
|
)
|
||||||
|
|
||||||
|
if (justSummary) {
|
||||||
|
return (
|
||||||
|
<NotificationSummaryFrame notification={notification} subtitle={subtitle}>
|
||||||
|
<Row className={'line-clamp-1'}>{description}</Row>
|
||||||
|
</NotificationSummaryFrame>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NotificationFrame
|
||||||
|
notification={notification}
|
||||||
|
isChildOfGroup={isChildOfGroup}
|
||||||
|
highlighted={highlighted}
|
||||||
|
subtitle={subtitle}
|
||||||
|
>
|
||||||
|
<Row>
|
||||||
|
<span>{description}</span>
|
||||||
|
</Row>
|
||||||
|
</NotificationFrame>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export const setNotificationsAsSeen = async (notifications: Notification[]) => {
|
export const setNotificationsAsSeen = async (notifications: Notification[]) => {
|
||||||
const unseenNotifications = notifications.filter((n) => !n.isSeen)
|
const unseenNotifications = notifications.filter((n) => !n.isSeen)
|
||||||
return await Promise.all(
|
return await Promise.all(
|
||||||
|
@ -1064,30 +1152,7 @@ function NotificationTextLabel(props: {
|
||||||
if (sourceType === 'contract') {
|
if (sourceType === 'contract') {
|
||||||
if (justSummary || !sourceText) return <div />
|
if (justSummary || !sourceText) return <div />
|
||||||
// Resolved contracts
|
// Resolved contracts
|
||||||
if (sourceType === 'contract' && sourceUpdateType === 'resolved') {
|
|
||||||
{
|
|
||||||
if (sourceText === 'YES' || sourceText == 'NO') {
|
|
||||||
return <BinaryOutcomeLabel outcome={sourceText as any} />
|
|
||||||
}
|
|
||||||
if (sourceText.includes('%'))
|
|
||||||
return (
|
|
||||||
<ProbPercentLabel prob={parseFloat(sourceText.replace('%', ''))} />
|
|
||||||
)
|
|
||||||
if (sourceText === 'CANCEL') return <CancelLabel />
|
|
||||||
if (sourceText === 'MKT' || sourceText === 'PROB') return <MultiLabel />
|
|
||||||
|
|
||||||
// Numeric market
|
|
||||||
if (parseFloat(sourceText))
|
|
||||||
return <NumericValueLabel value={parseFloat(sourceText)} />
|
|
||||||
|
|
||||||
// Free response market
|
|
||||||
return (
|
|
||||||
<div className={className ? className : 'line-clamp-1 text-blue-400'}>
|
|
||||||
<Linkify text={sourceText} />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Close date will be a number - it looks better without it
|
// Close date will be a number - it looks better without it
|
||||||
if (sourceUpdateType === 'closed') {
|
if (sourceUpdateType === 'closed') {
|
||||||
return <div />
|
return <div />
|
||||||
|
|
Loading…
Reference in New Issue
Block a user