diff --git a/web/pages/notifications.tsx b/web/pages/notifications.tsx index 54dbdd09..382505e2 100644 --- a/web/pages/notifications.tsx +++ b/web/pages/notifications.tsx @@ -166,20 +166,6 @@ export default function Notifications() { ) } -export const setNotificationsAsSeen = (notifications: Notification[]) => { - notifications.forEach((notification) => { - if (!notification.isSeen) - updateDoc( - doc(db, `users/${notification.userId}/notifications/`, notification.id), - { - isSeen: true, - viewTime: new Date(), - } - ) - }) - return notifications -} - function IncomeNotificationGroupItem(props: { notificationGroup: NotificationGroup className?: string @@ -556,6 +542,369 @@ function NotificationGroupItem(props: { ) } +function NotificationItem(props: { + notification: Notification + justSummary?: boolean + hideTitle?: boolean +}) { + const { notification, justSummary, hideTitle } = props + const { + sourceType, + sourceId, + sourceUserName, + sourceUserAvatarUrl, + sourceUpdateType, + reasonText, + reason, + sourceUserUsername, + createdTime, + sourceText, + sourceContractCreatorUsername, + sourceContractSlug, + } = notification + + const [defaultNotificationText, setDefaultNotificationText] = + useState('') + + useEffect(() => { + if (sourceText) { + setDefaultNotificationText(sourceText) + } else if (reasonText) { + // Handle arbitrary notifications with reason text here. + setDefaultNotificationText(reasonText) + } + }, [reasonText, sourceText]) + + const [highlighted] = useState(!notification.isSeen) + + useEffect(() => { + setNotificationsAsSeen([notification]) + }, [notification]) + + if (justSummary) { + return ( + +
+
+ +
+ + {sourceType && + reason && + getReasonForShowingNotification(notification, true, true)} + +
+ +
+
+
+
+
+ ) + } + + return ( +
+ + + +
+
+ {sourceUpdateType != 'closed' && ( + + )} + {sourceType && reason && ( +
+ + {getReasonForShowingNotification(notification, false, true)} + + {!hideTitle && ( + + )} +
+ )} + {sourceId && + sourceContractSlug && + sourceContractCreatorUsername ? ( + + ) : ( + + )} +
+
+
+
+ +
+ +
+ +
+ ) +} + +export const setNotificationsAsSeen = (notifications: Notification[]) => { + notifications.forEach((notification) => { + if (!notification.isSeen) + updateDoc( + doc(db, `users/${notification.userId}/notifications/`, notification.id), + { + isSeen: true, + viewTime: new Date(), + } + ) + }) + return notifications +} + +function NotificationLink(props: { notification: Notification }) { + const { notification } = props + const { + sourceType, + sourceContractTitle, + sourceContractCreatorUsername, + sourceContractSlug, + sourceSlug, + sourceTitle, + } = notification + return ( + + {sourceContractTitle || sourceTitle} + + ) +} + +function getSourceUrl(notification: Notification) { + const { + sourceType, + sourceId, + sourceUserUsername, + sourceContractCreatorUsername, + sourceContractSlug, + sourceSlug, + } = notification + if (sourceType === 'follow') return `/${sourceUserUsername}` + if (sourceType === 'group' && sourceSlug) return `${groupPath(sourceSlug)}` + if ( + sourceContractCreatorUsername && + sourceContractSlug && + sourceType === 'user' + ) + return `/${sourceContractCreatorUsername}/${sourceContractSlug}` + if (sourceType === 'tip') + return `/${sourceContractCreatorUsername}/${sourceContractSlug}#${sourceSlug}` + if (sourceContractCreatorUsername && sourceContractSlug) + return `/${sourceContractCreatorUsername}/${sourceContractSlug}#${getSourceIdForLinkComponent( + sourceId ?? '', + sourceType + )}` +} + +function getSourceIdForLinkComponent( + sourceId: string, + sourceType?: notification_source_types +) { + switch (sourceType) { + case 'answer': + return `answer-${sourceId}` + case 'comment': + return sourceId + case 'contract': + return '' + default: + return sourceId + } +} + +function NotificationTextLabel(props: { + defaultText: string + contract?: Contract | null + notification: Notification + className?: string + justSummary?: boolean +}) { + const { contract, className, defaultText, notification, justSummary } = props + const { sourceUpdateType, sourceType, sourceText, sourceContractTitle } = + notification + if (sourceType === 'contract') { + if (justSummary) + return {contract?.question || sourceContractTitle} + if (!sourceText) return
+ // Resolved contracts + if (sourceType === 'contract' && sourceUpdateType === 'resolved') { + { + if (sourceText === 'YES' || sourceText == 'NO') { + return + } + if (sourceText.includes('%')) + return ( + + ) + if (sourceText === 'CANCEL') return + if (sourceText === 'MKT' || sourceText === 'PROB') return + } + } + // Close date will be a number - it looks better without it + if (sourceUpdateType === 'closed') { + return
+ } + // Updated contracts + // Description will be in default text + if (parseInt(sourceText) > 0) { + return ( + + Updated close time: {new Date(parseInt(sourceText)).toLocaleString()} + + ) + } + } else if (sourceType === 'user' && sourceText) { + return ( + + As a thank you, we sent you{' '} + + {formatMoney(parseInt(sourceText))} + + ! + + ) + } else if (sourceType === 'liquidity' && sourceText) { + return ( + {formatMoney(parseInt(sourceText))} + ) + } else if ((sourceType === 'bonus' || sourceType === 'tip') && sourceText) { + return ( + + {'+' + formatMoney(parseInt(sourceText))} + + ) + } + // return default text + return ( +
+ +
+ ) +} + +function getReasonForShowingNotification( + notification: Notification, + simple?: boolean, + replaceOn?: boolean +) { + const { sourceType, sourceUpdateType, reason, sourceSlug } = notification + let reasonText: string + switch (sourceType) { + case 'comment': + if (reason === 'reply_to_users_answer') + reasonText = !simple ? 'replied to you on' : 'replied' + else if (reason === 'tagged_user') + reasonText = !simple ? 'tagged you on' : 'tagged you' + else if (reason === 'reply_to_users_comment') + reasonText = !simple ? 'replied to you on' : 'replied' + else if (reason === 'on_users_contract') + reasonText = !simple ? `commented on your question` : 'commented' + else if (reason === 'on_contract_with_users_comment') + reasonText = `commented on` + else if (reason === 'on_contract_with_users_answer') + reasonText = `commented on` + else if (reason === 'on_contract_with_users_shares_in') + reasonText = `commented on` + else reasonText = `commented on` + break + case 'contract': + if (reason === 'you_follow_user') reasonText = 'asked' + else if (sourceUpdateType === 'resolved') reasonText = `resolved` + else if (sourceUpdateType === 'closed') + reasonText = `Please resolve your question` + else reasonText = `updated` + break + case 'answer': + if (reason === 'on_users_contract') reasonText = `answered your question ` + else if (reason === 'on_contract_with_users_comment') + reasonText = `answered` + else if (reason === 'on_contract_with_users_answer') + reasonText = `answered` + else if (reason === 'on_contract_with_users_shares_in') + reasonText = `answered` + else reasonText = `answered` + break + case 'follow': + reasonText = 'followed you' + break + case 'liquidity': + reasonText = 'added liquidity to your question' + break + case 'group': + reasonText = 'added you to the group' + break + case 'user': + if (sourceSlug && reason === 'user_joined_to_bet_on_your_market') + reasonText = 'joined to bet on your market' + else if (sourceSlug) reasonText = 'joined because you shared' + else reasonText = 'joined because of you' + break + default: + reasonText = '' + } + + return ( + + {replaceOn ? reasonText.replace(' on', '') : reasonText} + + ) +} + // TODO: where should we put referral bonus notifications? function NotificationSettings() { const user = useUser() @@ -751,352 +1100,3 @@ function NotificationSettings() {
) } - -function NotificationLink(props: { notification: Notification }) { - const { notification } = props - const { - sourceType, - sourceContractTitle, - sourceContractCreatorUsername, - sourceContractSlug, - sourceSlug, - sourceTitle, - } = notification - return ( - - {sourceContractTitle || sourceTitle} - - ) -} - -function getSourceUrl(notification: Notification) { - const { - sourceType, - sourceId, - sourceUserUsername, - sourceContractCreatorUsername, - sourceContractSlug, - sourceSlug, - } = notification - if (sourceType === 'follow') return `/${sourceUserUsername}` - if (sourceType === 'group' && sourceSlug) return `${groupPath(sourceSlug)}` - if ( - sourceContractCreatorUsername && - sourceContractSlug && - sourceType === 'user' - ) - return `/${sourceContractCreatorUsername}/${sourceContractSlug}` - if (sourceType === 'tip') - return `/${sourceContractCreatorUsername}/${sourceContractSlug}#${sourceSlug}` - if (sourceContractCreatorUsername && sourceContractSlug) - return `/${sourceContractCreatorUsername}/${sourceContractSlug}#${getSourceIdForLinkComponent( - sourceId ?? '', - sourceType - )}` -} - -function getSourceIdForLinkComponent( - sourceId: string, - sourceType?: notification_source_types -) { - switch (sourceType) { - case 'answer': - return `answer-${sourceId}` - case 'comment': - return sourceId - case 'contract': - return '' - default: - return sourceId - } -} - -function NotificationItem(props: { - notification: Notification - justSummary?: boolean - hideTitle?: boolean -}) { - const { notification, justSummary, hideTitle } = props - const { - sourceType, - sourceId, - sourceUserName, - sourceUserAvatarUrl, - sourceUpdateType, - reasonText, - reason, - sourceUserUsername, - createdTime, - sourceText, - sourceContractCreatorUsername, - sourceContractSlug, - } = notification - - const [defaultNotificationText, setDefaultNotificationText] = - useState('') - - useEffect(() => { - if (sourceText) { - setDefaultNotificationText(sourceText) - } else if (reasonText) { - // Handle arbitrary notifications with reason text here. - setDefaultNotificationText(reasonText) - } - }, [reasonText, sourceText]) - - const [highlighted] = useState(!notification.isSeen) - - useEffect(() => { - setNotificationsAsSeen([notification]) - }, [notification]) - - if (justSummary) { - return ( - -
-
- -
- - {sourceType && - reason && - getReasonForShowingNotification(notification, true, true)} - -
- -
-
-
-
-
- ) - } - - return ( -
- - - -
-
- {sourceUpdateType != 'closed' && ( - - )} - {sourceType && reason && ( -
- - {getReasonForShowingNotification(notification, false, true)} - - {!hideTitle && ( - - )} -
- )} - {sourceId && - sourceContractSlug && - sourceContractCreatorUsername ? ( - - ) : ( - - )} -
-
-
-
- -
- -
- -
- ) -} - -function NotificationTextLabel(props: { - defaultText: string - contract?: Contract | null - notification: Notification - className?: string - justSummary?: boolean -}) { - const { contract, className, defaultText, notification, justSummary } = props - const { sourceUpdateType, sourceType, sourceText, sourceContractTitle } = - notification - if (sourceType === 'contract') { - if (justSummary) - return {contract?.question || sourceContractTitle} - if (!sourceText) return
- // Resolved contracts - if (sourceType === 'contract' && sourceUpdateType === 'resolved') { - { - if (sourceText === 'YES' || sourceText == 'NO') { - return - } - if (sourceText.includes('%')) - return ( - - ) - if (sourceText === 'CANCEL') return - if (sourceText === 'MKT' || sourceText === 'PROB') return - } - } - // Close date will be a number - it looks better without it - if (sourceUpdateType === 'closed') { - return
- } - // Updated contracts - // Description will be in default text - if (parseInt(sourceText) > 0) { - return ( - - Updated close time: {new Date(parseInt(sourceText)).toLocaleString()} - - ) - } - } else if (sourceType === 'user' && sourceText) { - return ( - - As a thank you, we sent you{' '} - - {formatMoney(parseInt(sourceText))} - - ! - - ) - } else if (sourceType === 'liquidity' && sourceText) { - return ( - {formatMoney(parseInt(sourceText))} - ) - } else if ((sourceType === 'bonus' || sourceType === 'tip') && sourceText) { - return ( - - {'+' + formatMoney(parseInt(sourceText))} - - ) - } - // return default text - return ( -
- -
- ) -} - -function getReasonForShowingNotification( - notification: Notification, - simple?: boolean, - replaceOn?: boolean -) { - const { sourceType, sourceUpdateType, reason, sourceSlug } = notification - let reasonText: string - switch (sourceType) { - case 'comment': - if (reason === 'reply_to_users_answer') - reasonText = !simple ? 'replied to you on' : 'replied' - else if (reason === 'tagged_user') - reasonText = !simple ? 'tagged you on' : 'tagged you' - else if (reason === 'reply_to_users_comment') - reasonText = !simple ? 'replied to you on' : 'replied' - else if (reason === 'on_users_contract') - reasonText = !simple ? `commented on your question` : 'commented' - else if (reason === 'on_contract_with_users_comment') - reasonText = `commented on` - else if (reason === 'on_contract_with_users_answer') - reasonText = `commented on` - else if (reason === 'on_contract_with_users_shares_in') - reasonText = `commented on` - else reasonText = `commented on` - break - case 'contract': - if (reason === 'you_follow_user') reasonText = 'asked' - else if (sourceUpdateType === 'resolved') reasonText = `resolved` - else if (sourceUpdateType === 'closed') - reasonText = `Please resolve your question` - else reasonText = `updated` - break - case 'answer': - if (reason === 'on_users_contract') reasonText = `answered your question ` - else if (reason === 'on_contract_with_users_comment') - reasonText = `answered` - else if (reason === 'on_contract_with_users_answer') - reasonText = `answered` - else if (reason === 'on_contract_with_users_shares_in') - reasonText = `answered` - else reasonText = `answered` - break - case 'follow': - reasonText = 'followed you' - break - case 'liquidity': - reasonText = 'added liquidity to your question' - break - case 'group': - reasonText = 'added you to the group' - break - case 'user': - if (sourceSlug && reason === 'user_joined_to_bet_on_your_market') - reasonText = 'joined to bet on your market' - else if (sourceSlug) reasonText = 'joined because you shared' - else reasonText = 'joined because of you' - break - default: - reasonText = '' - } - - return ( - - {replaceOn ? reasonText.replace(' on', '') : reasonText} - - ) -}