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