@mundogamernetwork/shared-ui 1.1.83 → 1.1.84
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 +8 -1
- package/locales/en.json +8 -1
- package/locales/pt-BR.json +8 -1
- package/locales/ro.json +8 -1
- package/package.json +1 -1
- package/pages/key-campaigns/[slug].vue +10 -1
- package/pages/key-campaigns/index.vue +8 -1
- package/pages/key-campaigns/redeem-key-approved.vue +61 -29
- package/pages/key-campaigns/redeem-key.vue +19 -7
- package/services/campaignService.ts +3 -0
package/locales/de.json
CHANGED
|
@@ -194,7 +194,14 @@
|
|
|
194
194
|
"redeem_description_2": "Gehe zur Option „Code einlösen“, füge den kopierten Code ein und schließe den Vorgang ab.",
|
|
195
195
|
"redeem_description_3": "Der Inhalt wird auf deinem Konto aktiviert.",
|
|
196
196
|
"redeem_at": "Auf {platform} einlösen",
|
|
197
|
-
"no_redeemers": "Noch niemand hat diese Kampagne eingelöst."
|
|
197
|
+
"no_redeemers": "Noch niemand hat diese Kampagne eingelöst.",
|
|
198
|
+
"required_fields": "Bitte alle Pflichtfelder ausfüllen",
|
|
199
|
+
"plan": "Deckungspläne",
|
|
200
|
+
"plan_placeholder": "Beschreibe deinen Berichterstattungsplan: wo du über das Spiel streamen oder posten wirst, dein Publikum und das geplante Veröffentlichungsdatum",
|
|
201
|
+
"resources_title": "Ressourcen",
|
|
202
|
+
"press_kit_link": "Presse-Kit",
|
|
203
|
+
"review_guideline": "Review-Richtlinie",
|
|
204
|
+
"embargo_date": "Sperrfrist"
|
|
198
205
|
},
|
|
199
206
|
"materials": {
|
|
200
207
|
"title": "Submit material",
|
package/locales/en.json
CHANGED
|
@@ -194,7 +194,14 @@
|
|
|
194
194
|
"redeem_description_2": "Go to the 'Redeem code' option, paste the copied code, and complete the process.",
|
|
195
195
|
"redeem_description_3": "The content will be activated on your account.",
|
|
196
196
|
"redeem_at": "Redeem on {platform}",
|
|
197
|
-
"no_redeemers": "No one has redeemed this campaign yet."
|
|
197
|
+
"no_redeemers": "No one has redeemed this campaign yet.",
|
|
198
|
+
"required_fields": "Please fill in all required fields",
|
|
199
|
+
"plan": "Coverage plans",
|
|
200
|
+
"plan_placeholder": "Describe your coverage plan: where you will stream or post about this game, your audience, and expected publish date",
|
|
201
|
+
"resources_title": "Resources",
|
|
202
|
+
"press_kit_link": "Press Kit",
|
|
203
|
+
"review_guideline": "Review guideline",
|
|
204
|
+
"embargo_date": "Embargo date"
|
|
198
205
|
},
|
|
199
206
|
"materials": {
|
|
200
207
|
"title": "Submit material",
|
package/locales/pt-BR.json
CHANGED
|
@@ -194,7 +194,14 @@
|
|
|
194
194
|
"redeem_description_2": " Vá até a opção “Resgatar código”, cole o código copiado e finalize.",
|
|
195
195
|
"redeem_description_3": "O conteúdo será ativado na sua conta.",
|
|
196
196
|
"redeem_at": "Resgatar em {platform}",
|
|
197
|
-
"no_redeemers": "Nenhum criador resgatou esta campanha ainda."
|
|
197
|
+
"no_redeemers": "Nenhum criador resgatou esta campanha ainda.",
|
|
198
|
+
"required_fields": "Por favor, preencha todos os campos obrigatórios",
|
|
199
|
+
"plan": " Planos de cobertura",
|
|
200
|
+
"plan_placeholder": "Descreva seu plano de cobertura: onde vai fazer stream ou publicar sobre o jogo, seu público e a data prevista de publicação",
|
|
201
|
+
"resources_title": "Recursos",
|
|
202
|
+
"press_kit_link": "Press Kit",
|
|
203
|
+
"review_guideline": "Diretriz de review",
|
|
204
|
+
"embargo_date": "Data de embargo"
|
|
198
205
|
},
|
|
199
206
|
"materials": {
|
|
200
207
|
"title": "Submit material",
|
package/locales/ro.json
CHANGED
|
@@ -194,7 +194,14 @@
|
|
|
194
194
|
"redeem_description_2": "Accesează opțiunea „Redeem code”, lipește codul copiat și finalizează procesul.",
|
|
195
195
|
"redeem_description_3": "Conținutul va fi activat în contul tău.",
|
|
196
196
|
"redeem_at": "Revendică pe {platform}",
|
|
197
|
-
"no_redeemers": "Nimeni nu a revendicat această campanie încă."
|
|
197
|
+
"no_redeemers": "Nimeni nu a revendicat această campanie încă.",
|
|
198
|
+
"required_fields": "Vă rugăm să completați toate câmpurile obligatorii",
|
|
199
|
+
"plan": "Planuri de acoperire",
|
|
200
|
+
"plan_placeholder": "Descrie planul tău de acoperire: unde vei face stream sau vei posta despre joc, publicul tău și data estimată de publicare",
|
|
201
|
+
"resources_title": "Resurse",
|
|
202
|
+
"press_kit_link": "Press Kit",
|
|
203
|
+
"review_guideline": "Ghid de recenzie",
|
|
204
|
+
"embargo_date": "Data embargo"
|
|
198
205
|
},
|
|
199
206
|
"materials": {
|
|
200
207
|
"title": "Submit material",
|
package/package.json
CHANGED
|
@@ -604,7 +604,9 @@ onMounted(async () => {
|
|
|
604
604
|
</div>
|
|
605
605
|
</div>
|
|
606
606
|
|
|
607
|
-
<div class="
|
|
607
|
+
<div v-if="!campaign" class="state error">{{ $t("keys.campaigns.error_loading") }}</div>
|
|
608
|
+
|
|
609
|
+
<div v-else class="content-key">
|
|
608
610
|
<div class="content-key-header">
|
|
609
611
|
<h4>{{ campaign?.name }}</h4>
|
|
610
612
|
|
|
@@ -1031,6 +1033,13 @@ onMounted(async () => {
|
|
|
1031
1033
|
img { width: 100%; height: 400px; object-fit: cover; object-position: center top; }
|
|
1032
1034
|
}
|
|
1033
1035
|
|
|
1036
|
+
.state.error {
|
|
1037
|
+
padding: 64px 0;
|
|
1038
|
+
text-align: center;
|
|
1039
|
+
font-size: 14px;
|
|
1040
|
+
color: var(--danger, #e53935);
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1034
1043
|
.content-key {
|
|
1035
1044
|
display: flex;
|
|
1036
1045
|
flex-direction: column;
|
|
@@ -267,7 +267,11 @@
|
|
|
267
267
|
</div>
|
|
268
268
|
</div>
|
|
269
269
|
|
|
270
|
-
<div v-if="!loading &&
|
|
270
|
+
<div v-if="!loading && loadError" class="d-flex flex-column align-items-center">
|
|
271
|
+
<div class="no-content"><MGIcon icon="eye-slash" /></div>
|
|
272
|
+
<h4>{{ $t("keys.campaigns.error_loading") }}</h4>
|
|
273
|
+
</div>
|
|
274
|
+
<div v-else-if="!loading && filteredCards.length === 0" class="d-flex flex-column align-items-center">
|
|
271
275
|
<div class="no-content"><MGIcon icon="eye-slash" /></div>
|
|
272
276
|
<h4>{{ $t("keys.campaigns.no_results") }}</h4>
|
|
273
277
|
</div>
|
|
@@ -364,6 +368,7 @@ let slideInterval: ReturnType<typeof setInterval> | null = null
|
|
|
364
368
|
const loading = ref(true)
|
|
365
369
|
const loadingFeatured = ref(true)
|
|
366
370
|
const loadingRequests = ref(false)
|
|
371
|
+
const loadError = ref(false)
|
|
367
372
|
|
|
368
373
|
// ------------------------------------------------------------------
|
|
369
374
|
// Filters
|
|
@@ -556,9 +561,11 @@ async function loadCampaigns(page = 1) {
|
|
|
556
561
|
}
|
|
557
562
|
|
|
558
563
|
currentPage.value = page
|
|
564
|
+
loadError.value = false
|
|
559
565
|
applyUserRequestStatuses()
|
|
560
566
|
} catch {
|
|
561
567
|
hasMoreItems.value = false
|
|
568
|
+
if (page === 1) loadError.value = true
|
|
562
569
|
} finally {
|
|
563
570
|
loading.value = false
|
|
564
571
|
loadingMore.value = false
|
|
@@ -59,6 +59,9 @@ onMounted(async () => {
|
|
|
59
59
|
try {
|
|
60
60
|
const res = await fetchKeyRequestById(requestId)
|
|
61
61
|
requestData.value = res?.data?.data || res?.data || null
|
|
62
|
+
// Platform the user chose at request time — shown as a fallback/preview
|
|
63
|
+
// even before reveal, in case the assigned key item has no platform set.
|
|
64
|
+
platform.value = requestData.value?.platforms?.[0]?.name || ""
|
|
62
65
|
} catch {
|
|
63
66
|
error.value = $i18n.t("keys.campaigns.error_loading")
|
|
64
67
|
} finally {
|
|
@@ -72,8 +75,10 @@ async function reveal() {
|
|
|
72
75
|
try {
|
|
73
76
|
const res = await revealKey(requestId)
|
|
74
77
|
const data = res?.data?.data || res?.data || null
|
|
75
|
-
keyCode.value = data?.
|
|
76
|
-
|
|
78
|
+
keyCode.value = data?.code || (typeof data?.key === "string" ? data.key : null) || data?.value || null
|
|
79
|
+
// Keep the pre-reveal platform (chosen at request time) as fallback if the
|
|
80
|
+
// revealed item has no platform of its own.
|
|
81
|
+
platform.value = data?.platform || data?.platforms?.[0]?.name || platform.value
|
|
77
82
|
if (!keyCode.value) {
|
|
78
83
|
error.value = $i18n.t("keys.campaigns.error_reveal")
|
|
79
84
|
}
|
|
@@ -102,6 +107,13 @@ async function copyCode() {
|
|
|
102
107
|
}
|
|
103
108
|
}
|
|
104
109
|
|
|
110
|
+
function formatDate(dateString: string | null | undefined): string {
|
|
111
|
+
if (!dateString) return "-"
|
|
112
|
+
const date = new Date(dateString)
|
|
113
|
+
if (isNaN(date.getTime())) return "-"
|
|
114
|
+
return new Intl.DateTimeFormat(locale.value, { day: "numeric", month: "long", year: "numeric" }).format(date)
|
|
115
|
+
}
|
|
116
|
+
|
|
105
117
|
function goBack() {
|
|
106
118
|
if (typeof window !== "undefined" && window.history.length > 1) {
|
|
107
119
|
window.history.back()
|
|
@@ -135,6 +147,8 @@ function goBack() {
|
|
|
135
147
|
<span class="accent-text">{{ currentUser?.nickname || currentUser?.name }}</span>
|
|
136
148
|
</h3>
|
|
137
149
|
<p class="description">{{ $t("keys.campaigns.approved_subtitle") }}</p>
|
|
150
|
+
<p v-if="requestData?.key?.name" class="campaign-name">{{ requestData.key.name }}</p>
|
|
151
|
+
<p v-if="platform" class="platform-name">{{ $t("keys.campaigns.platform") }}: {{ platform }}</p>
|
|
138
152
|
</div>
|
|
139
153
|
|
|
140
154
|
<div class="cards">
|
|
@@ -194,12 +208,30 @@ function goBack() {
|
|
|
194
208
|
</div>
|
|
195
209
|
</div>
|
|
196
210
|
</div>
|
|
197
|
-
</div>
|
|
198
211
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
<
|
|
212
|
+
<div class="resources" v-if="requestData?.key?.press_kit_link || requestData?.key?.review_guideline || requestData?.key?.embargo_date">
|
|
213
|
+
<div class="resources-title">{{ $t("keys.campaigns.resources_title") }}</div>
|
|
214
|
+
|
|
215
|
+
<a
|
|
216
|
+
v-if="requestData?.key?.press_kit_link"
|
|
217
|
+
:href="requestData.key.press_kit_link"
|
|
218
|
+
target="_blank"
|
|
219
|
+
rel="noopener"
|
|
220
|
+
class="resource-link"
|
|
221
|
+
>
|
|
222
|
+
<MGIcon size="1x" icon="link" />
|
|
223
|
+
{{ $t("keys.campaigns.press_kit_link") }}
|
|
224
|
+
</a>
|
|
225
|
+
|
|
226
|
+
<div v-if="requestData?.key?.review_guideline" class="resource-item">
|
|
227
|
+
<div class="resource-label">{{ $t("keys.campaigns.review_guideline") }}</div>
|
|
228
|
+
<div class="resource-text">{{ requestData.key.review_guideline }}</div>
|
|
229
|
+
</div>
|
|
230
|
+
|
|
231
|
+
<div v-if="requestData?.key?.embargo_date" class="resource-item">
|
|
232
|
+
<div class="resource-label">{{ $t("keys.campaigns.embargo_date") }}</div>
|
|
233
|
+
<div class="resource-text">{{ formatDate(requestData.key.embargo_date) }}</div>
|
|
234
|
+
</div>
|
|
203
235
|
</div>
|
|
204
236
|
</div>
|
|
205
237
|
</div>
|
|
@@ -262,19 +294,13 @@ function goBack() {
|
|
|
262
294
|
}
|
|
263
295
|
.accent-text { color: var(--key-accent, var(--primary, #D297FF)); }
|
|
264
296
|
.description { font-size: 14px; color: var(--secondary-info-fg); margin: 0; }
|
|
297
|
+
.campaign-name { font-size: 13px; font-weight: 600; color: var(--card-article-title); margin: 4px 0 0; }
|
|
298
|
+
.platform-name { font-size: 12px; color: var(--secondary-info-fg); margin: 2px 0 0; }
|
|
265
299
|
}
|
|
266
300
|
|
|
267
301
|
.cards {
|
|
268
302
|
display: flex;
|
|
269
|
-
align-items: flex-start;
|
|
270
|
-
gap: 84px;
|
|
271
303
|
width: 100%;
|
|
272
|
-
justify-content: space-between;
|
|
273
|
-
|
|
274
|
-
@media (max-width: 767px) {
|
|
275
|
-
flex-direction: column;
|
|
276
|
-
gap: 32px;
|
|
277
|
-
}
|
|
278
304
|
}
|
|
279
305
|
|
|
280
306
|
.side {
|
|
@@ -377,27 +403,33 @@ function goBack() {
|
|
|
377
403
|
}
|
|
378
404
|
}
|
|
379
405
|
|
|
380
|
-
.
|
|
406
|
+
.req-error { font-size: 12px; color: var(--danger, #e53935); margin-top: 4px; }
|
|
407
|
+
|
|
408
|
+
.resources {
|
|
381
409
|
display: flex;
|
|
382
|
-
padding: 18px;
|
|
383
410
|
flex-direction: column;
|
|
384
|
-
gap:
|
|
385
|
-
|
|
411
|
+
gap: 12px;
|
|
412
|
+
padding: 20px;
|
|
413
|
+
background: var(--bg-app-badge);
|
|
386
414
|
border: 1px solid var(--button-secondary-default-bg);
|
|
387
|
-
|
|
415
|
+
}
|
|
388
416
|
|
|
389
|
-
|
|
417
|
+
.resources-title { font-size: 13px; font-weight: 600; color: var(--card-article-title); }
|
|
390
418
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
419
|
+
.resource-link {
|
|
420
|
+
display: inline-flex;
|
|
421
|
+
align-items: center;
|
|
422
|
+
gap: 6px;
|
|
423
|
+
width: fit-content;
|
|
424
|
+
font-size: 13px;
|
|
425
|
+
color: var(--key-accent, var(--primary, #D297FF));
|
|
426
|
+
text-decoration: none;
|
|
427
|
+
&:hover { text-decoration: underline; }
|
|
398
428
|
}
|
|
399
429
|
|
|
400
|
-
.
|
|
430
|
+
.resource-item { display: flex; flex-direction: column; gap: 2px; }
|
|
431
|
+
.resource-label { font-size: 12px; font-weight: 600; color: var(--card-article-title); }
|
|
432
|
+
.resource-text { font-size: 13px; color: var(--secondary-info-fg); }
|
|
401
433
|
}
|
|
402
434
|
|
|
403
435
|
@keyframes pulse {
|
|
@@ -71,9 +71,7 @@ onMounted(async () => {
|
|
|
71
71
|
}
|
|
72
72
|
})
|
|
73
73
|
|
|
74
|
-
const canSubmit = computed(() =>
|
|
75
|
-
!!selectedPlatformId.value && !!selectedRegionId.value && !!quantity.value && !submitting.value,
|
|
76
|
-
)
|
|
74
|
+
const canSubmit = computed(() => !submitting.value)
|
|
77
75
|
|
|
78
76
|
// Collapsible "Required data" box — matches tv's original toggle behavior
|
|
79
77
|
const isBoxOpen = ref(true)
|
|
@@ -104,16 +102,30 @@ const refusedReason = computed(() => campaign.value?.request_admin_notes || "")
|
|
|
104
102
|
|
|
105
103
|
async function submit() {
|
|
106
104
|
if (!canSubmit.value) return
|
|
107
|
-
submitting.value = true
|
|
108
105
|
requestError.value = ""
|
|
106
|
+
if (!selectedPlatformId.value || !selectedRegionId.value || !quantity.value || !description.value?.trim()) {
|
|
107
|
+
requestError.value = $i18n.t("keys.campaigns.required_fields")
|
|
108
|
+
return
|
|
109
|
+
}
|
|
110
|
+
submitting.value = true
|
|
109
111
|
try {
|
|
110
|
-
await requestKey({
|
|
112
|
+
const response = await requestKey({
|
|
111
113
|
key_id: keyId,
|
|
112
114
|
platform_ids: [selectedPlatformId.value],
|
|
113
115
|
region_ids: [selectedRegionId.value],
|
|
114
116
|
description: description.value || "-",
|
|
115
117
|
quantity_keys: Number(quantity.value) || 1,
|
|
116
118
|
})
|
|
119
|
+
const created = response?.data?.data ?? response?.data ?? {}
|
|
120
|
+
// requires_approval=false campaigns (or Pro/Business TV subscribers) get
|
|
121
|
+
// auto-approved by the backend observer synchronously — status 3 already
|
|
122
|
+
// reflects that by the time this response comes back, so skip the
|
|
123
|
+
// "request sent" wait screen and go straight to reveal.
|
|
124
|
+
const autoApproved = created.key_status_request_id === 3
|
|
125
|
+
if (autoApproved && created.id) {
|
|
126
|
+
navigateTo(`/${locale.value}/key-campaigns/redeem-key-approved?requestId=${created.id}`)
|
|
127
|
+
return
|
|
128
|
+
}
|
|
117
129
|
success.value = true
|
|
118
130
|
setTimeout(() => {
|
|
119
131
|
navigateTo(`/${locale.value}/key-campaigns`)
|
|
@@ -233,11 +245,11 @@ function goBack() {
|
|
|
233
245
|
</div>
|
|
234
246
|
|
|
235
247
|
<div class="form-row">
|
|
236
|
-
<label class="label">{{ $t("keys.campaigns.
|
|
248
|
+
<label class="label">{{ $t("keys.campaigns.plan") }}</label>
|
|
237
249
|
<textarea
|
|
238
250
|
v-model="description"
|
|
239
251
|
class="textarea"
|
|
240
|
-
:placeholder="$t('keys.campaigns.
|
|
252
|
+
:placeholder="$t('keys.campaigns.plan_placeholder')"
|
|
241
253
|
rows="3"
|
|
242
254
|
/>
|
|
243
255
|
</div>
|
|
@@ -283,6 +283,9 @@ export const fetchCampaignBySlug = async (slug: string) => {
|
|
|
283
283
|
max_keys_for_user: k.max_keys_for_user ?? 1,
|
|
284
284
|
game_summary: k.game?.summary,
|
|
285
285
|
game_videos: (k.game?.videos || []) as Array<{ external_id: string; name?: string }>,
|
|
286
|
+
press_kit_link: k.press_kit_link ?? null,
|
|
287
|
+
review_guideline: k.review_guideline ?? null,
|
|
288
|
+
embargo_date: k.embargo_date ?? null,
|
|
286
289
|
request_id: k.requests?.[0]?.id,
|
|
287
290
|
request_item_id: k.requests?.[0]?.key_item_id,
|
|
288
291
|
request_admin_notes: k.requests?.[0]?.admin_notes ?? null,
|