Analyze the code of the following js react components: chartcomponent and tablecomponent:

import React from "react";
import { Pie, Bar, Line, Scatter } from "react-chartjs-2";
import {
  Chart as ChartJS,
  ArcElement,
  Tooltip,
  Legend,
  CategoryScale,
  LinearScale,
  BarElement,
  Title,
  LineElement,
  PointElement,
} from "chart.js";
import ChartDataLabels from "chartjs-plugin-datalabels";
import TableComponent from "./TableComponent";

ChartJS.register(
  ArcElement,
  Tooltip,
  Legend,
  CategoryScale,
  LinearScale,
  BarElement,
  Title,
  ChartDataLabels,
  LineElement,
  PointElement
);

const calculateHeight = (type, data) => {
  const baseHeight = 300;
  const datasetCount = data.datasets ? data.datasets.length : 0;
  const labelCount = data.labels ? data.labels.length : 0;
  const legendHeight = 50;

  if (type === "pie") {
    return baseHeight + legendHeight;
  } else if (["line", "bar", "scatter", "dot"].includes(type)) {
    return baseHeight + datasetCount * 20 + labelCount * 10 + legendHeight;
  }
  return baseHeight + legendHeight;
};

const chartColors = [
  "rgba(255, 99, 132, 0.8)", // Red
  "rgba(54, 162, 235, 0.8)", // Blue
  "rgba(255, 206, 86, 0.8)", // Yellow
  "rgba(75, 192, 192, 0.8)", // Green
  "rgba(153, 102, 255, 0.8)", // Purple
  "rgba(255, 159, 64, 0.8)", // Orange
  "rgba(201, 203, 207, 0.8)", // Grey
];

const getColorFromString = (str) => {
  let hash = 0;
  for (let i = 0; i < str.length; i++) {
    hash = str.charCodeAt(i) + ((hash << 5) - hash);
  }
  return chartColors[Math.abs(hash) % chartColors.length];
};

const transformData = ({ headers, rows }, type) => {
  if (type === "table") return { headers, rows };

  if (type === "scatter" || type === "dot") {
    const xKey = headers[0];
    const yKeys = headers.slice(1);

    const datasets = yKeys.map((yKey) => ({
      label: yKey,
      data: rows.map((row) => ({
        x: type === "dot" ? row[xKey] : parseFloat(row[xKey]) || 0,
        y: parseFloat(row[yKey]) || 0,
      })),
      backgroundColor: getColorFromString(yKey),
      borderColor: getColorFromString(yKey),
      showLine: false,
      pointRadius: 5, // Adjust the size of the dots
    }));

    return { datasets };
  }

  const labels = rows.map((row) => row[headers[0]]);
  const datasets = headers.slice(1).map((header) => ({
    label: header,
    data: rows.map((row) => parseFloat(row[header]) || 0),
    backgroundColor: getColorFromString(header),
    borderColor: getColorFromString(header),
    fill: false,
  }));

  return { labels, datasets };
};

const ChartComponent = ({ type, data, width = 400, height }) => {
  if (type === "table") {
    return <TableComponent data={data} />;
  }

  const transformedData = transformData(data, type);
  const calculatedHeight = height || calculateHeight(type, transformedData);

  const options = {
    responsive: false,
    maintainAspectRatio: false,
    plugins: {
      tooltip: {
        enabled: true,
        bodyFont: { size: 14 },
      },
      datalabels: {
        display: () => !data.hideLabels && type === "pie",
        color: "#000",
        font: { weight: "bold", size: 16 },
        formatter: (_, context) =>
          context.chart.data.labels[context.dataIndex],
        align: "center",
        anchor: "center",
        offset: 0,
      },
      legend: {
        display: true,
        position: "top",
        align: "center",
        labels: {
          boxWidth: 20,
          font: { size: 12 },
        },
      },
      title: {
        display: true,
        text:
          data.title ||
          `${type.charAt(0).toUpperCase() + type.slice(1)} Chart`,
        font: { size: 18, weight: "bold" },
        padding: { top: 10, bottom: 30 },
      },
    },
    layout: {
      padding: {
        top: 50,
      },
    },
  };

  if (type === "scatter" || type === "dot") {
    options.scales = {
      x: {
        type: type === "dot" ? "category" : "linear",
        position: "bottom",
        title: {
          display: true,
          text: data.xAxisLabel || "X Axis",
          font: { size: 14, weight: "bold" },
        },
        ticks: { font: { size: 12 } },
      },
      y: {
        type: "linear",
        title: {
          display: true,
          text: data.yAxisLabel || "Y Axis",
          font: { size: 14, weight: "bold" },
        },
        ticks: { font: { size: 12 } },
      },
    };
  } else if (type !== "pie") {
    options.scales = {
      y: {
        beginAtZero: true,
        ticks: { font: { size: 12 } },
        grid: { display: true },
        title: {
          display: true,
          text: data.yAxisLabel || "Y Axis",
          font: { size: 14, weight: "bold" },
        },
      },
      x: {
        ticks: { font: { size: 12 } },
        grid: { display: false },
        title: {
          display: true,
          text: data.xAxisLabel || "X Axis",
          font: { size: 14, weight: "bold" },
        },
      },
    };
  }

  const chartProps = {
    data: transformedData,
    options,
    width,
    height: calculatedHeight,
  };

  switch (type) {
    case "pie":
      return <Pie {...chartProps} />;
    case "bar":
      return <Bar {...chartProps} />;
    case "line":
      return <Line {...chartProps} />;
    case "scatter":
    case "dot":
      return <Scatter {...chartProps} />;
    default:
      return <div>Unsupported chart type</div>;
  }
};

export { ChartComponent };

import React from "react";

const TableComponent = ({ data }) => {
  if (!data || !data.headers || !data.rows) {
    return <div>Invalid table data</div>;
  }

  const cellStyle = {
    border: '1px solid black',
    padding: '8px',
    textAlign: 'left !important'
  };

  return (
    <table style={{ width: '100%', borderCollapse: 'collapse', marginBottom: '20px' }}>
      <caption style={{ fontWeight: 'bold', marginBottom: '10px', textAlign: 'center' }}>{data.title}</caption>
      <thead>
        <tr>
          {data.headers.map((header, index) => (
            <th key={index} style={{ ...cellStyle, backgroundColor: '#f2f2f2' }}>{header}</th>
          ))}
        </tr>
      </thead>
      <tbody>
        {data.rows.map((row, rowIndex) => (
          <tr key={rowIndex}>
            {data.headers.map((header, cellIndex) => (
              <td key={cellIndex} style={cellStyle}>{row[header]}</td>
            ))}
          </tr>
        ))}
      </tbody>
    </table>
  );
};

export default TableComponent;