@mundogamernetwork/shared-ui 1.1.81 → 1.1.83
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 +12 -2
- package/locales/en.json +12 -2
- package/locales/pt-BR.json +12 -2
- package/locales/ro.json +12 -2
- package/package.json +1 -1
- package/pages/key-campaigns/[slug].vue +138 -1
- package/pages/key-campaigns/redeem-key-approved.vue +214 -125
- package/pages/key-campaigns/redeem-key.vue +4 -4
- package/services/gamesService.ts +8 -0
package/locales/de.json
CHANGED
|
@@ -135,7 +135,8 @@
|
|
|
135
135
|
"no_data": "Campaign not found",
|
|
136
136
|
"title": "Kampagne",
|
|
137
137
|
"about": "Über das Spiel",
|
|
138
|
-
"screenshot_alt": "Spiel-Screenshot"
|
|
138
|
+
"screenshot_alt": "Spiel-Screenshot",
|
|
139
|
+
"see_all": "alle anzeigen"
|
|
139
140
|
},
|
|
140
141
|
"other_campaigns": "Andere Kampagnen",
|
|
141
142
|
"available": "verfügbar",
|
|
@@ -184,7 +185,16 @@
|
|
|
184
185
|
"status_completed": "Anfrage abgeschlossen",
|
|
185
186
|
"status_refused": "Anfrage abgelehnt",
|
|
186
187
|
"status_cancelled": "Anfrage storniert",
|
|
187
|
-
"refused_reason": "Grund der Ablehnung:"
|
|
188
|
+
"refused_reason": "Grund der Ablehnung:",
|
|
189
|
+
"good": "Super!",
|
|
190
|
+
"good_text": "Du hast einen Code zum Einlösen erhalten",
|
|
191
|
+
"approved_subtitle": "Folge den Schritten und löse deinen Schlüssel ein.",
|
|
192
|
+
"cody_text": "Der Code kann nur einmal eingelöst werden und läuft nach Ende des Angebots ab",
|
|
193
|
+
"redeem_description_1": "Öffne die Website oder App der entsprechenden Plattform (Steam, PlayStation, Xbox usw.) und melde dich bei deinem Konto an.",
|
|
194
|
+
"redeem_description_2": "Gehe zur Option „Code einlösen“, füge den kopierten Code ein und schließe den Vorgang ab.",
|
|
195
|
+
"redeem_description_3": "Der Inhalt wird auf deinem Konto aktiviert.",
|
|
196
|
+
"redeem_at": "Auf {platform} einlösen",
|
|
197
|
+
"no_redeemers": "Noch niemand hat diese Kampagne eingelöst."
|
|
188
198
|
},
|
|
189
199
|
"materials": {
|
|
190
200
|
"title": "Submit material",
|
package/locales/en.json
CHANGED
|
@@ -135,7 +135,8 @@
|
|
|
135
135
|
"no_data": "Campaign not found",
|
|
136
136
|
"title": "Campaign",
|
|
137
137
|
"about": "About the game",
|
|
138
|
-
"screenshot_alt": "Game screenshot"
|
|
138
|
+
"screenshot_alt": "Game screenshot",
|
|
139
|
+
"see_all": "see all"
|
|
139
140
|
},
|
|
140
141
|
"other_campaigns": "Other campaigns",
|
|
141
142
|
"available": "available",
|
|
@@ -184,7 +185,16 @@
|
|
|
184
185
|
"status_completed": "Request completed",
|
|
185
186
|
"status_refused": "Request refused",
|
|
186
187
|
"status_cancelled": "Request cancelled",
|
|
187
|
-
"refused_reason": "Reason for refusal:"
|
|
188
|
+
"refused_reason": "Reason for refusal:",
|
|
189
|
+
"good": "Nice!",
|
|
190
|
+
"good_text": "You received a code to redeem",
|
|
191
|
+
"approved_subtitle": "Follow the steps and redeem your key.",
|
|
192
|
+
"cody_text": "The code can only be redeemed once and expires after the offer ends",
|
|
193
|
+
"redeem_description_1": "Open the website or app of the corresponding platform (Steam, PlayStation, Xbox, etc.) and log in to your account.",
|
|
194
|
+
"redeem_description_2": "Go to the 'Redeem code' option, paste the copied code, and complete the process.",
|
|
195
|
+
"redeem_description_3": "The content will be activated on your account.",
|
|
196
|
+
"redeem_at": "Redeem on {platform}",
|
|
197
|
+
"no_redeemers": "No one has redeemed this campaign yet."
|
|
188
198
|
},
|
|
189
199
|
"materials": {
|
|
190
200
|
"title": "Submit material",
|
package/locales/pt-BR.json
CHANGED
|
@@ -135,7 +135,8 @@
|
|
|
135
135
|
"no_data": "Campaign not found",
|
|
136
136
|
"title": "Campanha",
|
|
137
137
|
"about": "Sobre o jogo",
|
|
138
|
-
"screenshot_alt": "Captura de tela do jogo"
|
|
138
|
+
"screenshot_alt": "Captura de tela do jogo",
|
|
139
|
+
"see_all": "ver todos"
|
|
139
140
|
},
|
|
140
141
|
"other_campaigns": "Outras campanhas",
|
|
141
142
|
"available": "disponível",
|
|
@@ -184,7 +185,16 @@
|
|
|
184
185
|
"status_completed": "Solicitação concluída",
|
|
185
186
|
"status_refused": "Solicitação recusada",
|
|
186
187
|
"status_cancelled": "Solicitação cancelada",
|
|
187
|
-
"refused_reason": "Motivo da recusa:"
|
|
188
|
+
"refused_reason": "Motivo da recusa:",
|
|
189
|
+
"good": "Boa!",
|
|
190
|
+
"good_text": "Você recebeu um código para resgatar",
|
|
191
|
+
"approved_subtitle": "Siga as etapas e resgate sua chave.",
|
|
192
|
+
"cody_text": "O código só pode ser resgatado uma vez e expira após o término da oferta",
|
|
193
|
+
"redeem_description_1": "Abra o site ou app da plataforma correspondente (Steam, PlayStation, Xbox, etc.) e faça login na sua conta.",
|
|
194
|
+
"redeem_description_2": " Vá até a opção “Resgatar código”, cole o código copiado e finalize.",
|
|
195
|
+
"redeem_description_3": "O conteúdo será ativado na sua conta.",
|
|
196
|
+
"redeem_at": "Resgatar em {platform}",
|
|
197
|
+
"no_redeemers": "Nenhum criador resgatou esta campanha ainda."
|
|
188
198
|
},
|
|
189
199
|
"materials": {
|
|
190
200
|
"title": "Submit material",
|
package/locales/ro.json
CHANGED
|
@@ -135,7 +135,8 @@
|
|
|
135
135
|
"no_data": "Campaign not found",
|
|
136
136
|
"title": "Campanie",
|
|
137
137
|
"about": "Despre joc",
|
|
138
|
-
"screenshot_alt": "Captură de ecran a jocului"
|
|
138
|
+
"screenshot_alt": "Captură de ecran a jocului",
|
|
139
|
+
"see_all": "vezi toate"
|
|
139
140
|
},
|
|
140
141
|
"other_campaigns": "Alte campanii",
|
|
141
142
|
"available": "disponibil",
|
|
@@ -184,7 +185,16 @@
|
|
|
184
185
|
"status_completed": "Cerere finalizată",
|
|
185
186
|
"status_refused": "Cerere refuzată",
|
|
186
187
|
"status_cancelled": "Cerere anulată",
|
|
187
|
-
"refused_reason": "Motivul refuzului:"
|
|
188
|
+
"refused_reason": "Motivul refuzului:",
|
|
189
|
+
"good": "Super!",
|
|
190
|
+
"good_text": "Ai primit un cod de revendicare",
|
|
191
|
+
"approved_subtitle": "Urmează pașii și revendică-ți cheia.",
|
|
192
|
+
"cody_text": "Codul poate fi folosit o singură dată și expiră la finalul ofertei",
|
|
193
|
+
"redeem_description_1": "Deschide site-ul sau aplicația platformei corespunzătoare (Steam, PlayStation, Xbox etc.) și autentifică-te în contul tău.",
|
|
194
|
+
"redeem_description_2": "Accesează opțiunea „Redeem code”, lipește codul copiat și finalizează procesul.",
|
|
195
|
+
"redeem_description_3": "Conținutul va fi activat în contul tău.",
|
|
196
|
+
"redeem_at": "Revendică pe {platform}",
|
|
197
|
+
"no_redeemers": "Nimeni nu a revendicat această campanie încă."
|
|
188
198
|
},
|
|
189
199
|
"materials": {
|
|
190
200
|
"title": "Submit material",
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
revealKey,
|
|
11
11
|
requestKey,
|
|
12
12
|
} from "../../services/campaignService"
|
|
13
|
-
import { fetchDetailGameImage } from "../../services/gamesService"
|
|
13
|
+
import { fetchDetailGame, fetchDetailGameImage } from "../../services/gamesService"
|
|
14
14
|
|
|
15
15
|
// Injected by each front — provide in app.vue / a plugin
|
|
16
16
|
const mgPlatform = inject<string>("mgPlatform", "MGTV")
|
|
@@ -136,6 +136,20 @@ const { data: gameDetailsImages } = await useAsyncData(
|
|
|
136
136
|
{ watch: [campaign] },
|
|
137
137
|
)
|
|
138
138
|
|
|
139
|
+
const { data: gameDetails } = await useAsyncData(
|
|
140
|
+
`campaign-game-detail-${slug}`,
|
|
141
|
+
async () => {
|
|
142
|
+
if (!campaign.value?.game_slug) return null
|
|
143
|
+
try {
|
|
144
|
+
const response = await fetchDetailGame(locale.value, campaign.value.game_slug)
|
|
145
|
+
return response.data.data || null
|
|
146
|
+
} catch {
|
|
147
|
+
return null
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
{ watch: [campaign] },
|
|
151
|
+
)
|
|
152
|
+
|
|
139
153
|
const showVideoModal = ref(false)
|
|
140
154
|
const selectedVideoUrl = ref("")
|
|
141
155
|
const showImageModal = ref(false)
|
|
@@ -600,6 +614,17 @@ onMounted(async () => {
|
|
|
600
614
|
{{ b }}
|
|
601
615
|
</div>
|
|
602
616
|
</div>
|
|
617
|
+
|
|
618
|
+
<div class="tags-items" v-if="gameDetails?.platforms?.length">
|
|
619
|
+
<div class="tag" v-for="platform in gameDetails.platforms" :key="platform.id">
|
|
620
|
+
{{ platform.name }}
|
|
621
|
+
</div>
|
|
622
|
+
</div>
|
|
623
|
+
<div class="tags-items" v-if="gameDetails?.genres?.length">
|
|
624
|
+
<div class="tag" v-for="genre in gameDetails.genres" :key="genre.id">
|
|
625
|
+
{{ genre.localized_name }}
|
|
626
|
+
</div>
|
|
627
|
+
</div>
|
|
603
628
|
</div>
|
|
604
629
|
|
|
605
630
|
<!-- Cover when no game details -->
|
|
@@ -804,6 +829,36 @@ onMounted(async () => {
|
|
|
804
829
|
<span>+{{ redeemedUsers?.total ?? 0 }}</span>
|
|
805
830
|
{{ $t("keys.campaigns.creators") }}
|
|
806
831
|
</div>
|
|
832
|
+
<div class="see" v-if="(redeemedUsers?.users?.length ?? 0) > 0" @click="showUsersModal = true">
|
|
833
|
+
{{ $t("keys.campaigns.campaign.see_all") }}
|
|
834
|
+
</div>
|
|
835
|
+
</div>
|
|
836
|
+
</div>
|
|
837
|
+
|
|
838
|
+
<div class="users-modal" v-if="showUsersModal" @click.self="showUsersModal = false">
|
|
839
|
+
<div class="users-modal-content">
|
|
840
|
+
<div class="users-modal-header">
|
|
841
|
+
<span>{{ $t("keys.campaigns.campaign.who_redeem") }}</span>
|
|
842
|
+
<button class="close-button" @click="showUsersModal = false">
|
|
843
|
+
<MGIcon size="1x" icon="close" />
|
|
844
|
+
</button>
|
|
845
|
+
</div>
|
|
846
|
+
<div class="users-modal-body">
|
|
847
|
+
<div
|
|
848
|
+
v-if="!redeemedUsers?.users?.length"
|
|
849
|
+
class="users-modal-empty"
|
|
850
|
+
>
|
|
851
|
+
{{ $t("keys.campaigns.no_redeemers") }}
|
|
852
|
+
</div>
|
|
853
|
+
<div v-for="(u, index) in redeemedUsers?.users" :key="index" class="users-modal-row">
|
|
854
|
+
<img
|
|
855
|
+
:src="u.avatar_url || '/imgs/avatar-default.jpg'"
|
|
856
|
+
:alt="u.nickname"
|
|
857
|
+
@error="(e: Event) => { const t = e.target as HTMLImageElement; if (t && t.src !== '/imgs/avatar-default.jpg') t.src = '/imgs/avatar-default.jpg' }"
|
|
858
|
+
/>
|
|
859
|
+
<span>{{ u.nickname || `${u.first_name || ''} ${u.last_name || ''}`.trim() }}</span>
|
|
860
|
+
</div>
|
|
861
|
+
</div>
|
|
807
862
|
</div>
|
|
808
863
|
</div>
|
|
809
864
|
|
|
@@ -1008,6 +1063,24 @@ onMounted(async () => {
|
|
|
1008
1063
|
i { font-size: 13px; }
|
|
1009
1064
|
}
|
|
1010
1065
|
}
|
|
1066
|
+
|
|
1067
|
+
.tags-items {
|
|
1068
|
+
display: flex;
|
|
1069
|
+
gap: 4px;
|
|
1070
|
+
flex-flow: wrap;
|
|
1071
|
+
|
|
1072
|
+
.tag {
|
|
1073
|
+
height: 32px;
|
|
1074
|
+
display: flex;
|
|
1075
|
+
font-size: 12px;
|
|
1076
|
+
color: var(--secondary-info-fg);
|
|
1077
|
+
font-weight: 400;
|
|
1078
|
+
background-color: var(--button-secondary-default-bg);
|
|
1079
|
+
justify-content: center;
|
|
1080
|
+
padding: 12px;
|
|
1081
|
+
align-items: center;
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1011
1084
|
}
|
|
1012
1085
|
|
|
1013
1086
|
.cards {
|
|
@@ -1306,6 +1379,70 @@ onMounted(async () => {
|
|
|
1306
1379
|
width: -webkit-fill-available;
|
|
1307
1380
|
span { font-size: 16px; color: var(--key-accent, var(--primary, var(--key-accent, var(--primary, #D297FF)))); font-weight: 600; }
|
|
1308
1381
|
}
|
|
1382
|
+
|
|
1383
|
+
.see {
|
|
1384
|
+
font-size: 12px;
|
|
1385
|
+
color: var(--key-accent, var(--primary, #D297FF));
|
|
1386
|
+
cursor: pointer;
|
|
1387
|
+
text-decoration: underline;
|
|
1388
|
+
white-space: nowrap;
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
.users-modal {
|
|
1393
|
+
position: fixed;
|
|
1394
|
+
inset: 0;
|
|
1395
|
+
z-index: 1000;
|
|
1396
|
+
display: flex;
|
|
1397
|
+
align-items: center;
|
|
1398
|
+
justify-content: center;
|
|
1399
|
+
background: var(--overlay-dark-strong, rgba(0, 0, 0, 0.75));
|
|
1400
|
+
|
|
1401
|
+
.users-modal-content {
|
|
1402
|
+
width: 100%;
|
|
1403
|
+
max-width: 360px;
|
|
1404
|
+
max-height: 70vh;
|
|
1405
|
+
background: var(--button-secondary-default-bg);
|
|
1406
|
+
display: flex;
|
|
1407
|
+
flex-direction: column;
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1410
|
+
.users-modal-header {
|
|
1411
|
+
display: flex;
|
|
1412
|
+
align-items: center;
|
|
1413
|
+
justify-content: space-between;
|
|
1414
|
+
padding: 16px;
|
|
1415
|
+
font-size: 14px;
|
|
1416
|
+
font-weight: 600;
|
|
1417
|
+
color: var(--card-article-title);
|
|
1418
|
+
border-bottom: 1px solid var(--bg-app-badge);
|
|
1419
|
+
|
|
1420
|
+
.close-button { background: transparent; border: none; color: var(--secondary-info-fg); cursor: pointer; }
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
.users-modal-body {
|
|
1424
|
+
overflow-y: auto;
|
|
1425
|
+
padding: 8px 16px;
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
.users-modal-empty {
|
|
1429
|
+
padding: 24px 0;
|
|
1430
|
+
text-align: center;
|
|
1431
|
+
font-size: 13px;
|
|
1432
|
+
color: var(--secondary-info-fg);
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
.users-modal-row {
|
|
1436
|
+
display: flex;
|
|
1437
|
+
align-items: center;
|
|
1438
|
+
gap: 10px;
|
|
1439
|
+
padding: 10px 0;
|
|
1440
|
+
border-bottom: 1px solid var(--bg-app-badge);
|
|
1441
|
+
&:last-child { border-bottom: none; }
|
|
1442
|
+
|
|
1443
|
+
img { width: 36px; height: 36px; border-radius: 0; }
|
|
1444
|
+
span { font-size: 13px; color: var(--card-article-title); }
|
|
1445
|
+
}
|
|
1309
1446
|
}
|
|
1310
1447
|
|
|
1311
1448
|
.company {
|
|
@@ -20,6 +20,31 @@ const keyCode = ref<string | null>(null)
|
|
|
20
20
|
const error = ref("")
|
|
21
21
|
const requestData = ref<any>(null)
|
|
22
22
|
const copied = ref(false)
|
|
23
|
+
const platform = ref("")
|
|
24
|
+
|
|
25
|
+
// Maps a platform name to its official key-activation page.
|
|
26
|
+
const REDEEM_URLS: Record<string, string> = {
|
|
27
|
+
steam: "https://store.steampowered.com/account/registerkey",
|
|
28
|
+
playstation: "https://store.playstation.com/redeem",
|
|
29
|
+
"playstation 4": "https://store.playstation.com/redeem",
|
|
30
|
+
"playstation 5": "https://store.playstation.com/redeem",
|
|
31
|
+
xbox: "https://redeem.microsoft.com",
|
|
32
|
+
"xbox one": "https://redeem.microsoft.com",
|
|
33
|
+
"xbox series x/s": "https://redeem.microsoft.com",
|
|
34
|
+
"pc (microsoft windows)": "https://store.steampowered.com/account/registerkey",
|
|
35
|
+
epic: "https://store.epicgames.com/redeem",
|
|
36
|
+
"epic games": "https://store.epicgames.com/redeem",
|
|
37
|
+
gog: "https://www.gog.com/redeem",
|
|
38
|
+
nintendo: "https://ecommerce.nintendo.com/redeem",
|
|
39
|
+
"nintendo switch": "https://ecommerce.nintendo.com/redeem",
|
|
40
|
+
"google stadia": "https://stadia.google.com/redeem",
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const redeemUrl = computed(() => {
|
|
44
|
+
const key = (platform.value || "").trim().toLowerCase()
|
|
45
|
+
if (!key) return ""
|
|
46
|
+
return REDEEM_URLS[key] || ""
|
|
47
|
+
})
|
|
23
48
|
|
|
24
49
|
onMounted(async () => {
|
|
25
50
|
if (!currentUser) {
|
|
@@ -48,6 +73,7 @@ async function reveal() {
|
|
|
48
73
|
const res = await revealKey(requestId)
|
|
49
74
|
const data = res?.data?.data || res?.data || null
|
|
50
75
|
keyCode.value = data?.key || data?.code || data?.value || null
|
|
76
|
+
platform.value = data?.platform || data?.platforms?.[0]?.name || ""
|
|
51
77
|
if (!keyCode.value) {
|
|
52
78
|
error.value = $i18n.t("keys.campaigns.error_reveal")
|
|
53
79
|
}
|
|
@@ -103,49 +129,78 @@ function goBack() {
|
|
|
103
129
|
|
|
104
130
|
<div v-else class="content">
|
|
105
131
|
<div class="title-bar">
|
|
106
|
-
<
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
<
|
|
110
|
-
</
|
|
132
|
+
<h3>
|
|
133
|
+
<span class="accent-text">{{ $t("keys.campaigns.good") }}</span>
|
|
134
|
+
{{ $t("keys.campaigns.good_text") }}
|
|
135
|
+
<span class="accent-text">{{ currentUser?.nickname || currentUser?.name }}</span>
|
|
136
|
+
</h3>
|
|
137
|
+
<p class="description">{{ $t("keys.campaigns.approved_subtitle") }}</p>
|
|
111
138
|
</div>
|
|
112
139
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
140
|
+
<div class="cards">
|
|
141
|
+
<div class="side">
|
|
142
|
+
<div class="code-list">
|
|
143
|
+
<div class="code">
|
|
144
|
+
<div class="number">1</div>
|
|
145
|
+
<div class="texts">
|
|
146
|
+
<div class="code-box" v-if="!keyCode">
|
|
147
|
+
<input type="text" value="••••••••••••••••" readonly class="code-masked" />
|
|
148
|
+
<button class="btn" :class="{ disabled: revealing }" :disabled="revealing" @click="reveal">
|
|
149
|
+
{{ revealing ? $t("keys.campaigns.revealing") : $t("keys.campaigns.status_key.reveal_key") }}
|
|
150
|
+
</button>
|
|
151
|
+
</div>
|
|
152
|
+
|
|
153
|
+
<div class="code-box" v-else>
|
|
154
|
+
<input type="text" :value="keyCode" readonly class="code-value" />
|
|
155
|
+
<button class="btn" @click="copyCode">
|
|
156
|
+
<MGIcon :icon="copied ? 'check' : 'copy'" size="1x" />
|
|
157
|
+
{{ copied ? $t("keys.campaigns.copied") : $t("keys.campaigns.copy") }}
|
|
158
|
+
</button>
|
|
159
|
+
</div>
|
|
160
|
+
|
|
161
|
+
<div v-if="error" class="req-error">{{ error }}</div>
|
|
162
|
+
|
|
163
|
+
<div class="info">
|
|
164
|
+
<MGIcon size="1x" icon="version" />
|
|
165
|
+
{{ $t("keys.campaigns.cody_text") }}
|
|
166
|
+
</div>
|
|
167
|
+
</div>
|
|
168
|
+
</div>
|
|
169
|
+
|
|
170
|
+
<div class="code">
|
|
171
|
+
<div class="number">2</div>
|
|
172
|
+
<div class="texts">
|
|
173
|
+
<div class="description">{{ $t("keys.campaigns.redeem_description_1") }}</div>
|
|
174
|
+
<a
|
|
175
|
+
v-if="keyCode && redeemUrl"
|
|
176
|
+
:href="redeemUrl"
|
|
177
|
+
target="_blank"
|
|
178
|
+
rel="noopener"
|
|
179
|
+
class="btn redeem-link"
|
|
180
|
+
>
|
|
181
|
+
{{ $t("keys.campaigns.redeem_at", { platform }) }}
|
|
182
|
+
</a>
|
|
183
|
+
</div>
|
|
184
|
+
</div>
|
|
185
|
+
|
|
186
|
+
<div class="code">
|
|
187
|
+
<div class="number">3</div>
|
|
188
|
+
<div class="texts">
|
|
189
|
+
<div class="description">
|
|
190
|
+
{{ $t("keys.campaigns.redeem_description_2") }}
|
|
191
|
+
<br />
|
|
192
|
+
{{ $t("keys.campaigns.redeem_description_3") }}
|
|
193
|
+
</div>
|
|
194
|
+
</div>
|
|
195
|
+
</div>
|
|
196
|
+
</div>
|
|
136
197
|
</div>
|
|
137
|
-
<p class="redeem-info">{{ $t("keys.campaigns.redeem_on_platform") }}</p>
|
|
138
|
-
</div>
|
|
139
198
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
</div>
|
|
146
|
-
<div class="info-row" v-if="requestData.key?.name">
|
|
147
|
-
<span class="info-label">{{ $t("keys.campaigns.campaign.title") }}</span>
|
|
148
|
-
<span class="info-val">{{ requestData.key.name }}</span>
|
|
199
|
+
<div class="side-border">
|
|
200
|
+
<div class="title">{{ requestData?.key?.name }}</div>
|
|
201
|
+
<div class="imagem" v-if="requestData?.key?.cover_original_src">
|
|
202
|
+
<img :src="requestData.key.cover_original_src" :alt="requestData.key.name" />
|
|
203
|
+
</div>
|
|
149
204
|
</div>
|
|
150
205
|
</div>
|
|
151
206
|
</div>
|
|
@@ -196,119 +251,153 @@ function goBack() {
|
|
|
196
251
|
& + & { margin-top: 8px; }
|
|
197
252
|
}
|
|
198
253
|
|
|
199
|
-
.content { display: flex; flex-direction: column; gap:
|
|
254
|
+
.content { display: flex; flex-direction: column; gap: 42px; }
|
|
200
255
|
|
|
201
256
|
.title-bar {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
257
|
+
h3 {
|
|
258
|
+
font-size: 24px;
|
|
259
|
+
font-weight: 700;
|
|
260
|
+
color: var(--card-article-title);
|
|
261
|
+
margin: 0 0 8px;
|
|
262
|
+
}
|
|
263
|
+
.accent-text { color: var(--key-accent, var(--primary, #D297FF)); }
|
|
264
|
+
.description { font-size: 14px; color: var(--secondary-info-fg); margin: 0; }
|
|
208
265
|
}
|
|
209
266
|
|
|
210
|
-
.
|
|
267
|
+
.cards {
|
|
211
268
|
display: flex;
|
|
212
|
-
|
|
213
|
-
gap:
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
border: 1px solid var(--button-secondary-default-bg);
|
|
269
|
+
align-items: flex-start;
|
|
270
|
+
gap: 84px;
|
|
271
|
+
width: 100%;
|
|
272
|
+
justify-content: space-between;
|
|
217
273
|
|
|
218
|
-
|
|
274
|
+
@media (max-width: 767px) {
|
|
275
|
+
flex-direction: column;
|
|
276
|
+
gap: 32px;
|
|
277
|
+
}
|
|
219
278
|
}
|
|
220
279
|
|
|
221
|
-
.
|
|
280
|
+
.side {
|
|
222
281
|
display: flex;
|
|
223
282
|
flex-direction: column;
|
|
224
|
-
gap:
|
|
225
|
-
padding: 24px;
|
|
226
|
-
background: var(--bg-app-badge);
|
|
227
|
-
border: 1px solid var(--key-accent, var(--primary, var(--key-accent, var(--primary, #D297FF))));
|
|
283
|
+
gap: 42px;
|
|
228
284
|
}
|
|
229
285
|
|
|
230
|
-
.
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
letter-spacing: 0.5px;
|
|
235
|
-
color: var(--secondary-info-fg);
|
|
286
|
+
.code-list {
|
|
287
|
+
display: flex;
|
|
288
|
+
flex-direction: column;
|
|
289
|
+
gap: 42px;
|
|
236
290
|
}
|
|
237
291
|
|
|
238
|
-
.
|
|
292
|
+
.code {
|
|
239
293
|
display: flex;
|
|
240
294
|
align-items: center;
|
|
241
|
-
gap:
|
|
242
|
-
|
|
243
|
-
|
|
295
|
+
gap: 24px;
|
|
296
|
+
|
|
297
|
+
.number {
|
|
298
|
+
display: flex;
|
|
299
|
+
width: 80px;
|
|
300
|
+
height: 80px;
|
|
301
|
+
padding: 24px;
|
|
302
|
+
flex-direction: column;
|
|
303
|
+
justify-content: center;
|
|
304
|
+
align-items: center;
|
|
305
|
+
background-color: var(--button-secondary-default-bg);
|
|
306
|
+
color: var(--key-accent, var(--primary, #D297FF));
|
|
307
|
+
text-align: center;
|
|
308
|
+
font-size: 28px;
|
|
309
|
+
font-weight: 700;
|
|
310
|
+
flex-shrink: 0;
|
|
311
|
+
}
|
|
244
312
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
color: var(--card-article-title);
|
|
251
|
-
word-break: break-all;
|
|
252
|
-
}
|
|
313
|
+
.texts {
|
|
314
|
+
display: flex;
|
|
315
|
+
flex-direction: column;
|
|
316
|
+
gap: 8px;
|
|
317
|
+
}
|
|
253
318
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
319
|
+
.code-box {
|
|
320
|
+
display: flex;
|
|
321
|
+
align-items: center;
|
|
322
|
+
gap: 6px;
|
|
323
|
+
width: 100%;
|
|
324
|
+
|
|
325
|
+
input {
|
|
326
|
+
display: flex;
|
|
327
|
+
padding: 12px;
|
|
328
|
+
background-color: transparent;
|
|
329
|
+
height: 48px;
|
|
330
|
+
border: 1px solid var(--bg-app-badge);
|
|
331
|
+
width: 100%;
|
|
332
|
+
font-size: 16px;
|
|
333
|
+
color: var(--secondary-info-fg);
|
|
334
|
+
&:focus { border-color: var(--key-accent, var(--primary, #D297FF)); outline: 0; }
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
button {
|
|
338
|
+
background-color: var(--key-accent, var(--primary, #D297FF));
|
|
339
|
+
color: var(--key-accent-ink, #13161C);
|
|
340
|
+
height: 48px;
|
|
341
|
+
padding: 0 16px;
|
|
342
|
+
border: none;
|
|
343
|
+
cursor: pointer;
|
|
344
|
+
white-space: nowrap;
|
|
345
|
+
display: inline-flex;
|
|
346
|
+
align-items: center;
|
|
347
|
+
gap: 6px;
|
|
348
|
+
&.disabled, &:disabled { opacity: 0.45; cursor: not-allowed; }
|
|
349
|
+
}
|
|
350
|
+
}
|
|
268
351
|
|
|
269
|
-
|
|
270
|
-
font-size: 12px;
|
|
271
|
-
color: var(--secondary-info-fg);
|
|
272
|
-
margin: 0;
|
|
273
|
-
}
|
|
352
|
+
.code-masked { letter-spacing: 3px; color: rgba(128, 128, 128, 0.5) !important; }
|
|
274
353
|
|
|
275
|
-
|
|
354
|
+
.info {
|
|
355
|
+
display: flex;
|
|
356
|
+
align-items: flex-end;
|
|
357
|
+
gap: 4px;
|
|
358
|
+
font-size: 12px;
|
|
359
|
+
color: var(--secondary-info-fg);
|
|
360
|
+
svg { color: var(--key-accent, var(--primary, #D297FF)); }
|
|
361
|
+
}
|
|
276
362
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
363
|
+
.description {
|
|
364
|
+
font-size: 12px;
|
|
365
|
+
color: var(--secondary-info-fg);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
.redeem-link {
|
|
369
|
+
display: inline-flex;
|
|
370
|
+
width: fit-content;
|
|
371
|
+
margin-top: 8px;
|
|
372
|
+
padding: 8px 14px;
|
|
373
|
+
background: var(--key-accent, var(--primary, #D297FF));
|
|
374
|
+
color: var(--key-accent-ink, #13161C);
|
|
375
|
+
font-size: 13px;
|
|
376
|
+
text-decoration: none;
|
|
377
|
+
}
|
|
283
378
|
}
|
|
284
379
|
|
|
285
|
-
.
|
|
380
|
+
.side-border {
|
|
286
381
|
display: flex;
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
382
|
+
padding: 18px;
|
|
383
|
+
flex-direction: column;
|
|
384
|
+
gap: 24px;
|
|
385
|
+
flex: 1 0 0;
|
|
386
|
+
border: 1px solid var(--button-secondary-default-bg);
|
|
387
|
+
max-width: 391px;
|
|
290
388
|
|
|
291
|
-
|
|
292
|
-
color: var(--secondary-info-fg);
|
|
293
|
-
min-width: 100px;
|
|
294
|
-
}
|
|
389
|
+
.title { font-size: 14px; color: var(--card-article-title); font-weight: 600; }
|
|
295
390
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
font-weight: 700;
|
|
304
|
-
background: var(--key-accent, var(--primary, var(--key-accent, var(--primary, #D297FF))));
|
|
305
|
-
color: var(--key-accent-ink, #13161C);
|
|
306
|
-
border: none;
|
|
307
|
-
cursor: pointer;
|
|
308
|
-
transition: opacity 0.15s;
|
|
309
|
-
&.disabled, &:disabled { opacity: 0.45; cursor: not-allowed; }
|
|
310
|
-
&:not(.disabled):hover { opacity: 0.85; }
|
|
391
|
+
.imagem {
|
|
392
|
+
width: 100%;
|
|
393
|
+
max-height: 200px;
|
|
394
|
+
overflow: hidden;
|
|
395
|
+
text-align: center;
|
|
396
|
+
img { width: auto; height: 100%; max-width: 100%; }
|
|
397
|
+
}
|
|
311
398
|
}
|
|
399
|
+
|
|
400
|
+
.req-error { font-size: 12px; color: var(--danger, #e53935); margin-top: 4px; }
|
|
312
401
|
}
|
|
313
402
|
|
|
314
403
|
@keyframes pulse {
|
|
@@ -215,7 +215,7 @@ function goBack() {
|
|
|
215
215
|
<label class="label">{{ $t("keys.campaigns.region") }}</label>
|
|
216
216
|
<select v-model.number="selectedRegionId" class="select">
|
|
217
217
|
<option :value="null" disabled>{{ $t("keys.campaigns.select_option") }}</option>
|
|
218
|
-
<option v-for="r in regions" :key="r.id" :value="r.id">{{ r.name }}</option>
|
|
218
|
+
<option v-for="r in regions" :key="r.id" :value="r.id">{{ r.name || r.localized_name }}</option>
|
|
219
219
|
</select>
|
|
220
220
|
</div>
|
|
221
221
|
|
|
@@ -407,9 +407,9 @@ function goBack() {
|
|
|
407
407
|
|
|
408
408
|
.select, .input, .textarea {
|
|
409
409
|
width: 100%;
|
|
410
|
-
background:
|
|
411
|
-
border: 1px solid
|
|
412
|
-
color: var(--
|
|
410
|
+
background-color: transparent;
|
|
411
|
+
border: 1px solid rgba(128, 128, 128, 0.46);
|
|
412
|
+
color: var(--secondary-info-fg);
|
|
413
413
|
font-size: 13px;
|
|
414
414
|
padding: 10px 12px;
|
|
415
415
|
outline: none;
|
package/services/gamesService.ts
CHANGED
|
@@ -44,5 +44,13 @@ export interface GameImage {
|
|
|
44
44
|
url_image_src: string
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
export interface GameDetail {
|
|
48
|
+
platforms?: Array<{ id: number; name: string }>
|
|
49
|
+
genres?: Array<{ id: number; localized_name: string }>
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const fetchDetailGame = (lang: string, slug: string) =>
|
|
53
|
+
client.get<{ data: GameDetail }>(`/${lang}/games/details/${slug}`)
|
|
54
|
+
|
|
47
55
|
export const fetchDetailGameImage = (lang: string, slug: string) =>
|
|
48
56
|
client.get<{ data: GameImage[] }>(`/${lang}/games/details/${slug}/images`)
|