react-chartjs-2#Line TypeScript Examples

The following examples show how to use react-chartjs-2#Line. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: AppStats.tsx    From frontend with Apache License 2.0 6 votes vote down vote up
AppStatistics: FunctionComponent<Props> = ({ stats }) => {
  const { t } = useTranslation()
  let downloads_labels: Date[] = []
  let downloads_data: number[] = []
  if (stats.downloads_per_day) {
    for (const [key, value] of Object.entries(stats.downloads_per_day)) {
      downloads_labels.push(new Date(key))
      downloads_data.push(value)
    }
  }

  // Remove current day
  downloads_labels.pop()
  downloads_data.pop()

  const data = chartStyle(downloads_labels, downloads_data, t('installs'))
  const options = chartOptions(i18n.language)

  return (
    <div className={styles.downloads}>
      <h3>{t('installs-over-time')}</h3>
      <Line data={data} options={options} />
    </div>
  )
}
Example #2
Source File: MetricChart.tsx    From Pi-Tool with GNU General Public License v3.0 5 votes vote down vote up
MetricChart: React.FC<MetricChartProps> = ({ metric }) => {
    const chartOptions = {
        title: {
            text: metricLookup[metric].label,
            display: true
        },
        responsive: true,
        maintainAspectRatio: false,
        legend: { display: false },
        tooltips: { enabled: false },
        hover: { mode: null },
        scales: {
            xAxes: [{
                type: 'realtime',
                ticks: { display: false },
                realtime: {
                    duration: 60000,
                    refresh: 10000,
                    delay: 2000
                }
                /* time: { unit: 'seconds' } */
            }],
            yAxes: [{
                scaleLabel: false,
                ticks: {
                    suggestedMin: metricMinimum[metric],
                    callback: labelFormatter[metric]
                }
            }]
        }
    };

    //const [chartData, setChartData] = React.useState(getInitialDataset(metric as string));
    const chartData = React.useRef(getInitialDataset(metric as string));
    const chartRef = React.useRef<any>();

    useEffect(() => {
        let metricSubscriber = metricObservables[metric].subscribe((event: any) => {
            const { measurement } = event;

            // Append the new data to the existing chart data
            if (chartRef) {
                if (chartRef !== undefined && chartRef.current) {
                    chartRef.current.chartInstance.data.datasets[0].data.push({
                        x: new Date(measurement.timestamp * 1000),
                        y: measurement.value
                    });

                    chartRef.current.chartInstance.update({
                        preservation: true
                    });
                }
            }
        });

        return () => {
            console.log(`unsubscribe ${metric}`);
            metricSubscriber.unsubscribe();
        };

    }, [metric]);



    return (
        <Box width="100%">
            <Line ref={chartRef} options={chartOptions as any} data={chartData.current} key={`line-${metric as string}`} />
        </Box>
    );
}
Example #3
Source File: index.tsx    From prism-frontend with MIT License 5 votes vote down vote up
function Chart({ title, data, config, xAxisLabel }: ChartProps) {
  try {
    const chartData = formatChartData(data, config);

    switch (config.type) {
      case 'bar':
        return (
          <div>
            <Bar
              data={chartData}
              options={getChartConfig(
                config.stacked || false,
                title,
                xAxisLabel,
              )}
            />
          </div>
        );
      case 'line':
        return (
          <div>
            <Line
              data={chartData}
              options={getChartConfig(
                config.stacked || false,
                title,
                xAxisLabel,
              )}
            />
          </div>
        );
      default:
        throw new Error(
          `Charts of type ${config.type} have not been implemented yet.`,
        );
    }
  } catch (err) {
    console.error(
      err,
      'An error occured. This chart structure may not be supported yet.',
    );
  }
  return null;
}
Example #4
Source File: index.tsx    From interbtc-ui with Apache License 2.0 5 votes vote down vote up
LineChart = ({ colors, labels, yLabels, yAxes, datasets, wrapperClassName }: Props): JSX.Element => {
  const data = {
    labels: yLabels,
    datasets: datasets.map((dataset: number[] | string[], index: number) => ({
      label: labels[index],
      yAxisID: index.toString(),
      fill: false,
      borderWidth: 1,
      borderColor: colors[index],
      pointBackgroundColor: colors[index],
      pointHoverBackgroundColor: colors[index],
      data: dataset
    }))
  };

  let textPrimaryColor: string;
  let gridLineColor: string;
  let zeroLineColor: string;
  if (process.env.REACT_APP_RELAY_CHAIN_NAME === POLKADOT) {
    textPrimaryColor = INTERLAY_TEXT_PRIMARY_IN_LIGHT_MODE;
    gridLineColor = INTERLAY_GRID_LINE_COLOR;
    zeroLineColor = INTERLAY_ZERO_LINE_COLOR;
    // MEMO: should check dark mode as well
  } else if (process.env.REACT_APP_RELAY_CHAIN_NAME === KUSAMA) {
    textPrimaryColor = KINTSUGI_TEXT_PRIMARY_IN_DARK_MODE;
    gridLineColor = KINTSUGI_GRID_LINE_COLOR;
    zeroLineColor = KINTSUGI_ZERO_LINE_COLOR;
  } else {
    throw new Error('Something went wrong!');
  }

  const options = {
    maintainAspectRatio: false,
    legend: {
      labels: {
        fontSize: 12,
        fontColor: textPrimaryColor
      }
    },
    scales: {
      xAxes: [
        {
          gridLines: {
            color: gridLineColor,
            zeroLineColor
          },
          ticks: {
            fontColor: textPrimaryColor
          }
        }
      ],
      yAxes: yAxes.map(({ ticks, ...rest }, index) => ({
        id: index.toString(),
        type: 'linear',
        display: true,
        ticks: {
          fontColor: colors[index],
          ...ticks
        },
        gridLines: {
          color: gridLineColor,
          zeroLineColor
        },
        ...rest
      }))
    }
  };

  return (
    <div className={wrapperClassName}>
      <Line data={data} options={options} />
    </div>
  );
}
Example #5
Source File: time-chart.tsx    From polkabtc-ui with Apache License 2.0 5 votes vote down vote up
export default function TimeChart(props: TimeChartProps): ReactElement {
  const chartProps = {
    data: {
      datasets: [
        {
          label: 'Total',
          data: props.data,
          fill: false
        }
      ]
    },
    options: {
      title: {
        display: true,
        position: 'top',
        text: props.title,
        fontSize: 24
      },
      legend: {
        display: false
      },
      scales: {
        yAxes: [
          {
            ticks: {
              beginAtZero: true
            }
          }
        ],
        xAxes: [
          {
            type: 'time',
            time: {
              round: 'day',
              unit: 'day'
            }
          }
        ]
      }
    }
  };
  return <Line {...chartProps} />;
}
Example #6
Source File: line-chart-component.tsx    From polkabtc-ui with Apache License 2.0 5 votes vote down vote up
// TODO: should refactor by using a better package
export default function LineChartComponent(propsArg: ChartProps): React.ReactElement {
  const props =
    typeof propsArg.color === 'string' ? // meaning propsArg isn't SingleAxisProps
      ((propsArg: SingleAxisProps) => ({
        color: [propsArg.color],
        label: [propsArg.label],
        yLabels: propsArg.yLabels,
        yAxisProps: [propsArg.yAxisProps === undefined ? {} : propsArg.yAxisProps],
        data: [propsArg.data]
      }))(propsArg as SingleAxisProps) :
      (propsArg as MultiAxisProps);

  const data = {
    labels: props.yLabels,
    datasets: props.data.map((dataset, i) => ({
      label: props.label[i],
      yAxisID: i.toString(),
      fill: false,
      borderColor: getAccents(props.color[i]).color,
      borderWidth: 2,
      borderDash: [],
      borderDashOffset: 0.0,
      pointBackgroundColor: getAccents(props.color[i]).color,
      pointBorderColor: 'rgba(255,255,255,0)',
      pointHoverBackgroundColor: getAccents(props.color[i]).color,
      pointBorderWidth: 20,
      pointHoverRadius: 4,
      pointHoverBorderWidth: 15,
      pointRadius: 4,
      data: dataset,
      backgroundColor: 'rgba(255,255,255,0)'
    }))
  };

  const chartProps = {
    data,
    options: {
      responsive: true,
      maintainAspectRatio: false,
      legend: {
        labels: {
          fontSize: 9
        }
      },
      scales: {
        xAxes: [
          {
            gridLines: {
              display: false
            }
          }
        ],
        yAxes: props.yAxisProps.map((yArgs, i) => ({
          id: i.toString(),
          type: 'linear',
          display: true,
          ticks: {
            ...(yArgs.beginAtZero ? { beginAtZero: true } : {}),
            ...(yArgs.precision === undefined ? {} : { precision: yArgs.precision }),
            ...(yArgs.max === undefined ? {} : { max: yArgs.max }),
            ...(yArgs.maxTicksLimit === undefined ? {} : { maxTicksLimit: yArgs.maxTicksLimit })
          },
          ...(yArgs.position === undefined ? {} : { position: yArgs.position })
        }))
      }
    }
  };
  return (
    <div className='chart-container'>
      <Line {...chartProps} />
    </div>
  );
}
Example #7
Source File: LineGraph.tsx    From StratosDB with MIT License 5 votes vote down vote up
render() {
    // destructured queries, queryStatistics, and queryHistory from props
    const { queries, queryStatistics, queryHistory } = this.props;
    // function to create array of labels for X axis of Line graph
    const labelData = () => {
      let newArr = [];
      for (let i = 0; i < queryHistory.length; i++) {
        newArr.push(queryHistory[i]);
      }
      return newArr;
    };

    const data = {
      labels: labelData(),
      datasets: [
        {
          label: 'Run Time',
          fill: true,
          lineTension: 0.5,
          backgroundColor: '#399cff',
          borderColor: 'rgba(247,247,247,247)',
          borderWidth: 2,
          data: queryStatistics,
        },
      ],
    };

    return (
      <div id='line-graph' className='LineGraph'>
        <Line
          data={data}
          options={{
            title: {
              display: false,
              text: 'QUERY REQUEST VS RUNTIME (ms)',
              fontSize: 16,
              fontColor: '#ffffff',
            },
            legend: {
              display: false,
            },
            scales: {
              xAxes: [
                {
                  ticks: {
                    display: false,
                  },
                },
              ],
            },
          }}
        />
      </div>
    );
  }
