line_chart.jsx 2,1 ko
Newer Older
import React, { useRef, useEffect, useState } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faSpinner } from "@fortawesome/free-solid-svg-icons";
Thibault Fouchet's avatar
Thibault Fouchet a validé
import * as d3 from "d3";

function LineChart({ data }) {
    const chartRef = useRef(null);
Thibault Fouchet's avatar
Thibault Fouchet a validé
    const height = 400;
    const marginTop = 20;
    const marginRight = 20;
    const marginBottom = 30;
    const marginLeft = 60;

    const isLoading = data.length === 0;

Thibault Fouchet's avatar
Thibault Fouchet a validé

    useEffect(() => {
        const x = d3.scaleTime()
            .domain(d3.extent(data, d => new Date(d.year, d.month - 1)))
Thibault Fouchet's avatar
Thibault Fouchet a validé
            .range([marginLeft, width - marginRight]);

        const y = d3.scaleLinear()
            .domain([0, d3.max(data, d => d.averagePrice)])
Thibault Fouchet's avatar
Thibault Fouchet a validé
            .range([height - marginBottom, marginTop]);

        const svg = d3.select(chartRef.current)
            .attr("width", width)
            .attr("height", height);

        svg.append("g")
            .attr("transform", `translate(0,${height - marginBottom})`)
            .call(d3.axisBottom(x).ticks(d3.timeYear.every(1)).tickFormat(d3.timeFormat("%Y")));

        svg.append("g")
            .attr("transform", `translate(${marginLeft},0)`)
            .call(d3.axisLeft(y));

        const line = d3.line()
            .x(d => x(new Date(d.year, d.month - 1)))
            .y(d => y(d.averagePrice));
Thibault Fouchet's avatar
Thibault Fouchet a validé

        svg.append("path")
            .datum(data)
            .attr("fill", "none")
            .attr("stroke", "steelblue")
            .attr("stroke-width", 2)
            .attr("d", line);

    }, [data]);

    return (
        <div style={{ position: "relative" }}>
            {isLoading && (
                <div
                    style={{
                        position: "absolute",
                        top: "50%",
                        left: "50%",
                        transform: "translate(-50%, -50%)",
                    }}
                >
                    <FontAwesomeIcon icon={faSpinner} spin size="3x" />
                </div>
            )}
            <svg ref={chartRef}></svg>
        </div>
    );
Thibault Fouchet's avatar
Thibault Fouchet a validé
}

export default LineChart;