270 lines
6.4 KiB
Vue
270 lines
6.4 KiB
Vue
<script setup lang="ts">
|
|
import { getHighestPickrateBuildIndex, getFirstCoreItems } from '~/utils/buildHelpers'
|
|
import { MOCK_SUMMONER_SPELLS } from '~/utils/mockData'
|
|
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
|
|
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'))
|
|
|
|
// Use composable for builds management
|
|
const { builds } = useBuilds(toRef(props, 'builds'))
|
|
|
|
// Summoner spells data - use提供的 or fall back to mock
|
|
const displaySummonerSpells = computed(() =>
|
|
props.summonerSpells && props.summonerSpells.length > 0
|
|
? props.summonerSpells
|
|
: MOCK_SUMMONER_SPELLS
|
|
)
|
|
|
|
// Computed properties using utility functions
|
|
const firstCoreItems = computed(() => getFirstCoreItems(props.runes, builds.value))
|
|
|
|
const highestPickrateBuildIndex = computed(() => getHighestPickrateBuildIndex(props.runes))
|
|
|
|
// Reset selected build when runes change
|
|
watch(
|
|
() => props.runes,
|
|
() => {
|
|
currentlySelectedBuild.value = 0
|
|
}
|
|
)
|
|
|
|
function selectRune(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"
|
|
/>
|
|
|
|
<!-- 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"
|
|
/>
|
|
</div>
|
|
|
|
<!-- Compact Rune Selector -->
|
|
<CompactRuneSelector
|
|
:runes="runes"
|
|
:primary-styles="primaryStyles"
|
|
:secondary-styles="secondaryStyles"
|
|
:keystone-ids="keystoneIds"
|
|
:perks="perks"
|
|
:selected-index="currentlySelectedBuild"
|
|
@select="selectRune"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Right Column: Items -->
|
|
<div class="build-right-column">
|
|
<h3 class="section-title">Items</h3>
|
|
|
|
<!-- Start/Support + Boots Container -->
|
|
<div class="item-row-group">
|
|
<!-- Start Items -->
|
|
<ItemRow
|
|
v-if="!builds.suppItems"
|
|
label="Start"
|
|
:items="builds.start"
|
|
:item-map="itemMap"
|
|
:total-count="builds.tree.count"
|
|
/>
|
|
|
|
<!-- Support Items -->
|
|
<ItemRow
|
|
v-if="builds.suppItems"
|
|
label="Support"
|
|
:items="builds.suppItems"
|
|
:item-map="itemMap"
|
|
:total-count="builds.tree.count"
|
|
/>
|
|
|
|
<!-- Boots (regular or rush) -->
|
|
<ItemRow
|
|
:label="builds.bootsFirst > 0.5 ? 'Boots Rush' : 'Boots'"
|
|
:items="builds.boots.slice(0, 2)"
|
|
:item-map="itemMap"
|
|
:total-count="builds.tree.count"
|
|
:max-items="2"
|
|
/>
|
|
</div>
|
|
|
|
<!-- Core Items Tree -->
|
|
<div class="item-row">
|
|
<span class="item-row-label">Core</span>
|
|
<ItemTree :tree="builds.tree" />
|
|
</div>
|
|
|
|
<!-- Late Game -->
|
|
<ItemRow
|
|
label="Late Game"
|
|
:items="builds.lateGame.slice(0, 6)"
|
|
:item-map="itemMap"
|
|
:total-count="builds.tree.count"
|
|
:max-items="6"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style>
|
|
.build-viewer {
|
|
width: 100%;
|
|
max-width: 1100px;
|
|
margin: 0 auto;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
}
|
|
|
|
/* Main Build Content */
|
|
.build-content {
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 80px;
|
|
padding: 0 24px;
|
|
width: 100%;
|
|
}
|
|
|
|
.section-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 1rem;
|
|
font-weight: 600;
|
|
margin-bottom: 10px;
|
|
color: #4a9eff;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
}
|
|
|
|
/* Left Column: Runes + Summoner Spells */
|
|
.build-left-column {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 40px;
|
|
}
|
|
|
|
.rune-section {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.rune-page-wrapper {
|
|
margin-top: -45px;
|
|
transform: scale(0.7);
|
|
transform-origin: center;
|
|
}
|
|
|
|
/* Right Column: Items */
|
|
.build-right-column {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 20px;
|
|
}
|
|
|
|
.item-row-group {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 24px;
|
|
align-items: flex-start;
|
|
}
|
|
|
|
.item-row {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 4px;
|
|
}
|
|
|
|
.item-row-label {
|
|
font-size: 0.8rem;
|
|
font-weight: 500;
|
|
color: var(--color-on-surface);
|
|
opacity: 0.6;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.5px;
|
|
}
|
|
|
|
/* Responsive: Mobile */
|
|
@media only screen and (max-width: 900px) {
|
|
.build-content {
|
|
flex-direction: column;
|
|
gap: 40px;
|
|
align-items: center;
|
|
}
|
|
|
|
.build-left-column {
|
|
order: 1;
|
|
align-items: center;
|
|
}
|
|
|
|
.build-right-column {
|
|
order: 2;
|
|
align-items: center;
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
.rune-section,
|
|
.summoner-spells-section {
|
|
align-items: center;
|
|
}
|
|
|
|
.rune-page-wrapper {
|
|
transform: scale(1);
|
|
transform-origin: center center;
|
|
}
|
|
}
|
|
</style>
|