More styling, less reports
This commit is contained in:
parent
9a2b24524e
commit
1497cccd8c
|
@ -7,13 +7,9 @@ const formatter = new Intl.NumberFormat('en-US', {
|
||||||
minimumFractionDigits: 0,
|
minimumFractionDigits: 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
export function formatMoney(amount: number, explicitPositiveSign?: boolean) {
|
export function formatMoney(amount: number) {
|
||||||
const newAmount = Math.round(amount) === 0 ? 0 : Math.floor(amount) // handle -0 case
|
const newAmount = Math.round(amount) === 0 ? 0 : Math.floor(amount) // handle -0 case
|
||||||
return (
|
return ENV_CONFIG.moneyMoniker + formatter.format(newAmount).replace('$', '')
|
||||||
ENV_CONFIG.moneyMoniker +
|
|
||||||
(explicitPositiveSign && newAmount > 0 ? '+' : '') +
|
|
||||||
formatter.format(newAmount).replace('$', '')
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatMoneyWithDecimals(amount: number) {
|
export function formatMoneyWithDecimals(amount: number) {
|
||||||
|
|
|
@ -29,10 +29,10 @@
|
||||||
mso-table-lspace: 0;
|
mso-table-lspace: 0;
|
||||||
mso-table-rspace: 0;
|
mso-table-rspace: 0;
|
||||||
}
|
}
|
||||||
th {color:#000000; font-size:14px;}
|
th {color:#000000; font-size:17px;}
|
||||||
th, td {padding: 5px; }
|
th, td {padding: 10px; }
|
||||||
td{ font-size: 17px}
|
td{ font-size: 17px}
|
||||||
th, td { vertical-align: center; text-align: center }
|
th, td { vertical-align: center; text-align: left }
|
||||||
a { vertical-align: center; text-align: left}
|
a { vertical-align: center; text-align: left}
|
||||||
img {
|
img {
|
||||||
border: 0;
|
border: 0;
|
||||||
|
@ -48,13 +48,19 @@
|
||||||
margin: 13px 0;
|
margin: 13px 0;
|
||||||
}
|
}
|
||||||
p.change{
|
p.change{
|
||||||
margin: 0; vertical-align: middle;font-size:16px;display: inline; padding: 2px; border-radius: 5px;
|
margin: 0; vertical-align: middle;font-size:16px;display: inline; padding: 2px; border-radius: 5px; width: 20px; text-align: right;
|
||||||
}
|
}
|
||||||
p.prob{
|
p.prob{
|
||||||
font-size: 20px;display: inline; vertical-align: middle; font-weight: bold;
|
font-size: 22px;display: inline; vertical-align: middle; font-weight: bold; width: 50px;
|
||||||
}
|
}
|
||||||
a.question{
|
a.question{
|
||||||
font-size: 18px;display: inline; vertical-align: middle; padding-bottom: 25px;
|
font-size: 18px;display: inline; vertical-align: middle;
|
||||||
|
}
|
||||||
|
td.question{
|
||||||
|
vertical-align: middle; padding-bottom: 15px; text-align: left;
|
||||||
|
}
|
||||||
|
td.probs{
|
||||||
|
text-align: right; padding-left: 10px; min-width: 115px
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<!--[if mso]>
|
<!--[if mso]>
|
||||||
|
@ -240,65 +246,65 @@
|
||||||
</tr>
|
</tr>
|
||||||
<!--/ show 5 columns with headers titled: Investment value, 7-day change, current balance, tips received, and markets made/-->
|
<!--/ show 5 columns with headers titled: Investment value, 7-day change, current balance, tips received, and markets made/-->
|
||||||
<tr>
|
<tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th style='font-size: 22px; text-align: center'>
|
||||||
Profit
|
Profit
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr >
|
<tr>
|
||||||
<td style='padding-bottom: 30px'>
|
<td style='padding-bottom: 30px; text-align: center'>
|
||||||
{{profit}}
|
<p class='change' style='font-size: 24px; padding:4px; {{profit_style}}'>
|
||||||
</td>
|
{{profit}}
|
||||||
</tr>
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<td align="center"
|
<td align="center"
|
||||||
style="font-size:0px;padding:10px 20px;padding-top:0px;padding-bottom:0px;word-break:break-word;">
|
style="font-size:0px;padding:10px 20px;padding-top:0px;padding-bottom:0px;word-break:break-word;">
|
||||||
<table border="0" cellpadding="0" cellspacing="0" role="presentation"
|
<table border="0" cellpadding="0" cellspacing="0" role="presentation"
|
||||||
style="border-collapse:collapse;border-spacing:0px;">
|
style="border-collapse:collapse;border-spacing:0px; ">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<th style='width: 160px'>
|
<th style='width: 170px'>
|
||||||
Investment value
|
🔥 Prediction streak
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<td>
|
||||||
Balance
|
{{prediction_streak}}
|
||||||
</th>
|
</td>
|
||||||
<th>
|
</tr>
|
||||||
Tips
|
<tr>
|
||||||
</th>
|
<th>
|
||||||
<th>
|
💸 Tips received
|
||||||
Markets
|
</th>
|
||||||
</th>
|
<td>
|
||||||
<th style='width: 55px'>
|
{{tips_received}}
|
||||||
Traders
|
</td>
|
||||||
</th>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
📈 Markets traded
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
{{markets_traded}}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>
|
||||||
|
❓ Markets created
|
||||||
|
</th>
|
||||||
|
|
||||||
<td>
|
|
||||||
{{investment_value}}
|
|
||||||
<!-- M$10,000-->
|
|
||||||
<p style='font-size:16px; margin-left:1px; display: inline; padding: 2px; border-radius: 5px; {{investment_change_style}}'>
|
|
||||||
{{investment_change}}
|
|
||||||
<!-- +17%-->
|
|
||||||
</p>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{current_balance}}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<p style='font-size:16px; display: inline; padding: 2px; border-radius: 5px; {{tips_received_style}}' >
|
|
||||||
{{tips_received}}
|
|
||||||
</p>
|
|
||||||
<!-- +M$120-->
|
|
||||||
</td>
|
|
||||||
<td>
|
<td>
|
||||||
{{markets_created}}
|
{{markets_created}}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
|
||||||
{{unique_bettors}}
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th style='width: 55px'>
|
||||||
|
🥳 Unique traders
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
{{unique_bettors}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
@ -311,7 +317,7 @@
|
||||||
<div
|
<div
|
||||||
style="font-family:Arial, sans-serif;font-size:18px;letter-spacing:normal;line-height:1;text-align:left;color:#000000;">
|
style="font-family:Arial, sans-serif;font-size:18px;letter-spacing:normal;line-height:1;text-align:left;color:#000000;">
|
||||||
<p class="text-build-content"
|
<p class="text-build-content"
|
||||||
style="line-height: 24px; margin: 10px 0; margin-top: 10px; margin-bottom: 0px;"
|
style="line-height: 24px; margin: 10px 0; margin-top: 20px; margin-bottom: 20px;"
|
||||||
data-testid="4XoHRGw1Y">
|
data-testid="4XoHRGw1Y">
|
||||||
<span style="color:#000000;font-family:Arial, Helvetica, sans-serif;font-size:18px;">
|
<span style="color:#000000;font-family:Arial, Helvetica, sans-serif;font-size:18px;">
|
||||||
And here's some of the biggest changes in your portfolio:
|
And here's some of the biggest changes in your portfolio:
|
||||||
|
@ -325,17 +331,16 @@
|
||||||
<table role="presentation">
|
<table role="presentation">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<!-- <td style="{{investment_value_style}}">-->
|
<td class='question'>
|
||||||
<td style='text-align: left'>
|
|
||||||
<a class='question' href='{{question1Url}}'>
|
<a class='question' href='{{question1Url}}'>
|
||||||
{{question1Title}}
|
{{question1Title}}
|
||||||
<!-- Will the US economy recover from the pandemic?-->
|
<!-- Will the US economy recover from the pandemic?-->
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td style='padding-left: 10px; min-width: 115px'>
|
<td class='probs'>
|
||||||
<p class='prob'>
|
<p class='prob'>
|
||||||
{{question1Prob}}
|
{{question1Prob}}
|
||||||
<!-- 99.9%-->
|
<!-- 9.9%-->
|
||||||
<p class='change' style='{{question1ChangeStyle}}'>
|
<p class='change' style='{{question1ChangeStyle}}'>
|
||||||
{{question1Change}}
|
{{question1Change}}
|
||||||
<!-- +17%-->
|
<!-- +17%-->
|
||||||
|
@ -343,32 +348,31 @@
|
||||||
</p>
|
</p>
|
||||||
</td>
|
</td>
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
<!-- <td style="{{investment_value_style}}">-->
|
<td class='question'>
|
||||||
<td style='text-align: left'>
|
|
||||||
<a class='question' href='{{question2Url}}'>
|
<a class='question' href='{{question2Url}}'>
|
||||||
{{question2Title}}
|
{{question2Title}}
|
||||||
<!-- Will the US economy recover from the pandemic?-->
|
<!-- Will the US economy recover from the pandemic? blah blah blah-->
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td style='padding-left: 10px; min-width: 115px'>
|
<td class='probs'>
|
||||||
<p class='prob'>
|
<p class='prob'>
|
||||||
{{question2Prob}}
|
{{question2Prob}}
|
||||||
<!-- 99.9%-->
|
<!-- 99.9%-->
|
||||||
<p class='change' style='{{question2ChangeStyle}}'>
|
<p class='change' style='{{question2ChangeStyle}}'>
|
||||||
{{question2Change}}
|
{{question2Change}}
|
||||||
<!-- +17%-->
|
<!-- +7%-->
|
||||||
</p>
|
</p>
|
||||||
</p>
|
</p>
|
||||||
</td>
|
</td>
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
<!-- <td style="{{investment_value_style}}">-->
|
<!-- <td style="{{investment_value_style}}">-->
|
||||||
<td style='text-align: left'>
|
<td class='question'>
|
||||||
<a class='question' href='{{question3Url}}'>
|
<a class='question' href='{{question3Url}}'>
|
||||||
{{question3Title}}
|
{{question3Title}}
|
||||||
<!-- Will the US economy recover from the pandemic?-->
|
<!-- Will the US economy recover from the pandemic?-->
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td style='padding-left: 10px; min-width: 115px'>
|
<td class='probs'>
|
||||||
<p class='prob'>
|
<p class='prob'>
|
||||||
{{question3Prob}}
|
{{question3Prob}}
|
||||||
<!-- 99.9%-->
|
<!-- 99.9%-->
|
||||||
|
@ -380,13 +384,13 @@
|
||||||
</td>
|
</td>
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
<!-- <td style="{{investment_value_style}}">-->
|
<!-- <td style="{{investment_value_style}}">-->
|
||||||
<td style='text-align: left'>
|
<td class='question'>
|
||||||
<a class='question' href='{{question4Url}}'>
|
<a class='question' href='{{question4Url}}'>
|
||||||
{{question4Title}}
|
{{question4Title}}
|
||||||
<!-- Will the US economy recover from the pandemic?-->
|
<!-- Will the US economy recover from the pandemic?-->
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td style='padding-left: 10px; min-width: 115px'>
|
<td class='probs'>
|
||||||
<p class='prob'>
|
<p class='prob'>
|
||||||
{{question4Prob}}
|
{{question4Prob}}
|
||||||
<!-- 99.9%-->
|
<!-- 99.9%-->
|
||||||
|
|
|
@ -16,10 +16,7 @@ import { contractUrl, getUser } from './utils'
|
||||||
import { buildCardUrl, getOpenGraphProps } from '../../common/contract-details'
|
import { buildCardUrl, getOpenGraphProps } from '../../common/contract-details'
|
||||||
import { notification_reason_types } from '../../common/notification'
|
import { notification_reason_types } from '../../common/notification'
|
||||||
import { Dictionary } from 'lodash'
|
import { Dictionary } from 'lodash'
|
||||||
import {
|
import { getNotificationDestinationsForUser } from '../../common/user-notification-preferences'
|
||||||
getNotificationDestinationsForUser,
|
|
||||||
notification_preference,
|
|
||||||
} from '../../common/user-notification-preferences'
|
|
||||||
import {
|
import {
|
||||||
PerContractInvestmentsData,
|
PerContractInvestmentsData,
|
||||||
OverallPerformanceData,
|
OverallPerformanceData,
|
||||||
|
@ -156,9 +153,10 @@ export const sendWelcomeEmail = async (
|
||||||
const { name } = user
|
const { name } = user
|
||||||
const firstName = name.split(' ')[0]
|
const firstName = name.split(' ')[0]
|
||||||
|
|
||||||
const unsubscribeUrl = `${DOMAIN}/notifications?tab=settings§ion=${
|
const { unsubscribeUrl } = getNotificationDestinationsForUser(
|
||||||
'onboarding_flow' as notification_preference
|
privateUser,
|
||||||
}`
|
'onboarding_flow'
|
||||||
|
)
|
||||||
|
|
||||||
return await sendTemplateEmail(
|
return await sendTemplateEmail(
|
||||||
privateUser.email,
|
privateUser.email,
|
||||||
|
@ -224,9 +222,11 @@ export const sendOneWeekBonusEmail = async (
|
||||||
const { name } = user
|
const { name } = user
|
||||||
const firstName = name.split(' ')[0]
|
const firstName = name.split(' ')[0]
|
||||||
|
|
||||||
const unsubscribeUrl = `${DOMAIN}/notifications?tab=settings§ion=${
|
const { unsubscribeUrl } = getNotificationDestinationsForUser(
|
||||||
'onboarding_flow' as notification_preference
|
privateUser,
|
||||||
}`
|
'onboarding_flow'
|
||||||
|
)
|
||||||
|
|
||||||
return await sendTemplateEmail(
|
return await sendTemplateEmail(
|
||||||
privateUser.email,
|
privateUser.email,
|
||||||
'Manifold Markets one week anniversary gift',
|
'Manifold Markets one week anniversary gift',
|
||||||
|
@ -256,10 +256,10 @@ export const sendCreatorGuideEmail = async (
|
||||||
|
|
||||||
const { name } = user
|
const { name } = user
|
||||||
const firstName = name.split(' ')[0]
|
const firstName = name.split(' ')[0]
|
||||||
|
const { unsubscribeUrl } = getNotificationDestinationsForUser(
|
||||||
const unsubscribeUrl = `${DOMAIN}/notifications?tab=settings§ion=${
|
privateUser,
|
||||||
'onboarding_flow' as notification_preference
|
'onboarding_flow'
|
||||||
}`
|
)
|
||||||
return await sendTemplateEmail(
|
return await sendTemplateEmail(
|
||||||
privateUser.email,
|
privateUser.email,
|
||||||
'Create your own prediction market',
|
'Create your own prediction market',
|
||||||
|
@ -290,10 +290,10 @@ export const sendThankYouEmail = async (
|
||||||
|
|
||||||
const { name } = user
|
const { name } = user
|
||||||
const firstName = name.split(' ')[0]
|
const firstName = name.split(' ')[0]
|
||||||
|
const { unsubscribeUrl } = getNotificationDestinationsForUser(
|
||||||
const unsubscribeUrl = `${DOMAIN}/notifications?tab=settings§ion=${
|
privateUser,
|
||||||
'thank_you_for_purchases' as notification_preference
|
'thank_you_for_purchases'
|
||||||
}`
|
)
|
||||||
|
|
||||||
return await sendTemplateEmail(
|
return await sendTemplateEmail(
|
||||||
privateUser.email,
|
privateUser.email,
|
||||||
|
@ -473,9 +473,10 @@ export const sendInterestingMarketsEmail = async (
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
const unsubscribeUrl = `${DOMAIN}/notifications?tab=settings§ion=${
|
const { unsubscribeUrl } = getNotificationDestinationsForUser(
|
||||||
'trending_markets' as notification_preference
|
privateUser,
|
||||||
}`
|
'trending_markets'
|
||||||
|
)
|
||||||
|
|
||||||
const { name } = user
|
const { name } = user
|
||||||
const firstName = name.split(' ')[0]
|
const firstName = name.split(' ')[0]
|
||||||
|
@ -626,9 +627,10 @@ export const sendWeeklyPortfolioUpdateEmail = async (
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
const unsubscribeUrl = `${DOMAIN}/notifications?tab=settings§ion=${
|
const { unsubscribeUrl } = getNotificationDestinationsForUser(
|
||||||
'profit_loss_updates' as notification_preference
|
privateUser,
|
||||||
}`
|
'profit_loss_updates'
|
||||||
|
)
|
||||||
|
|
||||||
const { name } = user
|
const { name } = user
|
||||||
const firstName = name.split(' ')[0]
|
const firstName = name.split(' ')[0]
|
||||||
|
|
|
@ -134,6 +134,11 @@ export async function sendPortfolioUpdateEmailsToAllUsers() {
|
||||||
const contractsUserBetOn = contractsUsersBetOn.filter((contract) =>
|
const contractsUserBetOn = contractsUsersBetOn.filter((contract) =>
|
||||||
userBets.some((bet) => bet.contractId === contract.id)
|
userBets.some((bet) => bet.contractId === contract.id)
|
||||||
)
|
)
|
||||||
|
const contractsBetOnInLastWeek = uniq(
|
||||||
|
userBets
|
||||||
|
.filter((bet) => bet.createdTime > Date.now() - 7 * DAY_MS)
|
||||||
|
.map((bet) => bet.contractId)
|
||||||
|
)
|
||||||
// get the most recent bet for each contract
|
// get the most recent bet for each contract
|
||||||
// get the most recent portfolio metrics
|
// get the most recent portfolio metrics
|
||||||
const mostRecentPortfolioMetrics = last(
|
const mostRecentPortfolioMetrics = last(
|
||||||
|
@ -155,34 +160,27 @@ export async function sendPortfolioUpdateEmailsToAllUsers() {
|
||||||
log('No portfolio metrics a week ago for user', privateUser.id)
|
log('No portfolio metrics a week ago for user', privateUser.id)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const valueChange =
|
|
||||||
mostRecentPortfolioMetrics.investmentValue -
|
|
||||||
portfolioMetricsAWeekAgo.investmentValue
|
|
||||||
const totalTips = sum(
|
const totalTips = sum(
|
||||||
usersToTxnsReceived[privateUser.id]
|
usersToTxnsReceived[privateUser.id]
|
||||||
.filter((txn) => txn.category === 'TIP')
|
.filter((txn) => txn.category === 'TIP')
|
||||||
.map((txn) => txn.amount)
|
.map((txn) => txn.amount)
|
||||||
)
|
)
|
||||||
// get the difference
|
const greenBg = 'rgba(0,160,0,0.2)'
|
||||||
|
const redBg = 'rgba(160,0,0,0.2)'
|
||||||
const performanceData = {
|
const performanceData = {
|
||||||
profit: formatMoney(user.profitCached.weekly, true),
|
profit: formatMoney(user.profitCached.weekly),
|
||||||
investment_value: formatMoney(
|
profit_style: `background-color: ${
|
||||||
mostRecentPortfolioMetrics.investmentValue
|
user.profitCached.weekly > 0 ? greenBg : redBg
|
||||||
),
|
}`,
|
||||||
investment_change: formatMoney(valueChange, true),
|
|
||||||
current_balance: formatMoney(user.balance),
|
|
||||||
markets_created:
|
markets_created:
|
||||||
usersToContractsCreated[privateUser.id].length.toString(),
|
usersToContractsCreated[privateUser.id].length.toString(),
|
||||||
tips_received: formatMoney(totalTips, true),
|
tips_received: formatMoney(totalTips),
|
||||||
tips_received_style: `background-color: ${
|
|
||||||
totalTips > 0 ? 'rgba(0,160,0,0.2)' : 'rgba(160,0,0,0.2)'
|
|
||||||
};`,
|
|
||||||
unique_bettors: usersToTxnsReceived[privateUser.id]
|
unique_bettors: usersToTxnsReceived[privateUser.id]
|
||||||
.filter((txn) => txn.category === 'UNIQUE_BETTOR_BONUS')
|
.filter((txn) => txn.category === 'UNIQUE_BETTOR_BONUS')
|
||||||
.length.toString(),
|
.length.toString(),
|
||||||
investment_change_style: `background-color: ${
|
markets_traded: contractsBetOnInLastWeek.length.toString(),
|
||||||
valueChange > 0 ? 'rgba(0,160,0,0.2)' : 'rgba(160,0,0,0.2)'
|
prediction_streak:
|
||||||
};`,
|
(user.currentBettingStreak?.toString() ?? '0') + ' days',
|
||||||
// More options: bonuses, tips given,
|
// More options: bonuses, tips given,
|
||||||
} as OverallPerformanceData
|
} as OverallPerformanceData
|
||||||
type investmentDiff = {
|
type investmentDiff = {
|
||||||
|
@ -285,11 +283,9 @@ export type PerContractInvestmentsData = {
|
||||||
}
|
}
|
||||||
export type OverallPerformanceData = {
|
export type OverallPerformanceData = {
|
||||||
profit: string
|
profit: string
|
||||||
tips_received_style: string
|
prediction_streak: string
|
||||||
investment_change_style: string
|
markets_traded: string
|
||||||
investment_value: string
|
profit_style: string
|
||||||
investment_change: string
|
|
||||||
current_balance: string
|
|
||||||
tips_received: string
|
tips_received: string
|
||||||
markets_created: string
|
markets_created: string
|
||||||
unique_bettors: string
|
unique_bettors: string
|
||||||
|
|
Loading…
Reference in New Issue
Block a user