Skip to content

Commit

Permalink
✨ first pass at simple pie charts
Browse files Browse the repository at this point in the history
  • Loading branch information
haliphax committed Jul 11, 2022
1 parent 46b73ee commit 9c9f6ef
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 5 deletions.
36 changes: 31 additions & 5 deletions src/front-end/components/estimate.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script lang="ts">
import { Component } from 'vue';
import { estimate, participant, sessionState, storyState } from '../types';
import { estimate, participant, participantsState, sessionState, storyState } from '../types';
import PieChart from './piechart.vue';
const FIBONACCI = ['0', '1/2', '1', '2', '3', '5', '8', '13', '💬'] as const;
const TSHIRTS = ['XS', 'S', 'M', 'L', 'XL', '💬'] as const;
Expand All @@ -20,12 +21,35 @@ type pointsData = {
};
const Estimate: Component = {
components: {
PieChart,
},
computed: {
options(): Readonly<Array<string>> { return modeMap[this.mode as mode]; },
participants(): participantsState {
return this.$store.state.participants;
},
session(): sessionState { return this.$store.state.session; },
story(): storyState { return this.$store.state.story; },
votes() {
const votes = new Map<string, number>();
Object.values<participant>(this.participants.people).map(v => {
if (!v.value)
return;
const value = v.value!.toString();
if (!votes.hasOwnProperty(value))
votes.set(value, 0);
votes.set(value, votes.get(value)! + 1);
});
return votes;
},
you(): participant | undefined {
return Object.values<participant>(this.$store.state.participants.people)
return Object.values<participant>(this.participants.people)
.find(v => v.id === this.session.id);
},
},
Expand Down Expand Up @@ -61,14 +85,16 @@ export default Estimate;
<template>
<div>
<h2>Estimate</h2>
<ul class="unstyled grid">
<ul class="unstyled grid" v-if="!story.revealed">
<li v-for="option in options">
<button @click="setEstimate(option)" :class="classes(option)"
:disabled="story.revealed">
<button @click="setEstimate(option)" :class="classes(option)">
{{ option }}
</button>
</li>
</ul>
<div v-else>
<PieChart :data="votes"> </PieChart>
</div>
</div>
</template>

Expand Down
139 changes: 139 additions & 0 deletions src/front-end/components/piechart.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<script lang="ts">
import { Component } from 'vue';
type slice = {
key: string,
percent: number,
index: number,
rotation: number,
votes: number,
};
const PieChart: Component = {
computed: {
slices() {
const data = this.data as Map<string, number>;
const slices: Array<slice> = [];
const valIter = data.values();
let value: IteratorResult<number, any>;
let total = 0;
let rotation = 0;
while (value = valIter.next()) {
if (value.done) break;
total += value.value;
}
let index = 0;
for (let [k, v] of this.data.entries()) {
const percent = v / total;
slices.push({
key: k,
percent: percent,
index: index,
rotation: rotation,
votes: v,
});
index++;
rotation += (360 * percent);
};
return slices.sort((a, b) => a.votes - b.votes);
},
},
methods: {
styles(slice: slice) {
const output: Array<string> = [];
output.push(`--p:${slice.percent * 100}`);
output.push(`--i:${slice.index}`);
output.push(`--r:${slice.rotation}deg`);
return output.join(';');
}
},
props: ['data'],
};
export default PieChart;
</script>

<template>
<div class="pie">
<div v-for="s, idx in slices" :class="`slice color_${idx}`"
:style="styles(s)">
</div>
</div>
<div class="key">
<h3>Key</h3>
<ul>
<li v-for="s, idx in slices">
<span :class="`color color_${idx}`" :id="`slice_color_${s.key}`"
:style="styles(s)">
</span>
<label :for="`slice_color_${s.key}`">
{{ s.key }}: {{ s.votes }} vote(s)
</label>
</li>
</ul>
</div>
</template>

<style scoped>
.color {
background-color: var(--c);
display: inline-block;
height: 1em;
margin-right: .25em;
width: 1em;
}
.pie {
gap: 0;
margin: 0;
padding: 0;
position: relative;
}
.slice {
aspect-ratio: 1;
height: 100%;
margin: 0;
margin-top: calc(-100% * var(--i));
place-content: center;
position: relative;
width: 100%;
}
.slice::before {
content: '';
display: block;
position: absolute;
border-radius: 50%;
inset: 0;
background:
conic-gradient(from var(--r), var(--c) calc(var(--p) * 1%), #0000 0);
}
.color_0 {
--c: #000;
}
.color_1 {
--c: #fa0;
}
.color_2 {
--c: #7f7;
}
.color_3 {
--c: #faf;
}
.color_4 {
--c: #00f;
}
</style>

0 comments on commit 9c9f6ef

Please sign in to comment.