mirror of https://github.com/bra1n/townsquare.git
added vote locking and styling
This commit is contained in:
parent
6a37d17aec
commit
3b36c47f8e
|
@ -18,6 +18,7 @@
|
||||||
<EditionModal />
|
<EditionModal />
|
||||||
<RolesModal />
|
<RolesModal />
|
||||||
<ReferenceModal />
|
<ReferenceModal />
|
||||||
|
<Gradients />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -31,6 +32,7 @@ import EditionModal from "./components/modals/EditionModal";
|
||||||
import Intro from "./components/Intro";
|
import Intro from "./components/Intro";
|
||||||
import ReferenceModal from "./components/modals/ReferenceModal";
|
import ReferenceModal from "./components/modals/ReferenceModal";
|
||||||
import Vote from "./components/Vote";
|
import Vote from "./components/Vote";
|
||||||
|
import Gradients from "./components/Gradients";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
|
@ -41,7 +43,8 @@ export default {
|
||||||
TownSquare,
|
TownSquare,
|
||||||
Menu,
|
Menu,
|
||||||
EditionModal,
|
EditionModal,
|
||||||
RolesModal
|
RolesModal,
|
||||||
|
Gradients
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(["grimoire", "session"]),
|
...mapState(["grimoire", "session"]),
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
<template>
|
||||||
|
<!-- SVG Gradients -->
|
||||||
|
<div id="gradients">
|
||||||
|
<svg
|
||||||
|
width="0"
|
||||||
|
height="0"
|
||||||
|
v-for="(gradient, index) in gradients"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
|
<linearGradient :id="gradient[0]" x1="50%" y1="100%" x2="50%" y2="0%">
|
||||||
|
<stop
|
||||||
|
offset="0%"
|
||||||
|
:style="{ 'stop-color': gradient[2], 'stop-opacity': 1 }"
|
||||||
|
></stop>
|
||||||
|
<stop
|
||||||
|
offset="100%"
|
||||||
|
:style="{ 'stop-color': gradient[1], 'stop-opacity': 1 }"
|
||||||
|
></stop>
|
||||||
|
</linearGradient>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
gradients: [
|
||||||
|
["demon", "#ce0100", "#000"],
|
||||||
|
["townsfolk", "#1f65ff", "#000"],
|
||||||
|
["default", "#4E4E4E", "#000"]
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
svg {
|
||||||
|
position: absolute;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -8,7 +8,8 @@
|
||||||
dead: player.isDead,
|
dead: player.isDead,
|
||||||
'no-vote': player.isVoteless,
|
'no-vote': player.isVoteless,
|
||||||
you: player.id === session.playerId,
|
you: player.id === session.playerId,
|
||||||
'voted-yes': session.votes[index]
|
'vote-yes': session.votes[index],
|
||||||
|
'vote-lock': voteLocked
|
||||||
},
|
},
|
||||||
player.role.team
|
player.role.team
|
||||||
]"
|
]"
|
||||||
|
@ -44,7 +45,13 @@
|
||||||
<font-awesome-icon
|
<font-awesome-icon
|
||||||
icon="skull"
|
icon="skull"
|
||||||
class="vote"
|
class="vote"
|
||||||
title="Vote"
|
title="Voted YES"
|
||||||
|
@click="vote()"
|
||||||
|
/>
|
||||||
|
<font-awesome-icon
|
||||||
|
icon="times"
|
||||||
|
class="vote"
|
||||||
|
title="Voted NO"
|
||||||
@click="vote()"
|
@click="vote()"
|
||||||
/>
|
/>
|
||||||
<font-awesome-icon
|
<font-awesome-icon
|
||||||
|
@ -170,11 +177,20 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
index: function() {
|
...mapState("players", ["players"]),
|
||||||
return this.$store.state.players.players.indexOf(this.player);
|
|
||||||
},
|
|
||||||
...mapState(["grimoire", "session"]),
|
...mapState(["grimoire", "session"]),
|
||||||
...mapGetters({ nightOrder: "players/nightOrder" })
|
...mapGetters({ nightOrder: "players/nightOrder" }),
|
||||||
|
index: function() {
|
||||||
|
return this.players.indexOf(this.player);
|
||||||
|
},
|
||||||
|
voteLocked: function() {
|
||||||
|
const session = this.session;
|
||||||
|
const players = this.players.length;
|
||||||
|
if (!session.nomination) return false;
|
||||||
|
const indexAdjusted =
|
||||||
|
(this.index - 1 + players - session.nomination[1]) % players;
|
||||||
|
return indexAdjusted < session.lockedVote - 1;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -419,26 +435,36 @@ export default {
|
||||||
&.vote,
|
&.vote,
|
||||||
&.cancel {
|
&.cancel {
|
||||||
top: 9%;
|
top: 9%;
|
||||||
left: 20%;
|
left: 25%;
|
||||||
width: 60%;
|
width: 50%;
|
||||||
height: 60%;
|
height: 60%;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
transition: all 250ms;
|
transition: all 250ms;
|
||||||
transform: scale(0.2);
|
transform: scale(0.2);
|
||||||
&:hover {
|
* {
|
||||||
color: red;
|
stroke-width: 10px;
|
||||||
|
stroke: white;
|
||||||
|
fill: url(#default);
|
||||||
|
}
|
||||||
|
&:hover *,
|
||||||
|
&.fa-skull * {
|
||||||
|
fill: url(#demon);
|
||||||
|
}
|
||||||
|
&.fa-times * {
|
||||||
|
fill: url(#townsfolk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#townsquare.vote .player.voted-yes > svg.vote {
|
#townsquare.vote .player.vote-yes > svg.vote.fa-skull {
|
||||||
color: $demon;
|
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#townsquare.vote .player.you.voted-yes > svg.vote {
|
#townsquare.vote .player.you.vote-yes > svg.vote.fa-skull,
|
||||||
|
#townsquare.vote .player.vote-lock.vote-yes > svg.vote.fa-skull,
|
||||||
|
#townsquare.vote .player.vote-lock:not(.vote-yes) > svg.vote.fa-times {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,12 +26,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="button" @click="finish">Finish</div>
|
<div class="button" @click="finish">Finish</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="button-group" v-else-if="canVote">
|
||||||
class="button-group"
|
|
||||||
v-else-if="
|
|
||||||
player && (!player.isVoteless || nominee.role.team === 'traveler')
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<div class="button vote-no" @click="vote(false)">Vote NO</div>
|
<div class="button vote-no" @click="vote(false)">Vote NO</div>
|
||||||
<div class="button vote-yes" @click="vote(true)">Vote YES</div>
|
<div class="button vote-yes" @click="vote(true)">Vote YES</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -47,39 +42,45 @@ import { mapGetters, mapState } from "vuex";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapState("players", ["players"]),
|
||||||
|
...mapState(["session"]),
|
||||||
|
...mapGetters({ alive: "players/alive" }),
|
||||||
nominator: function() {
|
nominator: function() {
|
||||||
return this.$store.state.players.players[
|
return this.players[this.session.nomination[0]];
|
||||||
this.$store.state.session.nomination[0]
|
|
||||||
];
|
|
||||||
},
|
},
|
||||||
nominatorStyle: function() {
|
nominatorStyle: function() {
|
||||||
const players = this.$store.state.players.players.length;
|
const players = this.players.length;
|
||||||
const nomination = this.$store.state.session.nomination[0];
|
const nomination = this.session.nomination[0];
|
||||||
return {
|
return {
|
||||||
transform: `rotate(${Math.round((nomination / players) * 360)}deg)`
|
transform: `rotate(${Math.round((nomination / players) * 360)}deg)`
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
nominee: function() {
|
nominee: function() {
|
||||||
return this.$store.state.players.players[
|
return this.players[this.session.nomination[1]];
|
||||||
this.$store.state.session.nomination[1]
|
|
||||||
];
|
|
||||||
},
|
},
|
||||||
nomineeStyle: function() {
|
nomineeStyle: function() {
|
||||||
const players = this.$store.state.players.players.length;
|
const players = this.players.length;
|
||||||
const nomination = this.$store.state.session.nomination[1];
|
const nomination = this.session.nomination[1];
|
||||||
const lock = this.$store.state.session.lockedVote;
|
const lock = this.session.lockedVote;
|
||||||
const rotation = (360 * (nomination + Math.min(lock, players))) / players;
|
const rotation = (360 * (nomination + Math.min(lock, players))) / players;
|
||||||
return {
|
return {
|
||||||
transform: `rotate(${Math.round(rotation)}deg)`
|
transform: `rotate(${Math.round(rotation)}deg)`
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
player: function() {
|
player: function() {
|
||||||
const id = this.$store.state.session.playerId;
|
return this.players.find(p => p.id === this.session.playerId);
|
||||||
return this.$store.state.players.players.find(p => p.id === id);
|
|
||||||
},
|
},
|
||||||
...mapState("players", ["players"]),
|
canVote: function() {
|
||||||
...mapState(["session"]),
|
if (!this.player) return false;
|
||||||
...mapGetters({ alive: "players/alive" })
|
if (this.player.isVoteless && this.nominee.role.team !== "traveler")
|
||||||
|
return false;
|
||||||
|
const session = this.session;
|
||||||
|
const players = this.players.length;
|
||||||
|
const index = this.players.indexOf(this.player);
|
||||||
|
const indexAdjusted =
|
||||||
|
(index - 1 + players - session.nomination[1]) % players;
|
||||||
|
return indexAdjusted >= session.lockedVote - 1;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
start() {
|
start() {
|
||||||
|
@ -99,6 +100,7 @@ export default {
|
||||||
this.$store.commit("session/nomination", false);
|
this.$store.commit("session/nomination", false);
|
||||||
},
|
},
|
||||||
vote(vote) {
|
vote(vote) {
|
||||||
|
if (!this.canVote) return false;
|
||||||
const index = this.players.findIndex(p => p.id === this.session.playerId);
|
const index = this.players.findIndex(p => p.id === this.session.playerId);
|
||||||
if (index >= 0 && !!this.session.votes[index] !== vote) {
|
if (index >= 0 && !!this.session.votes[index] !== vote) {
|
||||||
this.$store.commit("session/vote", [index, vote]);
|
this.$store.commit("session/vote", [index, vote]);
|
||||||
|
|
|
@ -9,8 +9,8 @@ const faIcons = [
|
||||||
"BookOpen",
|
"BookOpen",
|
||||||
"BroadcastTower",
|
"BroadcastTower",
|
||||||
"Camera",
|
"Camera",
|
||||||
|
"Chair",
|
||||||
"CheckSquare",
|
"CheckSquare",
|
||||||
"Skull",
|
|
||||||
"Cog",
|
"Cog",
|
||||||
"Copy",
|
"Copy",
|
||||||
"ExchangeAlt",
|
"ExchangeAlt",
|
||||||
|
@ -23,16 +23,17 @@ const faIcons = [
|
||||||
"RedoAlt",
|
"RedoAlt",
|
||||||
"SearchMinus",
|
"SearchMinus",
|
||||||
"SearchPlus",
|
"SearchPlus",
|
||||||
|
"Skull",
|
||||||
"Square",
|
"Square",
|
||||||
"TheaterMasks",
|
"TheaterMasks",
|
||||||
|
"Times",
|
||||||
"TimesCircle",
|
"TimesCircle",
|
||||||
"Undo",
|
"Undo",
|
||||||
"User",
|
"User",
|
||||||
"UserEdit",
|
"UserEdit",
|
||||||
"UserFriends",
|
"UserFriends",
|
||||||
"Users",
|
"Users",
|
||||||
"VoteYea",
|
"VoteYea"
|
||||||
"Chair"
|
|
||||||
];
|
];
|
||||||
library.add(...faIcons.map(i => fas["fa" + i]));
|
library.add(...faIcons.map(i => fas["fa" + i]));
|
||||||
Vue.component("font-awesome-icon", FontAwesomeIcon);
|
Vue.component("font-awesome-icon", FontAwesomeIcon);
|
||||||
|
|
Loading…
Reference in New Issue