Example #8
Source File: DataDocChart.tsx    From querybook with Apache License 2.0 5 votes vote down vote up
DataDocChart = React.memo<IDataDocChartProps>(
    ({ meta, data = [], chartJSOptions = {}, chartJSRef }) => {
        const theme = useSelector(
            (state: IStoreState) => state.user.computedSettings.theme
        );

        React.useEffect(() => {
            Chart.defaults.color = `rgb(
            ${fontColor[theme][0]},
            ${fontColor[theme][1]},
            ${fontColor[theme][2]}
        )`;
            Chart.defaults.font = {
                family: 'Avenir Next',
                size: 14,
                style: 'normal',
                weight: undefined,
                lineHeight: 1.2,
            };
            Chart.defaults.plugins.filler.propagate = true;
        }, [theme]);

        const [xAxesScaleType, yAxesScaleType] = useChartScale(meta, data);
        const chartData = processChartJSData(
            data,
            meta,
            theme,
            xAxesScaleType,
            yAxesScaleType
        );
        const combinedChartJSOptions = useMemo(
            () => ({
                ...mapMetaToChartOptions(
                    meta,
                    theme,
                    xAxesScaleType,
                    yAxesScaleType
                ),
                ...chartJSOptions,
            }),
            [meta, theme, xAxesScaleType, yAxesScaleType, chartJSOptions]
        );

        const chartProps = {
            data: chartData,
            plugins: [ChartDataLabels],
            options: combinedChartJSOptions,
            ref: chartJSRef,
        };
        let chartDOM = null;
        if (meta.chart.type === 'line' || meta.chart.type === 'area') {
            chartDOM = <Line {...chartProps} />;
        } else if (
            meta.chart.type === 'bar' ||
            meta.chart.type === 'histogram'
        ) {
            chartDOM = <Bar {...chartProps} />;
        } else if (meta.chart.type === 'pie') {
            chartDOM = <Pie {...chartProps} />;
        } else if (meta.chart.type === 'doughnut') {
            chartDOM = <Doughnut {...chartProps} />;
        } else if (meta.chart.type === 'scatter') {
            chartDOM = <Scatter {...chartProps} />;
        } else if (meta.chart.type === 'bubble') {
            chartDOM = <Bubble {...chartProps} />;
        }

        return (
            <DataDocChartWrapper size={meta.visual.size}>
                {chartDOM}
            </DataDocChartWrapper>
        );
    }
)
Example #9
Source File: ImpressionWidgetMenu.tsx    From querybook with Apache License 2.0 5 votes vote down vote up
ImpressionWidgetTimeseries: React.FC<IProps> = ({ type, itemId }) => {
    const { data: viewsDates, isLoading } = useResource(
        React.useCallback(
            () => ImpressionResource.getTimeSeries(type, itemId),
            [type, itemId]
        )
    );

    if (isLoading) {
        return <Loading />;
    }

    const chartDOM = (
        <Line
            data={{
                datasets: [
                    {
                        label: 'Number of Views',
                        data: viewsDates.map((numViewDate) => numViewDate[0]),
                        lineTension: 0,
                    },
                ],
                labels: viewsDates.map(
                    (numViewDate) => new Date(numViewDate[1] * 1000)
                ),
            }}
            options={{
                elements: {
                    point: {
                        radius: 3,
                        hitRadius: 3,
                        hoverRadius: 3,
                        hoverBorderWidth: 5,
                    },
                },
                scales: {
                    x: {
                        type: 'time',

                        time: {
                            unit: 'week',
                            displayFormats: {
                                week: 'l',
                            },
                        },
                    },
                    y: {
                        beginAtZero: 0,
                    },
                },
            }}
        />
    );

    return <div className="ImpressionWidgetTimeseries">{chartDOM}</div>;
}
Example #10
Source File: ChartWithTooltip.tsx    From aqualink-app with MIT License 4 votes vote down vote up
function ChartWithTooltip({
  chartSettings,
  children,
  className,
  style,
  ...rest
}: PropsWithChildren<ChartWithTooltipProps>) {
  const { siteId, surveys, timeZone, startDate, endDate, datasets } = rest;
  const chartDataRef = useRef<Line>(null);

  const [tooltipPosition, setTooltipPosition] = useState({ top: 0, left: 0 });
  const [tooltipData, setTooltipData] = useState<TooltipData>({
    siteId,
    date: "",
    datasets: [],
    surveyId: null,
  });
  const [showTooltip, setShowTooltip] = useState<boolean>(false);

  const customTooltip =
    (ref: React.RefObject<Line>) => (tooltipModel: ChartTooltipModel) => {
      const chart = ref.current;
      if (!chart?.chartInstance.canvas) {
        return;
      }

      const date = tooltipModel.dataPoints?.[0]?.xLabel;
      if (typeof date !== "string") return;

      const dateObject = new Date(date);

      const surveyId = findSurveyFromDate(date, surveys);

      const datasetsDates = getDatasetsTimestamps(datasets);
      const minDataDate = minBy(datasetsDates, (item) => new Date(item));
      const maxDataDate = maxBy(datasetsDates, (item) => new Date(item));

      const closestDatasetData = getTooltipClosestData(dateObject, datasets);

      const nValues = closestDatasetData
        .map(({ data }) => head(data)?.value)
        .filter(isNumber).length;

      // Chart.js displays tooltips in a parallel to the X axis preference, meaning
      // that it will appear right or left from the chart point. We want to change that,
      // and display the tooltip in a Y axis preference, and more specifically, above the chart point.
      const position = chart.chartInstance.canvas.getBoundingClientRect();

      // We center the tooltip in the X axis by subtracting half its width.
      const left = position.left + tooltipModel.caretX - TOOLTIP_WIDTH / 2;

      // We increase the tooltip's top, so that it lands above the chart point. The amount by
      // which we increase varies based on how many values we display and if there is a survey at that point,
      // as we display a `VIEW SURVEY` button.
      const top =
        position.top +
        tooltipModel.caretY -
        ((surveyId ? 30 : 0) + nValues * 20 + 50);

      // We display the tooltip only if there are data to display at this point and it lands
      // between the chart's X axis limits.
      if (
        nValues > 0 &&
        moment(date).isBetween(
          moment(startDate || minDataDate),
          moment(endDate || maxDataDate),
          undefined,
          "[]"
        )
      ) {
        setTooltipPosition({ top, left });
        setTooltipData({
          ...tooltipData,
          date,
          surveyId,
          datasets: closestDatasetData,
        });
        setShowTooltip(true);
      }
    };

  const hideTooltip = () => {
    setShowTooltip(false);
  };

  // Hide tooltip on scroll to avoid dragging it on the page.
  if (showTooltip) {
    window.addEventListener("scroll", hideTooltip);
  }

  return (
    <div className={className} style={style} onMouseLeave={hideTooltip}>
      {children}
      <Chart
        {...rest}
        chartRef={chartDataRef}
        chartSettings={{
          tooltips: {
            enabled: false,
            intersect: false,
            custom: customTooltip(chartDataRef),
          },
          legend: {
            display: false,
          },
          // we could use mergeWith here too, but currently nothing would use it.
          ...chartSettings,
        }}
      />
      {showTooltip ? (
        <div
          className="chart-tooltip"
          id="chart-tooltip"
          style={{
            position: "fixed",
            top: tooltipPosition.top,
            left: tooltipPosition.left,
          }}
        >
          <Tooltip
            {...tooltipData}
            siteTimeZone={timeZone}
            userTimeZone={Intl.DateTimeFormat().resolvedOptions().timeZone}
          />
        </div>
      ) : null}
    </div>
  );
}
Example #11
Source File: index.tsx    From aqualink-app with MIT License 4 votes vote down vote up
function Chart({
  datasets,
  surveys,
  timeZone,
  startDate,
  endDate,
  chartPeriod,
  temperatureThreshold,
  maxMonthlyMean,
  background,
  showYearInTicks,
  hideYAxisUnits,
  chartSettings = {},
  chartRef: forwardRef,
}: ChartProps) {
  const chartRef = useRef<Line>(null);
  const selectedSurvey = useSelector(surveyDetailsSelector);
  const selectedSurveyDate = selectedSurvey?.diveDate
    ? new Date(convertToLocalTime(selectedSurvey.diveDate, timeZone))
    : undefined;

  if (forwardRef) {
    // this might be doable with forwardRef or callbacks, but its a little hard since we need to
    // use it in two places
    // eslint-disable-next-line no-param-reassign
    forwardRef.current = chartRef.current;
  }

  const [xTickShift, setXTickShift] = useState<number>(0);

  const [xPeriod, setXPeriod] = useState<"week" | "month">("week");

  const [hideLastTick, setHideLastTick] = useState<boolean>(false);

  const { processedDatasets, xAxisMax, xAxisMin, yAxisMax, yAxisMin } =
    useProcessedChartData(
      datasets,
      startDate,
      endDate,
      surveys,
      temperatureThreshold,
      selectedSurveyDate
    );

  const nYTicks = 5;
  const yStepSize = Math.ceil((yAxisMax - yAxisMin) / nYTicks);

  const changeXTickShiftAndPeriod = () => {
    const { current } = chartRef;
    if (current) {
      // not sure why 'scales' doesn't have a type. Possibly from a plugin?
      const xScale = (current.chartInstance as any).scales["x-axis-0"];
      const ticksPositions = xScale.ticks.map((_: any, index: number) =>
        xScale.getPixelForTick(index)
      );
      const nTicks = ticksPositions.length;
      const {
        chartArea: { right, left },
      } = current.chartInstance;
      const ticksWidth =
        typeof nTicks === "number" && nTicks > 0 ? (right - left) / nTicks : 0;
      // If last tick is too close to the chart's right edge then hide it
      if (right - ticksPositions[nTicks - 1] < ticksWidth) {
        setHideLastTick(true);
      } else {
        setHideLastTick(false);
      }
      setXTickShift((ticksPositions[2] - ticksPositions[1]) / 2);
      if (xScale.width > SMALL_WINDOW) {
        setXPeriod("week");
      } else {
        setXPeriod("month");
      }
    }
  };

  // Catch the "window done resizing" event as suggested by https://css-tricks.com/snippets/jquery/done-resizing-event/
  const onResize = useCallback(() => {
    setTimeout(() => {
      // Resize has stopped so stop updating the chart
      changeXTickShiftAndPeriod();
    }, 1);
  }, []);

  // Update chart when window is resized
  useEffect(() => {
    window.addEventListener("resize", onResize);
    return () => {
      window.removeEventListener("resize", onResize);
    };
  }, [onResize]);

  useEffect(() => {
    changeXTickShiftAndPeriod();
  });

  const settings = mergeWith(
    {
      layout: {
        padding: { right: 10 },
      },
      maintainAspectRatio: false,
      plugins: {
        chartJsPluginBarchartBackground: {
          color: background ? "rgb(158, 166, 170, 0.07)" : "#ffffff",
        },
      },
      tooltips: {
        enabled: false,
      },
      legend: {
        display: false,
      },

      annotation: {
        annotations: [
          makeAnnotation("Historical Max", maxMonthlyMean, "rgb(75, 192, 192)"),
          makeAnnotation(
            "Bleaching Threshold",
            temperatureThreshold,
            "#ff8d00"
          ),
        ],
      },
      scales: {
        xAxes: [
          {
            type: "time",
            time: {
              displayFormats: {
                week: `MMM D ${showYearInTicks ? "YY" : ""}`,
                month: `MMM ${showYearInTicks ? "YY" : ""}`,
              },
              unit: chartPeriod || xPeriod,
            },
            display: true,
            ticks: {
              labelOffset: xTickShift,
              min: xAxisMin,
              max: xAxisMax,
              padding: 10,
              callback: (value: number, index: number, values: string[]) =>
                index === values.length - 1 && hideLastTick ? undefined : value,
            },
            gridLines: {
              display: false,
              drawTicks: false,
            },
          },
        ],
        yAxes: [
          {
            gridLines: {
              drawTicks: false,
            },
            display: true,
            ticks: {
              min: yAxisMin,
              stepSize: yStepSize,
              max: yAxisMax,
              callback: (value: number, index: number, values: number[]) => {
                // Only show ticks when at least one of the following conditions holds:
                //   1: step size is equal to one
                //   2: it's not a marginal value (i.e. its index is between 1 and L - 2)
                //   3: it's the first value (index is 0) and its difference from the next one exceeds 80% of the step size
                //   4: it's the last value (index is L - 1) and its difference from the previous one exceeds 80% of the step size
                if (
                  yStepSize === 1 ||
                  (index > 0 && index < values.length - 1) ||
                  (index === 0 &&
                    value - values[index + 1] > 0.8 * yStepSize) ||
                  (index === values.length - 1 &&
                    values[index - 1] - value > 0.8 * yStepSize)
                ) {
                  return `${value}${!hideYAxisUnits ? "°" : ""}  `;
                }
                return "";
              },
            },
          },
        ],
      },
    },
    chartSettings,
    // makes sure arrays are merged correctly
    (el: any, toMerge: any) => {
      if (Array.isArray(el)) {
        return el.concat(toMerge);
      }
      return undefined;
    }
  );

  return (
    <Line
      ref={chartRef}
      options={settings}
      data={{ datasets: processedDatasets }}
    />
  );
}
Example #12
Source File: Dashboard.tsx    From platform with MIT License 4 votes vote down vote up
export default function Dashboard() {
  const [isPaid, setIsPaid] = useState(false);
  const { user } = useAuthState();
  const [member, setMember] = useState();
  const [isLoading, setIsLoading] = useState(false);
  const [previousEvents, setPreviousEvents] = useState([]);
  const [upcomingEvents, setUpComingEvents] = useState([]);

  useEffect(() => {

    document.title = "The Chess Centre | Dashboard";

    async function fetchMember() {
      setIsLoading(true);
      const {
        data: { getMember: member },
      } = await API.graphql({
        query: getMember,
        variables: { id: user.attributes.sub },
      });
      const membershipStatus = await isPaidMember();
      setIsPaid(membershipStatus);
      setMember(member);
      if (member?.entries?.items) {
        setEventData(member.entries.items);
      }
      setIsLoading(false);
    }
    fetchMember();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [user]);

  const setEventData = (data) => {
    const past = data.filter(
      ({ event }) => new Date(event.startDate) < new Date()
    );
    const upcoming = data.filter(
      ({ event }) => new Date(event.startDate) >= new Date()
    );
    setPreviousEvents(past);
    setUpComingEvents(upcoming);
  };

  return (
    <>
      <h1 className="relative my-6 text-2xl font-semibold text-gray-700 dark:text-gray-200">
        <i className="fad fa-chart-network text-teal-600"></i> Dashboard
        {isPaid && !isLoading && (
          <div className="inline-flex align-top top-2 ml-2">
            <span className="items-center px-2.5 py-0.5 rounded-md text-xs sm:text-sm font-medium bg-yellow-100 text-yellow-800 top-2">
              Premium
            </span>
          </div>
        )}
        {isLoading && (
          <div className="absolute text-teal-500 mt-2 align-middle ml-2 text-sm inline-flex">
            <i className="fal fa-spinner-third fa-spin fa-fw"></i>
          </div>
        )}
      </h1>

      <div className="pb-5 border-b border-gray-200 dark:border-gray-700">
        <div className="-ml-2 -mt-2 flex flex-wrap items-baseline">
          <p className="ml-2 mt-1 text-sm text-left text-gray-500 dark:text-gray-400">
            Insights from your previous games and results.
          </p>
        </div>
      </div>

      <Stats
        ratingData={member?.ratingInfo ? JSON.parse(member.ratingInfo) : []}
        eventData={{
          past: previousEvents.length || 0,
          future: upcomingEvents.length || 0,
        }}
        gameData={member?.gameInfo ? JSON.parse(member.gameInfo) : {}}
      />
      <div className="grid gap-2 xl:gap-4 mb-8 md:grid-cols-3 mt-6">
        <ChartCard title="Results">
          <Doughnut {...ResultsDoughnut(member?.gameInfo)} />
        </ChartCard>
        <ChartCard title="Games">
          <Bar {...GamesChart(member?.gameInfo)} />
        </ChartCard>
        <ChartCard title="Rating">
          <Line {...RatingProgressChart(member?.ratingInfo)} />
        </ChartCard>
      </div>
      <EventTable
        upcomingEvents={upcomingEvents}
        previousEvents={previousEvents}
      />
    </>
  );
}
Example #13
Source File: statistics.tsx    From frontend with Apache License 2.0 4 votes vote down vote up
Statistics = ({ stats }: { stats: Statistics }): JSX.Element => {
  const { t } = useTranslation()
  let country_data: { country: string; value: number }[] = []
  if (stats.countries) {
    for (const [key, value] of Object.entries(stats.countries)) {
      country_data.push({ country: key, value: value })
    }
  }

  let downloads_labels: string[] = []
  let downloads_data: number[] = []
  if (stats.downloads_per_day) {
    for (const [key, value] of Object.entries(stats.downloads_per_day)) {
      downloads_labels.push(key)
      downloads_data.push(value)
    }
  }

  // Remove current day
  downloads_labels.pop()
  downloads_data.pop()

  const data = chartStyle(downloads_labels, downloads_data, t('downloads'))

  const options = chartOptions(i18n.language)

  return (
    <Main>
      <NextSeo title={t('statistics')} description={t('flathub-statistics')} />
      <div className='main-container'>
        <h1>{t('statistics')}</h1>
        <div className={styles.stats}>
          <ListBox
            items={[
              {
                icon: <MdCloudDownload />,
                header: t('count-downloads'),
                content: {
                  type: 'text',
                  text: stats.downloads?.toLocaleString(),
                },
              },
            ]}
          />
          <ListBox
            items={[
              {
                icon: <MdFormatListNumbered />,
                header: t('count-applications'),
                content: {
                  type: 'text',
                  text: stats.number_of_apps?.toLocaleString(),
                },
              },
            ]}
          />
          <ListBox
            items={[
              {
                icon: <MdCalendarToday />,
                header: t('since'),
                content: {
                  type: 'text',
                  text: new Date(2018, 3, 29).toLocaleDateString(i18n.language.substring(0, 2)),
                },
              },
            ]}
          />
        </div>
        <div className={styles.downloadStats}>{ }</div>
        <h3>{t('downloads-per-country')}</h3>
        <div className={styles.map}>
          <WorldMap
            color='var(--color-primary)'
            backgroundColor='var(--bg-color-secondary)'
            borderColor='var(--text-primary)'
            valueSuffix='downloads'
            size='responsive'
            data={country_data}
          />
        </div>
        <h3>{t('downloads-over-time')}</h3>
        <div className={styles.downloadsOverTime}>
          <Line data={data} options={options} />
        </div>
      </div>
    </Main>
  )
}
Example #14
Source File: gaschart.tsx    From ethgaswatch with MIT License 4 votes vote down vote up
GasChart = (props: GasChartProps) => {
    const defaultTimePeriod = props.type === "daily" ? 7 : 24
    const [loading, setLoading] = useState(true);
    const [timePeriod, setTimePeriod] = useState(defaultTimePeriod);
    const [chartData, setChartData] = useState<any>();

    useEffect(() => {
        async function asyncEffect() {
            try {
                let body: TrendChartData | null = null;
                let registrations: AlertsChartData | null = null;

                if (props.type === "daily") { 
                    const response = await fetch(`/.netlify/functions/trend?days=${timePeriod}`);
                    body = await response.json() as TrendChartData;

                    const regResponse = await fetch(`/.netlify/functions/registrations?days=${timePeriod}`);
                    registrations = await regResponse.json() as AlertsChartData;
                }
                if (props.type === "hourly") { 
                    const response = await fetch(`/.netlify/functions/trend?hours=${timePeriod}`);
                    body = await response.json() as TrendChartData;
                }
                if (body === null) { 
                    console.log("Error retrieving gas chart data");
                    return;
                }

                const chartData = {
                    labels: body.labels,
                    datasets: [{
                        label: "Slow",
                        borderColor: "#FFFF9D",
                        borderWidth: "1",
                        data: body.slow
                    },
                    {
                        label: "Normal",
                        borderColor: "#FEDA6A",
                        borderWidth: "1",
                        data: body.normal,  
                    },
                    {
                        label: "Fast",
                        borderColor: "#CBA737",
                        borderWidth: "1",
                        data: body.fast,
                    },
                    {
                        label: "Instant",
                        borderColor: "#654100",
                        borderWidth: "1",
                        data: body.instant,
                    },],
                    options: {
                        legend: {
                            display: true,
                            position: 'top'
                        },
                        tooltips: {
	                        mode: 'index',
	                        intersect: false,
    	                },
                    }
                };

                if (registrations) { 
                    chartData.datasets.push(
                        {
                            label: "Registrations",
                            borderColor: "#dc3545",
                            borderWidth: "1",
                            data: registrations.registrations,
                        })
                }

                setChartData(chartData);
            } catch (ex) { 
                console.log("Couldn't retrieve gas chart data", ex);
            }

            setLoading(false);
        }
        
        asyncEffect();
    }, [timePeriod, props.type]);
    
    if (loading) { 
        return <Loading />
    }

    if (!chartData) { 
        return <Alert type="danger" message="Couldn't retrieve gas chart data." />
    } 

    const dailyOptions = (<>
        <option value={7}>Last week</option>
        <option value={14}>Last 2 weeks</option>
        <option value={30}>Last month</option>
    </>);

    const hourlyOptions = (<>
        <option value={24}>Last 24 hours</option>
        <option value={72}>Last 3 days</option>
        <option value={168}>Last week</option>
    </>);

    return (
        <div className="mt-4 mb-4">
            <h2 className="text-capitalize">{props.type} average gas prices</h2>

            <div className="input-group input-group-sm col-6 col-sm-4 mb-3 float-right">
                <select className="custom-select" id="inputPeriodSelector" value={timePeriod} onChange={e => setTimePeriod(Number(e.target.value))}>
                    {props.type === "daily" ? dailyOptions : <></>}
                    {props.type === "hourly" ? hourlyOptions : <></>}
                </select>
            </div>

            <div>
                <Line data={chartData} options={chartData.options} />
            </div>
        </div>
    );
}
Example #15
Source File: index.tsx    From exevo-pan with The Unlicense 4 votes vote down vote up
ComparisonChart = ({
  guildA,
  guildB,
  tooltipSuffix,
  dateLabelType,
  className,
  ...props
}: ComparisonChartProps) => {
  const {
    translations: { common },
  } = useTranslations()

  const { colors } = useTheme()

  const formatDateLabel = useCallback(
    (timestamp: number, formatType: 'Time' | 'Date'): string => {
      const currentDate = new Date(timestamp)

      switch (formatType) {
        case 'Time': {
          const hours = currentDate.getHours().toString().padStart(2, '0')
          const minutes = currentDate.getMinutes().toString().padStart(2, '0')
          return `${hours}:${minutes}h`
        }

        case 'Date': {
          const day = currentDate.getDate().toString()
          const month = currentDate.getMonth() + 1
          const weekday = currentDate.getDay()

          return `${day}/${month}, ${common.Weekdays[weekday]}`
        }

        default:
          return currentDate.toLocaleString()
      }
    },
    [common],
  )

  const options = useMemo(
    () => ({
      responsive: true,
      maintainAspectRatio: false,
      animation: {
        duration: 400,
        easing: 'easeOutCubic',
      },
      elements: {
        line: {
          tension: 0,
        },
      },
      legend: {
        display: false,
      },
      scales: {
        xAxes: [
          {
            ticks: {
              fontColor: colors.onSurface,
            },
            gridLines: {
              display: false,
            },
          },
        ],
        yAxes: [
          {
            ticks: {
              fontColor: colors.onSurface,
              callback: (value: number) => compactNumberFormatter(value),
            },
            gridLines: {
              color: `${colors.separator}60`,
            },
          },
        ],
        displayColors: false,
      },
      tooltips: {
        callbacks: {
          label: (tooltipItem: Record<string, number>) =>
            `${formatNumberWithCommas(tooltipItem.value)} ${tooltipSuffix}`,
        },
        displayColors: false,
      },
    }),
    [colors],
  )

  const chartDataObject = useMemo(
    () => ({
      labels: guildA.dataArray.map((snapshot) =>
        formatDateLabel(snapshot.timeStamp, dateLabelType),
      ),
      datasets: [
        {
          label: guildA.name,
          data: guildA.dataArray.map((snapshot) => snapshot.value),
          fill: false,
          backgroundColor: colorA,
          borderColor: colorA,
        },
        {
          label: guildB.name,
          data: guildB.dataArray.map((snapshot) => snapshot.value),
          fill: false,
          backgroundColor: colorB,
          borderColor: colorB,
        },
      ],
    }),
    [colors, guildA],
  )

  return (
    <section
      className={clsx(
        styles.wrapper,
        'card h-[500px] pt-5 pr-4 pb-[86px] pl-[26px] transition-colors',
        className,
      )}
      {...props}
    >
      <div className="child:text-onSurface mb-5 flex gap-6 md:gap-9">
        <div style={{ color: colorA }}>
          <GuildName>{guildA.name}</GuildName>
          <OnlineCount>{guildA.summaryValue}</OnlineCount>
        </div>

        <div style={{ color: colorB }}>
          <GuildName>{guildB.name}</GuildName>
          <OnlineCount>{guildB.summaryValue}</OnlineCount>
        </div>
      </div>

      <Line data={chartDataObject} options={options} />
    </section>
  )
}
Example #16
Source File: index.tsx    From exevo-pan with The Unlicense 4 votes vote down vote up
Chart = ({
  totalLabel,
  yesterdayLabel,
  tooltipLabel,
  chartData,
  className,
  ...props
}: ChartProps) => {
  const {
    translations: { statistics, common },
  } = useTranslations()

  const { colors } = useTheme()

  const [dataSize, setDataSize] = useState(DAYS_IN_A_WEEK)

  const { current, lastMonth: originalLastMonth } = chartData
  const lastMonth = useMemo(
    () => fillArrayUntil(originalLastMonth, DAYS_IN_A_MONTH),
    [originalLastMonth],
  )
  const todayValue = lastMonth[lastMonth.length - 1]
  const yesterdayValue = lastMonth[lastMonth.length - 2]
  const dailyDifference = todayValue - yesterdayValue

  const options = useMemo(
    () => ({
      responsive: true,
      maintainAspectRatio: false,
      animation: {
        duration: 400,
        easing: 'easeOutCubic',
      },
      elements: {
        line: {
          tension: 0,
        },
      },
      legend: {
        display: false,
      },
      scales: {
        xAxes: [
          {
            ticks: {
              fontColor: colors.onSurface,
            },
            gridLines: {
              display: false,
            },
          },
        ],
        yAxes: [
          {
            ticks: {
              callback: (value: number) => formatNumberWithCommas(value),
              fontColor: colors.onSurface,
            },
            gridLines: {
              color: `${colors.separator}60`,
            },
          },
        ],
      },
      tooltips: {
        callbacks: {
          title: (tooltipItem: Record<string, string>[]) =>
            `Day ${tooltipItem[0].xLabel}`,
          label: (tooltipItem: Record<string, number>) =>
            `${tooltipLabel}: ${formatNumberWithCommas(tooltipItem.yLabel)} TC`,
        },
        displayColors: false,
      },
    }),
    [colors, tooltipLabel],
  )

  const chartDataObject = useMemo(
    () => ({
      labels: lastMonth
        .slice(lastMonth.length - dataSize)
        .map((_, index) => {
          const date = new Date()
          date.setDate(date.getDate() - index)
          return `${date.getDate()}/${date.getMonth() + 1}, ${
            common.Weekdays[date.getDay()]
          }`
        })
        .reverse(),
      datasets: [
        {
          label: tooltipLabel,
          data: lastMonth.slice(lastMonth.length - dataSize),
          fill: false,
          backgroundColor: colors.primary,
          borderColor: colors.primary,
        },
      ],
    }),
    [colors, tooltipLabel, dataSize, lastMonth],
  )

  return (
    <section
      className={clsx(
        styles.wrapper,
        'card w-full py-5 pr-4 pl-[26px] transition-colors',
        className,
      )}
      {...props}
    >
      <div className="mb-5 flex items-center gap-12">
        <Summary
          title={totalLabel}
          value={current}
          percentage={(todayValue / (current - todayValue)) * 100}
        />
        <Summary
          title={yesterdayLabel}
          value={todayValue}
          percentage={(Math.abs(dailyDifference) / yesterdayValue) * 100}
          positive={dailyDifference > 0}
        />
      </div>

      <div className="h-[260px] w-full">
        <Line data={chartDataObject} options={options} />
      </div>

      <div className="mt-[22px] flex gap-2">
        <Chip
          overrideStatus={dataSize === DAYS_IN_A_MONTH}
          onClick={() => setDataSize(DAYS_IN_A_MONTH)}
        >
          {DAYS_IN_A_MONTH} {statistics.Days}
        </Chip>
        <Chip
          overrideStatus={dataSize === DAYS_IN_A_WEEK}
          onClick={() => setDataSize(DAYS_IN_A_WEEK)}
        >
          {DAYS_IN_A_WEEK} {statistics.Days}
        </Chip>
      </div>
    </section>
  )
}