이번에는 캐릭터의 공격대 진행 상황을 나타내는 컴포넌트를 만들것이다.

우선 캐릭터의 던전 진척도를 api를 통해 가져온다.

export function getDungeonProgress(store) {
this.$axios.$get(`https://kr.api.blizzard.com/profile/wow/character/${store.state.realmSlug}/${store.state.characterName}/encounters/raids`,
{
params:{
region:'kr',
namespace:'profile-kr',
locale:'ko-KR',
access_token: store.state.accessToken,
}
})
.then(function (result) {
store.commit('setRawData', result)
store.commit('setRaidProgressData', progressData.getRaidProgress(result))
})
.catch(function (error) {
console.log(error)
})
}
let progressData = {
raidProgress: [],
getRaidProgress: function (rawData) {
this.raidProgress = this.getRaidProgressData(rawData)
return this.raidProgress
},
getInstanceData: function (data, dungeonName, dungeonId) {
if(data.difficulty.type ==='LEGACY_10_MAN_HEROIC'){
data.difficulty.type = 'HEROIC'
}
else if(data.difficulty.type === 'LEGACY_25_MAN_HEROIC'){
data.difficulty.type = 'HEROIC'
}
else if(data.difficulty.type ==='LEGACY_10_MAN'){
data.difficulty.type = 'NORMAL'
}
else if(data.difficulty.type ==='LEGACY_25_MAN'){
data.difficulty.type = 'NORMAL'
}
let instanceData = {
name: dungeonName,
id: dungeonId,
difficulty: data.difficulty.type,
status: data.status.type,
completedCount: data.progress.completed_count,
totalCount: data.progress.total_count,
bossData: []
}
// 키가 있는지 확인 key:{}
// 데이터가 있는지 확인 없으면 밑에꺼 스킵
data.progress.encounters.forEach(boss => {
instanceData.bossData.push(boss)
})
return instanceData
},
getDungeonData: function (data) {//여기 data는 현재 가리키고 있는 던전 rawData.expansions[].instances[])
let data_sorted_by_difficulty = []
let dungeonName = data.instance.name
let dungeonId = data.instance.id
data.modes.forEach(difficulty => {
data_sorted_by_difficulty.push(this.getInstanceData(difficulty, dungeonName, dungeonId))
})
return data_sorted_by_difficulty
},
getExpansionData: function (data) {//rawData.expansions[]
let expansionData = {
expansionName: data.expansion.name,
dungeonData: []
}
data.instances.forEach(dungeon => {
expansionData.dungeonData.push(this.getDungeonData(dungeon))
})
return expansionData
},
getRaidProgressData: function (data) {
let RaidProgress = []
//console.log(data.expansions)
if(data.hasOwnProperty('expansions')){
data.expansions.forEach(expansion => {
RaidProgress.push(this.getExpansionData(expansion))
})
}
return RaidProgress
}
}
// 코드를 좔좔좔 데이터 가공 코드

데이터를 가져오면서 내가 쓰기 편한 형태로 가공해주었다.

비교적 최근 확장팩의 레이드와 그 이전의 확장팩 레이드가 난이도가 다르게 표기되는 부분이 있었다.

현재는 LFR(공격대 찾기), NORMAL(일반), HEROIC(영웅), MYTHIC(신화)로 구분되는데, 이전 일부 확장팩에서는 LEGACY_10_MAN 이런식으로 표기되어있어 이부분은 현재 확장팩의 난이도에 맞게 바꾸어주었다.

진척도 카드에 들어갈 이미지도 같이 불러올것이다.

export function getDungeonImage(store, payload) {
this.$axios.$get(`https://kr.api.blizzard.com/data/wow/media/journal-instance/${payload.id}`, {
params: {
namespace: 'static-kr',
locale: 'ko_KR',
access_token: store.state.accessToken
}//region은 kr.api us.api 처럼 앞에 어느 국가 서버에서 받아올지 결정. locale은 어느 언어로 표기할지 결정
})
.then(function (response) {
let imageData = {
id: payload.id,
url: response.assets[0].value
}
store.commit('setImgUrl', imageData)
})
.catch(function (error) {
console.log(error)
})
}

이제 v-card를 이용해 공격대 진행도를 나타내는 카드를 만들것이다

