Enrich limit order notification
This commit is contained in:
parent
69c2570ff9
commit
8c6a40bab7
|
@ -92,11 +92,6 @@ export type notification_reason_types =
|
||||||
| 'your_contract_closed'
|
| 'your_contract_closed'
|
||||||
| 'subsidized_your_market'
|
| 'subsidized_your_market'
|
||||||
|
|
||||||
export type BettingStreakData = {
|
|
||||||
streak: number
|
|
||||||
bonusAmount: number
|
|
||||||
}
|
|
||||||
|
|
||||||
type notification_descriptions = {
|
type notification_descriptions = {
|
||||||
[key in notification_preference]: {
|
[key in notification_preference]: {
|
||||||
simple: string
|
simple: string
|
||||||
|
@ -241,3 +236,15 @@ export const NOTIFICATION_DESCRIPTIONS: notification_descriptions = {
|
||||||
detailed: `Answers on markets that you're watching and that you're invested in`,
|
detailed: `Answers on markets that you're watching and that you're invested in`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type BettingStreakData = {
|
||||||
|
streak: number
|
||||||
|
bonusAmount: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export type BetFillData = {
|
||||||
|
betOutcome: string
|
||||||
|
creatorOutcome: string
|
||||||
|
probability: number
|
||||||
|
fillAmount: number
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import * as admin from 'firebase-admin'
|
import * as admin from 'firebase-admin'
|
||||||
import {
|
import {
|
||||||
|
BetFillData,
|
||||||
BettingStreakData,
|
BettingStreakData,
|
||||||
Notification,
|
Notification,
|
||||||
notification_reason_types,
|
notification_reason_types,
|
||||||
|
@ -542,6 +543,12 @@ export const createBetFillNotification = async (
|
||||||
sourceContractTitle: contract.question,
|
sourceContractTitle: contract.question,
|
||||||
sourceContractSlug: contract.slug,
|
sourceContractSlug: contract.slug,
|
||||||
sourceContractId: contract.id,
|
sourceContractId: contract.id,
|
||||||
|
data: {
|
||||||
|
betOutcome: bet.outcome,
|
||||||
|
creatorOutcome: userBet.outcome,
|
||||||
|
fillAmount,
|
||||||
|
probability: userBet.limitProb,
|
||||||
|
} as BetFillData,
|
||||||
}
|
}
|
||||||
return await notificationRef.set(removeUndefinedProps(notification))
|
return await notificationRef.set(removeUndefinedProps(notification))
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,14 @@ import { initAdmin } from './script-init'
|
||||||
initAdmin()
|
initAdmin()
|
||||||
|
|
||||||
import { getValues } from '../utils'
|
import { getValues } from '../utils'
|
||||||
import { Contract } from 'common/lib/contract'
|
import { Contract } from 'common/contract'
|
||||||
import { Comment } from 'common/lib/comment'
|
import { Comment } from 'common/comment'
|
||||||
import { uniq } from 'lodash'
|
import { uniq } from 'lodash'
|
||||||
import { Bet } from 'common/lib/bet'
|
import { Bet } from 'common/bet'
|
||||||
import {
|
import {
|
||||||
DEV_HOUSE_LIQUIDITY_PROVIDER_ID,
|
DEV_HOUSE_LIQUIDITY_PROVIDER_ID,
|
||||||
HOUSE_LIQUIDITY_PROVIDER_ID,
|
HOUSE_LIQUIDITY_PROVIDER_ID,
|
||||||
} from 'common/lib/antes'
|
} from 'common/antes'
|
||||||
|
|
||||||
const firestore = admin.firestore()
|
const firestore = admin.firestore()
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
import { ControlledTabs } from 'web/components/layout/tabs'
|
import { ControlledTabs } from 'web/components/layout/tabs'
|
||||||
import React, { useEffect, useMemo, useState } from 'react'
|
import React, { useEffect, useMemo, useState } from 'react'
|
||||||
import Router, { useRouter } from 'next/router'
|
import Router, { useRouter } from 'next/router'
|
||||||
import { Notification, notification_source_types } from 'common/notification'
|
import {
|
||||||
|
BetFillData,
|
||||||
|
Notification,
|
||||||
|
notification_source_types,
|
||||||
|
} from 'common/notification'
|
||||||
import { Avatar, EmptyAvatar } from 'web/components/avatar'
|
import { Avatar, EmptyAvatar } from 'web/components/avatar'
|
||||||
import { Row } from 'web/components/layout/row'
|
import { Row } from 'web/components/layout/row'
|
||||||
import { Page } from 'web/components/page'
|
import { Page } from 'web/components/page'
|
||||||
|
@ -141,6 +145,7 @@ function RenderNotificationGroups(props: {
|
||||||
<NotificationItem
|
<NotificationItem
|
||||||
notification={notification.notifications[0]}
|
notification={notification.notifications[0]}
|
||||||
key={notification.notifications[0].id}
|
key={notification.notifications[0].id}
|
||||||
|
justSummary={false}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<NotificationGroupItem
|
<NotificationGroupItem
|
||||||
|
@ -697,20 +702,11 @@ function NotificationGroupItem(props: {
|
||||||
|
|
||||||
function NotificationItem(props: {
|
function NotificationItem(props: {
|
||||||
notification: Notification
|
notification: Notification
|
||||||
justSummary?: boolean
|
justSummary: boolean
|
||||||
isChildOfGroup?: boolean
|
isChildOfGroup?: boolean
|
||||||
}) {
|
}) {
|
||||||
const { notification, justSummary, isChildOfGroup } = props
|
const { notification, justSummary, isChildOfGroup } = props
|
||||||
const {
|
const { sourceType, reason } = notification
|
||||||
sourceType,
|
|
||||||
sourceUserName,
|
|
||||||
sourceUserAvatarUrl,
|
|
||||||
sourceUpdateType,
|
|
||||||
reasonText,
|
|
||||||
reason,
|
|
||||||
sourceUserUsername,
|
|
||||||
sourceText,
|
|
||||||
} = notification
|
|
||||||
|
|
||||||
const [highlighted] = useState(!notification.isSeen)
|
const [highlighted] = useState(!notification.isSeen)
|
||||||
|
|
||||||
|
@ -718,9 +714,62 @@ function NotificationItem(props: {
|
||||||
setNotificationsAsSeen([notification])
|
setNotificationsAsSeen([notification])
|
||||||
}, [notification])
|
}, [notification])
|
||||||
|
|
||||||
const questionNeedsResolution = sourceUpdateType == 'closed'
|
// TODO Any new notification should be its own component
|
||||||
|
if (reason === 'bet_fill') {
|
||||||
|
return (
|
||||||
|
<BetFillNotification
|
||||||
|
notification={notification}
|
||||||
|
isChildOfGroup={isChildOfGroup}
|
||||||
|
highlighted={highlighted}
|
||||||
|
justSummary={justSummary}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// TODO Add new notification components here
|
||||||
|
|
||||||
if (justSummary) {
|
if (justSummary) {
|
||||||
|
return (
|
||||||
|
<NotificationSummaryFrame
|
||||||
|
notification={notification}
|
||||||
|
subtitle={
|
||||||
|
(sourceType &&
|
||||||
|
reason &&
|
||||||
|
getReasonForShowingNotification(notification, true)) ??
|
||||||
|
''
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<NotificationTextLabel
|
||||||
|
className={'line-clamp-1'}
|
||||||
|
notification={notification}
|
||||||
|
justSummary={true}
|
||||||
|
/>
|
||||||
|
</NotificationSummaryFrame>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NotificationFrame
|
||||||
|
notification={notification}
|
||||||
|
subtitle={getReasonForShowingNotification(
|
||||||
|
notification,
|
||||||
|
isChildOfGroup ?? false
|
||||||
|
)}
|
||||||
|
highlighted={highlighted}
|
||||||
|
>
|
||||||
|
<div className={'mt-1 ml-1 md:text-base'}>
|
||||||
|
<NotificationTextLabel notification={notification} />
|
||||||
|
</div>
|
||||||
|
</NotificationFrame>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function NotificationSummaryFrame(props: {
|
||||||
|
notification: Notification
|
||||||
|
subtitle: string
|
||||||
|
children: React.ReactNode
|
||||||
|
}) {
|
||||||
|
const { notification, subtitle, children } = props
|
||||||
|
const { sourceUserName, sourceUserUsername } = notification
|
||||||
return (
|
return (
|
||||||
<Row className={'items-center text-sm text-gray-500 sm:justify-start'}>
|
<Row className={'items-center text-sm text-gray-500 sm:justify-start'}>
|
||||||
<div className={'line-clamp-1 flex-1 overflow-hidden sm:flex'}>
|
<div className={'line-clamp-1 flex-1 overflow-hidden sm:flex'}>
|
||||||
|
@ -732,24 +781,35 @@ function NotificationItem(props: {
|
||||||
short={true}
|
short={true}
|
||||||
/>
|
/>
|
||||||
<div className={'inline-flex overflow-hidden text-ellipsis pl-1'}>
|
<div className={'inline-flex overflow-hidden text-ellipsis pl-1'}>
|
||||||
<span className={'flex-shrink-0'}>
|
<span className={'flex-shrink-0'}>{subtitle}</span>
|
||||||
{sourceType &&
|
<div className={'line-clamp-1 ml-1 text-black'}>{children}</div>
|
||||||
reason &&
|
|
||||||
getReasonForShowingNotification(notification, true)}
|
|
||||||
</span>
|
|
||||||
<div className={'ml-1 text-black'}>
|
|
||||||
<NotificationTextLabel
|
|
||||||
className={'line-clamp-1'}
|
|
||||||
notification={notification}
|
|
||||||
justSummary={true}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Row>
|
</Row>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function NotificationFrame(props: {
|
||||||
|
notification: Notification
|
||||||
|
highlighted: boolean
|
||||||
|
subtitle: string
|
||||||
|
children: React.ReactNode
|
||||||
|
isChildOfGroup?: boolean
|
||||||
|
}) {
|
||||||
|
const { notification, isChildOfGroup, highlighted, subtitle, children } =
|
||||||
|
props
|
||||||
|
const {
|
||||||
|
sourceType,
|
||||||
|
sourceUserName,
|
||||||
|
sourceUserAvatarUrl,
|
||||||
|
sourceUpdateType,
|
||||||
|
reason,
|
||||||
|
reasonText,
|
||||||
|
sourceUserUsername,
|
||||||
|
sourceText,
|
||||||
|
} = notification
|
||||||
|
const questionNeedsResolution = sourceUpdateType == 'closed'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -796,18 +856,13 @@ function NotificationItem(props: {
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
{!questionNeedsResolution && (
|
|
||||||
<UserLink
|
<UserLink
|
||||||
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={true}
|
||||||
/>
|
/>
|
||||||
)}
|
{subtitle}
|
||||||
{getReasonForShowingNotification(
|
|
||||||
notification,
|
|
||||||
isChildOfGroup ?? false
|
|
||||||
)}
|
|
||||||
{isChildOfGroup ? (
|
{isChildOfGroup ? (
|
||||||
<RelativeTimestamp time={notification.createdTime} />
|
<RelativeTimestamp time={notification.createdTime} />
|
||||||
) : (
|
) : (
|
||||||
|
@ -822,9 +877,7 @@ function NotificationItem(props: {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Row>
|
</Row>
|
||||||
<div className={'mt-1 ml-1 md:text-base'}>
|
<div className={'mt-1 ml-1 md:text-base'}>{children}</div>
|
||||||
<NotificationTextLabel notification={notification} />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={'mt-6 border-b border-gray-300'} />
|
<div className={'mt-6 border-b border-gray-300'} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -832,6 +885,66 @@ function NotificationItem(props: {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function BetFillNotification(props: {
|
||||||
|
notification: Notification
|
||||||
|
highlighted: boolean
|
||||||
|
justSummary: boolean
|
||||||
|
isChildOfGroup?: boolean
|
||||||
|
}) {
|
||||||
|
const { notification, isChildOfGroup, highlighted, justSummary } = props
|
||||||
|
const { sourceText, data } = notification
|
||||||
|
const { creatorOutcome, probability } = (data as BetFillData) ?? {}
|
||||||
|
const subtitle = 'bet against you'
|
||||||
|
const amount = formatMoney(parseInt(sourceText ?? '0'))
|
||||||
|
const description =
|
||||||
|
creatorOutcome && probability ? (
|
||||||
|
<span>
|
||||||
|
of your{' '}
|
||||||
|
<span
|
||||||
|
className={
|
||||||
|
creatorOutcome === 'YES'
|
||||||
|
? 'text-primary'
|
||||||
|
: creatorOutcome === 'NO'
|
||||||
|
? 'text-red-500'
|
||||||
|
: 'text-blue-500'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{creatorOutcome}{' '}
|
||||||
|
</span>
|
||||||
|
limit order at {Math.round(probability * 100)}% was filled
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span>of your limit order was filled</span>
|
||||||
|
)
|
||||||
|
|
||||||
|
if (justSummary) {
|
||||||
|
return (
|
||||||
|
<NotificationSummaryFrame notification={notification} subtitle={subtitle}>
|
||||||
|
<Row className={'line-clamp-1'}>
|
||||||
|
<span className={'text-primary mr-1'}>{amount}</span>
|
||||||
|
<span>{description}</span>
|
||||||
|
</Row>
|
||||||
|
</NotificationSummaryFrame>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NotificationFrame
|
||||||
|
notification={notification}
|
||||||
|
isChildOfGroup={isChildOfGroup}
|
||||||
|
highlighted={highlighted}
|
||||||
|
subtitle={subtitle}
|
||||||
|
>
|
||||||
|
<Row>
|
||||||
|
<span>
|
||||||
|
<span className="text-primary mr-1">{amount}</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(
|
||||||
|
@ -1002,15 +1115,6 @@ function NotificationTextLabel(props: {
|
||||||
return (
|
return (
|
||||||
<span className="text-blue-400">{formatMoney(parseInt(sourceText))}</span>
|
<span className="text-blue-400">{formatMoney(parseInt(sourceText))}</span>
|
||||||
)
|
)
|
||||||
} else if (sourceType === 'bet' && sourceText) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<span className="text-primary">
|
|
||||||
{formatMoney(parseInt(sourceText))}
|
|
||||||
</span>{' '}
|
|
||||||
<span>of your limit order was filled</span>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
} else if (sourceType === 'challenge' && sourceText) {
|
} else if (sourceType === 'challenge' && sourceText) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -1074,9 +1178,6 @@ function getReasonForShowingNotification(
|
||||||
else if (sourceSlug) reasonText = 'joined because you shared'
|
else if (sourceSlug) reasonText = 'joined because you shared'
|
||||||
else reasonText = 'joined because of you'
|
else reasonText = 'joined because of you'
|
||||||
break
|
break
|
||||||
case 'bet':
|
|
||||||
reasonText = 'bet against you'
|
|
||||||
break
|
|
||||||
case 'challenge':
|
case 'challenge':
|
||||||
reasonText = 'accepted your challenge'
|
reasonText = 'accepted your challenge'
|
||||||
break
|
break
|
||||||
|
|
Loading…
Reference in New Issue
Block a user