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;
queryInstructor: string;
}
const InstructorHistoryLineChart: React.FC<Props> = ({ dir, chartId, queryInstructor }) => {
const chartRef = useRef<any>(null);
const [courses, setCourses] = useState<any[]>([]);
// const port = 4321;
// const SERVER_URL = `http://localhost:${port}`;
useEffect(() => {
if (queryInstructor === "") {
setCourses([]);
return;
}
const queryProf = {
"WHERE": {
"IS": {
[`${chartId}_instructor`]: queryInstructor
}
},
"OPTIONS": {
"COLUMNS": [
`${chartId}_instructor`,
`${chartId}_dept`,
`${chartId}_id`,
"overallAVG",
"overallSections"
],
"ORDER": {
"dir": dir,
"keys": [
"overallAVG"
]
}
},
"TRANSFORMATIONS": {
"GROUP": [
`${chartId}_instructor`,
`${chartId}_dept`,
`${chartId}_id`
],
"APPLY": [
{
"overallAVG": {
"AVG": `${chartId}_avg`
}
},
{
"overallSections": {
"COUNT": `${chartId}_uuid`
}
}
]
}
}
const requestOptions = {
method: "POST",
body: JSON.stringify(queryProf),
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, queryInstructor, setCourses])
let departmentIds = [...new Set(courses?.map(course => `${course[`${chartId}_dept`]}${course[`${chartId}_id`]} (${course[`${chartId}_instructor`]})`))];
let averages = departmentIds.map(departmentId => {
const departmentCourses = courses.filter(course => `${course[`${chartId}_dept`]}${course[`${chartId}_id`]} (${course[`${chartId}_instructor`]})` === 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);
let sections = courses.map(course => course.overallSections).reverse().slice(-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",
yAxisID: 'y1',
},
{
label: 'Total Sections',
data: sections,
backgroundColor: 'rgba(75, 192, 192, 0.6)',
borderColor: 'rgba(75, 192, 192, 1)',
borderWidth: 2,
fill: false,
pointRadius: 5,
pointBackgroundColor: "green",
yAxisID: 'y2',
}
],
};
const options = {
responsive: true,
plugins: {
tooltip: {
callbacks: {
label: (tooltipItem: any) => {
return `Value: ${tooltipItem.raw}`;
},
},
},
legend: {
display: true,
},
},
scales: {
y1: {
type: "linear" as const,
position: "left" as const,
title: {
display: true,
text: "Average Score",
},
},
y2: {
type: "linear" as const,
position: "right" as const,
title: {
display: true,
text: "Total Sections",
},
grid: {
drawOnChartArea: false,
},
},
},
};
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('InstructorHistoryLineChart.pdf');
};
return (
<Container className="mt-4 container-xxl">
<h3 className="text-center">Instructor's History</h3>
<Line ref={chartRef} data={data} options={options} />
<button className="btn btn-primary mt-3" onClick={downloadPDF}>Download PDF</button>
</Container>
);
};
export default InstructorHistoryLineChart;