@eureca/eureca-ui
Version:
UI component library of Eureca's user and admin apps
133 lines (121 loc) • 4.2 kB
JavaScript
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { normalize } from 'normalizr';
import { celiSchema } from './celi.schema';
import { Box, RadioGroup, Typography } from '@material-ui/core';
import { EvaluationScore } from './evaluation-score';
import { Radio } from '../Radio';
import { Accordion } from '../Accordion';
import { Flex } from '../Flex';
import { shadows } from '../../theme';
import { colors } from '../../theme/colors';
/**
* @kkfuri: values mean score points and must be numbers in string so EvaluationScore translates it to number and radio can still read a value without falsy values like 0
*/
const radios = [
{ name: 'radio-question-no', label: 'Não', value: '0' },
{ name: 'radio-question-parcially', label: 'Parcialmente', value: '1' },
{ name: 'radio-question-yes', label: 'Sim', value: '2' },
];
const scoreReducer = (o, v, a) => (Number(a[v]) ? o + Number(a[v]) : o);
const styles = {
outerContainer: {
overflow: 'hidden',
borderRadius: 4,
boxShadow: shadows.cardShadow,
},
horizontalRule: {
borderColor: colors.gray5,
borderStyle: 'outset',
borderBottom: 0,
},
};
function AccordionWithCeliEvaluation({ title, questions, handleChange, scores = {} }) {
const currentScore = questions.reduce((acc, q) => scoreReducer(acc, q.id, scores), 0);
return (
<Accordion title={`Critério de ${title}`}>
{questions.map((question, index) => (
<Box px={2} mb={3} key={question.id}>
<Typography variant="subtitle2">{`${index + 1}. ${question.text}`}</Typography>
<RadioGroup
value={scores[question.id]}
onChange={e => handleChange(question.id, e.target.value)}
>
<Flex directionRow justifySpaceBetween>
{radios.map(data => (
<Radio key={data.value} {...data} />
))}
</Flex>
</RadioGroup>
</Box>
))}
<hr style={styles.horizontalRule} />
<EvaluationScore title={title} score={currentScore} />
</Accordion>
);
}
AccordionWithCeliEvaluation.propTypes = {
title: PropTypes.string.isRequired,
questions: PropTypes.arrayOf(
PropTypes.shape({
text: PropTypes.string.isRequired,
id: PropTypes.number.isRequired,
})
),
handleChange: PropTypes.func.isRequired,
scores: PropTypes.object,
};
function CeliEvaluation({ onChange, questions }) {
const { entities } = normalize(questions, celiSchema);
const { questions: normalizedQuestions } = entities;
// TODO: @tcp We should plug the data from the backend here
const [scores, setScores] = useState(() => {
let s = {};
Object.keys(normalizedQuestions).forEach(key => (s[key] = 0));
return s;
});
const handleChange = (questionId, value) =>
setScores(scores => {
const updatedScores = { ...scores };
updatedScores[questionId] = value;
return updatedScores;
});
const totalScore = Object.keys(scores).reduce((o, v) => scoreReducer(o, v, scores), 0);
const evaluationTitle = 'Avaliação por competências - CELI';
if (typeof onChange === 'function') onChange(scores, questions);
return (
<>
<Box px={2} mb={2}>
<Typography variant="h6">{evaluationTitle}</Typography>
</Box>
<div style={styles.outerContainer}>
{questions.map(set => (
<AccordionWithCeliEvaluation
key={set.id}
title={set.type}
questions={set.questions}
handleChange={handleChange}
scores={scores}
/>
))}
<EvaluationScore final score={totalScore} />
</div>
</>
);
}
CeliEvaluation.propTypes = {
onChange: PropTypes.func.isRequired,
questions: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
type: PropTypes.string.isRequired,
questions: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
text: PropTypes.string.isRequired,
})
).isRequired,
})
).isRequired,
};
export { CeliEvaluation };