import { usePrivateUser } from 'web/hooks/use-user' import React, { ReactNode, useEffect, useState } from 'react' import { LoadingIndicator } from 'web/components/loading-indicator' import { Row } from 'web/components/layout/row' import clsx from 'clsx' import { exhaustive_notification_subscribe_types, notification_receive_types, } from 'common/user' import { updatePrivateUser } from 'web/lib/firebase/users' import { Switch } from '@headlessui/react' import { Col } from 'web/components/layout/col' import { AdjustmentsIcon, CashIcon, ChatIcon, ChevronDownIcon, ChevronUpIcon, InformationCircleIcon, LightBulbIcon, TrendingUpIcon, UserIcon, } from '@heroicons/react/outline' import { WatchMarketModal } from 'web/components/contract/watch-market-modal' import { filterDefined } from 'common/util/array' import toast from 'react-hot-toast' export function NotificationSettings() { const privateUser = usePrivateUser() const [showWatchModal, setShowWatchModal] = useState(false) const prevPref = privateUser?.notificationPreferences const browserOnly = ['browser'] const emailOnly = ['email'] const both = ['email', 'browser'] const wantsLess = prevPref === 'less' const wantsAll = prevPref === 'all' const constructPref = (browserIf: boolean, emailIf: boolean | undefined) => { const browser = browserIf ? 'browser' : undefined const email = emailIf ? 'email' : undefined return filterDefined([browser, email]) as notification_receive_types[] } if (privateUser && !privateUser.notificationSubscriptionTypes) { updatePrivateUser(privateUser.id, { notificationSubscriptionTypes: { // Watched Markets all_comments: constructPref( wantsAll, !privateUser.unsubscribedFromCommentEmails ), all_answers: constructPref( wantsAll, !privateUser.unsubscribedFromAnswerEmails ), // Comments tipped_comments: constructPref(wantsAll || wantsLess, true), comments_by_followed_users: constructPref(wantsAll, false), //wantsAll ? browserOnly : none, all_replies_to_my_comments: constructPref(wantsAll || wantsLess, true), //wantsAll || wantsLess ? both : none, all_replies_to_my_answers: constructPref(wantsAll || wantsLess, true), //wantsAll || wantsLess ? both : none, // Answers answers_by_followed_users: constructPref( wantsAll || wantsLess, !privateUser.unsubscribedFromAnswerEmails ), //wantsAll || wantsLess ? both : none, answers_by_market_creator: constructPref( wantsAll || wantsLess, !privateUser.unsubscribedFromAnswerEmails ), //wantsAll || wantsLess ? both : none, // On users' markets my_markets_closed: constructPref( wantsAll || wantsLess, !privateUser.unsubscribedFromResolutionEmails ), //wantsAll || wantsLess ? both : none, // High priority all_comments_on_my_markets: constructPref(wantsAll || wantsLess, true), //wantsAll || wantsLess ? both : none, all_answers_on_my_markets: constructPref(wantsAll || wantsLess, true), //wantsAll || wantsLess ? both : none, // Market updates resolutions: constructPref(wantsAll || wantsLess, true), market_updates: constructPref(wantsAll || wantsLess, false), //Balance Changes loans: browserOnly, betting_streaks: browserOnly, referral_bonuses: both, unique_bettor_bonuses: browserOnly, // General user_tagged_you: constructPref(wantsAll || wantsLess, true), //wantsAll || wantsLess ? both : none, new_markets_by_followed_users: constructPref( wantsAll || wantsLess, true ), //wantsAll || wantsLess ? both : none, trending_markets: constructPref( false, !privateUser.unsubscribedFromWeeklyTrendingEmails ), profit_loss_updates: emailOnly, } as exhaustive_notification_subscribe_types, }) } if (!privateUser || !privateUser.notificationSubscriptionTypes) { return } const emailsEnabled = [ 'all_comments', 'all_answers', 'resolutions', 'all_replies_to_my_comments', 'all_replies_to_my_answers', 'all_comments_on_my_markets', 'all_answers_on_my_markets', 'my_markets_closed', 'probability_updates', 'user_tagged_you', 'new_markets_by_followed_users', 'trending_markets', 'profit_loss_updates', ] const browserDisabled = ['trending_markets', 'profit_loss_updates'] const watched_markets_explanations_comments: { [key in keyof Partial]: string } = { all_comments: 'All', // tipped_comments: 'Tipped', // comments_by_followed_users: 'By followed users', all_replies_to_my_comments: 'Replies to your comments', } const watched_markets_explanations_answers: { [key in keyof Partial]: string } = { all_answers: 'All', all_replies_to_my_answers: 'Replies to your answers', // answers_by_followed_users: 'By followed users', // answers_by_market_creator: 'Submitted by the market creator', } const watched_markets_explanations_your_markets: { [key in keyof Partial]: string } = { my_markets_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', } const watched_markets_explanations_market_updates: { [key in keyof Partial]: string } = { resolutions: 'Market resolutions', market_updates: 'Updates made by the creator', // probability_updates: 'Changes in probability', } const balance_change_explanations: { [key in keyof Partial]: string } = { loans: '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', } const general_explanations: { [key in keyof Partial]: string } = { user_tagged_you: 'A user tagged you', new_markets_by_followed_users: 'New markets created by users you follow', trending_markets: 'Weekly trending markets', // profit_loss_updates: 'Weekly profit and loss updates', } const NotificationSettingLine = ( description: string, key: string, value: notification_receive_types[] ) => { const previousInAppValue = value.includes('browser') const previousEmailValue = value.includes('email') const [inAppEnabled, setInAppEnabled] = useState(previousInAppValue) const [emailEnabled, setEmailEnabled] = useState(previousEmailValue) const loading = 'Changing Notifications Settings' const success = 'Changed Notification Settings!' useEffect(() => { if ( inAppEnabled !== previousInAppValue || emailEnabled !== previousEmailValue ) { toast.promise( updatePrivateUser(privateUser.id, { notificationSubscriptionTypes: { ...privateUser.notificationSubscriptionTypes, [key]: filterDefined([ inAppEnabled ? 'browser' : undefined, emailEnabled ? 'email' : undefined, ]), }, }), { success, loading, error: 'Error changing notification settings. Try again?', } ) } }, [ inAppEnabled, emailEnabled, previousInAppValue, previousEmailValue, key, ]) // for each entry in the exhaustive_notification_subscribe_types we'll want to load whether the user // wants email, browser, both, or none return ( {description} {!browserDisabled.includes(key) && ( In-app )} {emailsEnabled.includes(key) && ( Emails )} ) } 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 Section = ( icon: ReactNode, label: string, map: { [key: string]: string } ) => { const [expanded, setExpanded] = useState(false) return ( setExpanded(!expanded)} > {icon} {label} {expanded ? ( Hide ) : ( Show )} {Object.entries(map).map(([key, value]) => NotificationSettingLine(value, key, getUsersSavedPreference(key)) )} ) } return (
Notifications for Watched Markets setShowWatchModal(true)} /> {/*// TODO: add none option to each section*/} {Section( , 'New Comments', watched_markets_explanations_comments )} {Section( , 'New Answers', watched_markets_explanations_answers )} {Section( , 'On Your Markets', watched_markets_explanations_your_markets )} {Section( , 'Market Updates', watched_markets_explanations_market_updates )} Balance Changes {Section( , 'Loans and Bonuses', balance_change_explanations )} Other {Section( , 'General', general_explanations )}
) }