import { ExchangeRate } from '@arrow/bom/core'; import { CartHandoverService } from '@arrow/bom/core'; import { ConfigService } from '@arrow/bom/config'; import { Utils } from '@arrow/bom/core'; import { Pipe, PipeTransform, OnDestroy } from '@angular/core'; import { DecimalPipe } from '@angular/common'; import { Observable, of, BehaviorSubject, Subscription } from 'rxjs'; @Pipe({ name: 'currencyConverter' }) export class CurrencyConverterPipe implements PipeTransform, OnDestroy { private exchangeRates: Array = []; private exchangeRate: ExchangeRate; private subscriptions: Subscription[] = []; private decimalFormat: string = null; constructor( private cartHandover: CartHandoverService, private config: ConfigService, private decimalPipe: DecimalPipe, private utils: Utils ) {} ngOnDestroy(): void { this.subscriptions.forEach(sub => sub.unsubscribe()); } private _getFinalString(curSymbol: string, convertedPrice: number): string { // Sometimes we get a null/invalid number. This prevents a "$NULL" string from showing up if (convertedPrice > 0) { return ( curSymbol + this.decimalPipe.transform(convertedPrice, this.decimalFormat) ); } else { return '...'; } } private _setExchangeRate(): void { this.exchangeRate = this.exchangeRates.find( (rate: ExchangeRate) => rate.currencyCode === this.config.userSelectedCurrency ); } private _getConvertedValue(defaultCurrencyVal: number): number { return this.exchangeRate.exchangeRate * defaultCurrencyVal; } /** * * @param val the value in default currency (USD) * @param format how to format the number, this gets fed directly into the Angular "DecimalPipe" * @param showCurrencyCode whether to show the 3 letter currency code or just the * symbol (e.g. if the currency is USD and this is false, then the * output of this pipe will be "$ X.XX" rather than "USD X.XX") */ transform( val: number, format: string, showCurrencyCode = true ): Observable { this.decimalFormat = format; if (this.config.getTarget() === 'myarrow') { const displayCurrency = this.utils.getCurrencySymbol( this.config.userSelectedCurrency ); const finalString = this._getFinalString(displayCurrency, val); return of(showCurrencyCode ? finalString : val); } // If currency is default (USD). No conversion needed. if (this.config.userSelectedCurrency === this.config.defaultCurrency) { const displayCurrency = this.utils.getCurrencySymbol( this.config.defaultCurrency ); return of( showCurrencyCode ? this._getFinalString(displayCurrency, val) : val ); } const returnSubject: BehaviorSubject = new BehaviorSubject< string | number >(''); const returnObservable$: Observable< string | number > = returnSubject.asObservable(); this.subscriptions.push( this.cartHandover.exchangeRatesBehaveSub.subscribe( (response: ExchangeRate[]) => { this.exchangeRates = response; if (this.exchangeRates && this.exchangeRates.length > 0) { this._setExchangeRate(); const convertedVal = this._getConvertedValue(val); const displayCurrency = this.utils.getCurrencySymbol( this.exchangeRate.currencyCode ); const finalValue = showCurrencyCode ? this._getFinalString(displayCurrency, convertedVal) : convertedVal; returnSubject.next(finalValue); } else { returnSubject.next('...'); } }, () => { const displayCurrency = this.utils.getCurrencySymbol( this.config.defaultCurrency ); const finalValue = showCurrencyCode ? this._getFinalString(displayCurrency, val) : val; returnSubject.next(finalValue); } ) ); return returnObservable$; } private getDisplayCurrency( currencyCode: string, showCurrencyCode: boolean ): string { if (showCurrencyCode) { return currencyCode; } else { return this.utils.getCurrencySymbol(currencyCode); } } }