Skip to content

Commit 58dd774

Browse files
Add skins overview for champions
1 parent c51a215 commit 58dd774

File tree

4 files changed

+124
-4
lines changed

4 files changed

+124
-4
lines changed

core/client.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Champion, ChampionSummary, Item, LocaleVersionArgs, Perk, SummonerEmote, SummonerIcon, WardSkin, Companion, Loot, CherryAugment, Universe, TftItem, TftMapSkin, TftDamageSkin } from './models';
1+
import { Champion, ChampionSummary, Item, LocaleVersionArgs, Perk, SummonerEmote, SummonerIcon, WardSkin, Companion, Loot, CherryAugment, Universe, TftItem, TftMapSkin, TftDamageSkin, Skin } from './models';
22
import axios from "axios";
33

44
export abstract class ApiObject {
@@ -24,6 +24,7 @@ export class Client {
2424
public tftItems: TftItemApi;
2525
public tftMapSkins: TftMapSkinApi;
2626
public tftDamageSkins: TftDamageSkinApi;
27+
public skins: SkinApi;
2728

2829
constructor() {
2930
this.items = new ItemApi();
@@ -40,6 +41,7 @@ export class Client {
4041
this.tftItems = new TftItemApi();
4142
this.tftMapSkins = new TftMapSkinApi();
4243
this.tftDamageSkins = new TftDamageSkinApi();
44+
this.skins = new SkinApi();
4345
}
4446
}
4547

@@ -139,4 +141,11 @@ export class TftDamageSkinApi extends ApiObject {
139141
let res = await axios.get(`${this.getClientPath(args)}/v1/tftdamageskins.json`);
140142
return res.data.map((x: any) => new TftDamageSkin(x));
141143
}
144+
}
145+
146+
export class SkinApi extends ApiObject {
147+
async listAsync(args: LocaleVersionArgs): Promise<Array<Skin>> {
148+
let res = await axios.get(`${this.getClientPath(args)}/v1/skins.json`);
149+
return Object.entries(res.data).map(([key, value]) => new Skin(value));
150+
}
142151
}

core/models.ts

+33
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ export class Skin extends CommunityDragonObject {
7474
rarity: string;
7575
isLegacy: boolean;
7676
loadScreenPath: string;
77+
splashPath: string;
78+
uncenteredSplashPath: string;
79+
tilePath: string;
80+
description?: string;
81+
skinLines?: Array<SkinLine>;
82+
7783

7884
constructor(json: any) {
7985
super();
@@ -84,11 +90,38 @@ export class Skin extends CommunityDragonObject {
8490
this.rarity = json.rarity;
8591
this.isLegacy = json.isLegacy;
8692
this.loadScreenPath = json.loadScreenPath;
93+
this.splashPath = json.splashPath;
94+
this.uncenteredSplashPath = json.uncenteredSplashPath;
95+
this.tilePath = json.tilePath;
96+
this.description = json.description;
97+
this.skinLines = json.skinLines?.map((x: any) => new SkinLine(x)) ?? null;
8798
}
8899

89100
getLoadScreen(version: string): string {
90101
return this.resolveGamePath({path: this.loadScreenPath, version: version});
91102
}
103+
104+
getSplash(args: LocaleVersionArgs): string {
105+
return this.resolveClientPath({path: this.splashPath, args: args});
106+
}
107+
108+
getUncenteredSplash(args: LocaleVersionArgs): string {
109+
return this.resolveClientPath({path: this.uncenteredSplashPath, args: args});
110+
}
111+
112+
getTile(args: LocaleVersionArgs): string {
113+
return this.resolveClientPath({path: this.tilePath, args: args});
114+
}
115+
}
116+
117+
export class SkinLine extends CommunityDragonObject {
118+
id: number;
119+
120+
constructor(json: any) {
121+
super();
122+
123+
this.id = json.id;
124+
}
92125
}
93126

94127
export class Passive extends CommunityDragonObject {

pages/champions/overview/[id].vue

+6-3
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
<div class="col-md-6 col-sm-12">
2828
<div class="d-flex justify-content-between mb-2">
2929
<div style="min-height: 560px; min-width: 308px;" id="champion-loading-screen">
30-
<img class="border border-light border-opacity-25 rounded" :src="currentSkin" loading="lazy" />
30+
<NuxtLink class="text-decoration-none" :to="`/skins/overview/${currentSkin.id}`">
31+
<img class="border border-light border-opacity-25 rounded" :src="currentSkin.getLoadScreen('latest')" loading="lazy" />
32+
</NuxtLink>
3133
</div>
3234
<div class="d-flex flex-row flex-wrap align-items-center gap-2 border-start border-5 border-light border-opacity-10 ms-0 ps-2">
3335
<button class="btn btn-dark flex-grow-1 border-light border-opacity-25 bg-transparent bg-blur-3"
@@ -50,6 +52,7 @@ import Badge from '~/components/Badge.vue';
5052
import { useRoute } from 'vue-router';
5153
import useClient from '../../../composables/useClient';
5254
import useLocale from '~/composables/useLocale';
55+
import { Skin } from '../../../core/models';
5356
5457
const route = useRoute();
5558
const id = route.params.id as unknown;
@@ -63,8 +66,8 @@ watch(currentLocale, async () => {
6366
champion.value = await getChampion();
6467
});
6568
66-
const currentSkin = ref(champion.value.skins[0].getLoadScreen('latest'));
69+
const currentSkin = ref(champion.value.skins[0]);
6770
const swapLoadScreen = (id: number) => {
68-
currentSkin.value = champion.value.skins.find((x) => x.id == id)?.getLoadScreen('latest') as string;
71+
currentSkin.value = champion.value.skins.find((x) => x.id == id) as Skin;
6972
}
7073
</script>

pages/skins/overview/[id].vue

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<template>
2+
<div class="row">
3+
<div data-aos="fade-right" data-aos-duration="1000">
4+
<div>
5+
<h1 class="display-4">{{ skin!.name }}</h1>
6+
<p v-if="skin?.description">{{ skin.description }}</p>
7+
</div>
8+
<ul class="nav nav-tabs mb-4">
9+
<li class="nav-item">
10+
<button class="nav-link text-light"
11+
:class="{'active': selector == 'splash'}" @click="selector = 'splash'">Splash</button>
12+
</li>
13+
<li class="nav-item">
14+
<button class="nav-link text-light"
15+
:class="{'active': selector == 'uncenteredSplash'}" @click="selector = 'uncenteredSplash'">Uncentered Splash</button>
16+
</li>
17+
<li class="nav-item text-light">
18+
<button class="nav-link text-light"
19+
:class="{'active': selector == 'tile'}" @click="selector = 'tile'">Tile</button>
20+
</li>
21+
</ul>
22+
</div>
23+
<div class="d-flex justify-content-center align-items-center mb-4"
24+
data-aos="fade-left" data-aos-duration="1000">
25+
<img class="img-fluid" :src="selection"/>
26+
</div>
27+
<div v-if="skinUniverses.length > 0">
28+
<h5 class="border-bottom border-light border-opacity-25 border-2 mb-2 pb-2">Universes</h5>
29+
<div v-for="skinUniverse in skinUniverses">
30+
<div v-if="skinUniverse" :id="`${skinUniverse!.id}`">
31+
<h6 class="fw-bold">{{ skinUniverse?.name }}</h6>
32+
<p class="ms-2">{{ skinUniverse?.description }}</p>
33+
</div>
34+
</div>
35+
</div>
36+
</div>
37+
</template>
38+
39+
<script setup lang="ts">
40+
import useClient from '~/composables/useClient';
41+
import useLocale from '~/composables/useLocale';
42+
43+
const route = useRoute();
44+
const id = route.params.id as unknown;
45+
46+
const { client } = useClient();
47+
const { currentLocale } = useLocale();
48+
const getSkins = async () => await client.skins.listAsync({ locale: currentLocale.value, version: "latest"});
49+
const getUniverses = async () => await client.universes.listAsync({ locale: currentLocale.value, version: "latest"});
50+
51+
const skins = ref(await getSkins());
52+
const universes = ref(await getUniverses());
53+
watch(currentLocale, async() => {
54+
skins.value = await getSkins();
55+
universes.value = await getUniverses();
56+
});
57+
58+
const skin = computed(() => skins.value.find((x) => x.id == id));
59+
const selector = ref("splash");
60+
const selection = computed(() => {
61+
switch (selector.value) {
62+
case "splash":
63+
return skin.value!.getSplash({locale: currentLocale.value, version: "latest"});
64+
case "uncenteredSplash":
65+
return skin.value!.getUncenteredSplash({locale: currentLocale.value, version: "latest"});
66+
case "tile":
67+
return skin.value!.getTile({locale: currentLocale.value, version: "latest"});
68+
default:
69+
return "/img/error.png";
70+
}
71+
});
72+
const skinUniverses = computed(() => skin.value?.skinLines
73+
?.map((x) => universes.value.find((y) => y.skinSets.includes(x.id)))
74+
.filter(x => x != null) ?? []);
75+
</script>

0 commit comments

Comments
 (0)