import { ChangeDetectorRef, Component, ElementRef, Input, ViewChild, } from '@angular/core'; import { CommonModule } from '@angular/common'; //Services import { ChartManagerService } from './services/chart-manager.service'; //Models import { IChartBoundaries, IChartConfiguration, IChartDatasetHover, } from '../ca-chart/models'; import { ITooltipList, ITooltipListItem } from '../ca-tooltip-list/models'; //Enums import { ChartColorsStringEnum } from '../ca-chart/enums'; //Components import { CaChartComponent } from '../ca-chart/ca-chart.component'; import { CaTooltipListComponent } from '../ca-tooltip-list/ca-tooltip-list.component'; @Component({ selector: 'app-ca-chart-manager', templateUrl: './ca-chart-manager.component.html', styleUrls: ['./ca-chart-manager.component.scss'], imports: [ CommonModule, //Components CaChartComponent, CaTooltipListComponent, ], providers: [ChartManagerService] }) export class CaChartManagerComponent { @Input() chartConfigs: IChartConfiguration[] = []; @Input() tooltipLables: string[] = []; @Input() chartDatasetHover: IChartDatasetHover | null = null; @ViewChild('chartManagerContainer') chartManagerContainer!: ElementRef; @ViewChild('tooltipContainer') tooltipContainer!: ElementRef; public hoveredIndex: number | null = null; public hoveredChartId: string | null = null; public tooltipList: ITooltipList | null = null; public tooltipPosition = { x: 0, y: 0 }; constructor( private chartManagerService: ChartManagerService, private cdr: ChangeDetectorRef ) { this.chartManagerService.hoverState$.subscribe( ({ index, chartId, boundaries }) => { this.hoveredIndex = index; this.hoveredChartId = chartId; this.updateTooltipList(this.hoveredIndex, boundaries); this.cdr.markForCheck(); } ); } public calculateTooltipPosition(boundaries: IChartBoundaries): void { const containerRect = this.chartManagerContainer.nativeElement.getBoundingClientRect(); let x = boundaries.rightBoundary + 4; let y = containerRect.top; if (this.tooltipContainer) { const tooltipWidth = this.tooltipContainer.nativeElement.offsetWidth; const tooltipHeight = this.tooltipContainer.nativeElement.offsetHeight; y = containerRect.height / 2 - tooltipHeight / 2; if (x + tooltipWidth > containerRect.width) x = boundaries.leftBoundary - tooltipWidth - 4; } this.tooltipPosition = { x, y }; } private updateTooltipList( index: number | null, boundaries: IChartBoundaries | undefined ): void { if (index === null || !this.chartConfigs.length) { this.tooltipList = null; return; } if (boundaries) this.calculateTooltipPosition(boundaries); const selectedItems: ITooltipListItem[] = []; const otherItems: ITooltipListItem[] = []; this.chartConfigs.forEach((config) => { const visibleDatasets = config.chartData.datasets.filter( (dataset) => !dataset.hidden ); visibleDatasets.forEach((dataset) => { const rawData = dataset.data[index]; const value = Array.isArray(rawData) ? rawData[0] : rawData; const tooltipItem: ITooltipListItem = { label: dataset.label, value: value || 0, isCurrency: dataset.isCurrency || false, color: dataset.borderColor || ChartColorsStringEnum.WHITE, }; if (config.isTooltipItemInSelectedItems) selectedItems.push(tooltipItem); else otherItems.push(tooltipItem); }); }); this.tooltipList = { date: this.tooltipLables[index], selectedItems: selectedItems, otherItems: otherItems, showPercentage: false, }; } }