Skip to content

Commit fc60da5

Browse files
faridsalaudharit-tan
authored andcommitted
[PAY-3850][PAY-3849] Add listen streak noti on web (#11379)
1 parent 6431d6e commit fc60da5

File tree

10 files changed

+81
-15
lines changed

10 files changed

+81
-15
lines changed

packages/common/src/adapters/notification.ts

+1
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ export const notificationFromSDK = (
212212
challengeId,
213213
entityType: Entity.User,
214214
amount: data.amount as StringWei,
215+
listenStreak: data.listenStreak,
215216
...formatBaseNotification(notification)
216217
}
217218
}

packages/common/src/store/notifications/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,7 @@ export type ChallengeRewardNotification = BaseNotification & {
462462
challengeId: ChallengeRewardID
463463
entityType: string
464464
amount: StringWei
465+
listenStreak?: number
465466
}
466467

467468
export type ClaimableRewardNotification = BaseNotification & {

packages/discovery-provider/ddl/functions/handle_user_challenges.sql

+23-2
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ create or replace function handle_on_user_challenge() returns trigger as $$
22
declare
33
cooldown_days integer;
44
existing_notification integer;
5+
listen_streak_value integer;
56
begin
67
if (new.is_complete = true) then
78
-- attempt to insert a new notification, ignoring conflicts
89
select challenges.cooldown_days into cooldown_days from challenges where id = new.challenge_id;
910

10-
1111
if (cooldown_days is null or cooldown_days = 0) then
1212
-- Check if there is an existing notification with the same fields in the last 15 minutes
1313

@@ -27,6 +27,13 @@ begin
2727
on conflict do nothing;
2828
end if;
2929

30+
if new.challenge_id = 'e' then
31+
select listen_streak into listen_streak_value
32+
from challenge_listen_streak
33+
where user_id = new.user_id
34+
limit 1;
35+
end if;
36+
3037
insert into notification
3138
(blocknumber, user_ids, timestamp, type, group_id, specifier, data)
3239
values
@@ -37,7 +44,21 @@ begin
3744
'challenge_reward',
3845
'challenge_reward:' || new.user_id || ':challenge:' || new.challenge_id || ':specifier:' || new.specifier,
3946
new.user_id,
40-
json_build_object('specifier', new.specifier, 'challenge_id', new.challenge_id, 'amount', new.amount::text || '00000000' ) -- convert amount
47+
case
48+
when new.challenge_id = 'e' then
49+
json_build_object(
50+
'specifier', new.specifier,
51+
'challenge_id', new.challenge_id,
52+
'amount', new.amount::text || '00000000',
53+
'listen_streak', coalesce(listen_streak_value, 0)
54+
)
55+
else
56+
json_build_object(
57+
'specifier', new.specifier,
58+
'challenge_id', new.challenge_id,
59+
'amount', new.amount::text || '00000000'
60+
)
61+
end
4162
)
4263
on conflict do nothing;
4364
else

packages/discovery-provider/plugins/notifications/src/types/notifications.ts

+1
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ export type ChallengeRewardNotification = {
126126
amount: number
127127
specifier: string
128128
challenge_id: ChallengeId
129+
listen_streak?: number
129130
}
130131

131132
export type ClaimableRewardNotification = {

packages/discovery-provider/src/api/v1/models/notifications.py

+1
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@ def format(self, value):
377377
"amount": fields.String(required=True),
378378
"specifier": fields.String(required=True),
379379
"challenge_id": fields.String(required=True),
380+
"listen_streak": fields.Integer(required=False),
380381
},
381382
)
382383
challenge_reward_notification_action = ns.clone(

packages/discovery-provider/src/api/v1/utils/extend_notification.py

+1
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,7 @@ def extend_challenge_reward(action: NotificationAction):
343343
"amount": to_wei_string(data["amount"]),
344344
"specifier": data["specifier"],
345345
"challenge_id": data["challenge_id"],
346+
"listen_streak": data.get("listen_streak"),
346347
},
347348
}
348349

packages/discovery-provider/src/queries/get_notifications.py

+1
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ class ChallengeRewardNotification(TypedDict):
319319
amount: int
320320
specifier: str
321321
challenge_id: str
322+
listen_streak: Optional[int]
322323

323324

324325
class ClaimableRewardNotification(TypedDict):

packages/sdk/src/sdk/api/generated/full/models/ChallengeRewardNotificationActionData.ts

+8
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ export interface ChallengeRewardNotificationActionData {
3838
* @memberof ChallengeRewardNotificationActionData
3939
*/
4040
challengeId: string;
41+
/**
42+
*
43+
* @type {number}
44+
* @memberof ChallengeRewardNotificationActionData
45+
*/
46+
listenStreak?: number;
4147
}
4248

