@mundogamernetwork/shared-ui 1.0.1 → 1.0.2

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mundogamernetwork/shared-ui",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Mundo Gamer Network - Shared UI Layer (Nuxt 3)",
5
5
  "type": "module",
6
6
  "main": "./nuxt.config.ts",
@@ -22,8 +22,17 @@ const styles = computed(() => kit.value?.content_styles ?? []);
22
22
  const brands = computed(() => kit.value?.brands ?? []);
23
23
  const period = computed(() => kit.value?.period ?? null);
24
24
  const tpl = computed(() => kit.value?.theme || null);
25
+ // Layout emphasis template (premium): creator (default) / performance / commercial / audience
26
+ const template = computed(() => kit.value?.template || 'creator');
27
+ const platforms = computed(() => kit.value?.platforms ?? []);
28
+ const totalFollowers = computed(() => kit.value?.total_followers ?? 0);
25
29
  const mediaKitWall = computed(() => walls.value.find((w: any) => w.show_on_media_kit) ?? null);
26
30
 
31
+ const PLATFORM_LABEL: Record<string, string> = {
32
+ instagram: 'Instagram', tiktok: 'TikTok', youtube: 'YouTube', twitch: 'Twitch', x: 'X',
33
+ facebook: 'Facebook', kick: 'Kick', discord: 'Discord', telegram: 'Telegram', linkedin: 'LinkedIn', bluesky: 'Bluesky',
34
+ };
35
+
27
36
  const socials = computed(() => {
28
37
  const s = streamer.value?.social_links || {};
29
38
  return Object.entries(s).filter(([, v]) => v).map(([k, v]) => ({ platform: k, url: v as string }));
@@ -74,13 +83,13 @@ function onDownload() {
74
83
  </script>
75
84
 
76
85
  <template>
77
- <div class="kit-media" :data-tpl="tpl">
86
+ <div class="kit-media" :data-tpl="tpl" :data-template="template">
78
87
  <div v-if="loading" class="kit-state">{{ $t('kit.loading') }}</div>
79
88
  <div v-else-if="error || !kit" class="kit-state"><p>{{ $t('kit.media.not_available') }}</p></div>
80
89
 
81
90
  <template v-else>
82
91
  <div class="mk-cover" />
83
- <div class="kit-wrap">
92
+ <div class="kit-wrap mk-sections">
84
93
  <header class="mk-header">
85
94
  <img v-if="streamer.avatar" class="mk-avatar" :src="streamer.avatar" :alt="streamer.name" />
86
95
  <div v-else class="mk-avatar mk-avatar-ph" />
@@ -98,7 +107,25 @@ function onDownload() {
98
107
  </div>
99
108
  </header>
100
109
 
101
- <section v-if="stats" class="kit-block">
110
+ <section v-if="platforms.length" class="kit-block" data-sec="reach">
111
+ <h2>{{ $t('kit.media.reach') }}</h2>
112
+ <p v-if="totalFollowers" class="mk-total-reach">{{ fmt(totalFollowers) }} <span>{{ $t('kit.media.total_reach') }}</span></p>
113
+ <div class="mk-platforms">
114
+ <a v-for="p in platforms" :key="p.platform" class="mk-platform" :href="p.url || undefined" target="_blank" rel="noopener" @click="track('click')">
115
+ <div class="pl-head">
116
+ <span class="pl-name">{{ PLATFORM_LABEL[p.platform] || p.platform }}</span>
117
+ <span v-if="p.verified" class="pl-verified" :title="$t('kit.media.verified')">✓</span>
118
+ </div>
119
+ <div class="pl-followers">{{ fmt(p.followers) }}</div>
120
+ <div class="pl-meta">
121
+ <span v-if="p.engagement_rate != null">{{ p.engagement_rate }}% {{ $t('kit.media.eng_short') }}</span>
122
+ <span v-if="p.avg_views != null">{{ fmt(p.avg_views) }} {{ $t('kit.media.views_short') }}</span>
123
+ </div>
124
+ </a>
125
+ </div>
126
+ </section>
127
+
128
+ <section v-if="stats" class="kit-block" data-sec="metrics">
102
129
  <h2>{{ $t('kit.media.key_metrics') }}</h2>
103
130
  <p v-if="period" class="mk-period">{{ $t('kit.media.last_days', { days: period.days }) }} · {{ period.start }} — {{ period.end }}</p>
104
131
  <div class="mk-metrics">
@@ -113,7 +140,7 @@ function onDownload() {
113
140
  </div>
114
141
  </section>
115
142
 
116
- <section v-if="demographics" class="kit-block">
143
+ <section v-if="demographics" data-sec="audience" class="kit-block">
117
144
  <h2>{{ $t('kit.media.audience') }}</h2>
118
145
  <div class="mk-cols2">
119
146
  <div class="kit-card mk-pad" v-if="demographics.age_ranges?.length">
@@ -132,12 +159,12 @@ function onDownload() {
132
159
  </div>
133
160
  </section>
134
161
 
135
- <section v-if="styles.length" class="kit-block">
162
+ <section v-if="styles.length" data-sec="styles" class="kit-block">
136
163
  <h2>{{ $t('kit.media.styles') }}</h2>
137
164
  <div class="mk-tags"><span v-for="(s, i) in styles" :key="i" class="mk-tag">{{ s }}</span></div>
138
165
  </section>
139
166
 
140
- <section v-if="topGames.length" class="kit-block">
167
+ <section v-if="topGames.length" data-sec="games" class="kit-block">
141
168
  <h2>{{ $t('kit.media.top_games') }}</h2>
142
169
  <div class="mk-games">
143
170
  <div v-for="g in topGames" :key="g.game" class="mk-game">
@@ -147,7 +174,7 @@ function onDownload() {
147
174
  </div>
148
175
  </section>
149
176
 
150
- <section v-if="rateCards.length || bundles.length" class="kit-block">
177
+ <section v-if="rateCards.length || bundles.length" data-sec="rates" class="kit-block">
151
178
  <h2>{{ $t('kit.media.rates') }}</h2>
152
179
  <div v-if="rateCards.length" class="mk-rates">
153
180
  <div v-for="(r, i) in rateCards" :key="i" class="mk-rate">
@@ -162,17 +189,20 @@ function onDownload() {
162
189
  <span v-if="b.discount_percent" class="off">-{{ b.discount_percent }}%</span>
163
190
  <div class="bn">{{ b.name }}</div>
164
191
  <div v-if="b.description" class="bd">{{ b.description }}</div>
192
+ <ul v-if="b.rate_cards?.length" class="bundle-items">
193
+ <li v-for="(it, j) in b.rate_cards" :key="j"><b>{{ it.quantity || 1 }}×</b> {{ it.label }}</li>
194
+ </ul>
165
195
  <div class="bp">{{ b.currency }} {{ b.bundle_price }} <s v-if="b.original_price">{{ b.original_price }}</s></div>
166
196
  </div>
167
197
  </div>
168
198
  </section>
169
199
 
170
- <section v-if="brands.length" class="kit-block">
200
+ <section v-if="brands.length" data-sec="brands" class="kit-block">
171
201
  <h2>{{ $t('kit.media.brands') }}</h2>
172
202
  <div class="mk-brands"><div v-for="(b, i) in brands" :key="i" class="mk-brand">{{ b.name || b }}</div></div>
173
203
  </section>
174
204
 
175
- <section v-if="schedule.length" class="kit-block">
205
+ <section v-if="schedule.length" data-sec="schedule" class="kit-block">
176
206
  <h2>{{ $t('kit.media.schedule') }}</h2>
177
207
  <div class="mk-schedule">
178
208
  <div v-for="d in scheduleByDay" :key="d.d" class="mk-day" :class="{ on: d.slot }">
@@ -183,14 +213,14 @@ function onDownload() {
183
213
  </div>
184
214
  </section>
185
215
 
186
- <section v-if="socials.length" class="kit-block no-print">
216
+ <section v-if="socials.length" data-sec="connect" class="kit-block no-print">
187
217
  <h2>{{ $t('kit.media.connect') }}</h2>
188
218
  <div class="mk-socials">
189
219
  <a v-for="s in socials" :key="s.platform" class="mk-soc" :href="s.url" target="_blank" rel="noopener" @click="track('click')">{{ s.platform }}</a>
190
220
  </div>
191
221
  </section>
192
222
 
193
- <section v-if="mediaKitWall" class="kit-block">
223
+ <section v-if="mediaKitWall" data-sec="support" class="kit-block">
194
224
  <h2>{{ $t('kit.media.support') }}</h2>
195
225
  <div class="mk-indiewall">
196
226
  <div>
@@ -280,6 +310,9 @@ function onDownload() {
280
310
  .mk-bundle .bd { font-size: 13px; color: var(--kit-muted); margin: 4px 0 10px; }
281
311
  .mk-bundle .bp { font-family: 'Rajdhani'; font-weight: 700; font-size: 24px; color: var(--kit-accent); }
282
312
  .mk-bundle .bp s { color: var(--kit-muted); font-size: 15px; font-weight: 500; margin-left: 8px; }
313
+ .mk-bundle .bundle-items { list-style: none; padding: 0; margin: 0 0 12px; display: flex; flex-direction: column; gap: 4px; }
314
+ .mk-bundle .bundle-items li { font-size: 13px; color: #c4c4d2; }
315
+ .mk-bundle .bundle-items li b { color: var(--kit-accent); font-family: 'Rajdhani'; }
283
316
 
284
317
  .mk-brands { display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px; }
285
318
  .mk-brand { aspect-ratio: 5/2; background: var(--kit-surface-2); border: 1px solid var(--kit-line); display: flex; align-items: center; justify-content: center; color: var(--kit-muted); font-family: 'Rajdhani'; font-weight: 700; font-size: 14px; }
@@ -312,4 +345,40 @@ function onDownload() {
312
345
  .mk-header { flex-direction: column; align-items: flex-start; }
313
346
  }
314
347
  @media print { .no-print { display: none !important; } }
348
+
349
+ /* Reach / platform breakdown */
350
+ .mk-total-reach { font-family: 'Rajdhani'; font-weight: 700; font-size: 28px; color: var(--kit-accent); margin: -8px 0 16px; }
351
+ .mk-total-reach span { font-family: 'Inter'; font-size: 13px; color: var(--kit-muted); font-weight: 500; text-transform: uppercase; letter-spacing: 1px; }
352
+ .mk-platforms { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
353
+ .mk-platform { background: var(--kit-surface); border: 1px solid var(--kit-line); padding: 16px; text-decoration: none; color: inherit; display: flex; flex-direction: column; gap: 6px; }
354
+ .mk-platform:hover { border-color: var(--kit-accent); }
355
+ .mk-platform .pl-head { display: flex; align-items: center; justify-content: space-between; }
356
+ .mk-platform .pl-name { font-size: 12px; text-transform: uppercase; letter-spacing: 1px; color: var(--kit-muted); }
357
+ .mk-platform .pl-verified { color: #27ae60; font-weight: 700; }
358
+ .mk-platform .pl-followers { font-family: 'Rajdhani'; font-weight: 700; font-size: 24px; }
359
+ .mk-platform .pl-meta { display: flex; gap: 12px; font-size: 12px; color: var(--kit-muted); flex-wrap: wrap; }
360
+
361
+ /* Template = layout emphasis (section order). Default DOM order = Creator. */
362
+ .mk-sections { display: flex; flex-direction: column; }
363
+ .mk-sections > .mk-header { order: 0; }
364
+ .mk-sections > .mk-footer { order: 100; }
365
+ .mk-sections > [data-sec="reach"]{order:1} .mk-sections > [data-sec="metrics"]{order:2}
366
+ .mk-sections > [data-sec="audience"]{order:3} .mk-sections > [data-sec="styles"]{order:4}
367
+ .mk-sections > [data-sec="games"]{order:5} .mk-sections > [data-sec="rates"]{order:6}
368
+ .mk-sections > [data-sec="brands"]{order:7} .mk-sections > [data-sec="schedule"]{order:8}
369
+ .mk-sections > [data-sec="connect"]{order:9} .mk-sections > [data-sec="support"]{order:10}
370
+
371
+ [data-template="performance"] .mk-sections > [data-sec="metrics"]{order:1}
372
+ [data-template="performance"] .mk-sections > [data-sec="reach"]{order:2}
373
+ [data-template="performance"] .mk-sections > [data-sec="games"]{order:3}
374
+
375
+ [data-template="commercial"] .mk-sections > [data-sec="reach"]{order:1}
376
+ [data-template="commercial"] .mk-sections > [data-sec="rates"]{order:2}
377
+ [data-template="commercial"] .mk-sections > [data-sec="brands"]{order:3}
378
+ [data-template="commercial"] .mk-sections > [data-sec="metrics"]{order:4}
379
+
380
+ [data-template="audience"] .mk-sections > [data-sec="reach"]{order:1}
381
+ [data-template="audience"] .mk-sections > [data-sec="audience"]{order:2}
382
+ [data-template="audience"] .mk-sections > [data-sec="styles"]{order:3}
383
+ [data-template="audience"] .mk-sections > [data-sec="metrics"]{order:4}
315
384
  </style>