<template>
<v-card
class="mx-auto"
max-width="300"
style="background-color: #273239; !important;"
>
<v-img
class="white--text align-end"
gradient="to top, rgba(0,5,10,0.95), rgba(255,255,255,0)"
:height="imgHeight"
:src="stateData"
>
<v-card-title
class="justify-end"
style="font-size: 15px"
>{{dungeon[0].name}}
</v-card-title>
</v-img>
<v-card-text
class="text--primary"
style="font-size: 12px"
>
<v-row
v-for="(item, index) in difficultyList"
:key="index"
class="my-4"
no-gutters
>
<v-col
cols="4"
align="start"
class="align-self-center pl-1"
>
{{item}}
</v-col>
<v-col
class="pr-1"
cols="8"
>
<v-progress-linear
:value="(levelClear[item].clear/levelClear[item].total *100)"
:color="levelClear[item].percent === 100 ? clearedColor:defaultColor"
:height="height"
background-color="grey darken-4"
>
<template v-slot>
{{levelClear[item].clear}}/{{levelClear[item].total}}
</template>
</v-progress-linear>
</v-col>
</v-row>
</v-card-text>
</v-card>
</template>
<script>
export default {
name: "RaidProgressCard",
data() {
return {
progress: 0,
height: 28,
imgHeight: "200px",
clearedColor: 'green darken-2',
defaultColor: 'orange darken-2',
barColor: 'orange',
name: 'no name',
SRC: '',
difficultyList: ['LFR', 'NORMAL', 'HEROIC', 'MYTHIC']
}
},
computed: {
stateData() {
return this.$store.state.dungeonImageData[this.dungeon[0].id]
},
levelClear() {
let obj = {}
this.difficultyList.forEach(level => {
obj[level] = {}
obj[level].total = this.dungeon[0].totalCount
obj[level].clear = 0
obj[level].percent = 0
})
this.dungeon.forEach(dungeonObj => {
if (this.difficultyList.includes(dungeonObj['difficulty'])) {
obj[dungeonObj['difficulty']].clear = dungeonObj['completedCount']
obj[dungeonObj['difficulty']].total = dungeonObj['totalCount']
obj[dungeonObj['difficulty']].percent = dungeonObj['completedCount'] / dungeonObj['totalCount'] * 100
}
})
return obj
}
},
props: {
dungeon: {
type: Array,
required: true
}
}
}
</script>
<style scoped>
.custom-gradient {
height: 28px;
background-image: linear-gradient(to top, rgba(0, 0, 0, 0.5), rgba(255, 255, 255, 0)); /* Standard syntax (must be last) */
}
</style>
<template>
<v-row>
<v-col
style="max-width: 400px; min-width: 300px"
:items="dungeons"
v-for="item in dungeons"
:key="item.name"
cols="12"
sm="6"
md="3"
lg="2"
>
<raid-process-card :dungeon="item"></raid-process-card>
</v-col>
</v-row>
</template>
<script>
import RaidProcessCard from "./RaidProcessCard";
export default {
name: "ExpansionSort"
,
components:{
RaidProcessCard
},
computed:{
dungeons(){
return this.expansion['dungeonData']
}
},
props: {
expansion:{
type: Object,
required: true
}
}
}
</script>
<style scoped>
</style>
<template>
<v-container fluid>
<v-row
v-for="expansion in reversedExpansions"
>
<v-col>
<v-row>{{expansion['expansionName']}}</v-row>
<v-row>
<expansion-sort :expansion="expansion"></expansion-sort>
</v-row>
</v-col>
</v-row>
</v-container>
</template>
<script>
import RaidProcessCard from "./RaidProcessCard";
import ExpansionSort from "./ExpansionSort";
export default {
components: {
RaidProcessCard,
ExpansionSort
},
data() {
return {}
},
computed: {
reversedExpansions(){
return this.$store.state.raidProgressData.slice().reverse()
},
expansions() {
return this.$store.state.raidProgressData
},
dungeons() {
let dungeons = []
let data = this.$store.state.raidProgressData
data.forEach(expansion => {
expansion.dungeonData.forEach(dungeon => {
dungeons.push(dungeon)
})
})
return dungeons
}
}
}
</script>
<style scoped>
</style>

RaidProgressCard 컴포넌트로 v-card 틀을 만들고, ExpansionSort 컴포넌트로 확장팩별로 정리를 해주고, RaidProgressIter 컴포넌트로 확장팩별로 카드들을 출력했다. 결과는 다음과 같다.

각 컴포넌트간에 데이터를 넘겨줄때는 props를 이용하면 된다.

이 부분을 작업하면서 신경쓰였던 부분이 이미지가 전부 불러와지기 전에 컴포넌트가 구성되어서 그런지 이미지가 누락되는 문제가 있었다. 그래서 페이지가 구성될 때 미리 이미지를 불러오는 식으로 순서를 바꾸어주었다.

import auto from 'async/auto.js'
export function initPage(store,callback) {
auto({
get_token: getToken,
get_realm_data: ['get_token', getRealmData],
get_dungeon_image: ['get_token',getDungeonImg]
}, function (err, results) {
console.log('err = ', err)
console.log('results = ', results)
})
function getToken(callback){
console.log('token start')
store.dispatch('getAccessToken')
.then((result)=>{
if(result){
console.log('token pass')
callback(null)
}else{
callback('get access function err')
}
})
}
function getRealmData(nonUseArg, callback) {
console.log('realm call')
store.dispatch('getRealmSlug')
callback(null)
}
function getDungeonImg(nonUseArg, callback){
console.log('img call')
for(let i=0; i<store.state.dungeonIdList.length; i++){
store.dispatch('getDungeonImage', {id: store.state.dungeonIdList[i]})
}
callback(null)
}
}
view raw initPage.js hosted with ❤ by GitHub

async 모듈의 auto를 이용해 교통정리를 좀 해줬다.

auto를 사용하면서 잘 안돼서 골머리를 좀 썩혔는데, 알고보니 action에서 사용된 IO함수때문에 문제가 발생했던것이다. 떄문에 accessToken을 dispatch할떄 promise를 리턴하게 하고 .then()을 붙여주었다. 

+ Recent posts