@mundogamernetwork/shared-ui 1.3.2 → 1.3.6
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/assets/kit/kit-base.css +17 -0
- package/components/MediaKit/MgRateCardBundleEditor.vue +131 -1
- package/components/MediaKit/MgRateCardEditor.vue +133 -0
- package/components/keys/KeyCampaignDashboardCard.vue +21 -15
- package/locales/de.json +2 -2
- package/locales/en.json +1 -1
- package/locales/pt-BR.json +2 -2
- package/locales/ro.json +2 -2
- package/package.json +1 -1
- package/pages/key-campaign/[slug].vue +8 -8
- package/pages/key-campaigns/index.vue +61 -26
- package/pages/key-campaigns/redeem-key.vue +0 -3
- package/pages/presskit/game/[slug].vue +26 -1
- package/services/campaignService.ts +13 -15
package/assets/kit/kit-base.css
CHANGED
|
@@ -34,6 +34,23 @@ body:has(.kit-press) {
|
|
|
34
34
|
color: var(--kit-muted, #8b92a0);
|
|
35
35
|
font-size: 1rem;
|
|
36
36
|
}
|
|
37
|
+
.kit-state--not-found {
|
|
38
|
+
min-height: 100vh;
|
|
39
|
+
justify-content: flex-start;
|
|
40
|
+
padding-top: 15vh;
|
|
41
|
+
width: 100%;
|
|
42
|
+
}
|
|
43
|
+
.kit-state__desc {
|
|
44
|
+
max-width: 420px;
|
|
45
|
+
text-align: center;
|
|
46
|
+
margin: -8px 0 4px;
|
|
47
|
+
font-size: 0.9rem;
|
|
48
|
+
line-height: 1.5;
|
|
49
|
+
}
|
|
50
|
+
.kit-more--not-found {
|
|
51
|
+
width: 100%;
|
|
52
|
+
margin-top: 40px;
|
|
53
|
+
}
|
|
37
54
|
.kit-state h2 {
|
|
38
55
|
font-size: 1.5rem;
|
|
39
56
|
color: var(--kit-text, #f4f6fa);
|
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
|
|
12
12
|
<!-- Bundle Form -->
|
|
13
13
|
<div v-if="showForm" class="bundle-form">
|
|
14
|
+
<div class="visibility-note">
|
|
15
|
+
<MGIcon icon="info" />
|
|
16
|
+
<span>{{ $t("media_kit.bundles.visibility_note") }}</span>
|
|
17
|
+
</div>
|
|
14
18
|
<div class="form-group">
|
|
15
19
|
<label>{{ $t("media_kit.bundles.bundle_name") }}</label>
|
|
16
20
|
<input v-model="form.name" type="text" :placeholder="$t('media_kit.bundles.name_placeholder')" />
|
|
@@ -105,6 +109,20 @@
|
|
|
105
109
|
</div>
|
|
106
110
|
</div>
|
|
107
111
|
|
|
112
|
+
<label class="visibility-checkbox" :class="{ disabled: !isSubscriber }">
|
|
113
|
+
<input
|
|
114
|
+
type="checkbox"
|
|
115
|
+
:checked="showPublicly"
|
|
116
|
+
:disabled="!isSubscriber"
|
|
117
|
+
@change="onToggleVisibility(($event.target as HTMLInputElement).checked)"
|
|
118
|
+
/>
|
|
119
|
+
<span>{{ $t("media_kit.bundles.show_publicly") }}</span>
|
|
120
|
+
<button v-if="!isSubscriber" type="button" class="upgrade-link" @click.prevent="emit('paywall', 'rates')">
|
|
121
|
+
<MGIcon icon="lock" />
|
|
122
|
+
{{ $t("media_kit.editor.upgrade_to_show") }}
|
|
123
|
+
</button>
|
|
124
|
+
</label>
|
|
125
|
+
|
|
108
126
|
<div class="form-actions">
|
|
109
127
|
<button class="btn-cancel" @click="cancelForm">{{ $t("media_kit.editor.cancel") }}</button>
|
|
110
128
|
<button class="btn-save" @click="saveBundle" :disabled="saving || form.rate_card_ids.length < 2">
|
|
@@ -186,19 +204,32 @@ const props = withDefaults(
|
|
|
186
204
|
availableRateCards: RateCard[];
|
|
187
205
|
influencerProInfoId: number;
|
|
188
206
|
isEnabled?: boolean;
|
|
207
|
+
/** Whether the account has an active paid subscription — gates public visibility only, not creation. */
|
|
208
|
+
isSubscriber?: boolean;
|
|
209
|
+
/** Current value of the account-wide "show bundles publicly" setting. */
|
|
210
|
+
showPublicly?: boolean;
|
|
189
211
|
}>(),
|
|
190
212
|
{
|
|
191
213
|
isEnabled: true,
|
|
214
|
+
isSubscriber: false,
|
|
215
|
+
showPublicly: true,
|
|
192
216
|
}
|
|
193
217
|
);
|
|
194
218
|
|
|
195
219
|
const emit = defineEmits<{
|
|
196
220
|
(e: "refresh"): void;
|
|
197
221
|
(e: "error", message: string): void;
|
|
198
|
-
/**
|
|
222
|
+
/** Fired when a non-subscriber clicks the upgrade CTA next to the disabled checkbox, or when isEnabled is false at save time. */
|
|
199
223
|
(e: "paywall", feature: string): void;
|
|
224
|
+
/** Fired when the "show publicly" checkbox changes (only reachable while isSubscriber). */
|
|
225
|
+
(e: "toggle-visibility", value: boolean): void;
|
|
200
226
|
}>();
|
|
201
227
|
|
|
228
|
+
function onToggleVisibility(value: boolean) {
|
|
229
|
+
if (!props.isSubscriber) return;
|
|
230
|
+
emit('toggle-visibility', value);
|
|
231
|
+
}
|
|
232
|
+
|
|
202
233
|
const showForm = ref(false);
|
|
203
234
|
const editing = ref<number | null>(null);
|
|
204
235
|
const saving = ref(false);
|
|
@@ -216,6 +247,53 @@ const defaultForm = {
|
|
|
216
247
|
|
|
217
248
|
const form = ref({ ...defaultForm, quantities: {} });
|
|
218
249
|
|
|
250
|
+
// --- Draft persistence (new-item only) --------------------------------------
|
|
251
|
+
// Guards against losing a half-filled form on accidental navigation/refresh.
|
|
252
|
+
// Scoped per profile so switching accounts in the same browser can't leak a
|
|
253
|
+
// draft between them. Only the "new item" flow is persisted — editing an
|
|
254
|
+
// existing bundle already has server data as the source of truth.
|
|
255
|
+
const DRAFT_KEY = computed(() => `mgn_bundle_draft_${props.influencerProInfoId}`);
|
|
256
|
+
|
|
257
|
+
function loadDraft() {
|
|
258
|
+
if (typeof window === 'undefined') return null;
|
|
259
|
+
try {
|
|
260
|
+
const raw = window.localStorage.getItem(DRAFT_KEY.value);
|
|
261
|
+
return raw ? JSON.parse(raw) : null;
|
|
262
|
+
} catch {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function saveDraft() {
|
|
268
|
+
if (typeof window === 'undefined' || editing.value) return;
|
|
269
|
+
try {
|
|
270
|
+
window.localStorage.setItem(DRAFT_KEY.value, JSON.stringify(form.value));
|
|
271
|
+
} catch {
|
|
272
|
+
// storage unavailable (private browsing, quota) — draft just won't persist
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function clearDraft() {
|
|
277
|
+
if (typeof window === 'undefined') return;
|
|
278
|
+
try {
|
|
279
|
+
window.localStorage.removeItem(DRAFT_KEY.value);
|
|
280
|
+
} catch {
|
|
281
|
+
// ignore
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
watch(form, () => {
|
|
286
|
+
if (!editing.value) saveDraft();
|
|
287
|
+
}, { deep: true });
|
|
288
|
+
|
|
289
|
+
onMounted(() => {
|
|
290
|
+
const draft = loadDraft();
|
|
291
|
+
if (draft) {
|
|
292
|
+
form.value = { ...defaultForm, quantities: {}, ...draft };
|
|
293
|
+
showForm.value = true;
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
|
|
219
297
|
function qtyFor(id: number): number {
|
|
220
298
|
return form.value.quantities[id] || 1;
|
|
221
299
|
}
|
|
@@ -254,6 +332,7 @@ function cancelForm() {
|
|
|
254
332
|
showForm.value = false;
|
|
255
333
|
editing.value = null;
|
|
256
334
|
form.value = { ...defaultForm, rate_card_ids: [], quantities: {} };
|
|
335
|
+
clearDraft();
|
|
257
336
|
}
|
|
258
337
|
|
|
259
338
|
function editBundle(bundle: Bundle) {
|
|
@@ -353,7 +432,58 @@ async function removeBundle(id: number) {
|
|
|
353
432
|
margin: -8px 0 0;
|
|
354
433
|
}
|
|
355
434
|
|
|
435
|
+
.visibility-checkbox {
|
|
436
|
+
display: flex;
|
|
437
|
+
align-items: center;
|
|
438
|
+
gap: 8px;
|
|
439
|
+
font-size: 13px;
|
|
440
|
+
color: #E4E6EB;
|
|
441
|
+
cursor: pointer;
|
|
442
|
+
|
|
443
|
+
input[type="checkbox"] {
|
|
444
|
+
width: 16px;
|
|
445
|
+
height: 16px;
|
|
446
|
+
cursor: pointer;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
&.disabled {
|
|
450
|
+
cursor: not-allowed;
|
|
451
|
+
color: #7A7D89;
|
|
452
|
+
|
|
453
|
+
input[type="checkbox"] { cursor: not-allowed; }
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
.upgrade-link {
|
|
457
|
+
display: inline-flex;
|
|
458
|
+
align-items: center;
|
|
459
|
+
gap: 4px;
|
|
460
|
+
margin-left: 4px;
|
|
461
|
+
padding: 3px 8px;
|
|
462
|
+
background: none;
|
|
463
|
+
border: 1px solid #FDB215;
|
|
464
|
+
color: #FDB215;
|
|
465
|
+
font-size: 12px;
|
|
466
|
+
cursor: pointer;
|
|
467
|
+
|
|
468
|
+
&:hover { background: rgba(253, 178, 21, 0.1); }
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
356
472
|
.bundle-form {
|
|
473
|
+
.visibility-note {
|
|
474
|
+
display: flex;
|
|
475
|
+
align-items: flex-start;
|
|
476
|
+
gap: 8px;
|
|
477
|
+
padding: 10px 12px;
|
|
478
|
+
background: rgba(255, 255, 255, 0.04);
|
|
479
|
+
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
480
|
+
border-radius: 4px;
|
|
481
|
+
font-size: 13px;
|
|
482
|
+
color: #B7BAC4;
|
|
483
|
+
|
|
484
|
+
svg { flex-shrink: 0; margin-top: 2px; }
|
|
485
|
+
}
|
|
486
|
+
|
|
357
487
|
background: #1E1E22;
|
|
358
488
|
padding: 20px;
|
|
359
489
|
display: flex;
|
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
</div>
|
|
9
9
|
|
|
10
10
|
<div v-if="showForm" class="rate-card-form">
|
|
11
|
+
<div class="visibility-note">
|
|
12
|
+
<MGIcon icon="info" />
|
|
13
|
+
<span>{{ $t("media_kit.editor.visibility_note") }}</span>
|
|
14
|
+
</div>
|
|
15
|
+
|
|
11
16
|
<div class="form-row">
|
|
12
17
|
<div class="form-group">
|
|
13
18
|
<label>{{ $t("media_kit.editor.content_format") }}</label>
|
|
@@ -79,6 +84,20 @@
|
|
|
79
84
|
<textarea v-model="form.description" rows="3"
|
|
80
85
|
:placeholder="$t('media_kit.editor.description_placeholder')"></textarea>
|
|
81
86
|
</div>
|
|
87
|
+
<label class="visibility-checkbox" :class="{ disabled: !isSubscriber }">
|
|
88
|
+
<input
|
|
89
|
+
type="checkbox"
|
|
90
|
+
:checked="showPublicly"
|
|
91
|
+
:disabled="!isSubscriber"
|
|
92
|
+
@change="onToggleVisibility(($event.target as HTMLInputElement).checked)"
|
|
93
|
+
/>
|
|
94
|
+
<span>{{ $t("media_kit.editor.show_publicly") }}</span>
|
|
95
|
+
<button v-if="!isSubscriber" type="button" class="upgrade-link" @click.prevent="emit('paywall', 'rates')">
|
|
96
|
+
<MGIcon icon="lock" />
|
|
97
|
+
{{ $t("media_kit.editor.upgrade_to_show") }}
|
|
98
|
+
</button>
|
|
99
|
+
</label>
|
|
100
|
+
|
|
82
101
|
<div class="form-actions">
|
|
83
102
|
<button class="btn-cancel" @click="cancelForm">{{ $t("media_kit.editor.cancel") }}</button>
|
|
84
103
|
<button class="btn-save" @click="saveRateCard" :disabled="saving">
|
|
@@ -143,19 +162,34 @@ const props = withDefaults(
|
|
|
143
162
|
commissionPercent?: number;
|
|
144
163
|
/** Current plan name, used in the fee label. */
|
|
145
164
|
planName?: string;
|
|
165
|
+
/** Whether the account has an active paid subscription — gates public visibility only, not creation. */
|
|
166
|
+
isSubscriber?: boolean;
|
|
167
|
+
/** Current value of the account-wide "show rate cards publicly" setting. */
|
|
168
|
+
showPublicly?: boolean;
|
|
146
169
|
}>(),
|
|
147
170
|
{
|
|
148
171
|
isEnabled: true,
|
|
149
172
|
commissionPercent: 20,
|
|
150
173
|
planName: "Free",
|
|
174
|
+
isSubscriber: false,
|
|
175
|
+
showPublicly: true,
|
|
151
176
|
}
|
|
152
177
|
);
|
|
153
178
|
|
|
154
179
|
const emit = defineEmits<{
|
|
155
180
|
(e: "refresh"): void;
|
|
156
181
|
(e: "error", message: string): void;
|
|
182
|
+
/** Fired when the "show publicly" checkbox changes (only reachable while isSubscriber). */
|
|
183
|
+
(e: "toggle-visibility", value: boolean): void;
|
|
184
|
+
/** Fired when a non-subscriber clicks the upgrade CTA next to the disabled checkbox. */
|
|
185
|
+
(e: "paywall", feature: string): void;
|
|
157
186
|
}>();
|
|
158
187
|
|
|
188
|
+
function onToggleVisibility(value: boolean) {
|
|
189
|
+
if (!props.isSubscriber) return;
|
|
190
|
+
emit('toggle-visibility', value);
|
|
191
|
+
}
|
|
192
|
+
|
|
159
193
|
const showForm = ref(false);
|
|
160
194
|
const editing = ref<number | null>(null);
|
|
161
195
|
const saving = ref(false);
|
|
@@ -173,10 +207,58 @@ const defaultForm = {
|
|
|
173
207
|
|
|
174
208
|
const form = ref({ ...defaultForm });
|
|
175
209
|
|
|
210
|
+
// --- Draft persistence (new-item only) --------------------------------------
|
|
211
|
+
// Guards against losing a half-filled form on accidental navigation/refresh.
|
|
212
|
+
// Scoped per profile so switching accounts in the same browser can't leak a
|
|
213
|
+
// draft between them. Only the "new item" flow is persisted — editing an
|
|
214
|
+
// existing card already has server data as the source of truth.
|
|
215
|
+
const DRAFT_KEY = computed(() => `mgn_rate_card_draft_${props.influencerProInfoId}`);
|
|
216
|
+
|
|
217
|
+
function loadDraft() {
|
|
218
|
+
if (typeof window === 'undefined') return null;
|
|
219
|
+
try {
|
|
220
|
+
const raw = window.localStorage.getItem(DRAFT_KEY.value);
|
|
221
|
+
return raw ? JSON.parse(raw) : null;
|
|
222
|
+
} catch {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function saveDraft() {
|
|
228
|
+
if (typeof window === 'undefined' || editing.value) return;
|
|
229
|
+
try {
|
|
230
|
+
window.localStorage.setItem(DRAFT_KEY.value, JSON.stringify(form.value));
|
|
231
|
+
} catch {
|
|
232
|
+
// storage unavailable (private browsing, quota) — draft just won't persist
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function clearDraft() {
|
|
237
|
+
if (typeof window === 'undefined') return;
|
|
238
|
+
try {
|
|
239
|
+
window.localStorage.removeItem(DRAFT_KEY.value);
|
|
240
|
+
} catch {
|
|
241
|
+
// ignore
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
watch(form, () => {
|
|
246
|
+
if (!editing.value) saveDraft();
|
|
247
|
+
}, { deep: true });
|
|
248
|
+
|
|
249
|
+
onMounted(() => {
|
|
250
|
+
const draft = loadDraft();
|
|
251
|
+
if (draft) {
|
|
252
|
+
form.value = { ...defaultForm, ...draft };
|
|
253
|
+
showForm.value = true;
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
|
|
176
257
|
const cancelForm = () => {
|
|
177
258
|
showForm.value = false;
|
|
178
259
|
editing.value = null;
|
|
179
260
|
form.value = { ...defaultForm };
|
|
261
|
+
clearDraft();
|
|
180
262
|
};
|
|
181
263
|
|
|
182
264
|
const editCard = (card: RateCard) => {
|
|
@@ -284,6 +366,57 @@ const netDisplay = computed(() => {
|
|
|
284
366
|
flex-direction: column;
|
|
285
367
|
gap: 16px;
|
|
286
368
|
|
|
369
|
+
.visibility-note {
|
|
370
|
+
display: flex;
|
|
371
|
+
align-items: flex-start;
|
|
372
|
+
gap: 8px;
|
|
373
|
+
padding: 10px 12px;
|
|
374
|
+
background: rgba(255, 255, 255, 0.04);
|
|
375
|
+
border: 1px solid rgba(255, 255, 255, 0.08);
|
|
376
|
+
border-radius: 4px;
|
|
377
|
+
font-size: 13px;
|
|
378
|
+
color: #B7BAC4;
|
|
379
|
+
|
|
380
|
+
svg { flex-shrink: 0; margin-top: 2px; }
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
.visibility-checkbox {
|
|
384
|
+
display: flex;
|
|
385
|
+
align-items: center;
|
|
386
|
+
gap: 8px;
|
|
387
|
+
font-size: 13px;
|
|
388
|
+
color: #E4E6EB;
|
|
389
|
+
cursor: pointer;
|
|
390
|
+
|
|
391
|
+
input[type="checkbox"] {
|
|
392
|
+
width: 16px;
|
|
393
|
+
height: 16px;
|
|
394
|
+
cursor: pointer;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
&.disabled {
|
|
398
|
+
cursor: not-allowed;
|
|
399
|
+
color: #7A7D89;
|
|
400
|
+
|
|
401
|
+
input[type="checkbox"] { cursor: not-allowed; }
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
.upgrade-link {
|
|
405
|
+
display: inline-flex;
|
|
406
|
+
align-items: center;
|
|
407
|
+
gap: 4px;
|
|
408
|
+
margin-left: 4px;
|
|
409
|
+
padding: 3px 8px;
|
|
410
|
+
background: none;
|
|
411
|
+
border: 1px solid #FDB215;
|
|
412
|
+
color: #FDB215;
|
|
413
|
+
font-size: 12px;
|
|
414
|
+
cursor: pointer;
|
|
415
|
+
|
|
416
|
+
&:hover { background: rgba(253, 178, 21, 0.1); }
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
287
420
|
.mgn-fee-note {
|
|
288
421
|
display: flex;
|
|
289
422
|
flex-direction: column;
|
|
@@ -120,7 +120,7 @@ const detailRoute = computed(() =>
|
|
|
120
120
|
</div>
|
|
121
121
|
|
|
122
122
|
<!-- Tier-locked badge -->
|
|
123
|
-
<div v-else-if="card.is_tier_locked && card.access_tier !== 'free'" class="kc-card__exclusive-badge">
|
|
123
|
+
<div v-else-if="card.is_tier_locked && card.access_tier !== 'free' && !userCanAccess" class="kc-card__exclusive-badge">
|
|
124
124
|
<i class="fa-solid fa-crown" /> {{ cardTierLabel(card.access_tier) }}
|
|
125
125
|
</div>
|
|
126
126
|
|
|
@@ -148,21 +148,21 @@ const detailRoute = computed(() =>
|
|
|
148
148
|
<span class="lock-label">{{ $t("keys.card.exclusive_lock_title") }}</span>
|
|
149
149
|
<span class="lock-cta">{{ $t("keys.card.exclusive_upgrade_cta") }}</span>
|
|
150
150
|
</div>
|
|
151
|
-
</div>
|
|
152
|
-
</NuxtLink>
|
|
153
151
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
152
|
+
<div class="kc-card__meta-bar">
|
|
153
|
+
<div class="kc-card__days" v-if="card.early_access_hours && card.early_access_hours > 0 && userCanAccess">
|
|
154
|
+
<span>{{ card.early_access_hours }}</span>h {{ $t("keys.card.days") }}
|
|
155
|
+
</div>
|
|
156
|
+
<div class="kc-card__days" v-else> </div>
|
|
157
|
+
<span v-if="card.type" class="kc-card__type">
|
|
158
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="13" viewBox="0 0 16 17" fill="none">
|
|
159
|
+
<path d="M13.3333 4.1112L12.8666 3.64453L11.9333 4.57786L10.9333 3.64453L8.33329 4.1112L2.66663 9.77786L7.19996 14.3112L12.8666 8.64453L13.3333 6.04453L12.4 5.1112L13.3333 4.1112ZM12.6 6.24453L12.2666 8.3112L7.19996 13.3779L3.59996 9.77786L8.66663 4.7112L10.7333 4.3112L11.4666 5.04453L11 5.5112L10.5333 5.04453L9.99996 5.57786L11.4 6.97786L11.8666 6.5112L11.4 6.04453L11.8666 5.57786L12.6 6.24453Z" fill="#D297FF"/>
|
|
160
|
+
</svg>
|
|
161
|
+
{{ card.type }}
|
|
162
|
+
</span>
|
|
163
|
+
</div>
|
|
157
164
|
</div>
|
|
158
|
-
|
|
159
|
-
<span v-if="card.type" class="kc-card__type">
|
|
160
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="13" viewBox="0 0 16 17" fill="none">
|
|
161
|
-
<path d="M13.3333 4.1112L12.8666 3.64453L11.9333 4.57786L10.9333 3.64453L8.33329 4.1112L2.66663 9.77786L7.19996 14.3112L12.8666 8.64453L13.3333 6.04453L12.4 5.1112L13.3333 4.1112ZM12.6 6.24453L12.2666 8.3112L7.19996 13.3779L3.59996 9.77786L8.66663 4.7112L10.7333 4.3112L11.4666 5.04453L11 5.5112L10.5333 5.04453L9.99996 5.57786L11.4 6.97786L11.8666 6.5112L11.4 6.04453L11.8666 5.57786L12.6 6.24453Z" fill="#D297FF"/>
|
|
162
|
-
</svg>
|
|
163
|
-
{{ card.type }}
|
|
164
|
-
</span>
|
|
165
|
-
</div>
|
|
165
|
+
</NuxtLink>
|
|
166
166
|
</div>
|
|
167
167
|
|
|
168
168
|
<div class="kc-card__body">
|
|
@@ -317,12 +317,18 @@ const detailRoute = computed(() =>
|
|
|
317
317
|
}
|
|
318
318
|
|
|
319
319
|
&__meta-bar {
|
|
320
|
+
position: absolute;
|
|
321
|
+
left: 0;
|
|
322
|
+
right: 0;
|
|
323
|
+
bottom: 0;
|
|
320
324
|
display: flex;
|
|
321
325
|
align-items: center;
|
|
322
326
|
justify-content: space-between;
|
|
323
327
|
padding: 6px 8px;
|
|
324
|
-
background:
|
|
328
|
+
background: rgba(13, 13, 13, 0.82);
|
|
329
|
+
backdrop-filter: blur(2px);
|
|
325
330
|
min-height: 30px;
|
|
331
|
+
z-index: 2;
|
|
326
332
|
}
|
|
327
333
|
|
|
328
334
|
&__days {
|
package/locales/de.json
CHANGED
|
@@ -133,7 +133,7 @@
|
|
|
133
133
|
"rp_label": "Redeemed by",
|
|
134
134
|
"who_redeem": "Who redeemed",
|
|
135
135
|
"created_by": "Published by",
|
|
136
|
-
"no_data": "
|
|
136
|
+
"no_data": "Diese Kampagne ist noch keinem Spiel im System zugeordnet",
|
|
137
137
|
"title": "Kampagne",
|
|
138
138
|
"about": "Über das Spiel",
|
|
139
139
|
"screenshot_alt": "Spiel-Screenshot",
|
|
@@ -237,4 +237,4 @@
|
|
|
237
237
|
"video_thumbnail": "Video-Vorschaubild",
|
|
238
238
|
"expanded_image": "Vergrößertes Bild"
|
|
239
239
|
}
|
|
240
|
-
}
|
|
240
|
+
}
|
package/locales/en.json
CHANGED
|
@@ -133,7 +133,7 @@
|
|
|
133
133
|
"rp_label": "Redeemed by",
|
|
134
134
|
"who_redeem": "Who redeemed",
|
|
135
135
|
"created_by": "Published by",
|
|
136
|
-
"no_data": "
|
|
136
|
+
"no_data": "This campaign is not associated with a game in our system yet",
|
|
137
137
|
"title": "Campaign",
|
|
138
138
|
"about": "About the game",
|
|
139
139
|
"screenshot_alt": "Game screenshot",
|
package/locales/pt-BR.json
CHANGED
|
@@ -133,7 +133,7 @@
|
|
|
133
133
|
"rp_label": "Redeemed by",
|
|
134
134
|
"who_redeem": "Who redeemed",
|
|
135
135
|
"created_by": "Published by",
|
|
136
|
-
"no_data": "
|
|
136
|
+
"no_data": "Esta campanha ainda não foi associada a um jogo no sistema",
|
|
137
137
|
"title": "Campanha",
|
|
138
138
|
"about": "Sobre o jogo",
|
|
139
139
|
"screenshot_alt": "Captura de tela do jogo",
|
|
@@ -237,4 +237,4 @@
|
|
|
237
237
|
"video_thumbnail": "Miniatura do vídeo",
|
|
238
238
|
"expanded_image": "Imagem ampliada"
|
|
239
239
|
}
|
|
240
|
-
}
|
|
240
|
+
}
|
package/locales/ro.json
CHANGED
|
@@ -133,7 +133,7 @@
|
|
|
133
133
|
"rp_label": "Redeemed by",
|
|
134
134
|
"who_redeem": "Who redeemed",
|
|
135
135
|
"created_by": "Published by",
|
|
136
|
-
"no_data": "
|
|
136
|
+
"no_data": "Această campanie nu este încă asociată cu un joc în sistem",
|
|
137
137
|
"title": "Campanie",
|
|
138
138
|
"about": "Despre joc",
|
|
139
139
|
"screenshot_alt": "Captură de ecran a jocului",
|
|
@@ -237,4 +237,4 @@
|
|
|
237
237
|
"video_thumbnail": "Miniatură video",
|
|
238
238
|
"expanded_image": "Imagine mărită"
|
|
239
239
|
}
|
|
240
|
-
}
|
|
240
|
+
}
|
package/package.json
CHANGED
|
@@ -63,18 +63,18 @@ useSeoMeta({
|
|
|
63
63
|
const restriction = computed(() => {
|
|
64
64
|
const k = key.value;
|
|
65
65
|
if (!k) return '';
|
|
66
|
-
if (k.is_exclusive) return '
|
|
67
|
-
if (k.is_tier_locked && k.access_tier && k.access_tier !== 'free') return `
|
|
68
|
-
if (k.streamer_type_id === 2) return '
|
|
69
|
-
if (k.streamer_type_id === 3) return '
|
|
66
|
+
if (k.is_exclusive) return 'Exclusive to official streamers';
|
|
67
|
+
if (k.is_tier_locked && k.access_tier && k.access_tier !== 'free') return `Exclusive to ${String(k.access_tier).toUpperCase()} plan or higher`;
|
|
68
|
+
if (k.streamer_type_id === 2) return 'Exclusive to official streamers';
|
|
69
|
+
if (k.streamer_type_id === 3) return 'Exclusive to affiliates';
|
|
70
70
|
return '';
|
|
71
71
|
});
|
|
72
72
|
</script>
|
|
73
73
|
|
|
74
74
|
<template>
|
|
75
75
|
<div class="kc">
|
|
76
|
-
<div v-if="loading" class="kc__state">
|
|
77
|
-
<div v-else-if="error" class="kc__state">
|
|
76
|
+
<div v-if="loading" class="kc__state">Loading…</div>
|
|
77
|
+
<div v-else-if="error" class="kc__state">Campaign not found.</div>
|
|
78
78
|
|
|
79
79
|
<template v-else>
|
|
80
80
|
<div class="kc__hero">
|
|
@@ -83,8 +83,8 @@ const restriction = computed(() => {
|
|
|
83
83
|
<h1 class="kc__title">{{ key.name }}</h1>
|
|
84
84
|
<div v-if="restriction" class="kc__badge">🔒 {{ restriction }}</div>
|
|
85
85
|
<div class="kc__avail">
|
|
86
|
-
<span v-if="key.available_count > 0">{{ key.available_count }}
|
|
87
|
-
<span v-else>
|
|
86
|
+
<span v-if="key.available_count > 0">{{ key.available_count }} {{ key.available_count === 1 ? 'key' : 'keys' }} available to redeem</span>
|
|
87
|
+
<span v-else>Keys sold out</span>
|
|
88
88
|
</div>
|
|
89
89
|
</div>
|
|
90
90
|
</div>
|
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
<div class="stepper-header">
|
|
6
6
|
<div
|
|
7
7
|
:class="['stepper-step', { complete: currentStep > 1, active: currentStep === 1 }]"
|
|
8
|
-
@click="
|
|
8
|
+
@click="setStep(1)"
|
|
9
9
|
>
|
|
10
10
|
{{ $t("keys.campaigns.title") }}
|
|
11
11
|
</div>
|
|
12
12
|
<div
|
|
13
13
|
:class="['stepper-step', { complete: currentStep > 2, active: currentStep === 2 }]"
|
|
14
|
-
@click="
|
|
14
|
+
@click="setStep(2)"
|
|
15
15
|
>
|
|
16
16
|
{{ $t("keys.campaigns.my_requests") }}
|
|
17
17
|
</div>
|
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
</div>
|
|
135
135
|
|
|
136
136
|
<div
|
|
137
|
-
v-else-if="card.is_tier_locked && card.access_tier !== 'free'"
|
|
137
|
+
v-else-if="card.is_tier_locked && card.access_tier !== 'free' && !card.user_can_access"
|
|
138
138
|
class="exclusive-badge"
|
|
139
139
|
>
|
|
140
140
|
<i class="fa-solid fa-crown" /> {{ cardTierLabel(card.access_tier) }}
|
|
@@ -179,23 +179,23 @@
|
|
|
179
179
|
<span class="lock-label">{{ $t("keys.campaigns.exclusive_lock_title") }}</span>
|
|
180
180
|
<span class="lock-cta">{{ $t("keys.campaigns.exclusive_upgrade_cta") }}</span>
|
|
181
181
|
</div>
|
|
182
|
+
|
|
183
|
+
<div class="title">
|
|
184
|
+
<div class="days" v-if="card.time > 0 && card.user_can_access">
|
|
185
|
+
<span>{{ card.time }}</span> {{ $t("keys.campaigns.days") }}
|
|
186
|
+
</div>
|
|
187
|
+
<div class="days" v-else></div>
|
|
188
|
+
<span>
|
|
189
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="17" viewBox="0 0 16 17" fill="none">
|
|
190
|
+
<path d="M13.3333 4.1112L12.8666 3.64453L11.9333 4.57786L10.9333 3.64453L8.33329 4.1112L2.66663 9.77786L7.19996 14.3112L12.8666 8.64453L13.3333 6.04453L12.4 5.1112L13.3333 4.1112ZM12.6 6.24453L12.2666 8.3112L7.19996 13.3779L3.59996 9.77786L8.66663 4.7112L10.7333 4.3112L11.4666 5.04453L11 5.5112L10.5333 5.04453L9.99996 5.57786L11.4 6.97786L11.8666 6.5112L11.4 6.04453L11.8666 5.57786L12.6 6.24453Z" fill="var(--key-accent, var(--key-accent, var(--primary, #D297FF)))" />
|
|
191
|
+
</svg>
|
|
192
|
+
{{ card.type }}
|
|
193
|
+
</span>
|
|
194
|
+
</div>
|
|
182
195
|
</div>
|
|
183
196
|
</nuxt-link>
|
|
184
197
|
</div>
|
|
185
198
|
|
|
186
|
-
<div class="title">
|
|
187
|
-
<div class="days" v-if="card.time > 0 && card.user_can_access">
|
|
188
|
-
<span>{{ card.time }}</span> {{ $t("keys.campaigns.days") }}
|
|
189
|
-
</div>
|
|
190
|
-
<div class="days" v-else></div>
|
|
191
|
-
<span>
|
|
192
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="17" viewBox="0 0 16 17" fill="none">
|
|
193
|
-
<path d="M13.3333 4.1112L12.8666 3.64453L11.9333 4.57786L10.9333 3.64453L8.33329 4.1112L2.66663 9.77786L7.19996 14.3112L12.8666 8.64453L13.3333 6.04453L12.4 5.1112L13.3333 4.1112ZM12.6 6.24453L12.2666 8.3112L7.19996 13.3779L3.59996 9.77786L8.66663 4.7112L10.7333 4.3112L11.4666 5.04453L11 5.5112L10.5333 5.04453L9.99996 5.57786L11.4 6.97786L11.8666 6.5112L11.4 6.04453L11.8666 5.57786L12.6 6.24453Z" fill="var(--key-accent, var(--key-accent, var(--primary, #D297FF)))" />
|
|
194
|
-
</svg>
|
|
195
|
-
{{ card.type }}
|
|
196
|
-
</span>
|
|
197
|
-
</div>
|
|
198
|
-
|
|
199
199
|
<div class="text">
|
|
200
200
|
<div v-if="card.platforms && card.platforms.length" class="card-platforms">
|
|
201
201
|
<span v-for="p in card.platforms" :key="p" class="card-platform-tag">
|
|
@@ -344,13 +344,15 @@
|
|
|
344
344
|
</template>
|
|
345
345
|
|
|
346
346
|
<script setup lang="ts">
|
|
347
|
-
import { ref, computed, onMounted, onUnmounted, watch, inject } from "vue"
|
|
347
|
+
import { ref, computed, onMounted, onUnmounted, watch, inject, unref } from "vue"
|
|
348
348
|
import { useNuxtApp, navigateTo } from "#app"
|
|
349
349
|
import { useCampaignsStore } from "../../stores/campaigns"
|
|
350
350
|
import { fetchMyRequests, fetchRedeemedUsers } from "../../services/campaignService"
|
|
351
|
+
import { useLoginStore } from "../../stores/login"
|
|
351
352
|
|
|
352
353
|
// Injected by each consuming front — provide these in app.vue / a plugin
|
|
353
354
|
const mgPlatform = inject<string>("mgPlatform", "MGTV")
|
|
355
|
+
const currentUser = inject<any>("currentUser", null)
|
|
354
356
|
const loginUrl = inject<string>("loginUrl", "/")
|
|
355
357
|
const upgradeRoute = inject<string>("upgradeRoute", "/")
|
|
356
358
|
|
|
@@ -358,6 +360,7 @@ const { $i18n } = useNuxtApp()
|
|
|
358
360
|
const locale = $i18n.locale
|
|
359
361
|
|
|
360
362
|
const campaignsStore = useCampaignsStore()
|
|
363
|
+
const loginStore = useLoginStore()
|
|
361
364
|
|
|
362
365
|
const currentStep = ref(1)
|
|
363
366
|
const searchTerm = ref("")
|
|
@@ -374,6 +377,26 @@ const loadingFeatured = ref(true)
|
|
|
374
377
|
const loadingRequests = ref(false)
|
|
375
378
|
const loadError = ref(false)
|
|
376
379
|
|
|
380
|
+
function truthyFlag(value: unknown) {
|
|
381
|
+
return value === true || value === 1 || value === "1"
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
function hasCurrentUser() {
|
|
385
|
+
return !!unref(currentUser)
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function requestLogin() {
|
|
389
|
+
loginStore.showLoginModalComponent = true
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function setStep(step: number) {
|
|
393
|
+
if (step === 2 && !hasCurrentUser()) {
|
|
394
|
+
requestLogin()
|
|
395
|
+
return
|
|
396
|
+
}
|
|
397
|
+
currentStep.value = step
|
|
398
|
+
}
|
|
399
|
+
|
|
377
400
|
// ------------------------------------------------------------------
|
|
378
401
|
// Filters
|
|
379
402
|
// ------------------------------------------------------------------
|
|
@@ -489,12 +512,17 @@ async function loadFeaturedCampaigns() {
|
|
|
489
512
|
loadingFeatured.value = true
|
|
490
513
|
try {
|
|
491
514
|
const response = await campaignsStore.fetchFeaturedCampaigns(mgPlatform)
|
|
492
|
-
sliderImages.value = (response.data || [])
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
515
|
+
sliderImages.value = (response.data || [])
|
|
516
|
+
// Featured/highlight alone isn't enough — a campaign that's ended or
|
|
517
|
+
// sold out but still flagged featured must not show in the hero
|
|
518
|
+
// carousel. is_open already accounts for status/dates/available_count.
|
|
519
|
+
.filter((item: any) => (truthyFlag(item.featured) || truthyFlag(item.highlight)) && truthyFlag(item.is_open))
|
|
520
|
+
.map((item: any) => ({
|
|
521
|
+
id: item.id,
|
|
522
|
+
cover: item.game?.url_banner_src || item.cover_src,
|
|
523
|
+
name: item.name,
|
|
524
|
+
slug: item.slug,
|
|
525
|
+
}))
|
|
498
526
|
} catch {
|
|
499
527
|
// silent
|
|
500
528
|
} finally {
|
|
@@ -600,6 +628,7 @@ function applyUserRequestStatuses() {
|
|
|
600
628
|
}
|
|
601
629
|
|
|
602
630
|
async function loadMyRequests() {
|
|
631
|
+
if (!hasCurrentUser()) return
|
|
603
632
|
loadingRequests.value = true
|
|
604
633
|
try {
|
|
605
634
|
const response = await fetchMyRequests({ page: 1, per_page: 30, sort: "id", order: "asc" })
|
|
@@ -759,7 +788,7 @@ onMounted(async () => {
|
|
|
759
788
|
await loadCampaigns(1)
|
|
760
789
|
await loadCampaignTypes()
|
|
761
790
|
await loadPlatforms()
|
|
762
|
-
await loadMyRequests()
|
|
791
|
+
if (hasCurrentUser()) await loadMyRequests()
|
|
763
792
|
|
|
764
793
|
updateSlider()
|
|
765
794
|
startAutoplay()
|
|
@@ -811,7 +840,7 @@ onUnmounted(() => {
|
|
|
811
840
|
|
|
812
841
|
.keys-badge {
|
|
813
842
|
position: absolute;
|
|
814
|
-
|
|
843
|
+
top: 8px;
|
|
815
844
|
right: 8px;
|
|
816
845
|
background: var(--key-accent-dark, var(--key-accent-bg, rgba(107, 21, 172, 0.9)));
|
|
817
846
|
color: #fff;
|
|
@@ -1141,12 +1170,18 @@ onUnmounted(() => {
|
|
|
1141
1170
|
}
|
|
1142
1171
|
|
|
1143
1172
|
.title {
|
|
1173
|
+
position: absolute;
|
|
1174
|
+
left: 0;
|
|
1175
|
+
right: 0;
|
|
1176
|
+
bottom: 0;
|
|
1144
1177
|
display: flex;
|
|
1145
1178
|
padding: 8px 16px;
|
|
1146
1179
|
align-items: center;
|
|
1147
|
-
background: rgba(13, 13, 13, 0.
|
|
1180
|
+
background: rgba(13, 13, 13, 0.82);
|
|
1181
|
+
backdrop-filter: blur(2px);
|
|
1148
1182
|
width: 100%;
|
|
1149
1183
|
justify-content: space-between;
|
|
1184
|
+
z-index: 2;
|
|
1150
1185
|
|
|
1151
1186
|
.days {
|
|
1152
1187
|
font-size: 12px;
|
|
@@ -147,9 +147,6 @@ async function submit() {
|
|
|
147
147
|
return
|
|
148
148
|
}
|
|
149
149
|
success.value = true
|
|
150
|
-
setTimeout(() => {
|
|
151
|
-
navigateTo(`/${locale.value}/key-campaigns`)
|
|
152
|
-
}, 2000)
|
|
153
150
|
} catch (e: any) {
|
|
154
151
|
const status = e?.response?.status
|
|
155
152
|
const errorCode = e?.response?.data?.error_code
|
|
@@ -205,8 +205,33 @@ useSeoMeta({
|
|
|
205
205
|
<template>
|
|
206
206
|
<div class="kit-press" :data-tpl="tpl" :data-layout="layout">
|
|
207
207
|
<div v-if="loading" class="kit-state">{{ $t('kit.loading') }}</div>
|
|
208
|
-
<div v-else-if="error || !kit" class="kit-state">
|
|
208
|
+
<div v-else-if="error || !kit" class="kit-state kit-state--not-found">
|
|
209
209
|
<h2>{{ $t('kit.press.not_found') }}</h2>
|
|
210
|
+
<p class="kit-state__desc">{{ $t('kit.press.not_found_desc') }}</p>
|
|
211
|
+
<a :href="`${agencyBase}/presskit`" target="_blank" rel="noopener" class="kit-footer__cta">
|
|
212
|
+
{{ $t('kit.press.create_yours_cta') }}
|
|
213
|
+
</a>
|
|
214
|
+
|
|
215
|
+
<section v-if="moreKits.length" class="kit-more kit-more--not-found">
|
|
216
|
+
<h2 class="kit-more__title">{{ $t('kit.press.more_games') }}</h2>
|
|
217
|
+
<div class="kit-more__track">
|
|
218
|
+
<a
|
|
219
|
+
v-for="k in moreKits"
|
|
220
|
+
:key="k.slug"
|
|
221
|
+
:href="`/presskit/game/${k.slug}`"
|
|
222
|
+
class="kit-more__card"
|
|
223
|
+
>
|
|
224
|
+
<div
|
|
225
|
+
class="kit-more__cover"
|
|
226
|
+
:style="k.cover_image_url ? { backgroundImage: `url(${k.cover_image_url})` } : {}"
|
|
227
|
+
>
|
|
228
|
+
<div v-if="!k.cover_image_url" class="kit-more__cover-fallback">{{ k.name?.charAt(0) }}</div>
|
|
229
|
+
</div>
|
|
230
|
+
<div class="kit-more__name">{{ k.name }}</div>
|
|
231
|
+
<div v-if="k.developer" class="kit-more__dev">{{ k.developer }}</div>
|
|
232
|
+
</a>
|
|
233
|
+
</div>
|
|
234
|
+
</section>
|
|
210
235
|
</div>
|
|
211
236
|
|
|
212
237
|
<template v-else>
|
|
@@ -22,10 +22,6 @@ function withApiV1(baseURL?: string): string {
|
|
|
22
22
|
return /\/api\/v1$/.test(base) ? base : `${base}/api/v1`
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
function withoutApiV1(baseURL?: string): string {
|
|
26
|
-
return (baseURL || "").replace(/\/api\/v1\/?$/, "").replace(/\/$/, "")
|
|
27
|
-
}
|
|
28
|
-
|
|
29
25
|
function getPublicApiBaseURL(): string {
|
|
30
26
|
return withApiV1(
|
|
31
27
|
import.meta.env.VITE_KEY_API_URL ||
|
|
@@ -47,6 +43,14 @@ function getAuthenticatedApiBaseURL(): string {
|
|
|
47
43
|
)
|
|
48
44
|
}
|
|
49
45
|
|
|
46
|
+
function setHeader(config: any, name: string, value: string) {
|
|
47
|
+
if (config.headers?.set) {
|
|
48
|
+
config.headers.set(name, value)
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
config.headers = { ...(config.headers || {}), [name]: value }
|
|
52
|
+
}
|
|
53
|
+
|
|
50
54
|
function getMainClient(): AxiosInstance {
|
|
51
55
|
if (_mainClient) return _mainClient
|
|
52
56
|
|
|
@@ -54,7 +58,9 @@ function getMainClient(): AxiosInstance {
|
|
|
54
58
|
|
|
55
59
|
_mainClient.interceptors.request.use((config) => {
|
|
56
60
|
const lang = resolveLang()
|
|
61
|
+
const systemId = import.meta.env.VITE_SYSTEM_ID
|
|
57
62
|
config.params = { ...config.params, lang }
|
|
63
|
+
if (systemId) setHeader(config, "X-System-Id", String(systemId))
|
|
58
64
|
// Only attach the shared debug token in true local dev — "!== production"
|
|
59
65
|
// also matches "hlg" (staging), which has real logged-in users relying on
|
|
60
66
|
// their own session cookie via withCredentials. Attaching this static
|
|
@@ -80,7 +86,9 @@ function getAuthClient(): AxiosInstance {
|
|
|
80
86
|
|
|
81
87
|
_authClient.interceptors.request.use((config) => {
|
|
82
88
|
const lang = resolveLang()
|
|
89
|
+
const systemId = import.meta.env.VITE_SYSTEM_ID
|
|
83
90
|
config.params = { ...config.params, lang }
|
|
91
|
+
if (systemId) setHeader(config, "X-System-Id", String(systemId))
|
|
84
92
|
// Only attach the shared debug token in true local dev — "!== production"
|
|
85
93
|
// also matches "hlg" (staging), which has real logged-in users relying on
|
|
86
94
|
// their own session cookie via withCredentials. Attaching this static
|
|
@@ -367,17 +375,7 @@ export const fetchCampaignTypes = (params: Record<string, any> = {}) => {
|
|
|
367
375
|
* Fetch active platforms (for the platform filter select).
|
|
368
376
|
*/
|
|
369
377
|
export const fetchCampaignPlatforms = () => {
|
|
370
|
-
|
|
371
|
-
import.meta.env.VITE_KEY_PLATFORMS_API_URL ||
|
|
372
|
-
import.meta.env.VITE_BASE_URL_COMMUNITY ||
|
|
373
|
-
(/community/i.test(import.meta.env.VITE_API_BASE_URL || "") ? import.meta.env.VITE_API_BASE_URL : ""),
|
|
374
|
-
)
|
|
375
|
-
if (communityBaseURL) {
|
|
376
|
-
return axios.get(`${communityBaseURL}/${resolveLang()}/platforms/currently`, {
|
|
377
|
-
withCredentials: true,
|
|
378
|
-
})
|
|
379
|
-
}
|
|
380
|
-
return authClient.get("/platforms/currently")
|
|
378
|
+
return authClient.get("/public/key-platforms")
|
|
381
379
|
}
|
|
382
380
|
|
|
383
381
|
/**
|