import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'; import { AbstractControl, ValidationErrors } from '@angular/forms'; import { Mask } from './models/mask'; import { Observable, combineLatestWith, map, of, startWith } from 'rxjs'; import { ChevronDown, DollarSign, X } from 'lucide-angular'; @Component({ selector: 'kit-input-currency', templateUrl: './input-currency.component.html', styleUrls: ['../styles/index.scss'], }) export class InputCurrencyComponent implements OnInit , OnChanges{ @Input() options: any[] = []; @Input() type: string = ''; @Input() placeholderType: string = ''; @Input() isLoading: boolean = false; @Input() label: string = ''; @Input() labelInput: string = ''; @Input() valueCurrency: AbstractControl | any; @Input() minlength?: number; @Input() maxlength?: number; @Input() onlyNumbers?: boolean; @Input() typeCurrency: AbstractControl | any; @Input() mask: Mask | any; @Input() iconClear:string =""; @Input() useChipListbox: boolean = true; @Input() showValueInput: boolean = true; @Input() currency: string = ''; @Output() chipSelected = new EventEmitter(); public filteredOptions$: Observable | undefined; readonly dollarSignI = DollarSign; readonly chevronDownI = ChevronDown; readonly xI = X; ngOnInit(): void { this.setFilterObservable() } ngOnChanges(changes: SimpleChanges): void { if(changes['options']) { this.setFilterObservable() } } private setFilterObservable(){ this.filteredOptions$ = this.typeCurrency.valueChanges.pipe( startWith(this.typeCurrency.value || ''), combineLatestWith(of(this.options || [])), map(([inputValue, optionslist]) => { if(inputValue){ let filterValue: string; if (typeof inputValue === 'object' && inputValue) { filterValue = inputValue.value ? inputValue.value.toLowerCase() : ''; } else if (typeof inputValue === 'string') { filterValue = inputValue.toLowerCase(); } else { filterValue = ''; } if (!filterValue) { return optionslist; } return optionslist.filter((option: any) => option.value.toLowerCase().includes(filterValue) || // Filtra por value option.label.toLowerCase().includes(filterValue) // O por label ); } else { return optionslist; } }) ); if (this.options.length > 0 ) { const existingValidators = this.typeCurrency.validator ? [this.typeCurrency.validator] : []; this.typeCurrency.setValidators([this.validateOption.bind(this), ...existingValidators]) } } displayFn(option: any): string { return option && option.label ? option.label : ''; } clearSelection(){ this.typeCurrency.setValue(null); } private validateOption(control: AbstractControl): ValidationErrors|null { const value = control.value; // Valida si el valor es un objeto o un primitivo y si está en las opciones if(this.options && value) { const isValid = this.options?.some(option => typeof value === 'object' ? option.value === value.value : option.value === value ); return isValid ? null : { invalidOption: true }; } return null } isControlRequired(): boolean { if(this.valueCurrency && this.valueCurrency.validator && this.typeCurrency && this.typeCurrency.validator) { const validatorValue = this.valueCurrency.validator({} as any); const validatorType = this.typeCurrency.validator({} as any); return !!( (validatorValue && validatorValue.required) || (validatorType && validatorType.required) ); } return false } compareChipOptions(option1: any, option2: any): boolean { // Si alguno de los dos es nulo o indefinido, no son iguales if (!option1 || !option2) return false; // Comparar por valor si ambos son objetos if (typeof option1 === 'object' && typeof option2 === 'object') { return option1.value === option2.value; } // Comparación directa en otros casos return option1 === option2; } }