add page results

This commit is contained in:
Tatiana Nikolaeva 2025-05-26 12:50:14 +05:00
parent 33f2b5ef62
commit 6b8197ce10
6 changed files with 396 additions and 8 deletions

View file

@ -1,16 +1,72 @@
import SurveyInfo from "../SurveyInfo/SurveyInfo.tsx";
import styles from './Results.module.css'
import styles from './Results.module.css';
import {Bar, Pie} from 'react-chartjs-2';
import {Chart as ChartJS, ArcElement, Tooltip, Legend, CategoryScale, LinearScale, BarElement, Title} from 'chart.js';
import {useOutletContext} from "react-router-dom";
import {ISurvey} from "../../api/SurveyApi.ts";
import ChartDataLabels from 'chartjs-plugin-datalabels';
import annotationPlugin from 'chartjs-plugin-annotation';
import Group from '../../assets/gmail_groups.svg?react';
import Send from '../../assets/send.svg?react';
ChartJS.register(
ArcElement, Tooltip, Legend,
CategoryScale, LinearScale, BarElement, Title, ChartDataLabels, annotationPlugin
);
// Типы для данных
interface QuestionStats {
questionText: string;
totalAnswers: number;
options: {
text: string;
percentage: number;
}[];
isMultipleChoice?: boolean;
}
export const Results = () => {
const { survey, setSurvey } = useOutletContext<{
survey: ISurvey;
setSurvey: (survey: ISurvey) => void;
}>();
return(
const surveyStats = {
totalParticipants: 100,
completionPercentage: 80,
status: 'Активен',
questions: [
{
questionText: "Вопрос 1",
totalAnswers: 80,
options: [
{ text: "Вариант 1", percentage: 46 },
{ text: "Вариант 2", percentage: 15 },
{ text: "Вариант 3", percentage: 39 }
],
isMultipleChoice: false
},
{
questionText: "Вопрос 2",
totalAnswers: 100,
options: [
{ text: "Вариант 1", percentage: 50 },
{ text: "Вариант 2", percentage: 20 },
{ text: "Вариант 3", percentage: 100 },
{ text: "Вариант 4", percentage: 80 }
],
isMultipleChoice: true
}
] as QuestionStats[]
};
// Цветовая палитра
const colorsForPie = ['#67C587', '#C9EAD4', '#EAF6ED'];
const colorsForBar = ['#8979FF'];
return (
<div className={styles.results}>
<SurveyInfo
titleSurvey={survey.title}
@ -18,6 +74,135 @@ export const Results = () => {
setDescriptionSurvey={(value) => setSurvey({ ...survey, description: value })}
setTitleSurvey={(value) => setSurvey({ ...survey, title: value })}
/>
<div className={styles.statsContainer}>
<div className={`${styles.statItem} ${styles.countAnswer}`}>
<h3>Количество ответов</h3>
<div className={styles.result}>
<p>{surveyStats.totalParticipants}</p>
<Group className={styles.imgGroup}/>
</div>
</div>
<div className={`${styles.statItem} ${styles.completion_percentage}`}>
<h3>Процент завершения</h3>
<div className={styles.result}>
<p>{surveyStats.completionPercentage}%</p>
<Send className={styles.imgSend}/>
</div>
</div>
<div className={`${styles.statItem} ${styles.status}`}>
<h3>Статус опроса</h3>
<p>{surveyStats.status}</p>
</div>
</div>
{surveyStats.questions.map((question, index) => (
<div key={index} className={styles.questionContainer}>
<div className={styles.questionContent}>
<div className={styles.textContainer}>
<h3>{question.questionText}</h3>
<p className={styles.answerCount}>Ответов: {question.totalAnswers}</p>
</div>
<div className={styles.chartContainer}>
{question.isMultipleChoice ? (
<div className={styles.barContainer}>
<Bar
data={{
labels: question.options.map(opt => opt.text),
datasets: [{
label: '% выбравших',
data: question.options.map(opt => opt.percentage),
backgroundColor: colorsForBar,
borderColor: colorsForBar,
borderWidth: 2,
borderRadius: 8,
borderSkipped: false,
}]
}}
options={{
responsive: true,
plugins: {
legend: {
display: false
},
tooltip: { enabled: true },
datalabels: { display: false },
annotation: {
annotations: question.options.map((opt, i) => ({
type: 'label',
xValue: i,
yValue: opt.percentage + 5,
content: `${opt.percentage}%`,
font: { size: 16, weight: 400 },
color: '#000'
}))
}
},
scales: {
y: {
beginAtZero: true,
max: 100,
ticks: { callback: (val) => `${val}%` }
},
x: {
ticks: {
color: '#000000',
font: {
size: 16,
weight: 400
}
},
grid: { display: false }
}
}
}}
/>
</div>
) : (
<div className={styles.pieContainer}>
<Pie
data={{
labels: question.options.map(opt => opt.text),
datasets: [{
data: question.options.map(opt => opt.percentage),
backgroundColor: colorsForPie,
borderColor: '#fff',
borderWidth: 2
}]
}}
options={{
responsive: true,
plugins: {
legend: {
position: 'right',
labels: {
color: '#000000',
font: {
size: 18,
weight: 500
}
}
},
tooltip: {
callbacks: {
label: (ctx) => `${ctx.label}: ${ctx.raw}%`
}
},
datalabels: {
formatter: (value) => `${value}%`,
color: '#000',
font: { weight: 400, size: 16 }
}
},
animation: { animateRotate: true }
}}
/>
</div>
)}
</div>
</div>
</div>
))}
</div>
)
}
);
};