Skip to content

Commit

Permalink
Add filter feature
Browse files Browse the repository at this point in the history
  • Loading branch information
jprodrigues70 committed May 6, 2021
1 parent 80ffdba commit 7784a24
Show file tree
Hide file tree
Showing 9 changed files with 219 additions and 30 deletions.
12 changes: 12 additions & 0 deletions src/assets/styles/struct/index.sass
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,18 @@ a
.v--hide
display: none!important

.v--link
color: #067bc2
background: none
border: none
padding: 0
cursor: pointer
font-weight: 600
display: inline
text-align: left
&:hover
color: darken(#067bc2, 15)

@keyframes spin
from
transform: rotate(0deg)
Expand Down
32 changes: 21 additions & 11 deletions src/components/AnswerPane/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,17 @@ import "./style.sass";
import key from "../../plugins/key";
import AnswerClassifier from "../../plugins/AnswerClassifier";
import AnswerPrinter from "../../contracts/AnswerPrinter";
import Btn from "../Btn";
import SentimentItem from "../SentimentItem";
import SentimentList from "../SentimentList";
import AnswerTreatment from "../../plugins/AnswerTreatment";

export default class AnswerPane extends AnswerPrinter {
constructor(props, context) {
super(props, context);
}

summarizeDates = () => {
summarizeDates = (type, onClick) => {
const answers = this.valids
.map((i) => i.answer.split(" ")[0])
.map((i) => AnswerTreatment[type.key](i.answer))
.reduce((acc, item) => {
acc[item] = acc[item] ? acc[item] + 1 : 1;
return acc;
Expand All @@ -25,11 +24,13 @@ export default class AnswerPane extends AnswerPrinter {
</span>,
<span>
was the day that received the <b>fewest responses</b>
</span>
</span>,
type,
onClick
);
};

summarizeCityState = () => {
summarizeCityState = (type, onClick) => {
const answers = AnswerClassifier.groupCityAnswers(this.valids);
return this.summaryAnswer(
answers,
Expand All @@ -38,24 +39,33 @@ export default class AnswerPane extends AnswerPrinter {
</span>,
<span>
was the place that received the <b>fewest responses</b>
</span>
</span>,
type,
onClick
);
};

summarize = () => {
summarize = (type, onClick) => {
const answers = AnswerClassifier.groupAnswers(this.valids);
return this.summaryAnswer(answers);
return this.summaryAnswer(answers, null, null, type, onClick);
};

categorizeAndMerge = (type) => {
categorizeAndMerge = (type, onClick) => {
return this.categoryAnswer(type, (set) => {
const grouped = AnswerClassifier.groupAnswers(set);

return () => (
<ul>
{Object.keys(grouped).map((i) => (
<li key={key(`categorie-${i}`)}>
<b>{i}</b>: {grouped[i]} respondents
{onClick ? (
<button className="v--link" onClick={() => onClick(i)}>
<b>{i}</b>
</button>
) : (
<b>{i}</b>
)}
: {grouped[i]} respondents
</li>
))}
</ul>
Expand Down
15 changes: 14 additions & 1 deletion src/components/Question/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,20 @@ export default class Question extends Component {
});
}

onClick = (item) => {
this.props.onAnswerClick(item, this.state.classification);
};

render() {
const answers = this.rows.map((row, line) => ({
let answers = this.rows;

this.props.filters.forEach((f) => {
answers = answers.filter((i) =>
f.filter(i, f.params.question, f.params.answer)
);
});

answers = answers.map((row, line) => ({
line,
answer: row[this.props.position],
}));
Expand Down Expand Up @@ -69,6 +81,7 @@ export default class Question extends Component {
question-classification={this.state.classification}
answers={answers}
question={this.props.position}
onClick={(i) => this.onClick(i)}
></AnswerPane>
</div>
</div>
Expand Down
79 changes: 79 additions & 0 deletions src/components/QuestionMapper/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import "./style.sass";
import { Context } from "../../store";
import key from "../../plugins/key";
import QuestionClassifier from "../../plugins/QuestionClassifier";
import AnswerTreatment from "../../plugins/AnswerTreatment";

export default class QuestionMapper extends Component {
static contextType = Context;
Expand All @@ -13,13 +14,87 @@ export default class QuestionMapper extends Component {

const table = this.context.state["database.table"];
this.titles = (table && table.titles) || [];
this.state = {
filters: [
{
filter: (i) => i,
params: {
question: null,
answer: "",
},
},
],
phrase: [],
};
}

removeFilter = (f) => {
const filters = this.state.filters.filter(
(i) =>
!(
i.params.question === f.params.question &&
i.params.answer === f.params.answer
)
);
this.setState({
filters,
phrase: this.getPhrase(filters),
});
};

getPhrase = (filters) => {
return filters.reduce((acc, f) => {
if (f.params.question === null) {
return acc;
}
return [
...acc,
<span
onClick={() => this.removeFilter(f)}
className="c-question-mapper__filter"
key={key(`${f.params.question}-${f.params.answer}`)}
>
{`Q.${f.params.question + 1} answer == "${f.params.answer}"`}
</span>,
];
}, []);
};

onAnswerClick = (question, answer, classification) => {
const filters = [
...this.state.filters,
{
filter: (i, question, answer) => {
if (AnswerTreatment[classification.key]) {
return AnswerTreatment[classification.key](i[question]) === answer;
}
return i[question] === answer;
},
params: {
question,
answer,
},
},
];
console.log(filters);
this.setState({
filters,
phrase: this.getPhrase(filters),
});
};

render() {
const classifier = new QuestionClassifier();

return (
<div className="c-question-mapper">
{this.state.phrase.length ? (
<p className="c-question-mapper__query">
{this.state.phrase.map((i) => i)}
</p>
) : (
""
)}
<div className="c-question-mapper__questions">
{this.titles.map((item, index) => {
return (
Expand All @@ -28,6 +103,10 @@ export default class QuestionMapper extends Component {
position={index}
key={key(`question-${index}`)}
classifier={classifier}
onAnswerClick={(i, classification) =>
this.onAnswerClick(index, i, classification)
}
filters={this.state.filters}
></Question>
);
})}
Expand Down
25 changes: 25 additions & 0 deletions src/components/QuestionMapper/style.sass
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,28 @@
display: grid
grid-gap: 8px
grid-template-columns: 1fr
&__query
position: fixed
bottom: 8px
right: 16px
color: #f48024
background-color: #000
padding: 12px 12px
border-radius: 8px
font-size: 16px
z-index: 9
margin: 8px
max-height: 80px
overflow: auto
display: flex
gap: 4px
flex-wrap: wrap
max-width: 100%
&__filter
border: 1px solid #252424
padding: 8px
background-color: #252424
border-radius: 8px
cursor: pointer
&:hover
background-color: #27447d
1 change: 0 additions & 1 deletion src/components/Suitable/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Component } from "react";
import key from "../../plugins/key";
import Btn from "../Btn";
import SuitableContent from "./Content";
import "./style.sass";
Expand Down
72 changes: 56 additions & 16 deletions src/contracts/AnswerPrinter.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export default class AnswerPrinter extends Component {
}

categoryAnswer = (type, item, items = null) => {
const a = this.setState(
this.setState(
{
sets: {
...(items === null
Expand Down Expand Up @@ -219,7 +219,7 @@ export default class AnswerPrinter extends Component {
this.setState({ component });
};

summaryAnswer(answers, maxText, minText) {
summaryAnswer(answers, maxText, minText, type, onClick) {
const answersKeys = Object.keys(answers);
const max = answersKeys.reduce(
(acc, key) => {
Expand All @@ -228,7 +228,7 @@ export default class AnswerPrinter extends Component {
{ total: 0 }
);

const min = answersKeys.reduce(
const min = answersKeys.reverse().reduce(
(acc, key) => {
return answers[key] < acc.total || acc.total === 0
? { key, total: answers[key] }
Expand All @@ -252,28 +252,68 @@ export default class AnswerPrinter extends Component {
was the option that you received the <b>fewest responses</b>
</span>
);

let content = (
<ul>
<li>
"
{onClick ? (
<button className="v--link" onClick={() => onClick(max.key)}>
<b>{max.key}</b>
</button>
) : (
max.key
)}
" {maxText} . {max.total} in total
</li>
<li>
"
{onClick ? (
<button className="v--link" onClick={() => onClick(min.key)}>
<b>{min.key}</b>
</button>
) : (
min.key
)}
" {minText}. {min.total} in total
</li>
</ul>
);
if (max.key === min.key) {
content = (
<ul>
<li>
"
{onClick ? (
<button className="v--link" onClick={() => onClick(max.key)}>
<b>{max.key}</b>
</button>
) : (
max.key
)}
" {maxText} . {max.total} in total
</li>
</ul>
);
}
const areas = [
{
key: "Summary",
content: () => (
<ul>
<li>
<b>"{max.key}"</b> {maxText} . {max.total} in total
</li>
<li>
<b>"{min.key}"</b> {minText}. {min.total} in total
</li>
</ul>
),
content: () => content,
},
{
key: "Compiled data",
content: () => (
<ul>
{answersKeys.map((i) => (
<li key={key(`ctst-${i}`)}>
{i}: {answers[i]}
{onClick ? (
<button className="v--link" onClick={() => onClick(i)}>
<b>{i}</b>
</button>
) : (
i
)}
: {answers[i]}
</li>
))}
</ul>
Expand Down Expand Up @@ -354,7 +394,7 @@ export default class AnswerPrinter extends Component {
type.answers &&
type.answers.printStyle &&
this[`${type.answers.printStyle}`] &&
this[`${type.answers.printStyle}`](type)
this[`${type.answers.printStyle}`](type, this.props.onClick)
);
}
}
2 changes: 1 addition & 1 deletion src/layouts/painel/style.sass
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
&__content
padding: 20px 5%
max-height: calc(100vh - 80px)
padding-bottom: 80px
padding-bottom: 100px
overflow: auto
width: 100%
height: 100%
Expand Down
Loading

0 comments on commit 7784a24

Please sign in to comment.