import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core'; import { FormDefinitionComponent, FormDefinitionForUi, ReportFieldDataOptions } from '@features/configure-forms/form.typing'; import { TypeToken } from '@yourcause/common'; import { set } from 'lodash'; import { ComponentConfigTabType, ComponentTabOptionsWithValue, ComponentTabSettingWithValue, ComponentValueType } from '../component-configuration.typing'; import { CurrencyChange } from '../currency-settings/currency-settings.component'; import { DecisionSettingsChange } from '../decision-recused-settings/decision-recused-settings.component'; import { InKindDataSettingsChange } from '../in-kind-data-settings/in-kind-data-settings.component'; import { InKindValidationChange } from '../in-kind-validation-settings/in-kind-validation-settings.component'; @Component({ selector: 'gc-component-configuration-tab', templateUrl: './component-configuration-tab.component.html', styleUrls: ['./component-configuration-tab.component.scss'] }) export class ComponentConfigurationTabComponent implements OnChanges { @Input() component: FormDefinitionComponent; @Input() type: ComponentConfigTabType; @Input() formDefinition: FormDefinitionForUi[]; @Input() config: Record; @Output() onValidChange = new EventEmitter(); @Output() onModalOpenOrClose = new EventEmitter(); @Output() onChange = new EventEmitter(); components: ComponentTabSettingWithValue[] = []; validityMap: Record = {}; $string = new TypeToken(); $number = new TypeToken(); $boolean = new TypeToken(); ngOnChanges (changes: SimpleChanges) { if (changes.component || changes.type || changes.config) { this.components = this.config[this.type].components; this.setInitialValidityMap(); } } setInitialValidityMap () { this.validityMap = this.components.reduce((acc, comp) => { const uniqueAttr = this.getUniqueAttr(comp); if (comp.hasCustomValidity || !comp.required) { // Default to valid. Custom validity will fire and update these after init return { ...acc, [uniqueAttr]: true }; } else if (comp.required) { return { ...acc, [uniqueAttr]: this.hasValue(comp.value) }; } return { ...acc }; }, {} as Record); this.emitValidity(); } getUniqueAttr (component: ComponentTabSettingWithValue) { return component.key || component.type; } hasValue (value: ComponentValueType) { return !!value || value === 0; } updateBasicValidity (component: ComponentTabSettingWithValue) { if (component.required) { const uniqueAttr = this.getUniqueAttr(component); const hasValue = this.hasValue(component.value); this.validityMap[uniqueAttr] = hasValue; this.emitValidity(); } } updateCustomValidity ( comp: ComponentTabSettingWithValue, isValid: boolean ) { this.validityMap[this.getUniqueAttr(comp)] = isValid; this.emitValidity(); } emitValidity () { let isValid = true; Object.keys(this.validityMap).forEach((key) => { if (!this.validityMap[key]) { isValid = false; } }); this.onValidChange.emit(isValid); } onConfigChange ( comp: ComponentTabSettingWithValue, value: any ) { comp.value = value; set(this.component, comp.key, value); this.updateBasicValidity(comp); this.onChange.emit(this.component); } inKindValidationChange (change: InKindValidationChange) { set(this.component, 'willBeValid', change.willBeValid); set(this.component, 'validationType', change.validationType); set(this.component, 'validationItem', change.validationItem); set(this.component, 'validationAmount', change.validationAmount); set(this.component, 'validationErrorMessage', change.validationErrorMessage); this.onChange.emit(this.component); } inKindDataSettingsChange (change: InKindDataSettingsChange) { set(this.component, 'allowMultiple', change.allowMultiple); set(this.component, 'maxItems', change.maxItems); set(this.component, 'showCategory', change.showCategory); set(this.component, 'displayInKindValues', change.displayInKindValues); set(this.component, 'items', change.items); this.onChange.emit(this.component); } currencyChange (change: CurrencyChange) { set(this.component, 'useCustomCurrency', change.useCustomCurrency); set(this.component, 'customCurrency', change.customCurrency); this.onChange.emit(this.component); } decisionRecusedChange (change: DecisionSettingsChange) { set(this.component, 'allowRecused', change.allowRecused); set(this.component, 'recuseValue', change.recuseValue); this.onChange.emit(this.component); } reportFieldDataOptionsChange (change: ReportFieldDataOptions) { set(this.component, 'reportFieldDataOptions.reportFieldDisplay', change.reportFieldDisplay); set(this.component, 'reportFieldDataOptions.reportFieldObject', change.reportFieldObject); this.onChange.emit(this.component); } }