diff --git a/package.json b/package.json index ba6002d..d8a2d39 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "typescript": "4.9.5" }, "dependencies": { + "chart.js": "3.7.1", "classnames": "2.3.2", "cozy-bar": "^12.2.4", "cozy-client": "^48.1.1", @@ -67,6 +68,7 @@ "date-fns": "2.29.3", "lodash": "4.17.21", "react": "18.3.1", + "react-chartjs-2": "4.1.0", "react-dom": "18.3.1", "react-inspector": "5.1.1", "react-router-dom": "6.23.1" diff --git a/src/components/Atoms/Grades/GradesChart.jsx b/src/components/Atoms/Grades/GradesChart.jsx new file mode 100644 index 0000000..3af3132 --- /dev/null +++ b/src/components/Atoms/Grades/GradesChart.jsx @@ -0,0 +1,118 @@ +import { + Chart as ChartJS, + CategoryScale, + LinearScale, + BarElement, + Title, + Tooltip, + Legend +} from 'chart.js' +import React from 'react' +import { Bar } from 'react-chartjs-2' +import { getSubjectName } from 'src/format/subjectName' + +import useBreakpoints from 'cozy-ui/transpiled/react/providers/Breakpoints' +import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n' + +ChartJS.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend) + +const truncateLabel = (label, maxLength) => { + if (label.length > maxLength) { + return label.substring(0, maxLength) + '...' + } + return label +} + +const GradesChart = ({ subjects }) => { + const { t } = useI18n() + const { isMobile } = useBreakpoints() + + const primaryColor = getComputedStyle( + document.documentElement + ).getPropertyValue('--primaryColor') + const primaryColorLightest = getComputedStyle( + document.documentElement + ).getPropertyValue('--primaryColorLightest') + const maxColor = getComputedStyle(document.documentElement).getPropertyValue( + '--successColorLight' + ) + const minColor = getComputedStyle(document.documentElement).getPropertyValue( + '--errorColorLight' + ) + + const data = { + labels: subjects.map(subject => + truncateLabel(getSubjectName(subject.subject).pretty, 10) + ), + datasets: [ + { + label: t('Grades.values.class.title'), + data: subjects.map(subject => subject.aggregation?.avgClass ?? 0), + backgroundColor: primaryColorLightest, + borderRadius: 5 + }, + { + label: t('Grades.values.student.title'), + data: subjects.map(subject => subject.aggregation?.avgGrades ?? 0), + backgroundColor: primaryColor, + borderRadius: 5 + }, + { + label: t('Grades.values.max.title'), + data: subjects.map(subject => subject.aggregation?.maxClass ?? 0), + backgroundColor: maxColor + '60', + borderRadius: 5, + hidden: true + }, + { + label: t('Grades.values.min.title'), + data: subjects.map(subject => subject.aggregation?.minClass ?? 0), + backgroundColor: minColor + '60', + borderRadius: 5, + hidden: true + } + ] + } + + const options = { + responsive: true, + plugins: { + legend: { + labels: { + font: { + size: 14, + family: 'Lato', + weight: '500' + } + } + }, + title: { + display: false + } + }, + scales: { + x: { + grid: { + display: false + } + }, + y: { + grid: { + drawBorder: false // Masquer la bordure verticale gauche + } + } + } + } + + return ( +
+ +
+ ) +} + +export default GradesChart diff --git a/src/components/Views/GradesView.jsx b/src/components/Views/GradesView.jsx index 7680481..6f4411e 100644 --- a/src/components/Views/GradesView.jsx +++ b/src/components/Views/GradesView.jsx @@ -10,6 +10,7 @@ import useBreakpoints from 'cozy-ui/transpiled/react/providers/Breakpoints' import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n' import { GradeItem } from '../Atoms/Grades/GradeItem' +import GradesChart from '../Atoms/Grades/GradesChart' import { GradesSubjectSubheader } from '../Atoms/Grades/GradesSubjectSubheader' import { PeriodSelector } from '../Atoms/Grades/PeriodSelector' import { TabTitle } from '../Atoms/TabTitle' @@ -123,6 +124,16 @@ export const GradesView = () => { + {(subjects ?? []).length > 0 && !isLoading && ( + subject.title === selectedPeriod) + : [] + } + /> + )} + {(subjects ?? []).length === 0 && !isLoading && (