add page results
This commit is contained in:
parent
33f2b5ef62
commit
6b8197ce10
6 changed files with 396 additions and 8 deletions
|
|
@ -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>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue