CourseInsights / frontend / src / components / CourseThroughYearsLineChart.tsx
CourseThroughYearsLineChart.tsx
Raw
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;