@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 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",
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mundogamernetwork/shared-ui",
3
- "version": "1.8.15",
3
+ "version": "1.8.16",
4
4
  "description": "Mundo Gamer Network - Shared UI Layer (Nuxt 3)",
5
5
  "type": "module",
6
6
  "main": "./nuxt.config.ts",
@@ -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">{{ $t("keys.campaigns.campaign.rp_label") }}</div>
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
  */