import { Injectable, NgZone } from '@angular/core'; import { SpinnerService } from '@core/services/spinner.service'; import { TokenService } from '@core/services/token/token.service'; import { ContactSupport } from '@core/typings/ui/support.typing'; import { UserService } from '@features/users/user.service'; import { TypeaheadSelectOption } from '@yourcause/common'; import { I18nService } from '@yourcause/common/i18n'; import { LogService } from '@yourcause/common/logging'; import { ModalFactory } from '@yourcause/common/modals'; import { NotifierService } from '@yourcause/common/notifier'; import { AttachYCState, BaseYCService } from '@yourcause/common/state'; import { ContactSupportModalComponent } from './contact-support-modal/contact-support-modal.component'; import { SupportResources } from './support.resources'; import { SupportState } from './support.state'; @AttachYCState(SupportState) @Injectable({ providedIn: 'root'}) export class SupportService extends BaseYCService { readonly contactReasonPreAuthOptions: TypeaheadSelectOption[] = [ { label: this.i18n.translate('common:textUpdateMyEmail', {}, 'Update my email'), value: ContactSupport.ContactReasonFullList.UPDATE_EMAIL }, { label: this.i18n.translate('common:textChangeMyPassword', {}, 'Change my password'), value: ContactSupport.ContactReasonFullList.CHANGE_PASSWORD }, { label: this.i18n.translate('common:textOther', {}, 'Other'), value: ContactSupport.ContactReasonFullList.OTHER }]; readonly contactReasonPostAuthOptions: TypeaheadSelectOption[] = [ { label: this.i18n.translate('common:textForms', {}, 'Forms'), value: ContactSupport.ContactReasonFullList.FORMS }, { label: this.i18n.translate('common:textDataMissing', {}, 'Data missing'), value: ContactSupport.ContactReasonFullList.DATA_MISSING }, { label: this.i18n.translate('common:textApplicationNomination', {}, 'Application/Nomination'), value: ContactSupport.ContactReasonFullList.APPLICATION_NOMINATION }, { label: this.i18n.translate('common:textUnableToFindOrg', {}, 'Unable to find organization'), value: ContactSupport.ContactReasonFullList.UNABLE_TO_FIND_ORG }, { label: this.i18n.translate('common:textProfileInformation', {}, 'Profile information'), value: ContactSupport.ContactReasonFullList.PROFILE_INFO }, ...this.contactReasonPreAuthOptions ]; availableData = { available: true, class: 'text-info', text: this.i18n.translate( 'common:textWeAreAvailable', {}, 'We are available' )}; unavailableData = { available: false, class: 'text-warning', text: this.i18n.translate( 'common:textWeAreUnavailableAtThisTime', {}, 'Our apologies, we are unavailable at this time' )}; constructor ( private logger: LogService, private i18n: I18nService, private supportResources: SupportResources, private notifier: NotifierService, private tokenService: TokenService, private modalFactory: ModalFactory, private spinnerService: SpinnerService, private userService: UserService, private zone: NgZone ) { super(); } get $zopim () { return (window).$zopim; } get liveChatData () { return this.get('liveChatData'); } get liveChatAvailable () { return (this.$zopim ? this.$zopim.livechat ? this.$zopim.livechat.departments.getDepartment('YourCause') ? this.$zopim.livechat.departments.getDepartment('YourCause').status === 'online' : false : false : false); } get prepopData () { return this.get('prepopData'); } get contactReasonOptions () { const isLoggedIn = this.tokenService.getIsLoggedIn(); if (isLoggedIn) { return this.contactReasonPostAuthOptions; } return this.contactReasonPreAuthOptions; } setPrepopData (payload: ContactSupport.ContactSupportModalReturn) { this.set('prepopData', payload); } adaptPayloadForEmail (payload: ContactSupport.ContactSupportModalReturn) { // grab contact reason text const contactReason = this.contactReasonOptions.find((option) => { return option.value === payload.contactReason; }); // build simple data string for email let payloadString = ''; payloadString += `Contact reason: ${contactReason.label}
`; payloadString += `Name: ${payload.firstName} ${payload.lastName}
`; payloadString += `Email: ${payload.email}
`; payloadString += `Phone number: ${payload.phoneNumber}
`; payloadString += `Client name: ${payload.clientName}
`; payloadString += `Application ID: ${payload.applicationId}
`; payloadString += `Program name: ${payload.programName}
`; payloadString += `Organization name: ${payload.organizationName}
`; payloadString += `Organization tax ID: ${payload.taxId}
`; payloadString += `Description: ${payload.description}
`; return payloadString; } async sendSupportEmail (payload: ContactSupport.ContactSupportModalReturn) { try { const emailBody = this.adaptPayloadForEmail(payload); await this.supportResources.sendSupportEmail(emailBody); this.notifier.success(this.i18n.translate( 'common:textSupportTicketSuccessfullySubmitted', {}, 'Support ticket successfully submitted' )); } catch (e) { this.notifier.error(this.i18n.translate( 'common:textErrorSubmittingTicket', {}, 'There was an error submitting your support ticket' )); this.logger.error(e); } } async openSupportEmailModal () { const modalResponse = await this.modalFactory.open( ContactSupportModalComponent, { contactReasonPostAuthOptions: this.contactReasonOptions, prepopData: { ...this.prepopData, contactReason: null, firstName: this.userService.currentUser?.firstName, lastName: this.userService.currentUser?.lastName, email: this.userService.currentUser?.email, phoneNumber: this.userService.applicant?.phoneNumber ?? '', description: '' } } ); if (modalResponse) { this.spinnerService.startSpinner(); await this.sendSupportEmail(modalResponse); this.spinnerService.stopSpinner(); } } openLiveChat () { return this.$zopim.livechat.window.show(); } setZendeskStatus () { // logic pulled from index.html // let zendesk run this logic when it is ready this.$zopim(() => this.$zopim.livechat.setOnConnected(() => { // because zendesk is ultimately firing this // we need to run it in the context of angular // so that change detection can occur this.zone.run(() => { const available = this.$zopim?.livechat?.departments?.getDepartment('YourCause')?.status === 'online' ?? false; if (available) { this.set('liveChatData', this.availableData); } else { this.set('liveChatData', this.unavailableData); } }); })); } }