Enrich limit order notification

This commit is contained in:
Ian Philips 2022-09-15 13:39:46 -06:00
parent 69c2570ff9
commit 8c6a40bab7
4 changed files with 190 additions and 75 deletions

View File

@ -92,11 +92,6 @@ export type notification_reason_types =
| 'your_contract_closed'
| 'subsidized_your_market'
export type BettingStreakData = {
streak: number
bonusAmount: number
}
type notification_descriptions = {
[key in notification_preference]: {
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`,
},
}
export type BettingStreakData = {
streak: number
bonusAmount: number
}
export type BetFillData = {
betOutcome: string
creatorOutcome: string
probability: number
fillAmount: number
}

View File

@ -1,5 +1,6 @@
import * as admin from 'firebase-admin'
import {
BetFillData,
BettingStreakData,
Notification,
notification_reason_types,
@ -542,6 +543,12 @@ export const createBetFillNotification = async (
sourceContractTitle: contract.question,
sourceContractSlug: contract.slug,
sourceContractId: contract.id,
data: {
betOutcome: bet.outcome,
creatorOutcome: userBet.outcome,
fillAmount,
probability: userBet.limitProb,
} as BetFillData,
}
return await notificationRef.set(removeUndefinedProps(notification))

View File

@ -4,14 +4,14 @@ import { initAdmin } from './script-init'
initAdmin()
import { getValues } from '../utils'
import { Contract } from 'common/lib/contract'
import { Comment } from 'common/lib/comment'
import { Contract } from 'common/contract'
import { Comment } from 'common/comment'
import { uniq } from 'lodash'
import { Bet } from 'common/lib/bet'
import { Bet } from 'common/bet'
import {
DEV_HOUSE_LIQUIDITY_PROVIDER_ID,
HOUSE_LIQUIDITY_PROVIDER_ID,
} from 'common/lib/antes'
} from 'common/antes'
const firestore = admin.firestore()

View File

@ -1,7 +1,11 @@
import { ControlledTabs } from 'web/components/layout/tabs'
import React, { useEffect, useMemo, useState } from 'react'
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 { Row } from 'web/components/layout/row'
import { Page } from 'web/components/page'
@ -141,6 +145,7 @@ function RenderNotificationGroups(props: {
<NotificationItem
notification={notification.notifications[0]}
key={notification.notifications[0].id}
justSummary={false}
/>
) : (
<NotificationGroupItem
@ -697,20 +702,11 @@ function NotificationGroupItem(props: {
function NotificationItem(props: {
notification: Notification
justSummary?: boolean
justSummary: boolean
isChildOfGroup?: boolean
}) {
const { notification, justSummary, isChildOfGroup } = props
const {
sourceType,
sourceUserName,
sourceUserAvatarUrl,
sourceUpdateType,
reasonText,
reason,
sourceUserUsername,
sourceText,
} = notification
const { sourceType, reason } = notification
const [highlighted] = useState(!notification.isSeen)
@ -718,39 +714,103 @@ function NotificationItem(props: {
setNotificationsAsSeen([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) {
return (
<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={'flex pl-1 sm:pl-0'}>
<UserLink
name={sourceUserName || ''}
username={sourceUserUsername || ''}
className={'mr-0 flex-shrink-0'}
short={true}
/>
<div className={'inline-flex overflow-hidden text-ellipsis pl-1'}>
<span className={'flex-shrink-0'}>
{sourceType &&
reason &&
getReasonForShowingNotification(notification, true)}
</span>
<div className={'ml-1 text-black'}>
<NotificationTextLabel
className={'line-clamp-1'}
notification={notification}
justSummary={true}
/>
</div>
</div>
</div>
</div>
</Row>
<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 (
<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={'flex pl-1 sm:pl-0'}>
<UserLink
name={sourceUserName || ''}
username={sourceUserUsername || ''}
className={'mr-0 flex-shrink-0'}
short={true}
/>
<div className={'inline-flex overflow-hidden text-ellipsis pl-1'}>
<span className={'flex-shrink-0'}>{subtitle}</span>
<div className={'line-clamp-1 ml-1 text-black'}>{children}</div>
</div>
</div>
</div>
</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 (
<div
className={clsx(
@ -796,18 +856,13 @@ function NotificationItem(props: {
}
>
<div>
{!questionNeedsResolution && (
<UserLink
name={sourceUserName || ''}
username={sourceUserUsername || ''}
className={'relative mr-1 flex-shrink-0'}
short={true}
/>
)}
{getReasonForShowingNotification(
notification,
isChildOfGroup ?? false
)}
<UserLink
name={sourceUserName || ''}
username={sourceUserUsername || ''}
className={'relative mr-1 flex-shrink-0'}
short={true}
/>
{subtitle}
{isChildOfGroup ? (
<RelativeTimestamp time={notification.createdTime} />
) : (
@ -822,9 +877,7 @@ function NotificationItem(props: {
)}
</div>
</Row>
<div className={'mt-1 ml-1 md:text-base'}>
<NotificationTextLabel notification={notification} />
</div>
<div className={'mt-1 ml-1 md:text-base'}>{children}</div>
<div className={'mt-6 border-b border-gray-300'} />
</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[]) => {
const unseenNotifications = notifications.filter((n) => !n.isSeen)
return await Promise.all(
@ -1002,15 +1115,6 @@ function NotificationTextLabel(props: {
return (
<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) {
return (
<>
@ -1074,9 +1178,6 @@ function getReasonForShowingNotification(
else if (sourceSlug) reasonText = 'joined because you shared'
else reasonText = 'joined because of you'
break
case 'bet':
reasonText = 'bet against you'
break
case 'challenge':
reasonText = 'accepted your challenge'
break