@mundogamernetwork/shared-ui 1.1.45 → 1.1.47
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/package.json +1 -1
- package/pages/presskit/[slug].vue +4 -289
- package/pages/presskit/game/[slug].vue +291 -0
package/package.json
CHANGED
|
@@ -1,291 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const route = useRoute();
|
|
7
|
-
const slug = route.params.slug as string;
|
|
8
|
-
|
|
9
|
-
const runtimeConfig = useRuntimeConfig();
|
|
10
|
-
const cfg = (runtimeConfig.public?.mgSharedUi || {}) as Record<string, any>;
|
|
11
|
-
// Consuming apps may set apiBaseURL at public root (agency/community/tv pattern)
|
|
12
|
-
// or inside mgSharedUi. pressKitApiUrl overrides both (e.g. community points to agency API).
|
|
13
|
-
const apiBase: string =
|
|
14
|
-
cfg.pressKitApiUrl ||
|
|
15
|
-
(runtimeConfig.public as any)?.pressKitApiUrl ||
|
|
16
|
-
cfg.apiBaseURL ||
|
|
17
|
-
(runtimeConfig.public as any)?.apiBaseURL ||
|
|
18
|
-
'';
|
|
19
|
-
|
|
20
|
-
const agencyBase: string =
|
|
21
|
-
cfg.agencyBaseUrl ||
|
|
22
|
-
(runtimeConfig.public as any)?.agencyBaseUrl ||
|
|
23
|
-
'';
|
|
24
|
-
|
|
25
|
-
const SUPPORTED_LOCALES = ['en', 'pt-BR', 'es', 'de', 'ro', 'ar-AE'];
|
|
26
|
-
const routePath = route.path.split('/');
|
|
27
|
-
const lang = SUPPORTED_LOCALES.find(l => routePath.includes(l)) || 'en';
|
|
28
|
-
|
|
29
|
-
const { data: kitData, error: fetchError, pending } = await useAsyncData(
|
|
30
|
-
`press-kit-${slug}`,
|
|
31
|
-
() => $fetch<any>(`${apiBase}/public/press-kits/${slug}`, {
|
|
32
|
-
params: { include: 'assets,videos,credits,awards,quotes', lang },
|
|
33
|
-
}),
|
|
34
|
-
{ lazy: false },
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
const kit = computed(() => kitData.value?.data || kitData.value || null);
|
|
38
|
-
const loading = pending;
|
|
39
|
-
const error = computed(() => !!fetchError.value || (!pending.value && !kit.value));
|
|
40
|
-
|
|
41
|
-
onMounted(() => {
|
|
42
|
-
if (kit.value) {
|
|
43
|
-
trackPressKitEvent(slug, {
|
|
44
|
-
event_type: 'view',
|
|
45
|
-
referrer: document.referrer || undefined,
|
|
46
|
-
}).catch(() => {});
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
// Fractal include shape: relation -> { data: [...] }
|
|
51
|
-
const list = (rel: any) => rel?.data || rel || [];
|
|
52
|
-
const assets = computed(() => list(kit.value?.assets));
|
|
53
|
-
const videos = computed(() => list(kit.value?.videos));
|
|
54
|
-
const awards = computed(() => list(kit.value?.awards));
|
|
55
|
-
const quotes = computed(() => list(kit.value?.quotes));
|
|
56
|
-
const team = computed(() => list(kit.value?.credits));
|
|
57
|
-
const features = computed(() => kit.value?.key_features || []);
|
|
58
|
-
// New, optional blocks (rendered only when the API provides them)
|
|
59
|
-
const articles = computed(() => list(kit.value?.articles));
|
|
60
|
-
const coverage = computed(() => list(kit.value?.coverage));
|
|
61
|
-
const showcases = computed(() => list(kit.value?.showcases));
|
|
62
|
-
const hasEcosystem = computed(() => showcases.value.length || kit.value?.ventures_url || kit.value?.magazine_feature || kit.value?.community_url);
|
|
63
|
-
|
|
64
|
-
const screenshots = computed(() => assets.value.filter((a: any) => ['screenshot', 'artwork', 'gif'].includes(a.type)));
|
|
65
|
-
const brandAssets = computed(() => assets.value.filter((a: any) => ['logo', 'document'].includes(a.type)));
|
|
66
|
-
|
|
67
|
-
const tpl = computed(() => kit.value?.theme || null);
|
|
68
|
-
const layout = computed(() => kit.value?.layout || 'classic');
|
|
69
|
-
const allowDownload = computed(() => kit.value?.allow_asset_download !== false);
|
|
70
|
-
|
|
71
|
-
const keyPoolsVisible = ref(false);
|
|
72
|
-
function onPoolsReady(count: number) {
|
|
73
|
-
keyPoolsVisible.value = count > 0;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const socials = computed(() => {
|
|
77
|
-
const s = kit.value?.social_links || {};
|
|
78
|
-
return Object.entries(s).filter(([, v]) => v).map(([k, v]) => ({ platform: k, url: v as string }));
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
const facts = computed(() => {
|
|
82
|
-
const k = kit.value || {};
|
|
83
|
-
const out: { label: string; value: string; accent?: boolean; href?: string }[] = [];
|
|
84
|
-
if (k.developer) out.push({ label: 'kit.press.developer', value: k.developer });
|
|
85
|
-
if (k.publisher) out.push({ label: 'kit.press.publisher', value: k.publisher });
|
|
86
|
-
if (k.release_date_tba) out.push({ label: 'kit.press.release', value: 'TBA', accent: true });
|
|
87
|
-
else if (k.release_date) out.push({ label: 'kit.press.release', value: k.release_date, accent: true });
|
|
88
|
-
if (k.release_status) out.push({ label: 'kit.press.status', value: String(k.release_status).replace(/_/g, ' ') });
|
|
89
|
-
if (k.price) out.push({ label: 'kit.press.price', value: `${k.price}${k.currency ? ' ' + k.currency : ''}` });
|
|
90
|
-
if (k.website_url) out.push({ label: 'kit.press.website', value: k.website_url, accent: true, href: k.website_url });
|
|
91
|
-
if (k.steam_url) out.push({ label: 'Steam', value: k.steam_url, href: k.steam_url });
|
|
92
|
-
if (k.press_contact_email) out.push({ label: 'kit.press.contact', value: k.press_contact_email, href: `mailto:${k.press_contact_email}` });
|
|
93
|
-
return out;
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
function track(type: 'click' | 'download' | 'contact') {
|
|
97
|
-
trackPressKitEvent(slug, { event_type: type, referrer: document.referrer || undefined }).catch(() => {});
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const requestUrl = useRequestURL();
|
|
101
|
-
useHead(() => ({
|
|
102
|
-
title: kit.value ? `${kit.value.name} — Press Kit` : 'Press Kit',
|
|
103
|
-
meta: [
|
|
104
|
-
{ name: 'description', content: kit.value?.tagline || '' },
|
|
105
|
-
{ property: 'og:title', content: kit.value?.name || 'Press Kit' },
|
|
106
|
-
{ property: 'og:description', content: kit.value?.tagline || '' },
|
|
107
|
-
{ property: 'og:image', content: kit.value?.hero_image_url || kit.value?.logo_url || '' },
|
|
108
|
-
{ property: 'og:type', content: 'article' },
|
|
109
|
-
{ property: 'og:url', content: requestUrl.href },
|
|
110
|
-
],
|
|
111
|
-
}));
|
|
2
|
+
// Redirect /presskit/[slug] → /presskit/game/[slug] (canonical press kit route)
|
|
3
|
+
definePageMeta({ layout: 'blank' })
|
|
4
|
+
const route = useRoute()
|
|
5
|
+
navigateTo(`/presskit/game/${route.params.slug}`, { redirectCode: 301 })
|
|
112
6
|
</script>
|
|
113
|
-
|
|
114
|
-
<template>
|
|
115
|
-
<div class="kit-press" :data-tpl="tpl" :data-layout="layout">
|
|
116
|
-
<div v-if="loading" class="kit-state">{{ $t('kit.loading') }}</div>
|
|
117
|
-
<div v-else-if="error || !kit" class="kit-state">
|
|
118
|
-
<h2>{{ $t('kit.press.not_found') }}</h2>
|
|
119
|
-
</div>
|
|
120
|
-
|
|
121
|
-
<template v-else>
|
|
122
|
-
<!-- CAPA / COVER -->
|
|
123
|
-
<header class="kit-cover">
|
|
124
|
-
<img v-if="kit.hero_image_url" class="kit-cover-art" :src="kit.hero_image_url" :alt="kit.name" />
|
|
125
|
-
<div class="kit-cover-inner">
|
|
126
|
-
<img v-if="kit.cover_image_url" class="kit-cover-poster" :src="kit.cover_image_url" :alt="kit.name" />
|
|
127
|
-
<div class="kit-cover-text">
|
|
128
|
-
<span v-if="kit.release_status" class="kit-eyebrow">{{ String(kit.release_status).replace(/_/g, ' ') }}</span>
|
|
129
|
-
<img v-if="kit.logo_url" class="kit-cover-logo-img" :src="kit.logo_url" :alt="kit.name" />
|
|
130
|
-
<h1 v-else>{{ kit.name }}</h1>
|
|
131
|
-
<p v-if="kit.tagline" class="kit-tagline">{{ kit.tagline }}</p>
|
|
132
|
-
<p v-if="kit.developer" class="kit-kicker">{{ kit.developer }}</p>
|
|
133
|
-
<div class="kit-actions">
|
|
134
|
-
<a v-if="allowDownload" class="kit-btn kit-btn-primary" @click="track('download')">{{ $t('kit.press.download_assets') }}</a>
|
|
135
|
-
<a v-if="kit.press_contact_email" class="kit-btn kit-btn-ghost" :href="`mailto:${kit.press_contact_email}`" @click="track('contact')">{{ $t('kit.press.request_key') }}</a>
|
|
136
|
-
</div>
|
|
137
|
-
</div>
|
|
138
|
-
</div>
|
|
139
|
-
</header>
|
|
140
|
-
|
|
141
|
-
<div class="kit-wrap">
|
|
142
|
-
<div class="kit-layout">
|
|
143
|
-
<aside class="kit-sidebar">
|
|
144
|
-
<div class="kit-card kit-factsheet">
|
|
145
|
-
<h3 class="kit-fact-title">{{ $t('kit.press.fact_sheet') }}</h3>
|
|
146
|
-
<div v-for="f in facts" :key="f.label" class="kit-fact">
|
|
147
|
-
<span class="k">{{ $te(f.label) ? $t(f.label) : f.label }}</span>
|
|
148
|
-
<a v-if="f.href" class="v accent" :href="f.href" target="_blank" rel="noopener" @click="track('click')">{{ f.value }}</a>
|
|
149
|
-
<span v-else class="v" :class="{ accent: f.accent }">{{ f.value }}</span>
|
|
150
|
-
</div>
|
|
151
|
-
<div v-if="socials.length" class="kit-fact">
|
|
152
|
-
<span class="k">{{ $t('kit.press.social') }}</span>
|
|
153
|
-
<div class="kit-socials">
|
|
154
|
-
<a v-for="s in socials" :key="s.platform" :href="s.url" target="_blank" rel="noopener" @click="track('click')">{{ s.platform.charAt(0).toUpperCase() }}</a>
|
|
155
|
-
</div>
|
|
156
|
-
</div>
|
|
157
|
-
</div>
|
|
158
|
-
</aside>
|
|
159
|
-
|
|
160
|
-
<main class="kit-main">
|
|
161
|
-
<section v-if="kit.description" class="kit-block">
|
|
162
|
-
<h2>{{ $t('kit.press.about') }}</h2>
|
|
163
|
-
<div class="kit-lead" v-html="kit.description" />
|
|
164
|
-
</section>
|
|
165
|
-
|
|
166
|
-
<section v-if="features.length" class="kit-block">
|
|
167
|
-
<h2>{{ $t('kit.press.features') }}</h2>
|
|
168
|
-
<div class="kit-features">
|
|
169
|
-
<div v-for="(f, i) in features" :key="i" class="kit-feature"><span class="m">▸</span>{{ f }}</div>
|
|
170
|
-
</div>
|
|
171
|
-
</section>
|
|
172
|
-
|
|
173
|
-
<section v-if="videos.length" class="kit-block">
|
|
174
|
-
<h2>{{ $t('kit.press.videos') }}</h2>
|
|
175
|
-
<PressKitVideoPlayer :videos="videos" />
|
|
176
|
-
</section>
|
|
177
|
-
|
|
178
|
-
<section v-if="screenshots.length" class="kit-block">
|
|
179
|
-
<div class="kit-shead"><h2>{{ $t('kit.press.screenshots') }}</h2><a v-if="allowDownload" class="kit-dl" @click="track('download')">{{ $t('kit.press.download_all') }}</a></div>
|
|
180
|
-
<div class="kit-gallery">
|
|
181
|
-
<a v-for="(s, i) in screenshots" :key="i" class="kit-shot" :href="s.url" target="_blank" rel="noopener"><img :src="s.thumbnail_url || s.url" :alt="s.title || ''" /></a>
|
|
182
|
-
</div>
|
|
183
|
-
</section>
|
|
184
|
-
|
|
185
|
-
<section v-if="brandAssets.length" class="kit-block">
|
|
186
|
-
<div class="kit-shead"><h2>{{ $t('kit.press.logo_icons') }}</h2></div>
|
|
187
|
-
<div class="kit-logos">
|
|
188
|
-
<a v-for="(b, i) in brandAssets" :key="i" class="kit-logo-tile" :href="b.url" target="_blank" rel="noopener" @click="track('download')">
|
|
189
|
-
<span class="ic">◆</span>{{ b.title || b.type }}
|
|
190
|
-
</a>
|
|
191
|
-
</div>
|
|
192
|
-
</section>
|
|
193
|
-
|
|
194
|
-
<!-- NEW: Conteúdos & Artigos (community + external) -->
|
|
195
|
-
<section v-if="articles.length" class="kit-block">
|
|
196
|
-
<div class="kit-shead"><h2>{{ $t('kit.press.articles') }}</h2></div>
|
|
197
|
-
<div class="kit-articles">
|
|
198
|
-
<a v-for="(a, i) in articles" :key="i" class="kit-article" :href="a.url" target="_blank" rel="noopener" @click="track('click')">
|
|
199
|
-
<div class="thumb" :style="a.image ? { backgroundImage: `url(${a.image})` } : {}"><span class="src" :class="{ ext: a.external }">{{ a.external ? $t('kit.press.external') : 'Mundo Gamer' }}</span></div>
|
|
200
|
-
<div class="a-body"><h4>{{ a.title }}</h4><div class="meta">{{ a.source }}<span v-if="a.date"> · {{ a.date }}</span></div></div>
|
|
201
|
-
</a>
|
|
202
|
-
</div>
|
|
203
|
-
</section>
|
|
204
|
-
|
|
205
|
-
<!-- NEW: Cobertura de Criadores -->
|
|
206
|
-
<section v-if="coverage.length" class="kit-block">
|
|
207
|
-
<h2>{{ $t('kit.press.coverage') }}</h2>
|
|
208
|
-
<div class="kit-creators">
|
|
209
|
-
<a v-for="(c, i) in coverage" :key="i" class="kit-creator" :href="c.url || undefined" target="_blank" rel="noopener">
|
|
210
|
-
<div class="av" :style="c.avatar ? { backgroundImage: `url(${c.avatar})` } : {}" />
|
|
211
|
-
<div class="cn">{{ c.name }}</div>
|
|
212
|
-
<div class="cp">{{ c.platform }}<span v-if="c.followers"> · {{ c.followers }}</span></div>
|
|
213
|
-
<div v-if="c.label" class="cv">{{ c.label }}</div>
|
|
214
|
-
</a>
|
|
215
|
-
</div>
|
|
216
|
-
</section>
|
|
217
|
-
|
|
218
|
-
<section v-if="awards.length" class="kit-block">
|
|
219
|
-
<h2>{{ $t('kit.press.awards') }}</h2>
|
|
220
|
-
<PressKitAwards :awards="awards" />
|
|
221
|
-
</section>
|
|
222
|
-
|
|
223
|
-
<section v-if="quotes.length" class="kit-block">
|
|
224
|
-
<h2>{{ $t('kit.press.press') }}</h2>
|
|
225
|
-
<PressKitQuotes :quotes="quotes" />
|
|
226
|
-
</section>
|
|
227
|
-
|
|
228
|
-
<!-- Créditos -> Equipe -->
|
|
229
|
-
<section v-if="team.length" class="kit-block">
|
|
230
|
-
<h2>{{ $t('kit.press.team') }}</h2>
|
|
231
|
-
<div class="kit-team">
|
|
232
|
-
<div v-for="(m, i) in team" :key="i" class="kit-member"><span>{{ m.name }}</span><span class="role">{{ m.role }}</span></div>
|
|
233
|
-
</div>
|
|
234
|
-
</section>
|
|
235
|
-
|
|
236
|
-
<!-- NEW: Ecossistema Mundo Gamer -->
|
|
237
|
-
<section v-if="hasEcosystem" class="kit-block">
|
|
238
|
-
<h2>{{ $t('kit.press.ecosystem') }}</h2>
|
|
239
|
-
<div class="kit-eco">
|
|
240
|
-
<div v-if="showcases.length" class="kit-eco-card full">
|
|
241
|
-
<div class="kit-eco-h"><span class="ic">★</span>{{ $t('kit.press.showcases') }}</div>
|
|
242
|
-
<div class="kit-sbadges">
|
|
243
|
-
<span v-for="(s, i) in showcases" :key="i" class="kit-sbadge" :class="{ feat: s.featured }"><span class="medal">{{ s.featured ? '🏵️' : '🎮' }}</span>{{ s.name }}<span v-if="s.year"> {{ s.year }}</span></span>
|
|
244
|
-
</div>
|
|
245
|
-
</div>
|
|
246
|
-
<div v-if="kit.ventures_url" class="kit-eco-card">
|
|
247
|
-
<div class="kit-eco-h"><span class="ic">◈</span>MGN Ventures</div>
|
|
248
|
-
<a class="kit-vrow" :href="kit.ventures_url" target="_blank" rel="noopener" @click="track('click')"><span class="vlogo">VENTURES</span><span class="vtxt">{{ $t('kit.press.ventures_text') }}</span></a>
|
|
249
|
-
</div>
|
|
250
|
-
<a v-if="kit.magazine_feature" class="kit-eco-card kit-mag" :href="kit.magazine_feature.url" target="_blank" rel="noopener" @click="track('click')">
|
|
251
|
-
<div class="kit-eco-h" style="width:100%"><span class="ic">▤</span>MGN Magazine</div>
|
|
252
|
-
<div class="kit-mag-row"><div class="mcover" :style="kit.magazine_feature.cover ? { backgroundImage: `url(${kit.magazine_feature.cover})` } : {}" /><div><div class="mtitle">{{ kit.magazine_feature.title }}</div><div class="mmeta">{{ kit.magazine_feature.issue }}</div></div></div>
|
|
253
|
-
</a>
|
|
254
|
-
<div v-if="kit.community_url" class="kit-eco-card full">
|
|
255
|
-
<div class="kit-ccta">
|
|
256
|
-
<div><div class="ctitle">{{ $t('kit.press.follow_community', { name: kit.name }) }}</div><div v-if="kit.community_followers" class="cmeta">{{ kit.community_followers }} {{ $t('kit.press.followers') }}</div></div>
|
|
257
|
-
<a class="kit-btn kit-btn-primary" :href="kit.community_url" target="_blank" rel="noopener" @click="track('click')">{{ $t('kit.press.follow') }}</a>
|
|
258
|
-
</div>
|
|
259
|
-
</div>
|
|
260
|
-
</div>
|
|
261
|
-
</section>
|
|
262
|
-
|
|
263
|
-
<!-- Key pools embed — shown when game has active pools -->
|
|
264
|
-
<section v-if="kit.game_id" v-show="keyPoolsVisible" class="kit-block kit-keys-section">
|
|
265
|
-
<h2 class="kit-keys-title">{{ $t('kit.press.get_key_title') }}</h2>
|
|
266
|
-
<p class="kit-keys-desc">{{ $t('kit.press.get_key_desc') }}</p>
|
|
267
|
-
<KeyBrowser
|
|
268
|
-
requester-context="user"
|
|
269
|
-
:game-id="kit.game_id"
|
|
270
|
-
@pools-ready="onPoolsReady"
|
|
271
|
-
/>
|
|
272
|
-
</section>
|
|
273
|
-
|
|
274
|
-
<section v-if="kit.press_contact_email" class="kit-block">
|
|
275
|
-
<div class="kit-cta">
|
|
276
|
-
<h2>{{ $t('kit.press.covering', { name: kit.name }) }}</h2>
|
|
277
|
-
<p>{{ $t('kit.press.cta_text') }}</p>
|
|
278
|
-
<a class="kit-btn kit-btn-primary" :href="`mailto:${kit.press_contact_email}`" @click="track('contact')">{{ $t('kit.press.contact_btn') }}</a>
|
|
279
|
-
</div>
|
|
280
|
-
</section>
|
|
281
|
-
|
|
282
|
-
<p class="kit-madewith">
|
|
283
|
-
{{ $t('kit.press.made_with') }} <strong>Mundo Gamer</strong> —
|
|
284
|
-
<a :href="kit.create_kit_url || `${agencyBase}/presskit`" target="_blank" rel="noopener">{{ $t('kit.press.create_yours') }}</a>
|
|
285
|
-
</p>
|
|
286
|
-
</main>
|
|
287
|
-
</div>
|
|
288
|
-
</div>
|
|
289
|
-
</template>
|
|
290
|
-
</div>
|
|
291
|
-
</template>
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { trackPressKitEvent } from '../../../services/pressKitService';
|
|
3
|
+
|
|
4
|
+
definePageMeta({ layout: 'blank' });
|
|
5
|
+
|
|
6
|
+
const route = useRoute();
|
|
7
|
+
const slug = route.params.slug as string;
|
|
8
|
+
|
|
9
|
+
const runtimeConfig = useRuntimeConfig();
|
|
10
|
+
const cfg = (runtimeConfig.public?.mgSharedUi || {}) as Record<string, any>;
|
|
11
|
+
// Consuming apps may set apiBaseURL at public root (agency/community/tv pattern)
|
|
12
|
+
// or inside mgSharedUi. pressKitApiUrl overrides both (e.g. community points to agency API).
|
|
13
|
+
const apiBase: string =
|
|
14
|
+
cfg.pressKitApiUrl ||
|
|
15
|
+
(runtimeConfig.public as any)?.pressKitApiUrl ||
|
|
16
|
+
cfg.apiBaseURL ||
|
|
17
|
+
(runtimeConfig.public as any)?.apiBaseURL ||
|
|
18
|
+
'';
|
|
19
|
+
|
|
20
|
+
const agencyBase: string =
|
|
21
|
+
cfg.agencyBaseUrl ||
|
|
22
|
+
(runtimeConfig.public as any)?.agencyBaseUrl ||
|
|
23
|
+
'';
|
|
24
|
+
|
|
25
|
+
const SUPPORTED_LOCALES = ['en', 'pt-BR', 'es', 'de', 'ro', 'ar-AE'];
|
|
26
|
+
const routePath = route.path.split('/');
|
|
27
|
+
const lang = SUPPORTED_LOCALES.find(l => routePath.includes(l)) || 'en';
|
|
28
|
+
|
|
29
|
+
const { data: kitData, error: fetchError, pending } = await useAsyncData(
|
|
30
|
+
`press-kit-${slug}`,
|
|
31
|
+
() => $fetch<any>(`${apiBase}/public/press-kits/${slug}`, {
|
|
32
|
+
params: { include: 'assets,videos,credits,awards,quotes', lang },
|
|
33
|
+
}),
|
|
34
|
+
{ lazy: false },
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const kit = computed(() => kitData.value?.data || kitData.value || null);
|
|
38
|
+
const loading = pending;
|
|
39
|
+
const error = computed(() => !!fetchError.value || (!pending.value && !kit.value));
|
|
40
|
+
|
|
41
|
+
onMounted(() => {
|
|
42
|
+
if (kit.value) {
|
|
43
|
+
trackPressKitEvent(slug, {
|
|
44
|
+
event_type: 'view',
|
|
45
|
+
referrer: document.referrer || undefined,
|
|
46
|
+
}).catch(() => {});
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Fractal include shape: relation -> { data: [...] }
|
|
51
|
+
const list = (rel: any) => rel?.data || rel || [];
|
|
52
|
+
const assets = computed(() => list(kit.value?.assets));
|
|
53
|
+
const videos = computed(() => list(kit.value?.videos));
|
|
54
|
+
const awards = computed(() => list(kit.value?.awards));
|
|
55
|
+
const quotes = computed(() => list(kit.value?.quotes));
|
|
56
|
+
const team = computed(() => list(kit.value?.credits));
|
|
57
|
+
const features = computed(() => kit.value?.key_features || []);
|
|
58
|
+
// New, optional blocks (rendered only when the API provides them)
|
|
59
|
+
const articles = computed(() => list(kit.value?.articles));
|
|
60
|
+
const coverage = computed(() => list(kit.value?.coverage));
|
|
61
|
+
const showcases = computed(() => list(kit.value?.showcases));
|
|
62
|
+
const hasEcosystem = computed(() => showcases.value.length || kit.value?.ventures_url || kit.value?.magazine_feature || kit.value?.community_url);
|
|
63
|
+
|
|
64
|
+
const screenshots = computed(() => assets.value.filter((a: any) => ['screenshot', 'artwork', 'gif'].includes(a.type)));
|
|
65
|
+
const brandAssets = computed(() => assets.value.filter((a: any) => ['logo', 'document'].includes(a.type)));
|
|
66
|
+
|
|
67
|
+
const tpl = computed(() => kit.value?.theme || null);
|
|
68
|
+
const layout = computed(() => kit.value?.layout || 'classic');
|
|
69
|
+
const allowDownload = computed(() => kit.value?.allow_asset_download !== false);
|
|
70
|
+
|
|
71
|
+
const keyPoolsVisible = ref(false);
|
|
72
|
+
function onPoolsReady(count: number) {
|
|
73
|
+
keyPoolsVisible.value = count > 0;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const socials = computed(() => {
|
|
77
|
+
const s = kit.value?.social_links || {};
|
|
78
|
+
return Object.entries(s).filter(([, v]) => v).map(([k, v]) => ({ platform: k, url: v as string }));
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const facts = computed(() => {
|
|
82
|
+
const k = kit.value || {};
|
|
83
|
+
const out: { label: string; value: string; accent?: boolean; href?: string }[] = [];
|
|
84
|
+
if (k.developer) out.push({ label: 'kit.press.developer', value: k.developer });
|
|
85
|
+
if (k.publisher) out.push({ label: 'kit.press.publisher', value: k.publisher });
|
|
86
|
+
if (k.release_date_tba) out.push({ label: 'kit.press.release', value: 'TBA', accent: true });
|
|
87
|
+
else if (k.release_date) out.push({ label: 'kit.press.release', value: k.release_date, accent: true });
|
|
88
|
+
if (k.release_status) out.push({ label: 'kit.press.status', value: String(k.release_status).replace(/_/g, ' ') });
|
|
89
|
+
if (k.price) out.push({ label: 'kit.press.price', value: `${k.price}${k.currency ? ' ' + k.currency : ''}` });
|
|
90
|
+
if (k.website_url) out.push({ label: 'kit.press.website', value: k.website_url, accent: true, href: k.website_url });
|
|
91
|
+
if (k.steam_url) out.push({ label: 'Steam', value: k.steam_url, href: k.steam_url });
|
|
92
|
+
if (k.press_contact_email) out.push({ label: 'kit.press.contact', value: k.press_contact_email, href: `mailto:${k.press_contact_email}` });
|
|
93
|
+
return out;
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
function track(type: 'click' | 'download' | 'contact') {
|
|
97
|
+
trackPressKitEvent(slug, { event_type: type, referrer: document.referrer || undefined }).catch(() => {});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const requestUrl = useRequestURL();
|
|
101
|
+
useHead(() => ({
|
|
102
|
+
title: kit.value ? `${kit.value.name} — Press Kit` : 'Press Kit',
|
|
103
|
+
meta: [
|
|
104
|
+
{ name: 'description', content: kit.value?.tagline || '' },
|
|
105
|
+
{ property: 'og:title', content: kit.value?.name || 'Press Kit' },
|
|
106
|
+
{ property: 'og:description', content: kit.value?.tagline || '' },
|
|
107
|
+
{ property: 'og:image', content: kit.value?.hero_image_url || kit.value?.logo_url || '' },
|
|
108
|
+
{ property: 'og:type', content: 'article' },
|
|
109
|
+
{ property: 'og:url', content: requestUrl.href },
|
|
110
|
+
],
|
|
111
|
+
}));
|
|
112
|
+
</script>
|
|
113
|
+
|
|
114
|
+
<template>
|
|
115
|
+
<div class="kit-press" :data-tpl="tpl" :data-layout="layout">
|
|
116
|
+
<div v-if="loading" class="kit-state">{{ $t('kit.loading') }}</div>
|
|
117
|
+
<div v-else-if="error || !kit" class="kit-state">
|
|
118
|
+
<h2>{{ $t('kit.press.not_found') }}</h2>
|
|
119
|
+
</div>
|
|
120
|
+
|
|
121
|
+
<template v-else>
|
|
122
|
+
<!-- CAPA / COVER -->
|
|
123
|
+
<header class="kit-cover">
|
|
124
|
+
<img v-if="kit.hero_image_url" class="kit-cover-art" :src="kit.hero_image_url" :alt="kit.name" />
|
|
125
|
+
<div class="kit-cover-inner">
|
|
126
|
+
<img v-if="kit.cover_image_url" class="kit-cover-poster" :src="kit.cover_image_url" :alt="kit.name" />
|
|
127
|
+
<div class="kit-cover-text">
|
|
128
|
+
<span v-if="kit.release_status" class="kit-eyebrow">{{ String(kit.release_status).replace(/_/g, ' ') }}</span>
|
|
129
|
+
<img v-if="kit.logo_url" class="kit-cover-logo-img" :src="kit.logo_url" :alt="kit.name" />
|
|
130
|
+
<h1 v-else>{{ kit.name }}</h1>
|
|
131
|
+
<p v-if="kit.tagline" class="kit-tagline">{{ kit.tagline }}</p>
|
|
132
|
+
<p v-if="kit.developer" class="kit-kicker">{{ kit.developer }}</p>
|
|
133
|
+
<div class="kit-actions">
|
|
134
|
+
<a v-if="allowDownload" class="kit-btn kit-btn-primary" @click="track('download')">{{ $t('kit.press.download_assets') }}</a>
|
|
135
|
+
<a v-if="kit.press_contact_email" class="kit-btn kit-btn-ghost" :href="`mailto:${kit.press_contact_email}`" @click="track('contact')">{{ $t('kit.press.request_key') }}</a>
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
</header>
|
|
140
|
+
|
|
141
|
+
<div class="kit-wrap">
|
|
142
|
+
<div class="kit-layout">
|
|
143
|
+
<aside class="kit-sidebar">
|
|
144
|
+
<div class="kit-card kit-factsheet">
|
|
145
|
+
<h3 class="kit-fact-title">{{ $t('kit.press.fact_sheet') }}</h3>
|
|
146
|
+
<div v-for="f in facts" :key="f.label" class="kit-fact">
|
|
147
|
+
<span class="k">{{ $te(f.label) ? $t(f.label) : f.label }}</span>
|
|
148
|
+
<a v-if="f.href" class="v accent" :href="f.href" target="_blank" rel="noopener" @click="track('click')">{{ f.value }}</a>
|
|
149
|
+
<span v-else class="v" :class="{ accent: f.accent }">{{ f.value }}</span>
|
|
150
|
+
</div>
|
|
151
|
+
<div v-if="socials.length" class="kit-fact">
|
|
152
|
+
<span class="k">{{ $t('kit.press.social') }}</span>
|
|
153
|
+
<div class="kit-socials">
|
|
154
|
+
<a v-for="s in socials" :key="s.platform" :href="s.url" target="_blank" rel="noopener" @click="track('click')">{{ s.platform.charAt(0).toUpperCase() }}</a>
|
|
155
|
+
</div>
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
</aside>
|
|
159
|
+
|
|
160
|
+
<main class="kit-main">
|
|
161
|
+
<section v-if="kit.description" class="kit-block">
|
|
162
|
+
<h2>{{ $t('kit.press.about') }}</h2>
|
|
163
|
+
<div class="kit-lead" v-html="kit.description" />
|
|
164
|
+
</section>
|
|
165
|
+
|
|
166
|
+
<section v-if="features.length" class="kit-block">
|
|
167
|
+
<h2>{{ $t('kit.press.features') }}</h2>
|
|
168
|
+
<div class="kit-features">
|
|
169
|
+
<div v-for="(f, i) in features" :key="i" class="kit-feature"><span class="m">▸</span>{{ f }}</div>
|
|
170
|
+
</div>
|
|
171
|
+
</section>
|
|
172
|
+
|
|
173
|
+
<section v-if="videos.length" class="kit-block">
|
|
174
|
+
<h2>{{ $t('kit.press.videos') }}</h2>
|
|
175
|
+
<PressKitVideoPlayer :videos="videos" />
|
|
176
|
+
</section>
|
|
177
|
+
|
|
178
|
+
<section v-if="screenshots.length" class="kit-block">
|
|
179
|
+
<div class="kit-shead"><h2>{{ $t('kit.press.screenshots') }}</h2><a v-if="allowDownload" class="kit-dl" @click="track('download')">{{ $t('kit.press.download_all') }}</a></div>
|
|
180
|
+
<div class="kit-gallery">
|
|
181
|
+
<a v-for="(s, i) in screenshots" :key="i" class="kit-shot" :href="s.url" target="_blank" rel="noopener"><img :src="s.thumbnail_url || s.url" :alt="s.title || ''" /></a>
|
|
182
|
+
</div>
|
|
183
|
+
</section>
|
|
184
|
+
|
|
185
|
+
<section v-if="brandAssets.length" class="kit-block">
|
|
186
|
+
<div class="kit-shead"><h2>{{ $t('kit.press.logo_icons') }}</h2></div>
|
|
187
|
+
<div class="kit-logos">
|
|
188
|
+
<a v-for="(b, i) in brandAssets" :key="i" class="kit-logo-tile" :href="b.url" target="_blank" rel="noopener" @click="track('download')">
|
|
189
|
+
<span class="ic">◆</span>{{ b.title || b.type }}
|
|
190
|
+
</a>
|
|
191
|
+
</div>
|
|
192
|
+
</section>
|
|
193
|
+
|
|
194
|
+
<!-- NEW: Conteúdos & Artigos (community + external) -->
|
|
195
|
+
<section v-if="articles.length" class="kit-block">
|
|
196
|
+
<div class="kit-shead"><h2>{{ $t('kit.press.articles') }}</h2></div>
|
|
197
|
+
<div class="kit-articles">
|
|
198
|
+
<a v-for="(a, i) in articles" :key="i" class="kit-article" :href="a.url" target="_blank" rel="noopener" @click="track('click')">
|
|
199
|
+
<div class="thumb" :style="a.image ? { backgroundImage: `url(${a.image})` } : {}"><span class="src" :class="{ ext: a.external }">{{ a.external ? $t('kit.press.external') : 'Mundo Gamer' }}</span></div>
|
|
200
|
+
<div class="a-body"><h4>{{ a.title }}</h4><div class="meta">{{ a.source }}<span v-if="a.date"> · {{ a.date }}</span></div></div>
|
|
201
|
+
</a>
|
|
202
|
+
</div>
|
|
203
|
+
</section>
|
|
204
|
+
|
|
205
|
+
<!-- NEW: Cobertura de Criadores -->
|
|
206
|
+
<section v-if="coverage.length" class="kit-block">
|
|
207
|
+
<h2>{{ $t('kit.press.coverage') }}</h2>
|
|
208
|
+
<div class="kit-creators">
|
|
209
|
+
<a v-for="(c, i) in coverage" :key="i" class="kit-creator" :href="c.url || undefined" target="_blank" rel="noopener">
|
|
210
|
+
<div class="av" :style="c.avatar ? { backgroundImage: `url(${c.avatar})` } : {}" />
|
|
211
|
+
<div class="cn">{{ c.name }}</div>
|
|
212
|
+
<div class="cp">{{ c.platform }}<span v-if="c.followers"> · {{ c.followers }}</span></div>
|
|
213
|
+
<div v-if="c.label" class="cv">{{ c.label }}</div>
|
|
214
|
+
</a>
|
|
215
|
+
</div>
|
|
216
|
+
</section>
|
|
217
|
+
|
|
218
|
+
<section v-if="awards.length" class="kit-block">
|
|
219
|
+
<h2>{{ $t('kit.press.awards') }}</h2>
|
|
220
|
+
<PressKitAwards :awards="awards" />
|
|
221
|
+
</section>
|
|
222
|
+
|
|
223
|
+
<section v-if="quotes.length" class="kit-block">
|
|
224
|
+
<h2>{{ $t('kit.press.press') }}</h2>
|
|
225
|
+
<PressKitQuotes :quotes="quotes" />
|
|
226
|
+
</section>
|
|
227
|
+
|
|
228
|
+
<!-- Créditos -> Equipe -->
|
|
229
|
+
<section v-if="team.length" class="kit-block">
|
|
230
|
+
<h2>{{ $t('kit.press.team') }}</h2>
|
|
231
|
+
<div class="kit-team">
|
|
232
|
+
<div v-for="(m, i) in team" :key="i" class="kit-member"><span>{{ m.name }}</span><span class="role">{{ m.role }}</span></div>
|
|
233
|
+
</div>
|
|
234
|
+
</section>
|
|
235
|
+
|
|
236
|
+
<!-- NEW: Ecossistema Mundo Gamer -->
|
|
237
|
+
<section v-if="hasEcosystem" class="kit-block">
|
|
238
|
+
<h2>{{ $t('kit.press.ecosystem') }}</h2>
|
|
239
|
+
<div class="kit-eco">
|
|
240
|
+
<div v-if="showcases.length" class="kit-eco-card full">
|
|
241
|
+
<div class="kit-eco-h"><span class="ic">★</span>{{ $t('kit.press.showcases') }}</div>
|
|
242
|
+
<div class="kit-sbadges">
|
|
243
|
+
<span v-for="(s, i) in showcases" :key="i" class="kit-sbadge" :class="{ feat: s.featured }"><span class="medal">{{ s.featured ? '🏵️' : '🎮' }}</span>{{ s.name }}<span v-if="s.year"> {{ s.year }}</span></span>
|
|
244
|
+
</div>
|
|
245
|
+
</div>
|
|
246
|
+
<div v-if="kit.ventures_url" class="kit-eco-card">
|
|
247
|
+
<div class="kit-eco-h"><span class="ic">◈</span>MGN Ventures</div>
|
|
248
|
+
<a class="kit-vrow" :href="kit.ventures_url" target="_blank" rel="noopener" @click="track('click')"><span class="vlogo">VENTURES</span><span class="vtxt">{{ $t('kit.press.ventures_text') }}</span></a>
|
|
249
|
+
</div>
|
|
250
|
+
<a v-if="kit.magazine_feature" class="kit-eco-card kit-mag" :href="kit.magazine_feature.url" target="_blank" rel="noopener" @click="track('click')">
|
|
251
|
+
<div class="kit-eco-h" style="width:100%"><span class="ic">▤</span>MGN Magazine</div>
|
|
252
|
+
<div class="kit-mag-row"><div class="mcover" :style="kit.magazine_feature.cover ? { backgroundImage: `url(${kit.magazine_feature.cover})` } : {}" /><div><div class="mtitle">{{ kit.magazine_feature.title }}</div><div class="mmeta">{{ kit.magazine_feature.issue }}</div></div></div>
|
|
253
|
+
</a>
|
|
254
|
+
<div v-if="kit.community_url" class="kit-eco-card full">
|
|
255
|
+
<div class="kit-ccta">
|
|
256
|
+
<div><div class="ctitle">{{ $t('kit.press.follow_community', { name: kit.name }) }}</div><div v-if="kit.community_followers" class="cmeta">{{ kit.community_followers }} {{ $t('kit.press.followers') }}</div></div>
|
|
257
|
+
<a class="kit-btn kit-btn-primary" :href="kit.community_url" target="_blank" rel="noopener" @click="track('click')">{{ $t('kit.press.follow') }}</a>
|
|
258
|
+
</div>
|
|
259
|
+
</div>
|
|
260
|
+
</div>
|
|
261
|
+
</section>
|
|
262
|
+
|
|
263
|
+
<!-- Key pools embed — shown when game has active pools -->
|
|
264
|
+
<section v-if="kit.game_id" v-show="keyPoolsVisible" class="kit-block kit-keys-section">
|
|
265
|
+
<h2 class="kit-keys-title">{{ $t('kit.press.get_key_title') }}</h2>
|
|
266
|
+
<p class="kit-keys-desc">{{ $t('kit.press.get_key_desc') }}</p>
|
|
267
|
+
<KeyBrowser
|
|
268
|
+
requester-context="user"
|
|
269
|
+
:game-id="kit.game_id"
|
|
270
|
+
@pools-ready="onPoolsReady"
|
|
271
|
+
/>
|
|
272
|
+
</section>
|
|
273
|
+
|
|
274
|
+
<section v-if="kit.press_contact_email" class="kit-block">
|
|
275
|
+
<div class="kit-cta">
|
|
276
|
+
<h2>{{ $t('kit.press.covering', { name: kit.name }) }}</h2>
|
|
277
|
+
<p>{{ $t('kit.press.cta_text') }}</p>
|
|
278
|
+
<a class="kit-btn kit-btn-primary" :href="`mailto:${kit.press_contact_email}`" @click="track('contact')">{{ $t('kit.press.contact_btn') }}</a>
|
|
279
|
+
</div>
|
|
280
|
+
</section>
|
|
281
|
+
|
|
282
|
+
<p class="kit-madewith">
|
|
283
|
+
{{ $t('kit.press.made_with') }} <strong>Mundo Gamer</strong> —
|
|
284
|
+
<a :href="kit.create_kit_url || `${agencyBase}/presskit`" target="_blank" rel="noopener">{{ $t('kit.press.create_yours') }}</a>
|
|
285
|
+
</p>
|
|
286
|
+
</main>
|
|
287
|
+
</div>
|
|
288
|
+
</div>
|
|
289
|
+
</template>
|
|
290
|
+
</div>
|
|
291
|
+
</template>
|