Multiple changes
- backend: add summoner spells - backend: add build variants - backend: builds are now storing full tree with runes (keystones) - backend: build trees are split on starter items and merged on runes - frontend: computing core tree now - frontend: variant selectors
This commit is contained in:
@@ -1,21 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import { getHighestPickrateBuildIndex, getFirstCoreItems } from '~/utils/buildHelpers'
|
||||
import { MOCK_SUMMONER_SPELLS } from '~/utils/mockData'
|
||||
import { getCoreItems, getLateGameItems } from '~/utils/buildHelpers'
|
||||
import BuildVariantSelector from '~/components/build/BuildVariantSelector.vue'
|
||||
import SummonerSpells from '~/components/build/SummonerSpells.vue'
|
||||
import CompactRuneSelector from '~/components/build/CompactRuneSelector.vue'
|
||||
import ItemRow from '~/components/build/ItemRow.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
runes: Array<{
|
||||
count: number
|
||||
primaryStyle: number
|
||||
secondaryStyle: number
|
||||
selections: Array<number>
|
||||
pickrate: number
|
||||
}>
|
||||
builds: Builds
|
||||
summonerSpells?: Array<{ id: number; count: number; pickrate: number }>
|
||||
}>()
|
||||
|
||||
// State
|
||||
@@ -23,76 +13,75 @@ const currentlySelectedBuild = ref(0)
|
||||
|
||||
// Use composables for data fetching
|
||||
const { itemMap } = useItemMap()
|
||||
const { summonerSpellMap } = useSummonerSpellMap()
|
||||
|
||||
// Use composable for rune styles
|
||||
const { perks, primaryStyles, secondaryStyles, keystoneIds } = useRuneStyles(toRef(props, 'runes'))
|
||||
const { perks, perkStyles } = useRuneStyles()
|
||||
|
||||
// Use composable for builds management
|
||||
const { builds } = useBuilds(toRef(props, 'builds'))
|
||||
const currentBuild = computed(() => builds.value[currentlySelectedBuild.value])
|
||||
|
||||
// Summoner spells data - use提供的 or fall back to mock
|
||||
const displaySummonerSpells = computed(() =>
|
||||
props.summonerSpells && props.summonerSpells.length > 0
|
||||
? props.summonerSpells
|
||||
: MOCK_SUMMONER_SPELLS
|
||||
)
|
||||
// Late game items for current build
|
||||
const lateGameItems = computed(() => {
|
||||
if (!currentBuild.value) return []
|
||||
return getLateGameItems(currentBuild.value).slice(0, 6)
|
||||
})
|
||||
|
||||
// Computed properties using utility functions
|
||||
const firstCoreItems = computed(() => getFirstCoreItems(props.runes, builds.value))
|
||||
const currentlySelectedRunes = ref(0)
|
||||
|
||||
const highestPickrateBuildIndex = computed(() => getHighestPickrateBuildIndex(props.runes))
|
||||
|
||||
// Reset selected build when runes change
|
||||
// Reset selected build when variant changes
|
||||
watch(
|
||||
() => props.runes,
|
||||
() => currentBuild,
|
||||
() => {
|
||||
currentlySelectedBuild.value = 0
|
||||
currentlySelectedRunes.value = 0
|
||||
}
|
||||
)
|
||||
|
||||
function selectRune(index: number): void {
|
||||
currentlySelectedRunes.value = index
|
||||
}
|
||||
function selectBuild(index: number): void {
|
||||
currentlySelectedBuild.value = index
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="build-viewer">
|
||||
<!-- Global Build Variant Selector - Single variant with highest pickrate -->
|
||||
<BuildVariantSelector
|
||||
:keystone-id="keystoneIds[highestPickrateBuildIndex]"
|
||||
:item-id="firstCoreItems[highestPickrateBuildIndex]"
|
||||
:keystore="perks"
|
||||
:item-map="itemMap"
|
||||
:pickrate="1"
|
||||
/>
|
||||
<div v-if="currentBuild" class="build-viewer">
|
||||
<div style="display: flex">
|
||||
<BuildVariantSelector
|
||||
v-for="(build, i) in builds"
|
||||
:key="i"
|
||||
:keystone-id="build.runeKeystone"
|
||||
:item-id="build.items.children[0].data"
|
||||
:keystore="perks"
|
||||
:item-map="itemMap"
|
||||
:pickrate="build.pickrate"
|
||||
:selected="currentBuild == build"
|
||||
:index="i"
|
||||
@select="selectBuild"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Main Build Content -->
|
||||
<div class="build-content">
|
||||
<!-- Left Column: Summoner Spells + Runes -->
|
||||
<div class="build-left-column">
|
||||
<!-- Summoner Spells -->
|
||||
<SummonerSpells :spells="displaySummonerSpells" :summoner-spell-map="summonerSpellMap" />
|
||||
|
||||
<!-- Rune Page -->
|
||||
<div class="rune-section">
|
||||
<h3 class="section-title">Runes</h3>
|
||||
<div class="rune-page-wrapper">
|
||||
<RunePage
|
||||
v-if="runes[currentlySelectedBuild]"
|
||||
:primary-style-id="runes[currentlySelectedBuild].primaryStyle"
|
||||
:secondary-style-id="runes[currentlySelectedBuild].secondaryStyle"
|
||||
:selection-ids="runes[currentlySelectedBuild].selections"
|
||||
v-if="currentBuild.runes"
|
||||
:primary-style-id="currentBuild.runes[currentlySelectedRunes].primaryStyle"
|
||||
:secondary-style-id="currentBuild.runes[currentlySelectedRunes].secondaryStyle"
|
||||
:selection-ids="currentBuild.runes[currentlySelectedRunes].selections"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Compact Rune Selector -->
|
||||
<CompactRuneSelector
|
||||
:runes="runes"
|
||||
:primary-styles="primaryStyles"
|
||||
:secondary-styles="secondaryStyles"
|
||||
:keystone-ids="keystoneIds"
|
||||
:runes="currentBuild.runes"
|
||||
:perks="perks"
|
||||
:perk-styles="perkStyles"
|
||||
:selected-index="currentlySelectedBuild"
|
||||
@select="selectRune"
|
||||
/>
|
||||
@@ -105,46 +94,47 @@ function selectRune(index: number): void {
|
||||
|
||||
<!-- Start/Support + Boots Container -->
|
||||
<div class="item-row-group">
|
||||
<!-- Start Items -->
|
||||
<!-- Start Item (root of the tree) -->
|
||||
<ItemRow
|
||||
v-if="!builds.suppItems"
|
||||
v-if="currentBuild.startItems && currentBuild.startItems.length > 0"
|
||||
label="Start"
|
||||
:items="builds.start"
|
||||
:items="currentBuild.startItems"
|
||||
:item-map="itemMap"
|
||||
:total-count="builds.tree.count"
|
||||
:total-count="currentBuild.count"
|
||||
/>
|
||||
|
||||
<!-- Support Items -->
|
||||
<ItemRow
|
||||
v-if="builds.suppItems"
|
||||
v-if="currentBuild.suppItems && currentBuild.suppItems.length > 0"
|
||||
label="Support"
|
||||
:items="builds.suppItems"
|
||||
:items="currentBuild.suppItems"
|
||||
:item-map="itemMap"
|
||||
:total-count="builds.tree.count"
|
||||
:total-count="currentBuild.count"
|
||||
/>
|
||||
|
||||
<!-- Boots (regular or rush) -->
|
||||
<ItemRow
|
||||
:label="builds.bootsFirst > 0.5 ? 'Boots Rush' : 'Boots'"
|
||||
:items="builds.boots.slice(0, 2)"
|
||||
:label="currentBuild.bootsFirst > 0.5 ? 'Boots Rush' : 'Boots'"
|
||||
:items="currentBuild.boots.slice(0, 2)"
|
||||
:item-map="itemMap"
|
||||
:total-count="builds.tree.count"
|
||||
:total-count="currentBuild.count"
|
||||
:max-items="2"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Core Items Tree -->
|
||||
<div class="item-row">
|
||||
<!-- Core Items Tree (children of start item) -->
|
||||
<div v-if="currentBuild.items?.children?.length" class="item-row">
|
||||
<span class="item-row-label">Core</span>
|
||||
<ItemTree :tree="builds.tree" />
|
||||
<ItemTree :tree="getCoreItems(currentBuild)" />
|
||||
</div>
|
||||
|
||||
<!-- Late Game -->
|
||||
<ItemRow
|
||||
v-if="lateGameItems.length > 0"
|
||||
label="Late Game"
|
||||
:items="builds.lateGame.slice(0, 6)"
|
||||
:items="lateGameItems"
|
||||
:item-map="itemMap"
|
||||
:total-count="builds.tree.count"
|
||||
:total-count="currentBuild.count"
|
||||
:max-items="6"
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user