diff --git a/web/pages/notifications.tsx b/web/pages/notifications.tsx index 4059e077..728f6ce2 100644 --- a/web/pages/notifications.tsx +++ b/web/pages/notifications.tsx @@ -1,11 +1,6 @@ import {type Notification, NOTIFICATIONS_PER_PAGE,} from 'common/notifications' -import {PrivateUser, type User} from 'common/src/user' -import { - notification_destination_types, - notification_preference, - notification_preferences, -} from 'common/user-notification-preferences' -import {Fragment, useCallback, useEffect, useMemo, useState} from 'react' +import {type User} from 'common/src/user' +import {Fragment, useEffect, useMemo, useState} from 'react' import {NoSEO} from 'web/components/NoSEO' import {Col} from 'web/components/layout/col' import {UncontrolledTabs} from 'web/components/layout/tabs' @@ -17,9 +12,6 @@ import {Title} from 'web/components/widgets/title' import {useGroupedNotifications} from 'web/hooks/use-notifications' import {usePrivateUser, useUser} from 'web/hooks/use-user' import {api} from 'web/lib/api' -import {MultiSelectAnswers} from 'web/components/answers/answer-compatibility-question-content' -import {usePersistentInMemoryState} from 'web/hooks/use-persistent-in-memory-state' -import {debounce} from 'lodash' import {useRedirectIfSignedOut} from "web/hooks/use-redirect-if-signed-out"; export default function NotificationsPage() { @@ -31,7 +23,6 @@ export default function NotificationsPage() { }, - {title: 'Settings', content: }, ]} trackingName={'notifications page'} /> @@ -132,142 +123,3 @@ function RenderNotificationGroups(props: { ) } - -const NotificationSettings = () => { - const privateUser = usePrivateUser() - if (!privateUser) return null - return -} - -const LoadedNotificationSettings = (props: { privateUser: PrivateUser }) => { - const {privateUser} = props - - const [prefs, setPrefs] = - usePersistentInMemoryState( - privateUser.notificationPreferences, - 'notification-preferences' - ) - - const notificationTypes: { - type: notification_preference - question: string - }[] = [ - { - type: 'new_match', - question: - 'Where do you want to be notified when someone ... matches with you?', - }, - { - type: 'new_message', - question: '... sends you a new message?', - }, - { - type: 'new_profile_like', - question: '... likes your profile?', - }, - { - type: 'new_endorsement', - question: '... endorses you?', - }, - { - type: 'new_profile_ship', - question: '... ships you?', - }, - { - type: 'tagged_user', - question: '... mentions you?', - }, - { - type: 'on_new_follow', - question: '... follows you?', - }, - { - type: 'new_search_alerts', - question: 'Alerts from bookmarked searches?', - }, - { - type: 'opt_out_all', - question: - 'Regardless, do you NEVER want to be notified via any of these channels?', - }, - ] - - return ( -
-
- {notificationTypes.map(({type, question}) => ( - { - setPrefs((prevPrefs) => ({...prevPrefs, [type]: selected})) - }} - /> - ))} -
-
- ) -} - -const NotificationOption = (props: { - type: notification_preference - question: string - selected: notification_destination_types[] - onUpdate: (selected: notification_destination_types[]) => void -}) => { - const {type, question, selected, onUpdate} = props - - const getSelectedValues = (destinations: string[]) => { - const values: number[] = [] - if ((destinations ?? []).includes('email')) values.push(0) - if ((destinations ?? []).includes('browser')) values.push(1) - return values - } - - const setValue = async (value: number[]) => { - const newDestinations: notification_destination_types[] = [] - if (value.includes(0)) newDestinations.push('email') - if (value.includes(1)) newDestinations.push('browser') - - onUpdate(newDestinations) - save(selected, newDestinations) - } - - const save = useCallback( - debounce( - ( - oldDestinations: notification_destination_types[], - newDestinations: notification_destination_types[] - ) => { - // for each medium, if it changed, trigger a save - const mediums = ['email', 'browser'] as const - mediums.forEach((medium) => { - const wasEnabled = oldDestinations.includes(medium) - const isEnabled = newDestinations.includes(medium) - if (wasEnabled !== isEnabled) { - api('update-notif-settings', { - type, - medium, - enabled: isEnabled, - }) - } - }) - }, - 500 - ), - [] - ) - - return ( -
-
{question}
- -
- ) -} diff --git a/web/pages/settings.tsx b/web/pages/settings.tsx new file mode 100644 index 00000000..5af93c76 --- /dev/null +++ b/web/pages/settings.tsx @@ -0,0 +1,174 @@ +import {PrivateUser} from 'common/src/user' +import { + notification_destination_types, + notification_preference, + notification_preferences, +} from 'common/user-notification-preferences' +import {useCallback} from 'react' +import {NoSEO} from 'web/components/NoSEO' +import {UncontrolledTabs} from 'web/components/layout/tabs' +import {PageBase} from 'web/components/page-base' +import {Title} from 'web/components/widgets/title' +import {usePrivateUser} from 'web/hooks/use-user' +import {api} from 'web/lib/api' +import {MultiSelectAnswers} from 'web/components/answers/answer-compatibility-question-content' +import {usePersistentInMemoryState} from 'web/hooks/use-persistent-in-memory-state' +import {debounce} from 'lodash' +import {useRedirectIfSignedOut} from "web/hooks/use-redirect-if-signed-out"; + +export default function NotificationsPage() { + useRedirectIfSignedOut() + const privateUser = usePrivateUser() + if (!privateUser) return null + return ( + + + Settings + }, + {title: 'Notifications', content: }, + ]} + trackingName={'settings page'} + /> + + ) +} + +const AccountSettings = (props: { privateUser: PrivateUser }) => { + const {privateUser} = props + return <> +} + +const NotificationSettings = (props: { privateUser: PrivateUser }) => { + const {privateUser} = props + + const [prefs, setPrefs] = + usePersistentInMemoryState( + privateUser.notificationPreferences, + 'notification-preferences' + ) + + const notificationTypes: { + type: notification_preference + question: string + }[] = [ + { + type: 'new_match', + question: + 'Where do you want to be notified when someone ... matches with you?', + }, + { + type: 'new_message', + question: '... sends you a new message?', + }, + { + type: 'new_profile_like', + question: '... likes your profile?', + }, + { + type: 'new_endorsement', + question: '... endorses you?', + }, + { + type: 'new_profile_ship', + question: '... ships you?', + }, + { + type: 'tagged_user', + question: '... mentions you?', + }, + { + type: 'on_new_follow', + question: '... follows you?', + }, + { + type: 'new_search_alerts', + question: 'Alerts from bookmarked searches?', + }, + { + type: 'opt_out_all', + question: + 'Do you want to opt out of all notifications? (You can always change this later)?', + }, + ] + + return ( +
+
+ {notificationTypes.map(({type, question}) => ( + { + setPrefs((prevPrefs) => ({...prevPrefs, [type]: selected})) + }} + /> + ))} +
+
+ ) +} + +const NotificationOption = (props: { + type: notification_preference + question: string + selected: notification_destination_types[] + onUpdate: (selected: notification_destination_types[]) => void +}) => { + const {type, question, selected, onUpdate} = props + + const getSelectedValues = (destinations: string[]) => { + const values: number[] = [] + if ((destinations ?? []).includes('email')) values.push(0) + if ((destinations ?? []).includes('browser')) values.push(1) + return values + } + + const setValue = async (value: number[]) => { + const newDestinations: notification_destination_types[] = [] + if (value.includes(0)) newDestinations.push('email') + if (value.includes(1)) newDestinations.push('browser') + + onUpdate(newDestinations) + save(selected, newDestinations) + } + + const save = useCallback( + debounce( + ( + oldDestinations: notification_destination_types[], + newDestinations: notification_destination_types[] + ) => { + // for each medium, if it changed, trigger a save + const mediums = ['email', 'browser'] as const + mediums.forEach((medium) => { + const wasEnabled = oldDestinations.includes(medium) + const isEnabled = newDestinations.includes(medium) + if (wasEnabled !== isEnabled) { + api('update-notif-settings', { + type, + medium, + enabled: isEnabled, + }) + } + }) + }, + 500 + ), + [] + ) + + return ( +
+
{question}
+ +
+ ) +}