diff --git a/src/components/pages/dashboard/chart/DashboardLineChart.tsx b/src/components/pages/dashboard/chart/DashboardLineChart.tsx index e586b4a3..348f6c43 100644 --- a/src/components/pages/dashboard/chart/DashboardLineChart.tsx +++ b/src/components/pages/dashboard/chart/DashboardLineChart.tsx @@ -283,261 +283,311 @@ const DashboardLineChart = ({ })()} - {/* Chart */} - - { - // Transform data based on analysisMode - if (analysisMode === 'OVERVIEW') { - // For OVERVIEW mode, use the selected chart data - if (isOverviewCharts(data.charts)) { - const selectedChartData = data.charts[chartData]; - if (!selectedChartData || !selectedChartData.dataset) return []; - return selectedChartData.dataset; + {/* Chart Container with Empty State Overlay */} +
+ {/* Chart */} + + { + // Transform data based on analysisMode + if (analysisMode === 'OVERVIEW') { + // For OVERVIEW mode, use the selected chart data + if (isOverviewCharts(data.charts)) { + const selectedChartData = data.charts[chartData]; + if (!selectedChartData || !selectedChartData.dataset) + return []; + return selectedChartData.dataset; + } + return []; + } else { + // For COMPARISON mode, use the first available comparison chart + if (isComparisonCharts(data.charts)) { + const chartData = + data.charts.location || + data.charts.flock || + data.charts.kandang; + + if (!chartData || !chartData.dataset) return []; + return chartData.dataset; + } + return []; } - return []; - } else { - // For COMPARISON mode, use the first available comparison chart - if (isComparisonCharts(data.charts)) { - const chartData = - data.charts.location || - data.charts.flock || - data.charts.kandang; - - if (!chartData || !chartData.dataset) return []; - return chartData.dataset; - } - return []; - } - })()} - margin={{ - top: 5, - right: 10, - left: 0, - bottom: 5, - }} - > - - - { - // Calculate dynamic domain based on visible data - let seriesData: DashboardChartsSeries[] = []; - let dataset: DashboardChartsDataset[] = []; - - if ( - analysisMode === 'OVERVIEW' && - isOverviewCharts(data.charts) - ) { - seriesData = data.charts[chartData]?.series || []; - dataset = data.charts[chartData]?.dataset || []; - } else if ( - analysisMode === 'COMPARISON' && - isComparisonCharts(data.charts) - ) { - const comparisonChart = - data.charts.location || - data.charts.flock || - data.charts.kandang; - seriesData = comparisonChart?.series || []; - dataset = comparisonChart?.dataset || []; - } - - // Get all values from visible series - const visibleSeriesIds = Array.from(visibleSeries); - const allValues: number[] = []; - - dataset.forEach((item: DashboardChartsDataset) => { - visibleSeriesIds.forEach((seriesId) => { - const value = item[seriesId]; - if (typeof value === 'number') { - allValues.push(value); - } - }); - }); - - if (allValues.length === 0) return [0, 100]; - - const minValue = Math.min(...allValues); - const maxValue = Math.max(...allValues); - - // Add padding (10% on each side) - const padding = (maxValue - minValue) * 0.1; - const domainMin = Math.floor(Math.max(0, minValue - padding)); - const domainMax = Math.ceil(maxValue + padding); - - return [domainMin, domainMax]; })()} - ticks={(() => { - // Calculate dynamic ticks based on domain - let seriesData: DashboardChartsSeries[] = []; - let dataset: DashboardChartsDataset[] = []; - - if ( - analysisMode === 'OVERVIEW' && - isOverviewCharts(data.charts) - ) { - seriesData = data.charts[chartData]?.series || []; - dataset = data.charts[chartData]?.dataset || []; - } else if ( - analysisMode === 'COMPARISON' && - isComparisonCharts(data.charts) - ) { - const comparisonChart = - data.charts.location || - data.charts.flock || - data.charts.kandang; - seriesData = comparisonChart?.series || []; - dataset = comparisonChart?.dataset || []; - } - - const visibleSeriesIds = Array.from(visibleSeries); - const allValues: number[] = []; - - dataset.forEach((item: DashboardChartsDataset) => { - visibleSeriesIds.forEach((seriesId) => { - const value = item[seriesId]; - if (typeof value === 'number') { - allValues.push(value); - } - }); - }); - - if (allValues.length === 0) return [0, 25, 50, 75, 100]; - - const minValue = Math.min(...allValues); - const maxValue = Math.max(...allValues); - const padding = (maxValue - minValue) * 0.1; - const domainMin = Math.floor(Math.max(0, minValue - padding)); - const domainMax = Math.ceil(maxValue + padding); - - // Generate 5 evenly spaced ticks - const range = domainMax - domainMin; - const step = range / 4; - - return [ - domainMin, - Math.round(domainMin + step), - Math.round(domainMin + step * 2), - Math.round(domainMin + step * 3), - domainMax, - ]; - })()} - /> - `Week ${value}`} - formatter={( - value: number | undefined, - name: string | undefined - ) => { - if (value === undefined || name === undefined) return ['', '']; + > + + + { + // Calculate dynamic domain based on visible data + let seriesData: DashboardChartsSeries[] = []; + let dataset: DashboardChartsDataset[] = []; - // Get series data to find the unit - let seriesData: DashboardChartsSeries[] = []; - if ( - analysisMode === 'OVERVIEW' && - isOverviewCharts(data.charts) - ) { - seriesData = data.charts[chartData]?.series || []; - } else if ( - analysisMode === 'COMPARISON' && - isComparisonCharts(data.charts) - ) { - const comparisonChart = - data.charts.location || - data.charts.flock || - data.charts.kandang; - seriesData = comparisonChart?.series || []; - } + if ( + analysisMode === 'OVERVIEW' && + isOverviewCharts(data.charts) + ) { + seriesData = data.charts[chartData]?.series || []; + dataset = data.charts[chartData]?.dataset || []; + } else if ( + analysisMode === 'COMPARISON' && + isComparisonCharts(data.charts) + ) { + const comparisonChart = + data.charts.location || + data.charts.flock || + data.charts.kandang; + seriesData = comparisonChart?.series || []; + dataset = comparisonChart?.dataset || []; + } - // Find the series that matches this line's name - const series = seriesData.find((s) => s.label === name); - const unit = series?.unit || ''; + // Get all values from visible series + const visibleSeriesIds = Array.from(visibleSeries); + const allValues: number[] = []; - return [`${value} ${unit}`, name]; - }} - /> - {/* Dynamic Line rendering based on visible series */} - {(() => { - let seriesData: DashboardChartsSeries[] = []; - - if (analysisMode === 'OVERVIEW' && isOverviewCharts(data.charts)) { - seriesData = data.charts[chartData]?.series || []; - } else if ( - analysisMode === 'COMPARISON' && - isComparisonCharts(data.charts) - ) { - const comparisonChart = - data.charts.location || - data.charts.flock || - data.charts.kandang; - seriesData = comparisonChart?.series || []; - } - - return seriesData - .filter((series) => visibleSeries.has(series.id)) - .map((series, index) => { - const isStandard = series.id - .toString() - .toLowerCase() - .includes('std'); - // Use series.id directly as dataKey to match dataset fields - const dataKey = series.id.toString(); - - return ( - { + visibleSeriesIds.forEach((seriesId) => { + const value = item[seriesId]; + if (typeof value === 'number') { + allValues.push(value); } - activeDot={isStandard ? undefined : { r: 5 }} + }); + }); + + if (allValues.length === 0) return [0, 100]; + + const minValue = Math.min(...allValues); + const maxValue = Math.max(...allValues); + + // Add padding (10% on each side) + const padding = (maxValue - minValue) * 0.1; + const domainMin = Math.floor(Math.max(0, minValue - padding)); + const domainMax = Math.ceil(maxValue + padding); + + return [domainMin, domainMax]; + })()} + ticks={(() => { + // Calculate dynamic ticks based on domain + let seriesData: DashboardChartsSeries[] = []; + let dataset: DashboardChartsDataset[] = []; + + if ( + analysisMode === 'OVERVIEW' && + isOverviewCharts(data.charts) + ) { + seriesData = data.charts[chartData]?.series || []; + dataset = data.charts[chartData]?.dataset || []; + } else if ( + analysisMode === 'COMPARISON' && + isComparisonCharts(data.charts) + ) { + const comparisonChart = + data.charts.location || + data.charts.flock || + data.charts.kandang; + seriesData = comparisonChart?.series || []; + dataset = comparisonChart?.dataset || []; + } + + const visibleSeriesIds = Array.from(visibleSeries); + const allValues: number[] = []; + + dataset.forEach((item: DashboardChartsDataset) => { + visibleSeriesIds.forEach((seriesId) => { + const value = item[seriesId]; + if (typeof value === 'number') { + allValues.push(value); + } + }); + }); + + if (allValues.length === 0) return [0, 25, 50, 75, 100]; + + const minValue = Math.min(...allValues); + const maxValue = Math.max(...allValues); + const padding = (maxValue - minValue) * 0.1; + const domainMin = Math.floor(Math.max(0, minValue - padding)); + const domainMax = Math.ceil(maxValue + padding); + + // Generate 5 evenly spaced ticks + const range = domainMax - domainMin; + const step = range / 4; + + return [ + domainMin, + Math.round(domainMin + step), + Math.round(domainMin + step * 2), + Math.round(domainMin + step * 3), + domainMax, + ]; + })()} + /> + `Week ${value}`} + formatter={( + value: number | undefined, + name: string | undefined + ) => { + if (value === undefined || name === undefined) return ['', '']; + + // Get series data to find the unit + let seriesData: DashboardChartsSeries[] = []; + if ( + analysisMode === 'OVERVIEW' && + isOverviewCharts(data.charts) + ) { + seriesData = data.charts[chartData]?.series || []; + } else if ( + analysisMode === 'COMPARISON' && + isComparisonCharts(data.charts) + ) { + const comparisonChart = + data.charts.location || + data.charts.flock || + data.charts.kandang; + seriesData = comparisonChart?.series || []; + } + + // Find the series that matches this line's name + const series = seriesData.find((s) => s.label === name); + const unit = series?.unit || ''; + + return [`${value} ${unit}`, name]; + }} + /> + {/* Dynamic Line rendering based on visible series */} + {(() => { + let seriesData: DashboardChartsSeries[] = []; + + if ( + analysisMode === 'OVERVIEW' && + isOverviewCharts(data.charts) + ) { + seriesData = data.charts[chartData]?.series || []; + } else if ( + analysisMode === 'COMPARISON' && + isComparisonCharts(data.charts) + ) { + const comparisonChart = + data.charts.location || + data.charts.flock || + data.charts.kandang; + seriesData = comparisonChart?.series || []; + } + + return seriesData + .filter((series) => visibleSeries.has(series.id)) + .map((series, index) => { + const isStandard = series.id + .toString() + .toLowerCase() + .includes('std'); + // Use series.id directly as dataKey to match dataset fields + const dataKey = series.id.toString(); + + return ( + + ); + }); + })()} + + + + {/* Empty State Overlay */} + {(() => { + // Get current dataset + let dataset: DashboardChartsDataset[] = []; + + if (analysisMode === 'OVERVIEW' && isOverviewCharts(data.charts)) { + dataset = data.charts[chartData]?.dataset || []; + } else if ( + analysisMode === 'COMPARISON' && + isComparisonCharts(data.charts) + ) { + const comparisonChart = + data.charts.location || data.charts.flock || data.charts.kandang; + dataset = comparisonChart?.dataset || []; + } + + // Show empty state if dataset is empty + if (dataset.length === 0) { + return ( +
+ {/* Chart icon */} +
+ - ); - }); - })()} - - +
+ + {/* Empty state text */} +

+ Data Not Yet Available +

+

+ Please change your filters to get the data. +

+
+ ); + } + return null; + })()} +
); };