All files / components/hooks/lineChart useLineChartMetadataExpose.ts

0% Statements 0/35
0% Branches 0/31
0% Functions 0/13
0% Lines 0/29

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111                                                                                                                                                                                                                             
import { useEffect, useRef } from "react";
import { DataPoint, ChartMetadata } from "src/types/data";
 
// We'll use the project's built-in event system
const useLineChartMetadataExpose = (
  dataSet,
  xAxisDataType,
  yScale,
  disabledItems,
  lineData,
  filter,
  onChartDataProcessed,
  renderCompleteRef,
  prevChartDataRef
) => {
  // Keep track of the chart ID
  // Track if we've dispatched our first event
  const firstEventDispatchedRef = useRef(false);
 
  useEffect(() => {
    // Log whether render is complete for debugging
 
    if (renderCompleteRef.current) {
      // Extract all dates from all series
      const allDates = dataSet.flatMap(set =>
        set.series.map(point => (xAxisDataType === "number" ? point.date : String(point.date)))
      );
 
      // Create unique dates array
      const uniqueDates = [...new Set(allDates)];
 
      // Sort and filter series based on values at the filter date if filter exists
      let visibleSeries = dataSet.map(d => d.label);
      if (filter?.date) {
        visibleSeries = visibleSeries.sort((a, b) => {
          const aData = dataSet.find(d => d.label === a);
          const bData = dataSet.find(d => d.label === b);
          const aValue =
            aData?.series.find(d => String(d.date) === String(filter.date))?.value || 0;
          const bValue =
            bData?.series.find(d => String(d.date) === String(filter.date))?.value || 0;
          return filter.sortingDir === "desc" ? bValue - aValue : aValue - bValue;
        });
 
        // Apply limit if specified
        if (filter.limit) {
          visibleSeries = visibleSeries.slice(0, filter.limit);
        }
      }
 
      const currentMetadata: ChartMetadata = {
        xAxisDomain: uniqueDates.map(String),
        yAxisDomain: yScale.domain() as [number, number],
        visibleItems: visibleSeries.filter(
          label =>
            !disabledItems.includes(label) &&
            dataSet.find(d => d.label === label)?.series.length > 0
        ),
        renderedData: lineData.reduce(
          (acc, item) => {
            // Only include data for visible series
            if (item.points.length > 0 && visibleSeries.includes(item.label)) {
              acc[item.label] = item.points;
            }
            return acc;
          },
          {} as { [key: string]: DataPoint[] }
        ),
        chartType: "line-chart",
      };
 
      // Check if data has actually changed
      const hasChanged =
        !prevChartDataRef.current ||
        JSON.stringify(prevChartDataRef.current.xAxisDomain) !==
          JSON.stringify(currentMetadata.xAxisDomain) ||
        JSON.stringify(prevChartDataRef.current.yAxisDomain) !==
          JSON.stringify(currentMetadata.yAxisDomain) ||
        JSON.stringify(prevChartDataRef.current.visibleItems) !==
          JSON.stringify(currentMetadata.visibleItems) ||
        JSON.stringify(Object.keys(prevChartDataRef.current.renderedData).sort()) !==
          JSON.stringify(Object.keys(currentMetadata.renderedData).sort());
 
      // Always update the ref with latest metadata
      prevChartDataRef.current = currentMetadata;
 
      // Only emit event/call callback if data has changed
      // Also always emit on first render when data is available
      if (hasChanged || !firstEventDispatchedRef.current) {
        firstEventDispatchedRef.current = true;
 
        // Call the callback if it exists (for backward compatibility)
        if (onChartDataProcessed) {
          onChartDataProcessed(currentMetadata);
        }
      }
    }
  }, [
    dataSet,
    xAxisDataType,
    yScale,
    disabledItems,
    lineData,
    filter,
    onChartDataProcessed,
    prevChartDataRef,
  ]);
};
 
export default useLineChartMetadataExpose;