4349
/**
@@ -65,6 +71,7 @@ export function ChallengeRewardNotificationActionDataFromJSONTyped(json: any, ig
6571
'amount': json['amount'],
6672
'specifier': json['specifier'],
6773
'challengeId': json['challenge_id'],
74+
'listenStreak': !exists(json, 'listen_streak') ? undefined : json['listen_streak'],
6875
};
6976
}
7077

@@ -80,6 +87,7 @@ export function ChallengeRewardNotificationActionDataToJSON(value?: ChallengeRew
8087
'amount': value.amount,
8188
'specifier': value.specifier,
8289
'challenge_id': value.challengeId,
90+
'listen_streak': value.listenStreak,
8391
};
8492
}
8593

packages/web/src/components/notification/Notification/ChallengeRewardNotification.tsx

+43-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1-
import { useCallback } from 'react'
1+
import { useCallback, useMemo } from 'react'
22

3-
import { Name, BNAudio, ChallengeRewardID } from '@audius/common/models'
3+
import {
4+
BNAudio,
5+
ChallengeName,
6+
ChallengeRewardID,
7+
Name
8+
} from '@audius/common/models'
49
import { ChallengeRewardNotification as ChallengeRewardNotificationType } from '@audius/common/store'
510
import {
611
formatNumberCommas,
@@ -24,14 +29,22 @@ import { IconRewards } from './components/icons'
2429

2530
const { REWARDS_PAGE } = route
2631

32+
const formatNumber = (amount: BNAudio) => {
33+
return formatNumberCommas(Number(amount.toString()))
34+
}
35+
2736
const messages = {
2837
amountEarned: (amount: BNAudio) =>
29-
`You've earned ${formatNumberCommas(Number(amount.toString()))} $AUDIO`,
38+
`You've earned ${formatNumber(amount)} $AUDIO`,
3039
referredText:
3140
' for being referred! Invite your friends to join to earn more!',
3241
challengeCompleteText: ' for completing this challenge!',
3342
twitterShareText:
34-
'I earned $AUDIO for completing challenges on @audius #Audius #AudioRewards'
43+
'I earned $AUDIO for completing challenges on @audius #Audius #AudioRewards',
44+
streakMilestone: (amountEarned: number, listenStreak: number) =>
45+
`You've earned ${amountEarned} $AUDIO for hitting Day ${listenStreak} of your listening streak! You'll now earn an additional $AUDIO reward for every day you keep your streak going!`,
46+
streakMaintenance: (amountEarned: number) =>
47+
`You've earned ${amountEarned} $AUDIO for maintaining your listening streak! Keep your streak going to continue earning daily rewards!`
3548
}
3649

3750
type ChallengeRewardNotificationProps = {
@@ -50,7 +63,7 @@ export const ChallengeRewardNotification = (
5063
props: ChallengeRewardNotificationProps
5164
) => {
5265
const { notification } = props
53-
const { challengeId, timeLabel, isViewed, type } = notification
66+
const { challengeId, timeLabel, isViewed, type, listenStreak } = notification
5467
const dispatch = useDispatch()
5568
const record = useRecord()
5669
const mappedChallengeRewardsConfigKey =
@@ -65,17 +78,35 @@ export const ChallengeRewardNotification = (
6578
)
6679
}, [dispatch, record, type])
6780

81+
const notificationTitle = useMemo(() => {
82+
if (challengeId === ChallengeName.ListenStreakEndless) {
83+
return `${title}: Day ${listenStreak}`
84+
}
85+
return title
86+
}, [challengeId, listenStreak, title])
87+
88+
const amountEarnedText = useMemo(() => {
89+
switch (challengeId) {
90+
case ChallengeName.ListenStreakEndless: {
91+
const amountEarned = Number(formatNumber(amount))
92+
if (amountEarned > 1) {
93+
return messages.streakMilestone(amountEarned, listenStreak ?? 0)
94+
}
95+
return messages.streakMaintenance(amountEarned)
96+
}
97+
case 'referred':
98+
return messages.amountEarned(amount) + messages.referredText
99+
default:
100+
return messages.amountEarned(amount) + messages.challengeCompleteText
101+
}
102+
}, [challengeId, amount, listenStreak])
103+
68104
return (
69105
<NotificationTile notification={notification} onClick={handleClick}>
70106
<NotificationHeader icon={<IconRewards>{icon}</IconRewards>}>
71-
<NotificationTitle>{title}</NotificationTitle>
107+
<NotificationTitle>{notificationTitle}</NotificationTitle>
72108
</NotificationHeader>
73-
<NotificationBody>
74-
{messages.amountEarned(amount)}
75-
{challengeId === 'referred'
76-
? messages.referredText
77-
: messages.challengeCompleteText}
78-
</NotificationBody>
109+
<NotificationBody>{amountEarnedText}</NotificationBody>
79110
<TwitterShareButton
80111
type='static'
81112
url={env.AUDIUS_URL}

packages/web/src/pages/rewards-page/config.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ const webChallengesConfig: Record<ChallengeRewardID, WebChallengeInfo> = {
140140
}
141141
},
142142
[ChallengeName.ListenStreakEndless]: {
143-
icon: <i className='emoji large headphone' />,
143+
icon: <i className='emoji large fire' />,
144144
modalButtonInfo: {
145145
incomplete: linkButtonMap.trendingTracks,
146146
inProgress: linkButtonMap.trendingTracks,

0 commit comments

Comments
 (0)