Implement progress bar
parent
04f35e52f6
commit
16b0830139
|
@ -2,6 +2,7 @@
|
|||
"name": "my-app",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"homepage": "/makeachoice",
|
||||
"dependencies": {
|
||||
"@testing-library/jest-dom": "^5.11.10",
|
||||
"@testing-library/react": "^11.2.6",
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
<div id="main">
|
||||
<div class="header">
|
||||
<h1>Make a choice</h1>
|
||||
<h2>Make a choice</h2>
|
||||
</div>
|
||||
|
||||
<div class="content">
|
||||
|
|
111
src/index.js
111
src/index.js
|
@ -10,6 +10,22 @@ function shuffleArray(array) {
|
|||
}
|
||||
}
|
||||
|
||||
function choicesToMarkdown(choices) {
|
||||
const choiceNames = choices.map((c) => c.choice);
|
||||
const choiceWidth = Math.max(
|
||||
...choiceNames.concat("Choice").map((x) => x.length + 3)
|
||||
);
|
||||
const countWidth = 6;
|
||||
|
||||
let r = "| Choice".padEnd(choiceWidth, " ") + "| Count |\n";
|
||||
r += "|".padEnd(choiceWidth, "-") + "|-------|\n";
|
||||
for (const c of choices) {
|
||||
r += ("| " + c.choice).padEnd(choiceWidth, " ") + "| ";
|
||||
r += c.count.toString().padStart(countWidth, " ") + "|\n";
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
class Decision {
|
||||
constructor(indexA, indexB, choices) {
|
||||
this.indexA = indexA;
|
||||
|
@ -37,7 +53,7 @@ class Options extends React.Component {
|
|||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
choicesText: null,
|
||||
choicesText: "",
|
||||
choices: [],
|
||||
decisions: null,
|
||||
decisionsMade: null,
|
||||
|
@ -75,27 +91,49 @@ class Options extends React.Component {
|
|||
});
|
||||
}
|
||||
|
||||
startAgain() {
|
||||
this.setState({
|
||||
decisions: null,
|
||||
currentDecision: null,
|
||||
decisionsMade: null,
|
||||
});
|
||||
}
|
||||
|
||||
renderChoosing() {
|
||||
const current = this.state.currentDecision;
|
||||
const decision = this.state.decisions[current];
|
||||
const progress = (current / this.state.decisions.length) * 100;
|
||||
|
||||
return (
|
||||
<div className="pure-g">
|
||||
let choiceA = decision.choiceA;
|
||||
let choiceB = decision.choiceB;
|
||||
const maxChoiceLetters = Math.max(choiceA.length, choiceB.length);
|
||||
|
||||
let fullText = null;
|
||||
if (maxChoiceLetters > 20) {
|
||||
fullText = (
|
||||
<div className="pure-u-1 space-1">
|
||||
<div className="pure-u-9-24">
|
||||
<p>{decision.choiceA}</p>
|
||||
<p>{choiceA}</p>
|
||||
</div>
|
||||
<div className="pure-u-6-24" />
|
||||
<div className="pure-u-9-24">
|
||||
<p>{decision.choiceB}</p>
|
||||
<p>{choiceB}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
choiceA = choiceA.slice(0, 20) + "...";
|
||||
choiceB = choiceB.slice(0, 20) + "...";
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="pure-g">
|
||||
{fullText}
|
||||
<div className="pure-u-1 space-1">
|
||||
<button
|
||||
className="pure-button pure-u-9-24 button-warning"
|
||||
onClick={() => this.makeChoice(decision.indexA)}
|
||||
>
|
||||
a
|
||||
{choiceA}
|
||||
</button>
|
||||
<div className="pure-u-1-24" />
|
||||
<button
|
||||
|
@ -109,9 +147,14 @@ class Options extends React.Component {
|
|||
className="pure-button pure-u-9-24 button-warning"
|
||||
onClick={() => this.makeChoice(decision.indexB)}
|
||||
>
|
||||
b
|
||||
{choiceB}
|
||||
</button>
|
||||
</div>
|
||||
<div className="pure-u-1 space-1">
|
||||
<progress className="pure-u-1" max="100" value={progress}>
|
||||
{" "}
|
||||
</progress>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -146,9 +189,10 @@ class Options extends React.Component {
|
|||
<fieldset className="pure-group">
|
||||
<textarea
|
||||
onChange={(event) => this.choicesOnChange(event)}
|
||||
value={this.state.choicesText}
|
||||
className="pure-input-1"
|
||||
placeholder="Enter one choice per line"
|
||||
></textarea>
|
||||
/>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -190,15 +234,22 @@ class Options extends React.Component {
|
|||
return {
|
||||
choice: choice,
|
||||
count: 0,
|
||||
relativeCount: 0,
|
||||
};
|
||||
});
|
||||
|
||||
let totalCount = 0;
|
||||
for (const i of this.state.decisionsMade) {
|
||||
if (i !== -1) {
|
||||
choices[i].count += 1;
|
||||
totalCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (let c of choices) {
|
||||
c.relativeCount = (c.count / totalCount) * 100;
|
||||
}
|
||||
|
||||
choices.sort((a, b) => b.count - a.count);
|
||||
|
||||
let choicesToRender = choices.map((choice, index) => {
|
||||
|
@ -206,21 +257,45 @@ class Options extends React.Component {
|
|||
<tr key={index}>
|
||||
<td>{choice.choice}</td>
|
||||
<td>{choice.count}</td>
|
||||
<td>
|
||||
<progress max="100" value={choice.relativeCount} />
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
});
|
||||
|
||||
let choicesMarkdown = choicesToMarkdown(choices);
|
||||
|
||||
return (
|
||||
<div className="pure-u-1">
|
||||
<table class="pure-table space-1">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Choice</th>
|
||||
<th>Count</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>{choicesToRender}</tbody>
|
||||
</table>
|
||||
<div className="pure-g">
|
||||
<div className="pure-u-1">
|
||||
<table className="pure-table space-1">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Choice</th>
|
||||
<th>Count</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>{choicesToRender}</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<button
|
||||
className="pure-button button-warning pure-u-1-4 space-1"
|
||||
onClick={() => this.startAgain()}
|
||||
>
|
||||
Start again
|
||||
</button>
|
||||
<div className="pure-u-3-4" />
|
||||
<button
|
||||
className="pure-button button-secondary pure-u-1-4 space-1"
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(choicesMarkdown);
|
||||
}}
|
||||
>
|
||||
Copy result
|
||||
</button>
|
||||
<div className="pure-u-3-4" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue