further adjustments to store

This commit is contained in:
Steffen 2020-05-03 23:05:17 +02:00
parent 84e533640b
commit ca91112b26
No known key found for this signature in database
GPG Key ID: 764D74E98267DFC6
14 changed files with 417 additions and 286 deletions

View File

@ -11,11 +11,11 @@
}"
>
<Intro v-if="!players.length"></Intro>
<TownInfo :players="players" v-if="players.length"></TownInfo>
<TownSquare :players="players" @screenshot="takeScreenshot"></TownSquare>
<Menu ref="menu" :players="players"></Menu>
<EditionSelectionModal :players="players"></EditionSelectionModal>
<RoleSelectionModal :players="players"></RoleSelectionModal>
<TownInfo v-if="players.length"></TownInfo>
<TownSquare @screenshot="takeScreenshot"></TownSquare>
<Menu ref="menu"></Menu>
<EditionModal></EditionModal>
<RolesModal></RolesModal>
</div>
</template>
@ -24,26 +24,23 @@ import { mapState } from "vuex";
import TownSquare from "./components/TownSquare";
import TownInfo from "./components/TownInfo";
import Menu from "./components/Menu";
import RoleSelectionModal from "./components/RoleSelectionModal";
import EditionSelectionModal from "./components/EditionSelectionModal";
import RolesModal from "./components/modals/RolesModal";
import EditionModal from "./components/modals/EditionModal";
import Intro from "./components/Intro";
export default {
components: {
Intro,
EditionSelectionModal,
Menu,
TownSquare,
TownInfo,
RoleSelectionModal
TownSquare,
Menu,
EditionModal,
RolesModal
},
computed: mapState({
grimoire: state => state.grimoire,
players: state => state.players.players
}),
data: function() {
return {};
},
methods: {
takeScreenshot(dimensions) {
this.$refs.menu.takeScreenshot(dimensions);

View File

@ -80,11 +80,10 @@ export default {
components: {
Screenshot
},
props: ["players"],
data: function() {
return {};
},
computed: mapState(["grimoire"]),
computed: mapState({
grimoire: state => state.grimoire,
players: state => state.players.players
}),
methods: {
takeScreenshot(dimensions = {}) {
this.$store.commit("updateScreenshot");
@ -99,34 +98,23 @@ export default {
addPlayer() {
const name = prompt("Player name");
if (name) {
this.players.push({
name,
role: {},
reminders: []
});
this.$store.commit("players/add", name);
}
},
randomizeSeatings() {
if (confirm("Are you sure you want to randomize seatings?")) {
this.players = this.players
.map(a => [Math.random(), a])
.sort((a, b) => a[0] - b[0])
.map(a => a[1]);
this.$store.dispatch("players/randomize");
}
},
clearPlayers() {
if (confirm("Are you sure you want to remove all players?")) {
this.players = [];
this.$store.commit("players/clear");
}
},
clearRoles() {
this.$store.commit("showGrimoire");
if (confirm("Are you sure you want to remove all player roles?")) {
this.players.forEach(player => {
player.role = {};
player.hasDied = false;
player.reminders = [];
});
this.$store.dispatch("players/clearRoles");
}
},
...mapMutations([

View File

@ -31,7 +31,7 @@
}}</span>
</div>
<Token :role="player.role" @set-role="setRole" />
<Token :role="player.role" @set-role="$emit('set-role')" />
<div class="name" @click="changeName">
<span class="screenshot" @click.stop="takeScreenshot">
@ -40,7 +40,7 @@
<span class="name">
{{ player.name }}
</span>
<span class="remove" @click.stop="$emit('remove-player', player)">
<span class="remove" @click.stop="$emit('remove-player')">
<font-awesome-icon icon="times-circle" />
</span>
</div>
@ -64,7 +64,7 @@
{{ reminder.name }}
</div>
</template>
<div class="reminder add" @click="$emit('add-reminder', player)">
<div class="reminder add" @click="$emit('add-reminder')">
<span class="icon"></span>
</div>
</li>
@ -97,7 +97,7 @@ export default {
this.$emit("screenshot", { width, height, x, y });
},
toggleStatus() {
if (this.$store.state.grimoire.isPublic) {
if (this.grimoire.isPublic) {
if (!this.player.hasDied) {
this.$set(this.player, "hasDied", true);
} else if (this.player.hasVoted) {
@ -110,9 +110,6 @@ export default {
this.$set(this.player, "hasDied", !this.player.hasDied);
}
},
setRole() {
this.$emit("set-role", this.player);
},
changeName() {
const name = prompt("Player name", this.player.name);
this.player.name = name || this.player.name;

View File

@ -50,7 +50,7 @@ export default {
props: {
role: {
type: Object,
required: true
default: () => ({})
}
},
data() {

View File

@ -43,32 +43,26 @@ import gameJSON from "./../game";
import { mapState } from "vuex";
export default {
props: {
players: {
type: Array,
required: true
}
},
computed: {
teams: function() {
const nontravelers = Math.min(
this.players.filter(player => player.role.team !== "traveler").length,
15
);
const alive = this.players.filter(player => player.hasDied !== true)
.length;
const { players } = this.$store.state.players;
const nonTravelers = this.$store.getters["players/nonTravelers"];
const alive = players.filter(player => player.hasDied !== true).length;
return {
...gameJSON[nontravelers - 5],
traveler: this.players.length - nontravelers,
...gameJSON[nonTravelers - 5],
traveler: players.length - nonTravelers,
alive,
votes:
alive +
this.players.filter(
players.filter(
player => player.hasDied === true && player.hasVoted !== true
).length
};
},
...mapState(["edition"])
...mapState({
edition: state => state.edition,
players: state => state.players.players
})
}
};
</script>

View File

@ -10,97 +10,54 @@
v-for="(player, index) in players"
:key="index"
:player="player"
@add-reminder="openReminderModal"
@set-role="openRoleModal"
@remove-player="removePlayer"
@add-reminder="openReminderModal(index)"
@set-role="openRoleModal(index)"
@remove-player="removePlayer(index)"
@screenshot="$emit('screenshot', $event)"
></Player>
</ul>
<div class="bluffs" v-if="players.length > 6" ref="bluffs">
<h3>Demon bluffs</h3>
<font-awesome-icon icon="camera" @click.stop="takeScreenshot" />
<ul>
<li @click="openRoleModal(bluffs[0])">
<Token :role="bluffs[0].role"></Token>
</li>
<li @click="openRoleModal(bluffs[1])">
<Token :role="bluffs[1].role"></Token>
</li>
<li @click="openRoleModal(bluffs[2])">
<Token :role="bluffs[2].role"></Token>
<li
v-for="index in bluffs"
:key="index"
@click="openRoleModal(index * -1)"
>
<Token :role="grimoire.bluffs[index - 1]"></Token>
</li>
</ul>
</div>
<Modal
v-show="availableReminders.length && selectedPlayer"
@close="closeModal"
>
<h3>Choose a reminder token:</h3>
<ul class="reminders">
<li
v-for="reminder in availableReminders"
class="reminder"
v-bind:class="[reminder.role]"
v-bind:key="reminder.role + ' ' + reminder.name"
@click="addReminder(reminder)"
>
<span
class="icon"
v-bind:style="{
backgroundImage: `url(${require('../assets/icons/' +
reminder.role +
'.png')})`
}"
></span>
{{ reminder.name }}
</li>
</ul>
</Modal>
<Modal v-show="availableRoles.length && selectedPlayer" @close="closeModal">
<h3>Choose a new character:</h3>
<ul class="tokens">
<li
v-for="role in availableRoles"
v-bind:class="[role.team]"
v-bind:key="role.id"
@click="setRole(role)"
>
<Token :role="role" />
</li>
</ul>
</Modal>
<ReminderModal :player-index="selectedPlayer"></ReminderModal>
<RoleModal :player-index="selectedPlayer"></RoleModal>
</div>
</template>
<script>
import Player from "./Player";
import Modal from "./Modal";
import Token from "./Token";
import { mapState } from "vuex";
import Player from "./Player";
import Token from "./Token";
import ReminderModal from "./modals/ReminderModal";
import RoleModal from "./modals/RoleModal";
export default {
components: {
Player,
Token,
Modal,
Player
RoleModal,
ReminderModal
},
props: {
players: {
type: Array,
required: true
}
computed: {
...mapState(["grimoire", "roles"]),
...mapState("players", ["players"])
},
computed: mapState(["grimoire"]),
data() {
return {
selectedPlayer: false,
availableReminders: [],
availableRoles: [],
bluffs: Array(3)
.fill({})
.map(() => ({ role: {} }))
selectedPlayer: 0,
bluffs: 3
};
},
methods: {
@ -108,46 +65,22 @@ export default {
const { width, height, x, y } = this.$refs.bluffs.getBoundingClientRect();
this.$emit("screenshot", { width, height, x, y });
},
openReminderModal(player) {
this.availableRoles = [];
this.availableReminders = [];
this.selectedPlayer = player;
this.$store.state.roles.forEach(role => {
if (this.players.some(p => p.role.id === role.id)) {
this.availableReminders = [
...this.availableReminders,
...role.reminders.map(name => ({ role: role.id, name }))
];
}
});
this.availableReminders.push({ role: "good", name: "Good" });
this.availableReminders.push({ role: "evil", name: "Evil" });
openReminderModal(playerIndex) {
this.selectedPlayer = playerIndex;
this.$store.commit("toggleModal", "reminder");
},
openRoleModal(player) {
this.availableRoles = [];
this.availableReminders = [];
this.selectedPlayer = player;
this.$store.state.roles.forEach(role => {
if (player.role && role.id !== player.role.id) {
this.availableRoles.push(role);
}
});
this.availableRoles.push({});
openRoleModal(playerIndex) {
this.selectedPlayer = playerIndex;
this.$store.commit("toggleModal", "role");
},
addReminder(reminder) {
this.selectedPlayer.reminders.push(reminder);
this.closeModal();
},
setRole(role) {
this.selectedPlayer.role = role;
this.closeModal();
},
closeModal() {
this.selectedPlayer = false;
},
removePlayer(player) {
if (confirm(`Do you really want to remove ${player.name}?`)) {
this.players.splice(this.players.indexOf(player), 1);
removePlayer(playerIndex) {
if (
confirm(
`Do you really want to remove ${this.players[playerIndex].name}?`
)
) {
this.$store.commit("players/remove", playerIndex);
this.$store.dispatch("players/updateNightOrder");
}
}
}
@ -155,8 +88,6 @@ export default {
</script>
<style lang="scss">
@import "../vars.scss";
.circle {
padding: 0;
width: 100%;
@ -286,68 +217,4 @@ export default {
font-size: 18px;
}
}
/***** Role token modal ******/
ul.tokens li {
border-radius: 50%;
height: 120px;
width: 120px;
margin: 5px;
transition: transform 500ms ease;
&.townsfolk {
box-shadow: 0 0 10px $townsfolk, 0 0 10px #004cff;
}
&.outsider {
box-shadow: 0 0 10px $outsider, 0 0 10px $outsider;
}
&.minion {
box-shadow: 0 0 10px $minion, 0 0 10px $minion;
}
&.demon {
box-shadow: 0 0 10px $demon, 0 0 10px $demon;
}
&.traveler {
box-shadow: 0 0 10px $traveler, 0 0 10px $traveler;
}
&:hover {
transform: scale(1.2);
z-index: 10;
}
}
/***** Reminder token modal ******/
ul.reminders .reminder {
background: url("../assets/reminder.png") center center;
background-size: 100%;
width: 100px;
height: 100px;
color: black;
font-size: 65%;
font-weight: bold;
display: block;
margin: 5px;
text-align: center;
border-radius: 50%;
border: 3px solid black;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
cursor: pointer;
padding: 65px 9px 0;
line-height: 100%;
transition: transform 500ms ease;
.icon {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-size: 100%;
background-position: center 0;
background-repeat: no-repeat;
}
&:hover {
transform: scale(1.2);
}
}
</style>

View File

@ -20,7 +20,7 @@
</template>
<script>
import editionJSON from "../editions";
import editionJSON from "../../editions";
import { mapMutations, mapState } from "vuex";
import Modal from "./Modal";
@ -39,25 +39,25 @@ export default {
</script>
<style scoped lang="scss">
@import "../vars";
@import "../../vars";
// Editions
@each $img, $skipIcons in $editions {
.edition-#{$img} {
background-image: url("../assets/editions/#{$img}.png");
background-image: url("../../assets/editions/#{$img}.png");
}
@if $skipIcons != true {
.edition-#{$img}.townsfolk {
background-image: url("../assets/editions/#{$img}-townsfolk.png");
background-image: url("../../assets/editions/#{$img}-townsfolk.png");
}
.edition-#{$img}.outsider {
background-image: url("../assets/editions/#{$img}-outsider.png");
background-image: url("../../assets/editions/#{$img}-outsider.png");
}
.edition-#{$img}.minion {
background-image: url("../assets/editions/#{$img}-minion.png");
background-image: url("../../assets/editions/#{$img}-minion.png");
}
.edition-#{$img}.demon {
background-image: url("../assets/editions/#{$img}-demon.png");
background-image: url("../../assets/editions/#{$img}-demon.png");
}
}
}

View File

@ -0,0 +1,103 @@
<template>
<Modal
v-show="modals.reminder && availableReminders.length"
v-if="players[playerIndex]"
@close="toggleModal('reminder')"
>
<h3>Choose a reminder token:</h3>
<ul class="reminders">
<li
v-for="reminder in availableReminders"
class="reminder"
v-bind:class="[reminder.role]"
v-bind:key="reminder.role + ' ' + reminder.name"
@click="addReminder(reminder)"
>
<span
class="icon"
v-bind:style="{
backgroundImage: `url(${require('../../assets/icons/' +
reminder.role +
'.png')})`
}"
></span>
{{ reminder.name }}
</li>
</ul>
</Modal>
</template>
<script>
import Modal from "./Modal";
import { mapMutations, mapState } from "vuex";
export default {
components: { Modal },
props: ["playerIndex"],
computed: {
availableReminders() {
let reminders = [];
const players = this.$store.state.players.players;
this.$store.state.roles.forEach(role => {
if (players.some(p => p.role.id === role.id)) {
reminders = [
...reminders,
...role.reminders.map(name => ({ role: role.id, name }))
];
}
});
reminders.push({ role: "good", name: "Good" });
reminders.push({ role: "evil", name: "Evil" });
return reminders;
},
...mapState(["modals"]),
...mapState("players", ["players"])
},
methods: {
addReminder(reminder) {
const player = this.$store.state.players.players[this.playerIndex];
player.reminders.push(reminder);
this.$store.commit("players/update", { index: this.playerIndex, player });
this.$store.commit("toggleModal", "reminder");
},
...mapMutations(["toggleModal"])
}
};
</script>
<style scoped lang="scss">
ul.reminders .reminder {
background: url("../../assets/reminder.png") center center;
background-size: 100%;
width: 100px;
height: 100px;
color: black;
font-size: 65%;
font-weight: bold;
display: block;
margin: 5px;
text-align: center;
border-radius: 50%;
border: 3px solid black;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
cursor: pointer;
padding: 65px 9px 0;
line-height: 100%;
transition: transform 500ms ease;
.icon {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-size: 100%;
background-position: center 0;
background-repeat: no-repeat;
}
&:hover {
transform: scale(1.2);
}
}
</style>

View File

@ -0,0 +1,103 @@
<template>
<Modal
v-show="modals.role && availableRoles.length"
@close="toggleModal('role')"
>
<h3>Choose a new character: {{playerIndex}}</h3>
<ul class="tokens">
<li
v-for="role in availableRoles"
v-bind:class="[role.team]"
v-bind:key="role.id"
@click="setRole(role)"
>
<Token :role="role" />
</li>
</ul>
</Modal>
</template>
<script>
import { mapMutations, mapState } from "vuex";
import Modal from "./Modal";
import Token from "../Token";
export default {
components: { Token, Modal },
props: ["playerIndex"],
computed: {
availableRoles() {
const availableRoles = [];
const players = this.$store.state.players.players;
this.$store.state.roles.forEach(role => {
// don't show bluff roles that are already assigned to players
if (
this.playerIndex >= 0 ||
(this.playerIndex < 0 &&
!players.some(player => player.role.id === role.id))
) {
availableRoles.push(role);
}
});
availableRoles.push({});
return availableRoles;
},
...mapState(["modals", "roles"]),
...mapState("players", ["players"])
},
methods: {
setRole(role) {
if (this.playerIndex < 0) {
// assign to bluff slot
this.$store.commit("setBluff", {
index: this.playerIndex * -1 - 1,
role
});
} else {
// assign to player
const player = this.$store.state.players.players[this.playerIndex];
player.role = role;
this.$store.commit("players/update", {
index: this.playerIndex,
player
});
this.$store.dispatch("players/updateNightOrder");
}
this.$store.commit("toggleModal", "role");
},
...mapMutations(["toggleModal"])
}
};
</script>
<style scoped lang="scss">
@import "../../vars.scss";
ul.tokens li {
border-radius: 50%;
height: 120px;
width: 120px;
margin: 5px;
transition: transform 500ms ease;
&.townsfolk {
box-shadow: 0 0 10px $townsfolk, 0 0 10px #004cff;
}
&.outsider {
box-shadow: 0 0 10px $outsider, 0 0 10px $outsider;
}
&.minion {
box-shadow: 0 0 10px $minion, 0 0 10px $minion;
}
&.demon {
box-shadow: 0 0 10px $demon, 0 0 10px $demon;
}
&.traveler {
box-shadow: 0 0 10px $traveler, 0 0 10px $traveler;
}
&:hover {
transform: scale(1.2);
z-index: 10;
}
}
</style>

View File

@ -3,9 +3,9 @@
class="roles"
v-show="modals.roles"
@close="toggleModal('roles')"
v-if="nontravelerPlayers >= 5"
v-if="nonTravelers >= 5"
>
<h3>Select the characters for {{ nontravelerPlayers }} players:</h3>
<h3>Select the characters for {{ nonTravelers }} players:</h3>
<ul
class="tokens"
v-for="(teamRoles, team) in roleSelection"
@ -13,7 +13,7 @@
>
<li class="count" v-bind:class="[team]">
{{ teamRoles.filter(role => role.selected).length }} /
{{ game[nontravelerPlayers - 5][team] }}
{{ game[nonTravelers - 5][team] }}
</li>
<li
v-for="role in teamRoles"
@ -33,7 +33,7 @@
class="button"
@click="assignRoles"
v-bind:class="{
disabled: selectedRoles > nontravelerPlayers || !selectedRoles
disabled: selectedRoles > nonTravelers || !selectedRoles
}"
>
<font-awesome-icon icon="people-arrows" />
@ -49,9 +49,9 @@
<script>
import Modal from "./Modal";
import gameJSON from "./../game";
import Token from "./Token";
import { mapMutations, mapState } from "vuex";
import gameJSON from "./../../game";
import Token from "./../Token";
import { mapGetters, mapMutations, mapState } from "vuex";
const randomElement = arr => arr[Math.floor(Math.random() * arr.length)];
@ -60,12 +60,6 @@ export default {
Token,
Modal
},
props: {
players: {
type: Array,
required: true
}
},
data: function() {
return {
roleSelection: {},
@ -73,13 +67,6 @@ export default {
};
},
computed: {
nontravelerPlayers: function() {
return Math.min(
this.players.filter(({ role }) => role && role.team !== "traveler")
.length,
15
);
},
selectedRoles: function() {
return Object.values(this.roleSelection)
.map(roles => roles.filter(role => role.selected).length)
@ -90,7 +77,9 @@ export default {
roles.some(role => role.selected && role.setup)
);
},
...mapState(["roles", "modals"])
...mapState(["roles", "modals"]),
...mapState("players", ["players"]),
...mapGetters({ nonTravelers: "players/nonTravelers" })
},
methods: {
selectRandomRoles() {
@ -103,7 +92,7 @@ export default {
this.$set(role, "selected", false);
});
delete this.roleSelection["traveler"];
const playerCount = Math.max(5, this.nontravelerPlayers);
const playerCount = Math.max(5, this.nonTravelers);
const composition = this.game[playerCount - 5];
Object.keys(composition).forEach(team => {
for (let x = 0; x < composition[team]; x++) {
@ -117,7 +106,7 @@ export default {
});
},
assignRoles() {
if (this.selectedRoles <= this.nontravelerPlayers && this.selectedRoles) {
if (this.selectedRoles <= this.nonTravelers && this.selectedRoles) {
// generate list of selected roles and randomize it
const roles = Object.values(this.roleSelection)
.map(roles => roles.filter(role => role.selected))
@ -125,12 +114,14 @@ export default {
.map(a => [Math.random(), a])
.sort((a, b) => a[0] - b[0])
.map(a => a[1]);
this.players.forEach(player => {
this.players.forEach((player, index) => {
if (player.role.team !== "traveler" && roles.length) {
player.role = roles.pop();
this.$store.commit("players/update", { index, player });
}
});
this.close();
this.$store.dispatch("players/updateNightOrder");
this.$store.commit("toggleModal", "roles");
}
},
...mapMutations(["toggleModal"])
@ -148,17 +139,40 @@ export default {
};
</script>
<style lang="scss">
@import "../vars.scss";
<style lang="scss" scoped>
@import "../../vars.scss";
.roles .modal ul.tokens {
ul.tokens {
padding-left: 55px;
li {
border-radius: 50%;
height: 120px;
width: 120px;
margin: 5px;
opacity: 0.5;
transition: all 250ms;
&.selected {
opacity: 1;
}
&.townsfolk {
box-shadow: 0 0 10px $townsfolk, 0 0 10px #004cff;
}
&.outsider {
box-shadow: 0 0 10px $outsider, 0 0 10px $outsider;
}
&.minion {
box-shadow: 0 0 10px $minion, 0 0 10px $minion;
}
&.demon {
box-shadow: 0 0 10px $demon, 0 0 10px $demon;
}
&.traveler {
box-shadow: 0 0 10px $traveler, 0 0 10px $traveler;
}
&:hover {
transform: scale(1.2);
z-index: 10;
}
}
.count {
opacity: 1;

View File

@ -32,11 +32,14 @@ export default new Vuex.Store({
isScreenshot: false,
isScreenshotSuccess: false,
zoom: 1,
background: ""
background: "",
bluffs: []
},
modals: {
edition: false,
roles: false
roles: false,
role: false,
reminder: false
},
edition: "tb",
roles: getRolesByEdition()
@ -61,6 +64,9 @@ export default new Vuex.Store({
setBackground({ grimoire }, background) {
grimoire.background = background;
},
setBluff({ grimoire }, { index, role }) {
grimoire.bluffs.splice(index, 1, role);
},
toggleModal({ modals }, name) {
modals[name] = !modals[name];
},

View File

@ -1,7 +1,25 @@
const NEWPLAYER = {
role: {},
reminders: [],
hasVoted: false,
hasDied: false,
firstNight: 0,
otherNight: 0
};
const state = () => ({
players: []
});
const getters = {};
const getters = {
nonTravelers({ players }) {
const nonTravelers = players.filter(
player => player.role.team !== "traveler"
);
return Math.min(nonTravelers.length, 15);
}
};
const actions = {
// recalculate night order for all players
updateNightOrder({ state, commit }) {
@ -23,26 +41,44 @@ const actions = {
if (player.firstNight !== first || player.otherNight !== other) {
player.firstNight = first;
player.otherNight = other;
commit("updatePlayer", index, player);
commit("update", { index, player });
console.log("updated night order for player", player.name);
}
});
},
randomize({ state, commit }) {
const players = state.players
.map(a => [Math.random(), a])
.sort((a, b) => a[0] - b[0])
.map(a => a[1]);
commit("set", players);
},
clearRoles({ state, commit }) {
const players = state.players.map(({ name }) => ({
name,
...NEWPLAYER
}));
commit("set", players);
}
};
const mutations = {
setPlayers(state, players = []) {
clear(state) {
state.players = [];
},
set(state, players = []) {
state.players = players;
},
updatePlayer(state, index, player) {
update(state, { index, player }) {
state.players[index] = player;
},
addPlayer(state, name) {
add(state, name) {
state.players.push({
name,
role: {},
reminders: []
...NEWPLAYER
});
},
removePlayer(state, index) {
remove(state, index) {
state.players.splice(index, 1);
}
};

View File

@ -7,16 +7,27 @@ module.exports = store => {
store.commit("showGrimoire", JSON.parse(localStorage.isPublic));
}
if (localStorage.edition !== undefined) {
// this will initialize state.roles!
store.commit("setEdition", localStorage.edition);
}
if (localStorage.bluffs !== undefined) {
JSON.parse(localStorage.bluffs).forEach((role, index) => {
store.commit("setBluff", {
index,
role: store.state.roles.get(role) || {}
});
});
}
if (localStorage.players) {
store.commit(
"players/setPlayers",
"players/set",
JSON.parse(localStorage.players).map(player => ({
...player,
role: store.state.roles.get(player.role) || {}
}))
);
// recalculate night order
store.dispatch("players/updateNightOrder");
}
// listen to mutations
@ -39,20 +50,35 @@ module.exports = store => {
case "setEdition":
localStorage.setItem("edition", payload);
break;
case "addPlayer":
case "updatePlayer":
case "removePlayer":
case "setBluff":
localStorage.setItem(
"players",
JSON.stringify(
state.players.players.map(player => ({
...player,
role: player.role.id || {}
}))
)
"bluffs",
JSON.stringify(state.grimoire.bluffs.map(({ id }) => id))
);
break;
case "players/add":
case "players/update":
case "players/remove":
case "players/clear":
case "players/set":
if (state.players.players.length) {
localStorage.setItem(
"players",
JSON.stringify(
state.players.players.map(player => ({
...player,
// simplify the stored data
role: player.role.id || {},
firstNight: undefined,
otherNight: undefined
}))
)
);
} else {
localStorage.removeItem("players");
}
break;
}
console.log(type, payload);
console.log("persistance", type, payload);
});
};