diff --git a/common/util/format.ts b/common/util/format.ts index 2d8e5d00..4f123535 100644 --- a/common/util/format.ts +++ b/common/util/format.ts @@ -7,13 +7,9 @@ const formatter = new Intl.NumberFormat('en-US', { 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 - return ( - ENV_CONFIG.moneyMoniker + - (explicitPositiveSign && newAmount > 0 ? '+' : '') + - formatter.format(newAmount).replace('$', '') - ) + return ENV_CONFIG.moneyMoniker + formatter.format(newAmount).replace('$', '') } export function formatMoneyWithDecimals(amount: number) { diff --git a/functions/src/email-templates/weekly-portfolio-update.html b/functions/src/email-templates/weekly-portfolio-update.html index 547a6b3b..b4104205 100644 --- a/functions/src/email-templates/weekly-portfolio-update.html +++ b/functions/src/email-templates/weekly-portfolio-update.html @@ -29,10 +29,10 @@ mso-table-lspace: 0; mso-table-rspace: 0; } - th {color:#000000; font-size:14px;} - th, td {padding: 5px; } + th {color:#000000; font-size:17px;} + th, td {padding: 10px; } 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} img { border: 0; @@ -48,13 +48,19 @@ margin: 13px 0; } 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{ - 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{ - 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 }
+ {{profit}} +
+- Investment value - | -- Balance - | -- Tips - | -- Markets - | -- Traders - | - ++ 🔥 Prediction streak + | ++ {{prediction_streak}} + | +
---|---|---|---|---|---|---|
+ 💸 Tips received + | ++ {{tips_received}} + | +|||||
+ 📈 Markets traded + | ++ {{markets_traded}} + | |||||
+ ❓ Markets created + | -
- {{investment_value}}
-
- - {{investment_change}} - - - |
- - {{current_balance}} - | -
- - {{tips_received}} - - - |
{{markets_created}} | -- {{unique_bettors}} - | |
+ 🥳 Unique traders + | ++ {{unique_bettors}} + | +
And here's some of the biggest changes in your portfolio:
@@ -325,17 +331,16 @@
{{question1Prob}}
-
+
{{question1Change}}
@@ -343,32 +348,31 @@
{{question2Prob}}
{{question2Change}}
-
+
{{question3Prob}}
@@ -380,13 +384,13 @@
{{question4Prob}}
diff --git a/functions/src/emails.ts b/functions/src/emails.ts
index 298e5ef8..1beb8477 100644
--- a/functions/src/emails.ts
+++ b/functions/src/emails.ts
@@ -16,10 +16,7 @@ import { contractUrl, getUser } from './utils'
import { buildCardUrl, getOpenGraphProps } from '../../common/contract-details'
import { notification_reason_types } from '../../common/notification'
import { Dictionary } from 'lodash'
-import {
- getNotificationDestinationsForUser,
- notification_preference,
-} from '../../common/user-notification-preferences'
+import { getNotificationDestinationsForUser } from '../../common/user-notification-preferences'
import {
PerContractInvestmentsData,
OverallPerformanceData,
@@ -156,9 +153,10 @@ export const sendWelcomeEmail = async (
const { name } = user
const firstName = name.split(' ')[0]
- const unsubscribeUrl = `${DOMAIN}/notifications?tab=settings§ion=${
- 'onboarding_flow' as notification_preference
- }`
+ const { unsubscribeUrl } = getNotificationDestinationsForUser(
+ privateUser,
+ 'onboarding_flow'
+ )
return await sendTemplateEmail(
privateUser.email,
@@ -224,9 +222,11 @@ export const sendOneWeekBonusEmail = async (
const { name } = user
const firstName = name.split(' ')[0]
- const unsubscribeUrl = `${DOMAIN}/notifications?tab=settings§ion=${
- 'onboarding_flow' as notification_preference
- }`
+ const { unsubscribeUrl } = getNotificationDestinationsForUser(
+ privateUser,
+ 'onboarding_flow'
+ )
+
return await sendTemplateEmail(
privateUser.email,
'Manifold Markets one week anniversary gift',
@@ -256,10 +256,10 @@ export const sendCreatorGuideEmail = async (
const { name } = user
const firstName = name.split(' ')[0]
-
- const unsubscribeUrl = `${DOMAIN}/notifications?tab=settings§ion=${
- 'onboarding_flow' as notification_preference
- }`
+ const { unsubscribeUrl } = getNotificationDestinationsForUser(
+ privateUser,
+ 'onboarding_flow'
+ )
return await sendTemplateEmail(
privateUser.email,
'Create your own prediction market',
@@ -290,10 +290,10 @@ export const sendThankYouEmail = async (
const { name } = user
const firstName = name.split(' ')[0]
-
- const unsubscribeUrl = `${DOMAIN}/notifications?tab=settings§ion=${
- 'thank_you_for_purchases' as notification_preference
- }`
+ const { unsubscribeUrl } = getNotificationDestinationsForUser(
+ privateUser,
+ 'thank_you_for_purchases'
+ )
return await sendTemplateEmail(
privateUser.email,
@@ -473,9 +473,10 @@ export const sendInterestingMarketsEmail = async (
)
return
- const unsubscribeUrl = `${DOMAIN}/notifications?tab=settings§ion=${
- 'trending_markets' as notification_preference
- }`
+ const { unsubscribeUrl } = getNotificationDestinationsForUser(
+ privateUser,
+ 'trending_markets'
+ )
const { name } = user
const firstName = name.split(' ')[0]
@@ -626,9 +627,10 @@ export const sendWeeklyPortfolioUpdateEmail = async (
)
return
- const unsubscribeUrl = `${DOMAIN}/notifications?tab=settings§ion=${
- 'profit_loss_updates' as notification_preference
- }`
+ const { unsubscribeUrl } = getNotificationDestinationsForUser(
+ privateUser,
+ 'profit_loss_updates'
+ )
const { name } = user
const firstName = name.split(' ')[0]
diff --git a/functions/src/weekly-portfolio-emails.ts b/functions/src/weekly-portfolio-emails.ts
index 51a85c9c..e30e8e21 100644
--- a/functions/src/weekly-portfolio-emails.ts
+++ b/functions/src/weekly-portfolio-emails.ts
@@ -134,6 +134,11 @@ export async function sendPortfolioUpdateEmailsToAllUsers() {
const contractsUserBetOn = contractsUsersBetOn.filter((contract) =>
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 portfolio metrics
const mostRecentPortfolioMetrics = last(
@@ -155,34 +160,27 @@ export async function sendPortfolioUpdateEmailsToAllUsers() {
log('No portfolio metrics a week ago for user', privateUser.id)
return
}
- const valueChange =
- mostRecentPortfolioMetrics.investmentValue -
- portfolioMetricsAWeekAgo.investmentValue
const totalTips = sum(
usersToTxnsReceived[privateUser.id]
.filter((txn) => txn.category === 'TIP')
.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 = {
- profit: formatMoney(user.profitCached.weekly, true),
- investment_value: formatMoney(
- mostRecentPortfolioMetrics.investmentValue
- ),
- investment_change: formatMoney(valueChange, true),
- current_balance: formatMoney(user.balance),
+ profit: formatMoney(user.profitCached.weekly),
+ profit_style: `background-color: ${
+ user.profitCached.weekly > 0 ? greenBg : redBg
+ }`,
markets_created:
usersToContractsCreated[privateUser.id].length.toString(),
- tips_received: formatMoney(totalTips, true),
- tips_received_style: `background-color: ${
- totalTips > 0 ? 'rgba(0,160,0,0.2)' : 'rgba(160,0,0,0.2)'
- };`,
+ tips_received: formatMoney(totalTips),
unique_bettors: usersToTxnsReceived[privateUser.id]
.filter((txn) => txn.category === 'UNIQUE_BETTOR_BONUS')
.length.toString(),
- investment_change_style: `background-color: ${
- valueChange > 0 ? 'rgba(0,160,0,0.2)' : 'rgba(160,0,0,0.2)'
- };`,
+ markets_traded: contractsBetOnInLastWeek.length.toString(),
+ prediction_streak:
+ (user.currentBettingStreak?.toString() ?? '0') + ' days',
// More options: bonuses, tips given,
} as OverallPerformanceData
type investmentDiff = {
@@ -285,11 +283,9 @@ export type PerContractInvestmentsData = {
}
export type OverallPerformanceData = {
profit: string
- tips_received_style: string
- investment_change_style: string
- investment_value: string
- investment_change: string
- current_balance: string
+ prediction_streak: string
+ markets_traded: string
+ profit_style: string
tips_received: string
markets_created: string
unique_bettors: string
-
-
+
{{question1Title}}
-
+
-
-
+
{{question2Title}}
-
+
-
+
-
+
{{question3Title}}
-
+
-
+
{{question4Title}}
-
+