import React, { useEffect, useRef, useState } from 'react';
import { Line } from 'react-chartjs-2';
import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale, LineElement, PointElement } from 'chart.js';
import jsPDF from 'jspdf';
import { Container } from "react-bootstrap";
import { SERVER_URL } from '../App';
// Register necessary chart components
ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale, LineElement, PointElement);
interface Props {
dir: string;
chartId: string;
queryDept: string;
queryId: string;
}
const CourseThroughYearsLineChart: React.FC<Props> = ({ dir, chartId, queryDept, queryId }) => {
const chartRef = useRef<any>(null);
const [courses, setCourses] = useState<any[]>([]);
// const port = 4321;
// const SERVER_URL = `http://localhost:${port}`;
useEffect(() => {
const queryCourseByYear = {
"WHERE": {
"AND": [
{
"IS": {
[`${chartId}_dept`]: queryDept
}
},
{
"IS": {
[`${chartId}_id`]: queryId
}
}
]
},
"OPTIONS": {
"COLUMNS": [
`${chartId}_year`,
"overallAVG"
],
"ORDER": {
"dir": dir,
"keys": [
`${chartId}_year`
]
}
},
"TRANSFORMATIONS": {
"GROUP": [
`${chartId}_year`
],
"APPLY": [
{
"overallAVG": {
"AVG": `${chartId}_avg`
}
}
]
}
}
const requestOptions = {
method: "POST",
body: JSON.stringify(queryCourseByYear),
headers: {'Content-Type': 'application/json'},
}
const ENDPOINT_URL = `/query`;
fetch(`${SERVER_URL}${ENDPOINT_URL}`, requestOptions)
.then((res) => {
if (!res.ok) {
return "";
throw new Error(`Failed to query: ${res.json()}`);
}
return res.json();
})
.then((data) => {
if (data === "") {
return setCourses([]);
}
//console.log("Received data: TopCoursesBarChart", data);
setCourses(data.result);
})
.catch((_error) => {
//console.error("Error:", error);
});
}, [chartId, dir, queryDept, queryId, setCourses])
let departmentIds = [...new Set(courses?.map(course => String(course[`${chartId}_year`])))];
let averages = departmentIds.map(departmentId => {
const departmentCourses = courses.filter(course => String(course[`${chartId}_year`]) === departmentId);
const average = departmentCourses.reduce((sum, course) => sum + course.overallAVG, 0) / departmentCourses.length;
return average;
});
let combined = departmentIds.map((id, index) => ({
departmentId: id,
average: averages[index]
}));
combined = combined.sort((a, b) => a.average - b.average).slice(-10);
departmentIds = combined.map(item => item.departmentId);
averages = combined.map(item => item.average);
// // If you need descending order, just change the sort line to:
// combined = combined.sort((a, b) => b.average - a.average).slice(0, 10);
const data = {
labels: departmentIds, // x-axis labels (departments)
datasets: [
{
label: 'Average Score',
data: averages,
backgroundColor: 'rgba(54, 162, 235, 0.6)',
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 2,
fill: false,
pointRadius: 5,
pointBackgroundColor: "red",
},
],
};
const options = {
responsive: true,
plugins: {
tooltip: {
callbacks: {
label: (tooltipItem: any) => {
return `Avg: ${tooltipItem.raw}`; // Tooltip label customization
},
},
},
legend: {
display: true,
},
}
};
const downloadPDF = () => {
if (!chartRef.current) return;
const chartInstance = chartRef.current;
const chartImage = chartInstance.toBase64Image();
const pdf = new jsPDF('landscape');
pdf.addImage(chartImage, 'PNG', 15, 20, 250, 120);
pdf.save('CourseThroughYearsLineChart.pdf');
};
return (
<Container className="mt-4 container-xxl w-100">
<h3 className="text-center">Course through Years</h3>
<Line ref={chartRef} data={data} options={options} />
<button className="btn btn-primary mt-3" onClick={downloadPDF}>Download PDF</button>
</Container>
);
};
export default CourseThroughYearsLineChart;