Starts refactor using a PlayerView renderless component for Player logic

This commit is contained in:
2019-07-31 15:11:51 +02:00
parent 2991a88a30
commit fccd9b999b
8 changed files with 139 additions and 143 deletions

View File

@@ -62,8 +62,11 @@
"vue"
],
"transform": {
".*\\.(vue)$": "vue-jest",
"^.+\\.js$": "<rootDir>/node_modules/babel-jest"
"^.*\\.(vue)$": "vue-jest",
"^.+\\.js$": "babel-jest"
},
"moduleNameMapper": {
"^@/(.*)$": "<rootDir>/src/$1"
}
}
}

View File

@@ -1,11 +1,25 @@
<template>
<main id="app" class="container">
<Player></Player>
<PlayerView :id="state.player_id" v-slot="{ player, updateWealth }">
<section class="section">
<HeaderBar :app_state="state">
<template v-slot:title>{{ player.name }}</template>
</HeaderBar>
<Wealth
:wealth="[player.cp, player.sp, player.gp, player.pp]"
:debt="player.debt"
@update="updateWealth">
</wealth>
<Chest :player="state.show_player_chest ? player.id : 0"></Chest>
</section>
</PlayerView>
</main>
</template>
<script>
import Player from './components/Player.vue'
import PlayerView from './components/PlayerView.js'
import HeaderBar from './components/HeaderBar.vue'
import Wealth from './components/Wealth.vue'
import Chest from './components/Chest.vue'
import { AppStorage } from './AppStorage'
@@ -29,12 +43,14 @@ export default {
name: 'app',
data () {
return {
state: AppStorage.state,
state: AppStorage.state,
};
},
components: {
Player,
Chest
PlayerView,
HeaderBar,
Chest,
Wealth
},
created () {
// Initiate with active player set to value found in cookie

View File

@@ -60,7 +60,7 @@ export const AppStorage = {
const [players, claims] = data;
this.__initPlayerList(players);
this.__initClaimsStore(claims);
});
})
// TODO: when __initPlayerList won't use promises
//.then(_ => this.state.initiated = true);
},
@@ -94,7 +94,8 @@ export const AppStorage = {
));
promises.push(promise);
}
Promise.all(promises).then(_ => this.state.initiated = true);
Promise.all(promises)
.then(_ => this.state.initiated = true)
},
// User actions
// Sets a new active player by id

View File

@@ -0,0 +1,52 @@
<template>
<nav class="navbar is-info">
<div class="navbar-brand">
<p class="navbar-item is-size-4"><slot name="title">...</slot></p>
<a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div id="menu" class="navbar-menu">
<div class="navbar-start" v-if="!playerIsGroup">
<a class="navbar-item" @click="switchPlayerChestVisibility">
{{ app_state.show_player_chest ? 'Coffre de groupe' : 'Mon coffre' }}</a>
</div>
<div class="navbar-end">
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link">Autres</a>
<div class="navbar-dropdown is-right">
<a class="navbar-item">History of Loot</a>
<template v-if="playerIsGroup">
<hr class="navbar-divider">
<div class="navbar-item heading">Admin</div>
<a class="navbar-item">"Resolve claims"</a>
<a class="navbar-item">"Add player"</a>
</template>
<hr class="navbar-divider">
<div class="navbar-item heading">Changer</div>
<a v-for="(p,i) in app_state.player_list" :key="i"
@click="setActivePlayer(i)"
href="#" class="navbar-item">
{{ p.name }}</a>
</div>
</div>
</div>
</div>
</nav>
</template>
<script>
import { AppStorage } from '../AppStorage'
export default {
props: ["app_state"],
methods: {
setActivePlayer (idx) { AppStorage.setActivePlayer(idx); },
switchPlayerChestVisibility () { AppStorage.switchPlayerChestVisibility(); },
},
computed: {
playerIsGroup () { return this.app_state.player_id == 0 },
}
}
</script>

View File

@@ -1,124 +0,0 @@
<template>
<div class="">
<nav class="navbar is-info">
<div class="navbar-brand">
<p class="navbar-item is-size-4" @click="show_wealth = !show_wealth">{{ app_state.initiated ? player.name : "..." }}</p>
<a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div id="menu" class="navbar-menu">
<div class="navbar-start" v-if="!playerIsGroup">
<a class="navbar-item" @click="switchPlayerChestVisibility">
{{ app_state.show_player_chest ? 'Coffre de groupe' : 'Mon coffre' }}</a>
</div>
<div class="navbar-end">
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link">Autres</a>
<div class="navbar-dropdown is-right">
<a class="navbar-item">History of Loot</a>
<hr class="navbar-divider">
<div class="navbar-item heading">Changer</div>
<a v-for="(p,i) in app_state.player_list" :key="i"
@click="setActivePlayer(i)"
href="#" class="navbar-item">
{{ p.name }}</a>
</div>
</div>
</div>
</div>
</nav>
<section class="box is-shadowless" v-if="show_wealth">
<Wealth :wealth="wealth" :debt="player.debt"></Wealth>
</section>
<section class="card">
<div class="card-content">
<Loot v-if="is_adding"></Loot>
<Chest v-else :player="shownChest"></Chest>
</div>
<div class="card-footer" v-if="shownChest == player.id">
<template v-if="is_adding">
<a class="card-footer-item">Confirmer</a>
<a class="card-footer-item" @click="toggleAdding">Annuler</a>
</template>
<a v-else class="card-footer-item" @click="toggleAdding">
+ {{ playerIsGroup ? 'Nouveau loot' : 'Acheter' }}
</a>
</div>
</section>
</div>
</template>
<script>
import { AppStorage } from '../AppStorage'
import Chest from './Chest.vue'
import Wealth from './Wealth.vue'
import Loot from './Loot.vue'
/*
The Player control board.
*/
export default {
components: { Chest, Wealth, Loot },
data () {
return {
app_state: AppStorage.state,
is_adding: false,
show_wealth: true,
};
},
computed: {
player () {
if (!this.app_state.initiated) return {}
const idx = this.app_state.player_id;
return this.app_state.player_list[idx];
},
wealth () {
if (!this.app_state.initiated) {
return ["-", "-", "-", "-"];
} else {
const cp = this.player.cp
const sp = this.player.sp
const gp = this.player.gp
const pp = this.player.pp
return [cp, sp, gp, pp];
}
},
// Check if the active player is the special 'Group' player
playerIsGroup () {
return this.app_state.player_id == 0;
},
shownChest () {
return this.app_state.show_player_chest
? this.app_state.player_id
: 0;
}
},
methods: {
toggleAdding () {
this.is_adding = !this.is_adding;
},
switchPlayerChestVisibility () {
AppStorage.switchPlayerChestVisibility();
},
hidePlayerChest () {
if (this.app_state.show_player_chest) {
this.switchPlayerChestVisibility();
}
},
setActivePlayer (playerIdx) {
var playerIdx = Number(playerIdx);
AppStorage.setActivePlayer(playerIdx);
if (playerIdx == 0) { this.hidePlayerChest() }
},
closeDropdown () {
this.show_dropdown = false
}
},
}
</script>
<style scoped>
.fa-exchange-alt.disabled { opacity: 0.4; }
</style>

View File

@@ -0,0 +1,32 @@
import { AppStorage } from '../AppStorage'
export default {
props: ["id"],
data () { return {}},
methods: {
updateWealth (value) {
AppStorage.updatePlayerWealth(value)
.then(_ => {if (AppStorage.debug) console.log("Wealth updated")})
.catch(e => {if (AppStorage.debug) console.error("wealthUpdate Error", e)})
}
},
computed: {
player () {
if (!AppStorage.state.initiated) {
return { name: "Loading",
id: 0,
cp: '-', sp: '-', gp: '-', pp: '-',
debt: 0 };
} else {
console.log("Update player");
return AppStorage.state.player_list[this.id];
}
}
},
render () {
return this.$scopedSlots.default({
player: this.player,
updateWealth: this.updateWealth,
})
}
}

View File

@@ -2,12 +2,11 @@
<section class="level is-mobile">
<div class="level-left">
<div class="level-item">
<span class="icon is-large"
@click="edit = !edit">
<i class="fas fa-2x fa-piggy-bank"></i>
</span>
<span class="icon is-large" @click="edit = !edit">
<i class="fas fa-2x fa-piggy-bank"></i>
</span>
</div>
<template v-if="edit">
<template v-if="edit">
<div class="level-item">
<input class="input" type="number" step="0.01" v-model="edit_value"></input>
</div>
@@ -16,8 +15,8 @@
Modifier
</button>
</div>
</template>
<template v-else>
</template>
<template v-else>
<div class="level-item ">
<p class="is-size-4">{{ wealth[3] }}</p>
<p class="heading">PP</p>
@@ -46,7 +45,6 @@
</template>
<script>
import { AppStorage } from '../AppStorage.js'
export default {
props: ["wealth", "debt"],
data () {
@@ -57,8 +55,8 @@
},
methods: {
updateWealth () {
AppStorage.updatePlayerWealth(this.edit_value)
.then(_ => this.resetValues());
this.$emit("update", this.edit_value);
this.resetValues();
},
resetValues () {
this.edit = false;

View File

@@ -0,0 +1,18 @@
import { shallowMount } from '@vue/test-utils'
import NumberInput from '../NumberInput'
const factory = (value = 0) => {
return shallowMount(NumberInput, {
propsData: {
value: value
},
});
};
describe('NumberInput', () {
test('displays error when invalid', () => {
const wrapper = factory("fd2");
expect(wrapper.find("input").classes('is-danger')).toBe(true)
})
})