import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'; import { Validators } from '@angular/forms'; import { SpinnerService } from '@core/services/spinner.service'; import { ProgramApplicantType } from '@core/typings/program.typing'; import { ProgramService } from '@features/programs/program.service'; import { AllProgramsResolver } from '@features/programs/resolvers/all-programs.resolver'; import { TypeaheadSelectOption, TypeSafeFormBuilder, TypeSafeFormGroup } from '@yourcause/common'; import { I18nService } from '@yourcause/common/i18n'; import { Subscription } from 'rxjs'; export interface FallbackProgramFormGroup { useFallbackMessage: boolean; fallbackMessage: string; fallbackProgramId: number; } export interface FallbackAttrsChange { fallbackMessage: string; fallbackProgramId: number; } @Component({ selector: 'gc-program-automation-builder-fallback', templateUrl: './program-automation-builder-fallback.component.html', styleUrls: ['./program-automation-builder-fallback.component.scss'] }) export class ProgramAutomationBuilderFallbackComponent implements OnInit, OnDestroy { @Input() fallbackCustomMessage: string; @Input() fallbackProgramId: number; @Input() programApplicantType: ProgramApplicantType; @Output() onChange = new EventEmitter(); @Output() onValidChange = new EventEmitter(); formGroup: TypeSafeFormGroup; sub = new Subscription(); options: TypeaheadSelectOption[] = [{ label: this.i18n.translate( 'common:textDisplayACustomMessage', {}, 'Display a custom message' ), value: true }, { label: this.i18n.translate( 'common:textRouteToAFallbackProgram', {}, 'Route to a fallback program' ), value: false }]; fallbackProgramOptions: TypeaheadSelectOption[] = []; defaultFallbackMessage = this.i18n.translate( 'PROGRAM:textDefaultFallbackProgramAutomationMessage', {}, 'Based on your responses, you do not currently qualify for a grant program. Please reach out to your Grant Manager with any questions.' ); constructor ( private formBuilder: TypeSafeFormBuilder, private i18n: I18nService, private allProgramsResolver: AllProgramsResolver, private spinnerService: SpinnerService, private programService: ProgramService ) { } async ngOnInit () { this.spinnerService.startSpinner(); await this.allProgramsResolver.resolve(); this.spinnerService.stopSpinner(); this.fallbackProgramOptions = this.programService.getPublishedActiveProgramOptions( this.programApplicantType ); let fallbackProgramId = this.fallbackProgramId; if (!fallbackProgramId && this.fallbackProgramOptions.length > 0) { fallbackProgramId = this.fallbackProgramOptions[0].value; } const useFallbackProgram = !!this.fallbackProgramId; this.formGroup = this.formBuilder.group({ useFallbackMessage: [!useFallbackProgram, Validators.required], fallbackMessage: this.fallbackCustomMessage || this.defaultFallbackMessage, fallbackProgramId }, { validator: [ this.fallbackMessageRequired(), this.fallbackProgramRequired() ] }); this.sub.add(this.formGroup.statusChanges.subscribe((val) => { this.onValidChange.emit(val === 'VALID'); })); this.onValidChange.emit(this.formGroup.valid); } emitChanges () { const formVal = this.formGroup.value; const useFallbackMessage = formVal.useFallbackMessage; this.onChange.emit({ fallbackMessage: useFallbackMessage ? formVal.fallbackMessage : '', fallbackProgramId: useFallbackMessage ? null : formVal.fallbackProgramId }); } fallbackMessageRequired () { return (group: TypeSafeFormGroup) => { const useFallbackMessage = group.value.useFallbackMessage; const message = group.value.fallbackMessage; if (useFallbackMessage && !message) { return { fallbackMessage: { required: { i18nKey: 'common:textThisInputIsRequired', defaultValue: 'This input is required' } } }; } return null; }; } fallbackProgramRequired () { return (group: TypeSafeFormGroup) => { const useFallbackMessage = group.value.useFallbackMessage; const program = group.value.fallbackProgramId; if (!useFallbackMessage && !program) { return { fallbackProgramId: { required: { i18nKey: 'common:textThisInputIsRequired', defaultValue: 'This input is required' } } }; } return null; }; } ngOnDestroy (): void { this.sub.unsubscribe(); } }