Lint frontend
This commit is contained in:
@@ -32,8 +32,8 @@ const champions = computed(() => {
|
||||
|
||||
return championsData.value
|
||||
.slice(1)
|
||||
.filter((champion: any) => !champion.name.includes('Doom Bot'))
|
||||
.sort((a: any, b: any) => a.name.localeCompare(b.name))
|
||||
.filter((champion: ChampionSummary) => !champion.name.includes('Doom Bot'))
|
||||
.sort((a: ChampionSummary, b: ChampionSummary) => a.name.localeCompare(b.name))
|
||||
})
|
||||
|
||||
const lanesMap = computed(() => {
|
||||
@@ -64,7 +64,7 @@ function filterChampionsByLane(laneFilter: number): void {
|
||||
}
|
||||
|
||||
const laneName = filterToLane(laneFilter)
|
||||
filteredChampions.value = champions.value.filter((champion: any) => {
|
||||
filteredChampions.value = champions.value.filter((champion: ChampionSummary) => {
|
||||
const championLanes = lanesMap.value.get(champion.alias.toLowerCase())
|
||||
if (!championLanes) return false
|
||||
|
||||
@@ -77,14 +77,14 @@ const debouncedSearch = debounce((searchTerm: string) => {
|
||||
if (isEmpty(searchTerm)) {
|
||||
filteredChampions.value = [...champions.value]
|
||||
} else {
|
||||
filteredChampions.value = champions.value.filter((champion: any) =>
|
||||
filteredChampions.value = champions.value.filter((champion: ChampionSummary) =>
|
||||
champion.name.toLowerCase().includes(searchTerm.toLowerCase())
|
||||
)
|
||||
}
|
||||
}, 300)
|
||||
|
||||
// Watchers
|
||||
watch(searchBar, (newS, oldS) => {
|
||||
watch(searchBar, (_newS, _oldS) => {
|
||||
searchBar.value?.focus()
|
||||
})
|
||||
|
||||
@@ -124,7 +124,7 @@ const isLoading = computed(() => loadingChampions.value || loadingLanes.value)
|
||||
<div>
|
||||
<!-- Loading state -->
|
||||
<div v-if="isLoading" class="loading-state">
|
||||
<div class="loading-spinner"/>
|
||||
<div class="loading-spinner" />
|
||||
<p>Loading champions...</p>
|
||||
</div>
|
||||
|
||||
@@ -146,7 +146,7 @@ const isLoading = computed(() => loadingChampions.value || loadingLanes.value)
|
||||
@keyup.enter="
|
||||
() => filteredChampions.length > 0 && navigateToChampion(filteredChampions[0].alias)
|
||||
"
|
||||
>
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Empty state -->
|
||||
|
||||
@@ -46,6 +46,7 @@ function handleHover(laneImg: Ref<string>, index: number) {
|
||||
<div style="width: fit-content">
|
||||
<NuxtImg
|
||||
v-for="(laneImg, index) in laneImgs"
|
||||
:key="index"
|
||||
format="webp"
|
||||
:alt="POSITIONS_STR[index]"
|
||||
class="lane-img"
|
||||
|
||||
@@ -3,6 +3,11 @@ defineProps<{
|
||||
imgWidth?: string
|
||||
fontSize?: string
|
||||
}>()
|
||||
|
||||
// Component name must be multi-word
|
||||
defineOptions({
|
||||
name: 'AppLogo'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -108,14 +108,18 @@ function handleRefresh() {
|
||||
height="64"
|
||||
:alt="tree.data.toString()"
|
||||
:src="CDRAGON_BASE + mapPath(itemMap.get(tree.data).iconPath)"
|
||||
>
|
||||
/>
|
||||
<h3 style="width: fit-content; margin: auto; margin-bottom: 10px">
|
||||
{{ ((tree.count / parentCount!!) * 100).toFixed(0) }}%
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div style="margin-left: 30px">
|
||||
<div v-for="child in tree.children" style="width: fit-content; height: fit-content">
|
||||
<div
|
||||
v-for="child in tree.children"
|
||||
:key="child.data"
|
||||
style="width: fit-content; height: fit-content"
|
||||
>
|
||||
<ItemTree
|
||||
:tree="child"
|
||||
:parent-count="tree.count"
|
||||
|
||||
@@ -12,7 +12,7 @@ const ITEMS_API_URL = CDRAGON_BASE + 'plugins/rcp-be-lol-game-data/global/defaul
|
||||
|
||||
// State
|
||||
const { data: items, pending: loadingItems, error: itemsError } = await useFetch(ITEMS_API_URL)
|
||||
const itemMap = ref<Map<number, any>>(new Map())
|
||||
const itemMap = ref<Map<number, unknown>>(new Map())
|
||||
|
||||
// Initialize item map
|
||||
watch(
|
||||
@@ -21,7 +21,7 @@ watch(
|
||||
try {
|
||||
const itemsData = newItems || []
|
||||
if (Array.isArray(itemsData)) {
|
||||
const map = new Map<number, any>()
|
||||
const map = new Map<number, unknown>()
|
||||
for (const item of itemsData) {
|
||||
if (item?.id) {
|
||||
map.set(item.id, item)
|
||||
@@ -90,24 +90,9 @@ function trimLateGameItems(builds: Builds): void {
|
||||
trimLateGameItemsFromTree(builds.tree)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get item data safely
|
||||
*/
|
||||
function getItemData(itemId: number): any {
|
||||
return itemMap.value.get(itemId) || { iconPath: '' }
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate percentage for item display
|
||||
*/
|
||||
function getItemPercentage(item: { count: number }, total: number): string {
|
||||
if (total <= 0) return '0%'
|
||||
return ((item.count / total) * 100).toFixed(0) + '%'
|
||||
}
|
||||
|
||||
// Error and loading states
|
||||
const hasError = computed(() => itemsError.value || props.error)
|
||||
const isLoading = computed(() => loadingItems.value || props.loading)
|
||||
const _hasError = computed(() => itemsError.value || props.error)
|
||||
const _isLoading = computed(() => loadingItems.value || props.loading)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -116,14 +101,18 @@ const isLoading = computed(() => loadingItems.value || props.loading)
|
||||
<!-- Start items -->
|
||||
<ItemBox v-if="builds.suppItems == undefined || builds.suppItems == null" title="start">
|
||||
<div class="iv-items-container">
|
||||
<div v-for="item in builds.start" style="margin-left: 5px; margin-right: 5px">
|
||||
<div
|
||||
v-for="item in builds.start"
|
||||
:key="item.data"
|
||||
style="margin-left: 5px; margin-right: 5px"
|
||||
>
|
||||
<NuxtImg
|
||||
v-if="item.data != null && item.data != undefined"
|
||||
class="item-img"
|
||||
width="64"
|
||||
height="64"
|
||||
:alt="item.data.toString()"
|
||||
:src="CDRAGON_BASE + mapPath(itemMap.get(item.data).iconPath)"
|
||||
:src="CDRAGON_BASE + mapPath((itemMap.get(item.data) as any).iconPath)"
|
||||
/>
|
||||
<h3 style="width: fit-content; margin: auto; margin-bottom: 10px">
|
||||
{{ ((item.count / builds.tree.count) * 100).toFixed(0) }}%
|
||||
@@ -134,14 +123,18 @@ const isLoading = computed(() => loadingItems.value || props.loading)
|
||||
<!-- Supp items -->
|
||||
<ItemBox v-if="builds.suppItems != undefined && builds.suppItems != null" title="supp">
|
||||
<div class="iv-items-container">
|
||||
<div v-for="item in builds.suppItems" style="margin-left: 5px; margin-right: 5px">
|
||||
<div
|
||||
v-for="item in builds.suppItems"
|
||||
:key="item.data"
|
||||
style="margin-left: 5px; margin-right: 5px"
|
||||
>
|
||||
<NuxtImg
|
||||
v-if="item.data != null && item.data != undefined"
|
||||
class="item-img"
|
||||
width="64"
|
||||
height="64"
|
||||
:alt="item.data.toString()"
|
||||
:src="CDRAGON_BASE + mapPath(itemMap.get(item.data).iconPath)"
|
||||
:src="CDRAGON_BASE + mapPath((itemMap.get(item.data) as any).iconPath)"
|
||||
/>
|
||||
<h3 style="width: fit-content; margin: auto; margin-bottom: 10px">
|
||||
{{ ((item.count / builds.tree.count) * 100).toFixed(0) }}%
|
||||
@@ -154,14 +147,18 @@ const isLoading = computed(() => loadingItems.value || props.loading)
|
||||
<!-- Boots first : when champion rush boots -->
|
||||
<ItemBox v-if="builds.bootsFirst > 0.5" title="boots rush" :boots-first="builds.bootsFirst">
|
||||
<div class="iv-items-container">
|
||||
<div v-for="item in builds.boots" style="margin-left: 5px; margin-right: 5px">
|
||||
<div
|
||||
v-for="item in builds.boots"
|
||||
:key="item.data"
|
||||
style="margin-left: 5px; margin-right: 5px"
|
||||
>
|
||||
<NuxtImg
|
||||
v-if="item.data != null && item.data != undefined"
|
||||
class="item-img"
|
||||
width="64"
|
||||
height="64"
|
||||
:alt="item.data.toString()"
|
||||
:src="CDRAGON_BASE + mapPath(itemMap.get(item.data).iconPath)"
|
||||
:src="CDRAGON_BASE + mapPath((itemMap.get(item.data) as any).iconPath)"
|
||||
/>
|
||||
<h3 style="width: fit-content; margin: auto; margin-bottom: 10px">
|
||||
{{ ((item.count / builds.tree.count) * 100).toFixed(0) }}%
|
||||
@@ -178,14 +175,18 @@ const isLoading = computed(() => loadingItems.value || props.loading)
|
||||
<!-- Boots -->
|
||||
<ItemBox v-if="builds.bootsFirst <= 0.5" title="boots">
|
||||
<div class="iv-items-container">
|
||||
<div v-for="item in builds.boots.slice(0, 4)" style="margin-left: 5px; margin-right: 5px">
|
||||
<div
|
||||
v-for="item in builds.boots.slice(0, 4)"
|
||||
:key="item.data"
|
||||
style="margin-left: 5px; margin-right: 5px"
|
||||
>
|
||||
<NuxtImg
|
||||
v-if="item.data != null && item.data != undefined"
|
||||
class="item-img"
|
||||
width="64"
|
||||
height="64"
|
||||
:alt="item.data.toString()"
|
||||
:src="CDRAGON_BASE + mapPath(itemMap.get(item.data).iconPath)"
|
||||
:src="CDRAGON_BASE + mapPath((itemMap.get(item.data) as any).iconPath)"
|
||||
/>
|
||||
<h3 style="width: fit-content; margin: auto; margin-bottom: 10px">
|
||||
{{ ((item.count / builds.tree.count) * 100).toFixed(0) }}%
|
||||
@@ -200,6 +201,7 @@ const isLoading = computed(() => loadingItems.value || props.loading)
|
||||
<div class="iv-items-container">
|
||||
<div
|
||||
v-for="item in builds.lateGame.slice(0, 4)"
|
||||
:key="item.data"
|
||||
style="margin-left: 5px; margin-right: 5px"
|
||||
>
|
||||
<NuxtImg
|
||||
@@ -208,7 +210,7 @@ const isLoading = computed(() => loadingItems.value || props.loading)
|
||||
width="64"
|
||||
height="64"
|
||||
:alt="item.data.toString()"
|
||||
:src="CDRAGON_BASE + mapPath(itemMap.get(item.data).iconPath)"
|
||||
:src="CDRAGON_BASE + mapPath((itemMap.get(item.data) as any).iconPath)"
|
||||
/>
|
||||
<h3 style="width: fit-content; margin: auto; margin-bottom: 10px">
|
||||
{{ ((item.count / builds.tree.count) * 100).toFixed(0) }}%
|
||||
@@ -219,6 +221,7 @@ const isLoading = computed(() => loadingItems.value || props.loading)
|
||||
<div v-if="builds.lateGame.length > 4" class="iv-items-container">
|
||||
<div
|
||||
v-for="item in builds.lateGame.slice(4, 8)"
|
||||
:key="item.data"
|
||||
style="margin-left: 5px; margin-right: 5px"
|
||||
>
|
||||
<NuxtImg
|
||||
@@ -227,7 +230,7 @@ const isLoading = computed(() => loadingItems.value || props.loading)
|
||||
width="64"
|
||||
height="64"
|
||||
:alt="item.data.toString()"
|
||||
:src="CDRAGON_BASE + mapPath(itemMap.get(item.data).iconPath)"
|
||||
:src="CDRAGON_BASE + mapPath((itemMap.get(item.data) as any).iconPath)"
|
||||
/>
|
||||
<h3 style="width: fit-content; margin: auto; margin-bottom: 10px">
|
||||
{{ ((item.count / builds.tree.count) * 100).toFixed(0) }}%
|
||||
|
||||
@@ -49,6 +49,7 @@ if (route.path.startsWith('/tierlist/')) {
|
||||
|
||||
<div
|
||||
v-for="(lane, i) in championLanes"
|
||||
:key="i"
|
||||
style="display: flex; align-items: center; margin-left: 20px"
|
||||
>
|
||||
<NuxtImg
|
||||
@@ -82,6 +83,7 @@ if (route.path.startsWith('/tierlist/')) {
|
||||
<div style="display: flex">
|
||||
<NuxtLink
|
||||
v-for="(pos, i) in POSITIONS"
|
||||
:key="i"
|
||||
style="margin-top: 5px; margin-bottom: 5px"
|
||||
:to="'/tierlist/' + pos"
|
||||
>
|
||||
|
||||
@@ -33,7 +33,7 @@ if (route.path.startsWith('/tierlist/')) {
|
||||
|
||||
<template>
|
||||
<!-- To make content have a 300px margin -->
|
||||
<div class="sidebar-margin"/>
|
||||
<div class="sidebar-margin" />
|
||||
|
||||
<div class="sidebar-container">
|
||||
<Logo
|
||||
@@ -42,7 +42,7 @@ if (route.path.startsWith('/tierlist/')) {
|
||||
style="padding-left: 15px; padding-right: 15px; margin-top: 30px"
|
||||
/>
|
||||
|
||||
<div v-for="(lane, i) in championLanes">
|
||||
<div v-for="(lane, i) in championLanes" :key="i">
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
@@ -103,6 +103,7 @@ if (route.path.startsWith('/tierlist/')) {
|
||||
<h2 style="padding-left: 20px; font-size: 2.4rem; margin-bottom: 10px">Tierlist</h2>
|
||||
<NuxtLink
|
||||
v-for="(pos, i) in POSITIONS"
|
||||
:key="i"
|
||||
style="margin-top: 5px; margin-bottom: 5px"
|
||||
:to="'/tierlist/' + pos"
|
||||
>
|
||||
|
||||
@@ -21,13 +21,13 @@ const { data: stylesData }: PerkStylesResponse = await useFetch(
|
||||
)
|
||||
watch(
|
||||
() => props.primaryStyleId,
|
||||
async (newP, oldP) => {
|
||||
async (_newP, _oldP) => {
|
||||
refreshStyles()
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => props.secondaryStyleId,
|
||||
async (newP, oldP) => {
|
||||
async (_newP, _oldP) => {
|
||||
refreshStyles()
|
||||
}
|
||||
)
|
||||
@@ -55,9 +55,14 @@ refreshStyles()
|
||||
:src="CDRAGON_BASE + mapPath(primaryStyle.iconPath)"
|
||||
/>
|
||||
</div>
|
||||
<div v-for="slot in primaryStyle.slots.slice(0, 1)" class="rune-slot">
|
||||
<div
|
||||
v-for="(slot, slotIndex) in primaryStyle.slots.slice(0, 1)"
|
||||
:key="slotIndex"
|
||||
class="rune-slot"
|
||||
>
|
||||
<NuxtImg
|
||||
v-for="perk in slot.perks"
|
||||
:key="perk"
|
||||
width="48"
|
||||
:class="
|
||||
'rune-img rune-keystone ' + (props.selectionIds.includes(perk) ? 'rune-activated' : '')
|
||||
@@ -65,23 +70,33 @@ refreshStyles()
|
||||
:src="'https://raw.communitydragon.org/latest/' + mapPath(perks.get(perk).iconPath)"
|
||||
/>
|
||||
</div>
|
||||
<div v-for="slot in primaryStyle.slots.slice(1, 4)" class="rune-slot">
|
||||
<div
|
||||
v-for="(slot, slotIndex) in primaryStyle.slots.slice(1, 4)"
|
||||
:key="slotIndex"
|
||||
class="rune-slot"
|
||||
>
|
||||
<NuxtImg
|
||||
v-for="perk in slot.perks"
|
||||
:key="perk"
|
||||
width="48"
|
||||
:class="'rune-img ' + (props.selectionIds.includes(perk) ? 'rune-activated' : '')"
|
||||
:src="'https://raw.communitydragon.org/latest/' + mapPath(perks.get(perk).iconPath)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rune-spacer-bar"/>
|
||||
<div class="rune-spacer-bar" />
|
||||
<div class="rune-holder" style="align-content: end">
|
||||
<div class="rune-slot">
|
||||
<img style="margin: auto" :src="CDRAGON_BASE + mapPath(secondaryStyle.iconPath)" >
|
||||
<img style="margin: auto" :src="CDRAGON_BASE + mapPath(secondaryStyle.iconPath)" />
|
||||
</div>
|
||||
<div v-for="slot in secondaryStyle.slots.slice(1, 4)" class="rune-slot">
|
||||
<div
|
||||
v-for="(slot, slotIndex) in secondaryStyle.slots.slice(1, 4)"
|
||||
:key="slotIndex"
|
||||
class="rune-slot"
|
||||
>
|
||||
<NuxtImg
|
||||
v-for="perk in slot.perks"
|
||||
:key="perk"
|
||||
width="48"
|
||||
:class="'rune-img ' + (props.selectionIds.includes(perk) ? 'rune-activated' : '')"
|
||||
:src="'https://raw.communitydragon.org/latest/' + mapPath(perks.get(perk).iconPath)"
|
||||
|
||||
@@ -27,7 +27,7 @@ const { data: stylesData }: PerkStylesResponse = await useFetch(
|
||||
)
|
||||
watch(
|
||||
() => props.runes,
|
||||
(newRunes, oldRunes) => {
|
||||
(_newRunes, _oldRunes) => {
|
||||
currentlySelectedPage.value = 0
|
||||
primaryStyles.value = Array(props.runes.length)
|
||||
secondaryStyles.value = Array(props.runes.length)
|
||||
@@ -72,7 +72,7 @@ function runeSelect(index: number) {
|
||||
:selection-ids="runes[currentlySelectedPage].selections"
|
||||
/>
|
||||
<div style="display: flex; margin-top: 20px; justify-content: center">
|
||||
<div v-for="(_, i) in runes" @click="runeSelect(i)">
|
||||
<div v-for="(_, i) in runes" :key="i" @click="runeSelect(i)">
|
||||
<div
|
||||
:class="
|
||||
'rune-selector-entry ' +
|
||||
|
||||
@@ -6,9 +6,7 @@ import {
|
||||
Legend,
|
||||
BarElement,
|
||||
CategoryScale,
|
||||
LinearScale,
|
||||
plugins,
|
||||
scales
|
||||
LinearScale
|
||||
} from 'chart.js'
|
||||
import { Bar } from 'vue-chartjs'
|
||||
|
||||
@@ -72,10 +70,20 @@ const chartOptions = ref({
|
||||
const chartPlugins = [
|
||||
{
|
||||
id: 'image-draw',
|
||||
afterDraw: (chart: any) => {
|
||||
const ctx: CanvasRenderingContext2D = chart.ctx
|
||||
const xAxis = chart.scales.x
|
||||
xAxis.ticks.forEach((value: any, index: number) => {
|
||||
afterDraw: (chart: unknown) => {
|
||||
const ctx: CanvasRenderingContext2D = (chart as { ctx: CanvasRenderingContext2D }).ctx
|
||||
const xAxis = (
|
||||
chart as {
|
||||
scales: {
|
||||
x: {
|
||||
ticks: Array<unknown>
|
||||
getPixelForTick: (_index: number) => number
|
||||
bottom: number
|
||||
}
|
||||
}
|
||||
}
|
||||
).scales.x
|
||||
xAxis.ticks.forEach((value: unknown, index: number) => {
|
||||
const x = xAxis.getPixelForTick(index)
|
||||
const image = new Image()
|
||||
image.src = images[index]
|
||||
|
||||
@@ -11,6 +11,7 @@ defineProps<{
|
||||
<div class="tierlist-tier-container">
|
||||
<NuxtLink
|
||||
v-for="{ champion: champion } in tier"
|
||||
:key="champion.alias"
|
||||
:to="'/champion/' + champion.alias.toLowerCase()"
|
||||
>
|
||||
<div class="champion-img-container">
|
||||
|
||||
Reference in New Issue
Block a user