@mundogamernetwork/shared-ui 1.8.15 → 1.8.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/locales/de.json +2 -1
- package/locales/en.json +2 -1
- package/locales/pt-BR.json +2 -1
- package/locales/ro.json +2 -1
- package/package.json +1 -1
- package/pages/key-campaigns/[slug].vue +69 -1
- package/services/campaignService.ts +16 -0
package/locales/de.json
CHANGED
|
@@ -120,6 +120,8 @@
|
|
|
120
120
|
"status_active": "Active",
|
|
121
121
|
"status_upcoming": "Coming soon",
|
|
122
122
|
"opens_in": "Opens in",
|
|
123
|
+
"follow_campaign": "Benachrichtige mich bei Eröffnung",
|
|
124
|
+
"following": "Du wirst benachrichtigt",
|
|
123
125
|
"status_closed": "Closed",
|
|
124
126
|
"status_ending": "Ending soon",
|
|
125
127
|
"status_exhausted": "Keys exhausted",
|
|
@@ -137,7 +139,6 @@
|
|
|
137
139
|
"official": "Official streamers",
|
|
138
140
|
"affiliate": "Affiliate or above"
|
|
139
141
|
},
|
|
140
|
-
"rp_label": "Redeemed by",
|
|
141
142
|
"who_redeem": "Who redeemed",
|
|
142
143
|
"created_by": "Published by",
|
|
143
144
|
"no_data": "Diese Kampagne ist noch keinem Spiel im System zugeordnet",
|
package/locales/en.json
CHANGED
|
@@ -120,6 +120,8 @@
|
|
|
120
120
|
"status_active": "Active",
|
|
121
121
|
"status_upcoming": "Coming soon",
|
|
122
122
|
"opens_in": "Opens in",
|
|
123
|
+
"follow_campaign": "Notify me when it opens",
|
|
124
|
+
"following": "You'll be notified",
|
|
123
125
|
"status_closed": "Closed",
|
|
124
126
|
"status_ending": "Ending soon",
|
|
125
127
|
"status_exhausted": "Keys exhausted",
|
|
@@ -137,7 +139,6 @@
|
|
|
137
139
|
"official": "Official streamers",
|
|
138
140
|
"affiliate": "Affiliate or above"
|
|
139
141
|
},
|
|
140
|
-
"rp_label": "Redeemed by",
|
|
141
142
|
"who_redeem": "Who redeemed",
|
|
142
143
|
"created_by": "Published by",
|
|
143
144
|
"no_data": "This campaign is not associated with a game in our system yet",
|
package/locales/pt-BR.json
CHANGED
|
@@ -120,6 +120,8 @@
|
|
|
120
120
|
"status_active": "Active",
|
|
121
121
|
"status_upcoming": "Coming soon",
|
|
122
122
|
"opens_in": "Opens in",
|
|
123
|
+
"follow_campaign": "Me avise quando abrir",
|
|
124
|
+
"following": "Você será avisado",
|
|
123
125
|
"status_closed": "Closed",
|
|
124
126
|
"status_ending": "Ending soon",
|
|
125
127
|
"status_exhausted": "Keys exhausted",
|
|
@@ -137,7 +139,6 @@
|
|
|
137
139
|
"official": "Official streamers",
|
|
138
140
|
"affiliate": "Affiliate or above"
|
|
139
141
|
},
|
|
140
|
-
"rp_label": "Redeemed by",
|
|
141
142
|
"who_redeem": "Who redeemed",
|
|
142
143
|
"created_by": "Published by",
|
|
143
144
|
"no_data": "Esta campanha ainda não foi associada a um jogo no sistema",
|
package/locales/ro.json
CHANGED
|
@@ -120,6 +120,8 @@
|
|
|
120
120
|
"status_active": "Active",
|
|
121
121
|
"status_upcoming": "Coming soon",
|
|
122
122
|
"opens_in": "Opens in",
|
|
123
|
+
"follow_campaign": "Anunță-mă când se deschide",
|
|
124
|
+
"following": "Vei fi anunțat",
|
|
123
125
|
"status_closed": "Closed",
|
|
124
126
|
"status_ending": "Ending soon",
|
|
125
127
|
"status_exhausted": "Keys exhausted",
|
|
@@ -137,7 +139,6 @@
|
|
|
137
139
|
"official": "Official streamers",
|
|
138
140
|
"affiliate": "Affiliate or above"
|
|
139
141
|
},
|
|
140
|
-
"rp_label": "Redeemed by",
|
|
141
142
|
"who_redeem": "Who redeemed",
|
|
142
143
|
"created_by": "Published by",
|
|
143
144
|
"no_data": "Această campanie nu este încă asociată cu un joc în sistem",
|
package/package.json
CHANGED
|
@@ -9,6 +9,8 @@ import {
|
|
|
9
9
|
fetchKeyRequestById,
|
|
10
10
|
revealKey,
|
|
11
11
|
requestKey,
|
|
12
|
+
followCampaign,
|
|
13
|
+
unfollowCampaign,
|
|
12
14
|
} from "../../services/campaignService"
|
|
13
15
|
import { fetchDetailGame, fetchDetailGameImage } from "../../services/gamesService"
|
|
14
16
|
|
|
@@ -201,6 +203,35 @@ const campaignNotYetOpen = computed(() => {
|
|
|
201
203
|
return !!start && new Date(start).getTime() > Date.now()
|
|
202
204
|
})
|
|
203
205
|
|
|
206
|
+
// Personal "notify me when this opens" toggle — distinct from the global,
|
|
207
|
+
// one-time key_campaigns alert opt-in (enableKeyCampaignNotifications()).
|
|
208
|
+
// Most useful while campaignNotYetOpen, since that's the only case where
|
|
209
|
+
// KeyCampaignOpenedNotification will ever actually fire for this campaign.
|
|
210
|
+
const following = ref(!!campaign.value?.is_following)
|
|
211
|
+
const followBusy = ref(false)
|
|
212
|
+
|
|
213
|
+
async function toggleFollow() {
|
|
214
|
+
if (!currentUser) {
|
|
215
|
+
return navigateTo(`${loginUrl}?redirect_to=${encodeURIComponent(route.fullPath)}`, { external: true })
|
|
216
|
+
}
|
|
217
|
+
if (!campaign.value?.id || followBusy.value) return
|
|
218
|
+
|
|
219
|
+
followBusy.value = true
|
|
220
|
+
const wasFollowing = following.value
|
|
221
|
+
following.value = !wasFollowing
|
|
222
|
+
try {
|
|
223
|
+
if (wasFollowing) {
|
|
224
|
+
await unfollowCampaign(campaign.value.id)
|
|
225
|
+
} else {
|
|
226
|
+
await followCampaign(campaign.value.id)
|
|
227
|
+
}
|
|
228
|
+
} catch {
|
|
229
|
+
following.value = wasFollowing
|
|
230
|
+
} finally {
|
|
231
|
+
followBusy.value = false
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
204
235
|
let countdownInterval: ReturnType<typeof setInterval> | null = null
|
|
205
236
|
|
|
206
237
|
const updateCountdown = () => {
|
|
@@ -827,6 +858,18 @@ onMounted(async () => {
|
|
|
827
858
|
</div>
|
|
828
859
|
</div>
|
|
829
860
|
|
|
861
|
+
<button
|
|
862
|
+
v-if="campaignNotYetOpen"
|
|
863
|
+
type="button"
|
|
864
|
+
class="follow-btn"
|
|
865
|
+
:class="{ following }"
|
|
866
|
+
:disabled="followBusy"
|
|
867
|
+
@click="toggleFollow"
|
|
868
|
+
>
|
|
869
|
+
<MGIcon :icon="following ? 'check' : 'bell'" />
|
|
870
|
+
{{ following ? $t("keys.campaigns.campaign.following") : $t("keys.campaigns.campaign.follow_campaign") }}
|
|
871
|
+
</button>
|
|
872
|
+
|
|
830
873
|
<div class="requirements">
|
|
831
874
|
{{ $t("keys.campaigns.campaign.requirements") }}
|
|
832
875
|
<div class="tags">
|
|
@@ -938,7 +981,7 @@ onMounted(async () => {
|
|
|
938
981
|
</div>
|
|
939
982
|
<div class="texts">
|
|
940
983
|
{{ campaign?.company || "" }}
|
|
941
|
-
<div class="small">{{
|
|
984
|
+
<div v-if="campaign?.company_type" class="small">{{ campaign.company_type }}</div>
|
|
942
985
|
</div>
|
|
943
986
|
</div>
|
|
944
987
|
<div class="badge-tag" v-if="campaign?.email">
|
|
@@ -1364,6 +1407,31 @@ onMounted(async () => {
|
|
|
1364
1407
|
}
|
|
1365
1408
|
}
|
|
1366
1409
|
|
|
1410
|
+
.follow-btn {
|
|
1411
|
+
display: flex;
|
|
1412
|
+
align-items: center;
|
|
1413
|
+
justify-content: center;
|
|
1414
|
+
gap: 8px;
|
|
1415
|
+
width: 100%;
|
|
1416
|
+
padding: 10px;
|
|
1417
|
+
border: 1px solid var(--key-accent, var(--primary, #D297FF));
|
|
1418
|
+
background: transparent;
|
|
1419
|
+
color: var(--key-accent, var(--primary, #D297FF));
|
|
1420
|
+
font-size: 13px;
|
|
1421
|
+
font-weight: 600;
|
|
1422
|
+
font-family: inherit;
|
|
1423
|
+
cursor: pointer;
|
|
1424
|
+
transition: background-color 0.15s, opacity 0.15s;
|
|
1425
|
+
|
|
1426
|
+
&:hover:not(:disabled) { background-color: rgba(210, 151, 255, 0.1); }
|
|
1427
|
+
&:disabled { opacity: 0.6; cursor: not-allowed; }
|
|
1428
|
+
|
|
1429
|
+
&.following {
|
|
1430
|
+
background-color: var(--key-accent, var(--primary, #D297FF));
|
|
1431
|
+
color: var(--body-bg, #101012);
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1367
1435
|
.requirements {
|
|
1368
1436
|
display: flex;
|
|
1369
1437
|
flex-direction: column;
|
|
@@ -306,7 +306,9 @@ export const fetchCampaignBySlug = async (slug: string) => {
|
|
|
306
306
|
request_status: k.request_user_status,
|
|
307
307
|
end: k.end_date,
|
|
308
308
|
start: k.start_date,
|
|
309
|
+
is_following: k.is_following ?? false,
|
|
309
310
|
company: k.company?.name,
|
|
311
|
+
company_type: k.company?.company_type ?? null,
|
|
310
312
|
email: k.company?.email,
|
|
311
313
|
twitter: k.company?.twitter,
|
|
312
314
|
logo: k.company?.thumbnail_url,
|
|
@@ -448,6 +450,20 @@ export const fetchKeyActions = (keyId: number) => {
|
|
|
448
450
|
return authClient.get(`/public/keys/${keyId}/actions`)
|
|
449
451
|
}
|
|
450
452
|
|
|
453
|
+
/**
|
|
454
|
+
* Follow/unfollow a specific campaign — a personal reminder distinct from
|
|
455
|
+
* enableKeyCampaignNotifications() above (a one-time global opt-in to every
|
|
456
|
+
* eligible campaign). Most useful before a campaign with a future start
|
|
457
|
+
* date has opened: the user gets notified the moment it does.
|
|
458
|
+
*/
|
|
459
|
+
export const followCampaign = (keyId: number) => {
|
|
460
|
+
return authClient.post(`/public/keys/${keyId}/follow`)
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
export const unfollowCampaign = (keyId: number) => {
|
|
464
|
+
return authClient.delete(`/public/keys/${keyId}/follow`)
|
|
465
|
+
}
|
|
466
|
+
|
|
451
467
|
/**
|
|
452
468
|
* Submit a content material for a key request.
|
|
453
469
|
*/
|