It's alive... It's alive, it's moving, it's alive, it's alive, it's alive, it's alive, IT'S ALIVE'

This commit is contained in:
Ian Philips 2022-09-09 09:08:02 -06:00
parent 9c8d4c8d94
commit 06467dc1d7
5 changed files with 173 additions and 169 deletions

View File

@ -1,4 +1,4 @@
import { exhaustive_notification_subscribe_types } from 'common/user'
import { notification_subscription_types } from 'common/user'
export type Notification = {
id: string
@ -55,26 +55,17 @@ export type notification_source_update_types =
export type notification_reason_types =
| 'tagged_user'
// | 'on_users_contract'
// | 'on_contract_with_users_shares_in'
// | 'on_contract_with_users_shares_out'
// | 'on_contract_with_users_answer'
// | 'on_contract_with_users_comment'
| 'on_new_follow'
| 'contract_from_followed_user'
| 'added_you_to_group'
| 'you_referred_user'
| 'user_joined_to_bet_on_your_market'
| 'unique_bettors_on_your_contract'
// | 'on_group_you_are_member_of'
| 'tip_received'
| 'bet_fill'
| 'user_joined_from_your_group_invite'
| 'challenge_accepted'
| 'betting_streak_incremented'
| 'loan_income'
// | 'you_follow_contract'
| 'liked_your_contract'
| 'liked_and_tipped_your_contract'
| 'comment_on_your_contract'
| 'answer_on_your_contract'
@ -97,25 +88,19 @@ export type notification_reason_types =
| 'reply_to_users_answer'
| 'reply_to_users_comment'
| 'your_contract_closed'
| 'subsidized_your_market'
export const notificationReasonToSubscribeTypeMap: Record<
notification_reason_types,
keyof exhaustive_notification_subscribe_types
// Adding a new key:value here is optional, you can also just use a key of exhaustive_notification_subscribe_types
export const notificationReasonToSubscriptionType: Partial<
Record<notification_reason_types, keyof notification_subscription_types>
> = {
tagged_user: 'user_tagged_you',
on_new_follow: 'new_followers',
contract_from_followed_user: 'new_markets_by_followed_users',
added_you_to_group: 'group_adds',
you_referred_user: 'referral_bonuses',
user_joined_to_bet_on_your_market: 'referral_bonuses',
unique_bettors_on_your_contract: 'unique_bettor_bonuses',
tip_received: 'tips_on_your_comments',
bet_fill: 'limit_order_fills',
user_joined_from_your_group_invite: 'referral_bonuses',
challenge_accepted: 'limit_order_fills',
betting_streak_incremented: 'betting_streaks',
loan_income: 'loan_income',
liked_your_contract: 'tips_on_your_markets',
liked_and_tipped_your_contract: 'tips_on_your_markets',
comment_on_your_contract: 'all_comments_on_my_markets',
answer_on_your_contract: 'all_answers_on_my_markets',
@ -128,7 +113,7 @@ export const notificationReasonToSubscribeTypeMap: Record<
answer_on_contract_with_users_shares_in:
'all_answers_on_contracts_with_shares_in_on_watched_markets',
update_on_contract_with_users_shares_in:
'market_updates_with_shares_in_on_watched_markets',
'market_updates_on_watched_markets_with_shares_in',
resolution_on_contract_with_users_shares_in:
'resolutions_on_watched_markets_with_shares_in',
comment_on_contract_with_users_answer: 'all_comments_on_watched_markets',
@ -141,5 +126,4 @@ export const notificationReasonToSubscribeTypeMap: Record<
resolution_on_contract_with_users_comment: 'resolutions_on_watched_markets',
reply_to_users_answer: 'all_replies_to_my_answers_on_watched_markets',
reply_to_users_comment: 'all_replies_to_my_comments_on_watched_markets',
your_contract_closed: 'my_markets_closed',
}

View File

@ -66,12 +66,12 @@ export type PrivateUser = {
initialIpAddress?: string
apiKey?: string
notificationPreferences?: notification_subscribe_types
notificationSubscriptionTypes: exhaustive_notification_subscribe_types
notificationSubscriptionTypes: notification_subscription_types
}
export type notification_destination_types = 'email' | 'browser'
export type exhaustive_notification_subscribe_types = {
export type notification_subscription_types = {
// Watched Markets
all_comments_on_watched_markets: notification_destination_types[] // Email currently - seems bad
all_answers_on_watched_markets: notification_destination_types[] // Email currently - seems bad
@ -89,31 +89,31 @@ export type exhaustive_notification_subscribe_types = {
all_answers_on_contracts_with_shares_in_on_watched_markets: notification_destination_types[]
// On users' markets
my_markets_closed: notification_destination_types[] // Email, Recommended
your_contract_closed: notification_destination_types[] // Email, Recommended
all_comments_on_my_markets: notification_destination_types[] // Email
all_answers_on_my_markets: notification_destination_types[] // Email
subsidized_your_market: notification_destination_types[] // Email
// Market updates
resolutions_on_watched_markets: notification_destination_types[] // Email
resolutions_on_watched_markets_with_shares_in: notification_destination_types[] // Email
market_updates_on_watched_markets: notification_destination_types[]
market_updates_with_shares_in_on_watched_markets: notification_destination_types[]
market_updates_on_watched_markets_with_shares_in: notification_destination_types[]
probability_updates_on_watched_markets: notification_destination_types[] // Email - would want persistent changes only though
// Balance Changes
loan_income: notification_destination_types[]
betting_streaks: notification_destination_types[]
referral_bonuses: notification_destination_types[]
unique_bettor_bonuses: notification_destination_types[]
unique_bettors_on_your_contract: notification_destination_types[]
tips_on_your_comments: notification_destination_types[]
tips_on_your_markets: notification_destination_types[]
limit_order_fills: notification_destination_types[]
// General
user_tagged_you: notification_destination_types[] // Email
new_followers: notification_destination_types[] // Email
group_adds: notification_destination_types[] // Email
new_markets_by_followed_users: notification_destination_types[] // Email
tagged_user: notification_destination_types[] // Email
on_new_follow: notification_destination_types[] // Email
contract_from_followed_user: notification_destination_types[] // Email
trending_markets: notification_destination_types[] // Email
profit_loss_updates: notification_destination_types[] // Email
}
@ -169,15 +169,15 @@ export const getDefaultNotificationSettings = (
comments_by_followed_users_on_watched_markets: constructPref(
wantsAll,
false
), //wantsAll ? browserOnly : none,
),
all_replies_to_my_comments_on_watched_markets: constructPref(
wantsAll || wantsLess,
!unsubscribedFromCommentEmails
), //wantsAll || wantsLess ? both : none,
),
all_replies_to_my_answers_on_watched_markets: constructPref(
wantsAll || wantsLess,
!unsubscribedFromCommentEmails
), //wantsAll || wantsLess ? both : none,
),
all_comments_on_contracts_with_shares_in_on_watched_markets: constructPref(
wantsAll,
!unsubscribedFromCommentEmails
@ -187,29 +187,30 @@ export const getDefaultNotificationSettings = (
answers_by_followed_users_on_watched_markets: constructPref(
wantsAll || wantsLess,
!unsubscribedFromAnswerEmails
), //wantsAll || wantsLess ? both : none,
),
answers_by_market_creator_on_watched_markets: constructPref(
wantsAll || wantsLess,
!unsubscribedFromAnswerEmails
), //wantsAll || wantsLess ? both : none,
),
all_answers_on_contracts_with_shares_in_on_watched_markets: constructPref(
wantsAll,
!unsubscribedFromAnswerEmails
),
// On users' markets
my_markets_closed: constructPref(
your_contract_closed: constructPref(
wantsAll || wantsLess,
!unsubscribedFromResolutionEmails
), //wantsAll || wantsLess ? both : none, // High priority
), // High priority
all_comments_on_my_markets: constructPref(
wantsAll || wantsLess,
!unsubscribedFromCommentEmails
), //wantsAll || wantsLess ? both : none,
),
all_answers_on_my_markets: constructPref(
wantsAll || wantsLess,
!unsubscribedFromAnswerEmails
), //wantsAll || wantsLess ? both : none,
),
subsidized_your_market: constructPref(wantsAll || wantsLess, true),
// Market updates
resolutions_on_watched_markets: constructPref(
@ -220,7 +221,7 @@ export const getDefaultNotificationSettings = (
wantsAll || wantsLess,
false
),
market_updates_with_shares_in_on_watched_markets: constructPref(
market_updates_on_watched_markets_with_shares_in: constructPref(
wantsAll || wantsLess,
false
),
@ -233,7 +234,10 @@ export const getDefaultNotificationSettings = (
loan_income: constructPref(wantsAll || wantsLess, false),
betting_streaks: constructPref(wantsAll || wantsLess, false),
referral_bonuses: constructPref(wantsAll || wantsLess, true),
unique_bettor_bonuses: constructPref(wantsAll || wantsLess, false),
unique_bettors_on_your_contract: constructPref(
wantsAll || wantsLess,
false
),
tipped_comments_on_watched_markets: constructPref(
wantsAll || wantsLess,
!unsubscribedFromCommentEmails
@ -242,9 +246,9 @@ export const getDefaultNotificationSettings = (
limit_order_fills: constructPref(wantsAll || wantsLess, false),
// General
user_tagged_you: constructPref(wantsAll || wantsLess, true), //wantsAll || wantsLess ? both : none,
new_followers: constructPref(wantsAll || wantsLess, true),
new_markets_by_followed_users: constructPref(wantsAll || wantsLess, true), //wantsAll || wantsLess ? both : none,
tagged_user: constructPref(wantsAll || wantsLess, true),
on_new_follow: constructPref(wantsAll || wantsLess, true),
contract_from_followed_user: constructPref(wantsAll || wantsLess, true),
trending_markets: constructPref(
false,
!unsubscribedFromWeeklyTrendingEmails
@ -254,6 +258,5 @@ export const getDefaultNotificationSettings = (
wantsAll || wantsLess,
false
),
group_adds: constructPref(wantsAll || wantsLess, true),
} as exhaustive_notification_subscribe_types
} as notification_subscription_types
}

View File

@ -2,11 +2,9 @@ import * as admin from 'firebase-admin'
import {
Notification,
notification_reason_types,
notification_source_update_types,
notification_source_types,
notificationReasonToSubscribeTypeMap,
notificationReasonToSubscriptionType,
} from '../../common/notification'
import { User } from '../../common/user'
import { notification_subscription_types, User } from '../../common/user'
import { Contract } from '../../common/contract'
import { getPrivateUser, getValues } from './utils'
import { Comment } from '../../common/comment'
@ -20,6 +18,7 @@ import { Group } from '../../common/group'
import { Challenge } from '../../common/challenge'
import { Like } from '../../common/like'
import {
sendMarketCloseEmail,
sendMarketResolutionEmail,
sendNewAnswerEmail,
sendNewCommentEmail,
@ -32,8 +31,8 @@ type recipients_to_reason_texts = {
export const createNotification = async (
sourceId: string,
sourceType: notification_source_types,
sourceUpdateType: notification_source_update_types,
sourceType: 'contract' | 'liquidity' | 'follow',
sourceUpdateType: 'closed' | 'created',
sourceUser: User,
idempotencyKey: string,
sourceText: string,
@ -56,15 +55,14 @@ export const createNotification = async (
)
}
const createUsersNotifications = async (
const sendNotificationsIfSettingsPermit = async (
userToReasonTexts: recipients_to_reason_texts
) => {
await Promise.all(
Object.keys(userToReasonTexts).map(async (userId) => {
for (const userId in userToReasonTexts) {
const { reason } = userToReasonTexts[userId]
const { sendToBrowser } = await getDestinationsForUser(userId, reason)
if (!sendToBrowser) return Promise.resolve()
const { sendToBrowser, sendToEmail, privateUser } =
await getDestinationsForUser(userId, reason)
if (sendToBrowser) {
const notificationRef = firestore
.collection(`/users/${userId}/notifications`)
.doc(idempotencyKey)
@ -89,8 +87,22 @@ export const createNotification = async (
sourceTitle: title ? title : sourceContract?.question,
}
await notificationRef.set(removeUndefinedProps(notification))
})
)
}
if (!sendToEmail) continue
if (reason === 'your_contract_closed' && privateUser && sourceContract) {
await sendMarketCloseEmail(sourceUser, privateUser, sourceContract)
} else if (reason === 'tagged_user') {
// TODO: send email to tagged user in new contract
} else if (reason === 'subsidized_your_market') {
// TODO: send email to creator of market that was subsidized
} else if (reason === 'contract_from_followed_user') {
// TODO: send email to follower of user who created market
} else if (reason === 'on_new_follow') {
// TODO: send email to user who was followed
}
}
}
const notifyUsersFollowers = async (
@ -146,31 +158,18 @@ export const createNotification = async (
shouldGetNotification(sourceContract.creatorId, userToReasonTexts)
)
userToReasonTexts[sourceContract.creatorId] = {
reason: 'your_contract_closed',
reason:
sourceType === 'liquidity'
? 'subsidized_your_market'
: 'your_contract_closed',
}
}
const notifyUserAddedToGroup = (
userToReasonTexts: recipients_to_reason_texts,
relatedUserId: string
) => {
if (shouldGetNotification(relatedUserId, userToReasonTexts))
userToReasonTexts[relatedUserId] = {
reason: 'added_you_to_group',
}
}
const userToReasonTexts: recipients_to_reason_texts = {}
// The following functions modify the userToReasonTexts object in place.
const userToReasonTexts: recipients_to_reason_texts = {}
if (sourceType === 'follow' && recipients?.[0]) {
notifyFollowedUser(userToReasonTexts, recipients[0])
} else if (
sourceType === 'group' &&
sourceUpdateType === 'created' &&
recipients
) {
recipients.forEach((r) => notifyUserAddedToGroup(userToReasonTexts, r))
} else if (
sourceType === 'contract' &&
sourceUpdateType === 'created' &&
@ -194,27 +193,33 @@ export const createNotification = async (
await notifyContractCreator(userToReasonTexts, sourceContract)
}
await createUsersNotifications(userToReasonTexts)
await sendNotificationsIfSettingsPermit(userToReasonTexts)
}
const getDestinationsForUser = async (
userId: string,
reason: notification_reason_types
reason: notification_reason_types | keyof notification_subscription_types
) => {
const privateUser = await getPrivateUser(userId)
if (!privateUser) return { sendToEmail: false, sendToBrowser: false }
if (!privateUser)
return { sendToEmail: false, sendToBrowser: false, privateUser: null }
const notificationSettings = privateUser.notificationSubscriptionTypes
console.log('notificationSettings', notificationSettings)
console.log('reason', reason)
console.log('notif reason to type map', notificationReasonToSubscribeTypeMap)
const subscribeType = notificationReasonToSubscribeTypeMap[reason]
console.log('subscribeType', subscribeType)
const destinations =
notificationSettings[notificationReasonToSubscribeTypeMap[reason]]
console.log('destinations', destinations)
let destinations
if (Object.keys(notificationSettings).includes(reason)) {
const key = reason as keyof notification_subscription_types
destinations = notificationSettings[key]
} else {
const key = reason as notification_reason_types
const subscriptionType = notificationReasonToSubscriptionType[key]
destinations = subscriptionType
? notificationSettings[subscriptionType]
: []
}
return {
sendToEmail: destinations.includes('email'),
sendToBrowser: destinations.includes('browser'),
privateUser,
}
}
@ -463,21 +468,20 @@ export const createCommentOrAnswerOrUpdatedContractNotification = async (
)
}
const notifyRepliedUser = async (
relatedUserId: string,
relatedSourceType: notification_source_types
) => {
const notifyRepliedUser = async () => {
if (sourceType === 'comment' && repliedUserId && repliedToType)
await sendNotificationsIfSettingsPermit(
relatedUserId,
relatedSourceType === 'answer'
repliedUserId,
repliedToType === 'answer'
? 'reply_to_users_answer'
: 'reply_to_users_comment'
)
}
const notifyTaggedUsers = async (userIds: string[]) => {
const notifyTaggedUsers = async () => {
if (sourceType === 'comment' && taggedUserIds && taggedUserIds.length > 0)
await Promise.all(
userIds.map((userId) =>
taggedUserIds.map((userId) =>
sendNotificationsIfSettingsPermit(userId, 'tagged_user')
)
)
@ -506,11 +510,8 @@ export const createCommentOrAnswerOrUpdatedContractNotification = async (
)
}
if (sourceType === 'comment') {
if (repliedUserId && repliedToType)
await notifyRepliedUser(repliedUserId, repliedToType)
await notifyTaggedUsers(taggedUserIds ?? [])
}
await notifyRepliedUser()
await notifyTaggedUsers()
await notifyContractCreator()
await notifyOtherAnswerersOnContract()
await notifyLiquidityProviders()
@ -559,6 +560,8 @@ export const createTipNotification = async (
sourceTitle: group?.name,
}
return await notificationRef.set(removeUndefinedProps(notification))
// maybe TODO: send email notification to bet creator
}
export const createBetFillNotification = async (
@ -597,6 +600,8 @@ export const createBetFillNotification = async (
sourceContractId: contract.id,
}
return await notificationRef.set(removeUndefinedProps(notification))
// maybe TODO: send email notification to bet creator
}
export const createReferralNotification = async (
@ -650,6 +655,8 @@ export const createReferralNotification = async (
: referredByContract?.question,
}
await notificationRef.set(removeUndefinedProps(notification))
// TODO send email notification
}
export const createLoanIncomeNotification = async (
@ -779,13 +786,16 @@ export const createLikeNotification = async (
)
if (!sendToBrowser) return
// not handling just likes, must include tip
if (!tip) return
const notificationRef = firestore
.collection(`/users/${toUser.id}/notifications`)
.doc(idempotencyKey)
const notification: Notification = {
id: idempotencyKey,
userId: toUser.id,
reason: tip ? 'liked_and_tipped_your_contract' : 'liked_your_contract',
reason: 'liked_and_tipped_your_contract',
createdTime: Date.now(),
isSeen: false,
sourceId: like.id,
@ -802,20 +812,8 @@ export const createLikeNotification = async (
sourceTitle: contract.question,
}
return await notificationRef.set(removeUndefinedProps(notification))
}
export async function filterUserIdsForOnlyFollowerIds(
userIds: string[],
contractId: string
) {
// get contract follower documents and check here if they're a follower
const contractFollowersSnap = await firestore
.collection(`contracts/${contractId}/follows`)
.get()
const contractFollowersIds = contractFollowersSnap.docs.map(
(doc) => doc.data().id
)
return userIds.filter((id) => contractFollowersIds.includes(id))
// TODO send email notification
}
export const createUniqueBettorBonusNotification = async (
@ -857,4 +855,6 @@ export const createUniqueBettorBonusNotification = async (
sourceContractCreatorUsername: contract.creatorUsername,
}
return await notificationRef.set(removeUndefinedProps(notification))
// TODO send email notification
}

View File

@ -3,7 +3,6 @@ import * as admin from 'firebase-admin'
import { Contract } from '../../common/contract'
import { getPrivateUser, getUserByUsername } from './utils'
import { sendMarketCloseEmail } from './emails'
import { createNotification } from './create-notification'
export const marketCloseNotifications = functions
@ -56,7 +55,6 @@ async function sendMarketCloseEmails() {
const privateUser = await getPrivateUser(user.id)
if (!privateUser) continue
await sendMarketCloseEmail(user, privateUser, contract)
await createNotification(
contract.id,
'contract',

View File

@ -4,7 +4,7 @@ import { LoadingIndicator } from 'web/components/loading-indicator'
import { Row } from 'web/components/layout/row'
import clsx from 'clsx'
import {
exhaustive_notification_subscribe_types,
notification_subscription_types,
notification_destination_types,
} from 'common/user'
import { updatePrivateUser } from 'web/lib/firebase/users'
@ -33,29 +33,42 @@ export function NotificationSettings() {
return <LoadingIndicator spinnerClassName={'border-gray-500 h-4 w-4'} />
}
// should be keyof Partial<exhaustive_notification_subscribe_types>[] but can't figure out how to make that work
// TODO: re-enable emails for renamed subscribe types
const emailsEnabled = [
// 'all_comments',
// 'all_answers',
// 'resolutions',
'all_replies_to_my_comments',
'all_replies_to_my_answers',
const emailsEnabled: Array<keyof notification_subscription_types> = [
'all_comments_on_watched_markets',
'all_replies_to_my_comments_on_watched_markets',
'all_comments_on_contracts_with_shares_in_on_watched_markets',
'all_answers_on_watched_markets',
'all_replies_to_my_answers_on_watched_markets',
'all_answers_on_contracts_with_shares_in_on_watched_markets',
'your_contract_closed',
'all_comments_on_my_markets',
'all_answers_on_my_markets',
'my_markets_closed',
'probability_updates',
'user_tagged_you',
'new_markets_by_followed_users',
'resolutions_on_watched_markets_with_shares_in',
'resolutions_on_watched_markets',
'tagged_user',
'trending_markets',
'profit_loss_updates',
'all_comments_on_contracts_with_shares_in',
'all_answers_on_contracts_with_shares_in',
// TODO: add these
// 'contract_from_followed_user',
// 'referral_bonuses',
// 'unique_bettors_on_your_contract',
// 'tips_on_your_markets',
// 'tips_on_your_comments',
// 'subsidized_your_market',
// 'on_new_follow',
// maybe the following?
// 'profit_loss_updates',
// 'probability_updates_on_watched_markets',
// 'limit_order_fills',
]
const browserDisabled = ['trending_markets', 'profit_loss_updates']
const watched_markets_explanations_comments: {
[key in keyof Partial<exhaustive_notification_subscribe_types>]: string
[key in keyof Partial<notification_subscription_types>]: string
} = {
all_comments_on_watched_markets: 'All',
all_replies_to_my_comments_on_watched_markets: 'Replies to your comments',
@ -64,7 +77,7 @@ export function NotificationSettings() {
// comments_by_followed_users_on_watched_markets: 'By followed users',
}
const watched_markets_explanations_answers: {
[key in keyof Partial<exhaustive_notification_subscribe_types>]: string
[key in keyof Partial<notification_subscription_types>]: string
} = {
all_answers_on_watched_markets: 'All',
all_replies_to_my_answers_on_watched_markets: 'Replies to your answers',
@ -74,45 +87,49 @@ export function NotificationSettings() {
// answers_by_market_creator_on_watched_markets: 'By market creator',
}
const watched_markets_explanations_your_markets: {
[key in keyof Partial<exhaustive_notification_subscribe_types>]: string
[key in keyof Partial<notification_subscription_types>]: string
} = {
my_markets_closed: 'Your market has closed (and needs resolution)',
your_contract_closed: 'Your market has closed (and needs resolution)',
all_comments_on_my_markets: 'Comments on your markets',
all_answers_on_my_markets: 'Answers on your markets',
subsidized_your_market: 'Your market was subsidized',
}
const watched_markets_explanations_market_updates: {
[key in keyof Partial<exhaustive_notification_subscribe_types>]: string
[key in keyof Partial<notification_subscription_types>]: string
} = {
resolutions_on_watched_markets: 'Market resolutions',
resolutions_on_watched_markets_with_shares_in:
'Market resolutions you have shares in',
market_updates_on_watched_markets: 'Updates made by the creator',
market_updates_on_watched_markets_with_shares_in:
'Updates made by the creator on markets you have shares in',
// probability_updates_on_watched_markets: 'Probability updates',
}
const balance_change_explanations: {
[key in keyof Partial<exhaustive_notification_subscribe_types>]: string
[key in keyof Partial<notification_subscription_types>]: string
} = {
loan_income: 'Automatic loans from your profitable bets',
betting_streaks: 'Betting streak bonuses',
referral_bonuses: 'Referral bonuses from referring users',
unique_bettor_bonuses: 'Unique bettor bonuses on your markets',
unique_bettors_on_your_contract: 'Unique bettor bonuses on your markets',
tips_on_your_comments: 'Tips on your comments',
limit_order_fills: 'Limit order fills',
}
const general_explanations: {
[key in keyof Partial<exhaustive_notification_subscribe_types>]: string
[key in keyof Partial<notification_subscription_types>]: string
} = {
user_tagged_you: 'A user tagged you',
new_markets_by_followed_users: 'New markets created by users you follow',
tagged_user: 'A user tagged you',
contract_from_followed_user: 'New markets created by users you follow',
trending_markets: 'Weekly trending markets',
new_followers: 'New followers',
group_adds: 'When someone adds you to a group',
on_new_follow: 'New followers',
// profit_loss_updates: 'Weekly profit/loss updates',
}
const NotificationSettingLine = (
description: string,
key: string,
key: keyof notification_subscription_types,
value: notification_destination_types[]
) => {
const previousInAppValue = value.includes('browser')
@ -217,22 +234,18 @@ export function NotificationSettings() {
)
}
const getUsersSavedPreference = (key: string) => {
return Object.keys(privateUser.notificationSubscriptionTypes).includes(key)
? // eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
privateUser.notificationSubscriptionTypes[
Object.keys(privateUser.notificationSubscriptionTypes).filter(
(x) => x === key
)[0]
]
: ''
const getUsersSavedPreference = (
key: keyof notification_subscription_types
) => {
return privateUser.notificationSubscriptionTypes[key] ?? []
}
const Section = (
icon: ReactNode,
label: string,
map: { [key: string]: string }
subscriptionTypeToDescription: {
[key in keyof Partial<notification_subscription_types>]: string
}
) => {
const [expanded, setExpanded] = useState(false)
return (
@ -255,8 +268,14 @@ export function NotificationSettings() {
)}
</Row>
<Col className={clsx(expanded ? 'block' : 'hidden', 'gap-2 p-2')}>
{Object.entries(map).map(([key, value]) =>
NotificationSettingLine(value, key, getUsersSavedPreference(key))
{Object.entries(subscriptionTypeToDescription).map(([key, value]) =>
NotificationSettingLine(
value,
key as keyof notification_subscription_types,
getUsersSavedPreference(
key as keyof notification_subscription_types
)
)
)}
</Col>
</Col>