import { Component, Input, OnInit } from '@angular/core'; import { SpinnerService } from '@core/services/spinner.service'; import { Nominee } from '@core/typings/application.typing'; import { ClientSettingsService } from '@features/client-settings/client-settings.service'; import { ProgramService } from '@features/programs/program.service'; import { EmailService } from '@features/system-emails/email.service'; import { BaseEmailOptionsModel, EmailNotificationType } from '@features/system-emails/email.typing'; import { DuplicateCheckValidator, EmailValidator, GenericFile, TypeaheadSelectOption, TypeSafeFormBuilder, TypeSafeFormGroup } from '@yourcause/common'; import { AnalyticsService, EventType } from '@yourcause/common/analytics'; import { I18nService } from '@yourcause/common/i18n'; import { YCModalComponent } from '@yourcause/common/modals'; export interface ApproveDeclineFormGroup { comment: string; customMessage: string; notifyApplicant: boolean; grantProgram: number; isEmployeeOfClient: boolean; clientEmailTemplateId: number; cc: string[]; bcc: string[]; attachments: GenericFile[]; } export interface ApproveDeclineModalReturn extends ApproveDeclineFormGroup { emailOptionsModel: BaseEmailOptionsModel; } @Component({ selector: 'gc-approve-decline-modal', templateUrl: './approve-decline-modal.component.html', styleUrls: ['./approve-decline-modal.component.scss'] }) export class ApproveDeclineModalComponent extends YCModalComponent implements OnInit { @Input() type: 'Approve'|'Decline'; @Input() single = false; // only approving / declining one application @Input() isNomination = false; @Input() programId: number; @Input() nominees: Nominee[]; @Input() applicationIds: number[] = []; modalHeader: string; confirmText: string; primaryButtonText: string; formGroup: TypeSafeFormGroup; notifyOptionLabel = ''; programOptions: TypeaheadSelectOption[] = []; defaultSelectValue: string; grantProgramsSelectValue = this.i18n.translate( 'PROGRAM:textSelectProgramToRouteTo', {}, 'Select the program this nomination will route to' ); noGrantProgramsSelectValue = this.i18n.translate( 'PROGRAM:textNoGrantProgramsWithOpenCycleUpdate', {}, 'No grant programs with open cycles available. Please update eligible grant programs to have an open cycle.' ); nomineeIndex = 0; currentEmailActive: boolean; customEmailMessageLabel = ''; clientName = this.clientSettingsService.clientBranding.name; disableProgramSelector = false; showEmployeeCheckbox = this.clientSettingsService.showIsEmployeeOfClientCheckbox; constructor ( private i18n: I18nService, private formBuilder: TypeSafeFormBuilder, private programService: ProgramService, private spinnerService: SpinnerService, private emailService: EmailService, private clientSettingsService: ClientSettingsService, private analyticsService: AnalyticsService ) { super(); } get singleTurnary () { return this.single ? '' : 's'; } get currentEmailType () { if (this.type === 'Approve') { return this.isNomination ? EmailNotificationType.NomineeApplicantInvitation : EmailNotificationType.ApplicationApproved; } else { return this.isNomination ? EmailNotificationType.NominationDeclinedForNominatingApplicant : EmailNotificationType.ApplicationDeclined; } } async ngOnInit () { await this.setCurrentEmailActive(); if (this.isNomination && this.type === 'Approve') { this.spinnerService.startSpinner(); this.programOptions = await this.programService.getProgramOptionsForApproveNom( this.programId ); this.spinnerService.stopSpinner(); } this.formGroup = this.formBuilder.group({ comment: '', customMessage: '', notifyApplicant: true, grantProgram: this.programOptions.length === 1 ? this.programOptions[0].value : null, isEmployeeOfClient: false, clientEmailTemplateId: 0, cc: [[], EmailValidator()], bcc: [[], EmailValidator()], attachments: [] }, { validator: [ DuplicateCheckValidator('cc', 'bcc') ] }); this.setSelectOptions(); this.setDetailText(); } setSelectOptions () { if (this.programOptions.length === 0) { this.defaultSelectValue = this.noGrantProgramsSelectValue; this.disableProgramSelector = true; } else { this.defaultSelectValue = this.grantProgramsSelectValue; } } async setCurrentEmailActive () { this.currentEmailActive = await this.emailService.isProgramEmailActive( this.currentEmailType, this.programId ); } setDetailText () { if (!this.isNomination) { this.customEmailMessageLabel = this.i18n.translate( this.single ? 'MANAGE:textCustomMessageToApplicant' : 'MANAGE:textCustomMessageToApplicants', {}, `Custom message to applicant${this.singleTurnary}` ); this.notifyOptionLabel = this.i18n.translate( this.single ? 'common:textNotifyApplicantDesc' : 'APPLY:textNotifyApplicantsDesc', {}, `Send email to notify applicant${this.singleTurnary} of decision` ); } else { this.notifyOptionLabel = this.i18n.translate( this.single ? 'APPLY:textNotifyNominatorDesc' : 'APPLY:textNotifyNominatorsDesc', {}, `Send email to notify nominator${this.singleTurnary} of decision` ); } const approve = this.type === 'Approve'; if (approve) { if (this.isNomination) { // Approve Nomination this.modalHeader = this.i18n.translate( this.single ? 'MANAGE:textApproveNomination' : 'MANAGE:textApproveNominations', {}, this.single ? 'Approve Nomination' : 'Approve Nominations' ); this.primaryButtonText = this.i18n.translate( 'GLOBAL:btnApprove', {}, 'Approve' ); this.confirmText = this.i18n.translate( 'MANAGE:textApproveDeclineNominationLabelUpdate', {}, 'Once a nomination is approved an application will be created for the nominee. Select the grant program with an open cycle below that the nomination will be routed to in order for nominated individuals to complete application forms.' ); this.notifyOptionLabel = this.i18n.translate( this.nominees.length === 1 ? 'MANAGE:textSendInviteEmailToNominee' : 'MANAGE:textSendInviteEmailsToNominee', {}, this.nominees.length === 1 ? 'Send an invite email to the above individual' : 'Send invite emails to the nominees' ); } else { // Approve Application this.modalHeader = this.i18n.translate( this.single ? 'AWARDS:hdrApproveApplication' : 'MANAGE:textApproveApplications', {}, this.single ? 'Approve Application' : 'Approve Applications' ); this.primaryButtonText = this.i18n.translate( 'GLOBAL:btnApprove', {}, 'Approve' ); this.confirmText = this.i18n.translate( this.single ? 'MANAGE:textAreYouSureApproveApplication' : 'MANAGE:textAreYouSureApproveApplications', {}, this.single ? 'Are you sure you want to approve the application? This action cannot be undone.' : 'Are you sure you want to approve the applications? This action cannot be undone.' ); } } else { if (this.isNomination) { // Decline Nomination this.modalHeader = this.i18n.translate( this.single ? 'MANAGE:textDeclineNomination' : 'MANAGE:textDeclineNominations', {}, this.single ? 'Decline Nomination' : 'Decline Nominations' ); this.primaryButtonText = this.i18n.translate( 'GLOBAL:btnDecline', {}, 'Decline' ); this.confirmText = this.i18n.translate( this.single ? 'MANAGE:textAreYouSureDeclineNomination' : 'MANAGE:textAreYouSureDeclineNominations', {}, this.single ? 'Are you sure you want to decline the nomination? This action cannot be undone.' : 'Are you sure you want to decline the nominations? This action cannot be undone.' ); } else { // Decline Application this.modalHeader = this.i18n.translate( this.single ? 'GLOBAL:textDeclineApplication' : 'MANAGE:textDeclineApplications', {}, this.single ? 'Decline Application' : 'Decline Applications' ); this.primaryButtonText = this.i18n.translate( 'GLOBAL:btnDecline', {}, 'Decline' ); this.confirmText = this.i18n.translate( this.single ? 'MANAGE:textAreYouSureDeclineApplication' : 'MANAGE:textAreYouSureDeclineApplications', {}, this.single ? 'Are you sure you want to decline the application? This action cannot be undone.' : 'Are you sure you want to decline the applications? This action cannot be undone.' ); } } } viewPreviousNominee () { this.nomineeIndex = this.nomineeIndex - 1; } viewNextNominee () { this.nomineeIndex = this.nomineeIndex + 1; } onCancel () { this.closeModal.emit(); } onSubmit () { this.closeModal.emit({ ...this.formGroup.value, isEmployeeOfClient: this.clientSettingsService.getIsEmployeeOfClientForPayload( this.formGroup.value.isEmployeeOfClient ), customMessage: this.formGroup.value.notifyApplicant ? this.formGroup.value.customMessage : '', emailOptionsModel: { ccEmails: this.formGroup.value.cc || [], bccEmails: this.formGroup.value.bcc || [], attachments: this.formGroup.value.attachments } }); this.analyticsService.emitEvent({ eventName: 'Approve decline modal submit', eventType: EventType.Click, extras: null }); } }