/** * @Component Name: FeaturesComponent * @Module: Home * @Module Functionality : To display the features * @Creation Date: August 12,2017 * @Author: sbaireddy * @Version: 1.0 */ import { Component, Input, ChangeDetectionStrategy, OnInit, DoCheck, OnDestroy } from '@angular/core'; import Utils from '../../shared/utils'; import CartUtils from '../../shared/cart.utils'; import * as Constants from '../../shared/constants'; import { SORT_BY_OPTIONS } from '../../shared/form.constants'; import { IKeyValue } from '../../shared/modal/key.value'; import { IFeature, IOrderItemFeature, IFilterList, IFilter, IPackage } from '../../shared/modal/common'; import { Cart } from '../../shared/modal/cart'; import { SharedService } from '../../shared/shared.service'; import { CartService } from '../../services/cart.service'; import { CatalogService } from '../../services/catalog.service'; declare var jQuery: any; @Component( { moduleId: module.id, selector: 'features-cmp', templateUrl: 'features.component.html', styleUrls: ['features.component.css'] }) export class FeaturesComponent implements OnInit, OnDestroy { private COMPONENT_NAME: string = 'FeaturesComponent'; storeId: number; // update storeid categoryId: number = Constants.CATEGORY_ID_FEATURE; groupByCount: number = jQuery(window).width() <= 991 ? 2 : 3; cardsPerPage: number = Constants.CARDS_PER_PAGE; productType: string = Constants.PRODUCT_TYPE_GSM; // header section veriables groupName: string = Constants.GROUP_NAME_SUB; // for feature group slider searchText: string = ''; // search text sortByKey: string = ''; // sort by key sortByOptions: IKeyValue[]; // order by price and alphabet; // body section veriables features: IFeature[]; filters: IFilterList[]; accFeatureFilters: IFilter[]; subFeatureFilters: IFilter[]; prodFeatureFilters: IFilter[]; // sorted features for display sortedFeatures: Array>; // pagination allItems: any[]; // array of all items to be paged pager: any = {};  // pager object pagedItems: any[]; // paged items // added for expand and collapse expandedProductId: number; // adding item to cart functionality packageType: string; subscription: any; cart: Cart; // getting active package item package: IPackage; KarmaTestResult: any = {}; accountLevelFeatureIds: Array; disableUpdateFeature: boolean = false; constructor( public sharedService: SharedService, public cartService: CartService, public catalogService: CatalogService) { } /** * This function is used to initialize the directive/component after Angular * first displays the data-bound properties.It is invoked only once when the * directive is instantiated. Also updateActivePackage function is called to update cart object. * @returns void */ ngOnInit(): void { const METHOD_NAME: string = 'ngOnInit()'; // this.sharedService.addLogging(this.COMPONENT_NAME, METHOD_NAME, 'Loading features'); // Start-Switch Channel-Store id update this.sharedService.updateErrorMessage(null); this.sharedService.storeId.subscribe((val: number) => { this.storeId = val; console.log('updated storeid' + this.storeId); }); // End-Switch Channel-Store id update this.sortByOptions = SORT_BY_OPTIONS; if (this.sortByOptions) { this.sortByKey = this.sortByOptions[0].key; } this.groupByCount = Utils.groupByProductCount(); this.cardsPerPage = Utils.totalCardsPerPage(); // getting current cart/customer this.cart = this.cartService.getCart(); // getting cart changes... this.subscription = this.cartService.hasUpdate.subscribe((item) => { if (item) { this.cart = this.cartService.getCart(); } this.updateActivePackage(); console.log('Cart got updated..'); }); console.log('getting the master features'); this.features = this.catalogService.getFeatures(); if (!this.features) { console.log('GSMFeaturesComponent.ngOnInit()>>Getting the master features.'); this.sharedService.initializeCatalog(); } console.log('getting the master feature filters') this.filters = this.catalogService.getFeatureFiletrs(); if (!this.filters) { console.log('GSMFeaturesComponent.ngOnInit()>>Getting the master featre filters.'); this.sharedService.initializeCatalog(); } else { this.resetFeatureFilters(); } // getting the active package this.updateActivePackage(); } /** * Cleanup just before Angular destroys the directive/component. * Unsubscribe Observables and detach event handlers to avoid memory leaks. * @returns void */ ngOnDestroy(): void { const METHOD_NAME: string = 'ngOnDestroy()'; this.features = null; this.filters = null; this.pager = null; this.accFeatureFilters = null; this.subFeatureFilters = null; this.prodFeatureFilters = null; this.package = null; this.cart = null; this.KarmaTestResult = null; this.sortByOptions = null; this.sortedFeatures = null; this.allItems = null; this.pagedItems = null; this.subscription.unsubscribe(); } /** * This function is used to update the package including package type, active package id, * active line id.Also getting the customer details including credit profile and credit types * @returns void */ updateActivePackage(): void { const METHOD_NAME: string = 'updateActivePackage()'; this.package = CartUtils.getCurrentPackage(this.cart); if (this.package) { this.packageType = this.package.packageType; const rateplanSOC: string = this.package.plan.rateplanSOC; const deviceSKU: string = this.package.device.deviceSKU; let zipCode: string = Constants.DEFAULT_ZIP_CODE; const financeType: string = this.package.device.financeType; if (this.cart.customer && this.cart.customer.zipCode) { zipCode = this.cart.customer.zipCode; } this.sortByRateplandevice(rateplanSOC, deviceSKU, zipCode, financeType); } // Added to fetch customer account level features if they already exists - ACC and PROD level. if (this.cart && this.cart.customer && this.cart.customer.subscribers) { this.accountLevelFeatureIds = CartUtils.getAccProdLevelFeatureList(this.cart); } // applying the custom sorting // this.applyCustomSorting(); } /** * This function is used to add a feature to the cart through createFeature api call. * @param {IFeature} feature - contains feature information that has to be added to cart. * @param {number} index - index number of the feature element. * @returns void */ addFeature(feature: IFeature, index: number): void { const METHOD_NAME: string = 'addFeature()'; this.sharedService.addLogging(this.COMPONENT_NAME, METHOD_NAME, 'Adding a feature to cart:' + this.cart.orderId); console.log('[start]- adding rateplan to cart.'); // adding product into cart/package if (this.cart && this.package) { const inputData: any = CartUtils.createFeatureInput(this.package.packageType, feature); this.sharedService.showSpinner(true); // spinner this.cartService.createFeature(this.storeId, this.cart.orderId, this.package.packageId, this.package.lineId, inputData ).subscribe(result => { this.sharedService.showSpinner(false); // spinner this.cart = CartUtils.replaceRequired(this.cart, result); this.cartService.setCart(this.cart); }, error => { this.sharedService.showSpinner(false); // spinner this.sharedService.showErrorMessage(error, true); }); } console.log('[end]- adding feature to cart.'); } /** * This function is used to update a feature to the cart through updateFeature api call. * @param {IFeature} feature - contains feature information that has to be updated to cart. * @param {number} index - index number of the feature element. * @returns void */ updateFeature(feature: IFeature, index: number): void { const METHOD_NAME: string = 'updateFeature()'; // console.log('[start]- updating product to cart.'); this.sharedService.addLogging(this.COMPONENT_NAME, METHOD_NAME, 'Updating a feature to cart:' + this.cart.orderId); // updating product into cart/package if (this.cart && this.package && this.package.features) { let replaceItem: any; const products = this.getGroupProducts(feature); if (products && products.length > 0) { replaceItem = this.getSelectedProducts(products, this.package.features); } if (replaceItem && replaceItem.length > 0) { const inputData: any = CartUtils.createFeatureInput(this.package.packageType, feature); inputData.orderItemId = replaceItem[0].orderItemId; let conflictOrderItems: string = ''; for (const item of replaceItem) { conflictOrderItems += item.orderItemId + ','; } inputData.conflictedOrderItems = conflictOrderItems; this.sharedService.showSpinner(true); // spinner this.cartService.updateFeature(this.storeId, this.cart.orderId, this.package.packageId, this.package.lineId, replaceItem[0].orderItemId, inputData ).subscribe(result => { // this.sharedService.showSpinner(false); // spinner // this.cart = CartUtils.replaceRequired(this.cart, result); // this.cartService.setCart(this.cart); // console.log('Feature updated successfully.'); this.cartService.getCartSummary(this.storeId, this.cart.orderId).subscribe(getCartSummaryResult => { this.sharedService.showSpinner(false); // spinner this.cart = CartUtils.replaceRequired(this.cart, getCartSummaryResult); this.cartService.setCart(this.cart); }, error => { this.sharedService.showSpinner(false); // spinner this.sharedService.showErrorMessage(error, true); }); }, error => { this.sharedService.showSpinner(false); // spinner this.sharedService.showErrorMessage(error, true); }); } } console.log('[end]- updating product to cart.'); } /** * This function is used to remove a feature from the cart through updateFeature api call. * @param {IFeature} feature - contains feature information that has to be deleted from the cart. * @param {number} index - index number of the feature element. * @returns void */ removeFeature(feature: IFeature, index: number): void { const METHOD_NAME: string = 'removeFeature()'; this.sharedService.addLogging(this.COMPONENT_NAME, METHOD_NAME, 'Removing feature from cart:' + this.cart.orderId); console.log('[start]- removing product from cart.'); // adding product into cart/package if (this.cart && this.package && this.package.features) { let replaceItem: any; const products = this.getGroupProducts(feature); if (products && products.length > 0) { replaceItem = this.getSelectedProduct(products, this.package.features); } if (replaceItem) { this.sharedService.showSpinner(true); // spinner this.cartService.deleteFeature(this.storeId, this.cart.orderId, this.package.packageId, this.package.lineId, replaceItem.orderItemId ).subscribe(result => { this.sharedService.showSpinner(false); // spinner this.cart = CartUtils.replaceRequired(this.cart, result); this.cartService.setCart(this.cart); }, error => { this.sharedService.showSpinner(false); // spinner this.sharedService.showErrorMessage(error, true); }); } } console.log('[end]- removing product from cart.'); } /** * This function is used to apply the custom sorting of products * @return {void} */ applyCustomSorting(): void { const METHOD_NAME: string = 'applyCustomSorting()'; if (this.features && this.features.length > 0) { // console.log('group name:' + this.groupName) // console.log('total products count:'+ this.features.length ) // support products for full price/loan/lease let sortList = this.features.filter((product) => { // console.log('this.featureGroupName:' + this.groupName); if (this.groupName && this.groupName.length > 0) { if (this.groupName === Constants.GROUP_NAME_ACC) { return product.groupName === Constants.FEATURE_GRP_NAME_ACC; } else if (this.groupName === Constants.GROUP_NAME_SUB) { return product.groupName === Constants.FEATURE_GRP_NAME_SUB; } else if (this.groupName === Constants.GROUP_NAME_PROD) { return product.groupName === Constants.FEATURE_GRP_NAME_PROD; } else { return true; } } else { return true; } }); // console.log('total products count1:'+ sortList.length ) sortList = Utils.serachFilter(sortList, this.filters); // console.log('total products count2:'+ sortList.length ) sortList = Utils.serachSortBy(sortList, this.sortByKey); // console.log('total products count3:'+ sortList.length ) this.allItems = Utils.serachProducts(sortList, this.searchText); // initialize to page 1 this.setPage((this.pager && this.pager.currentPage) ? this.pager.currentPage : 1); } } /** * This function is used to get the index for pagination * @param {number} page - variable contains the page number * @return {void} */ setPage(page: number) { const METHOD_NAME: string = 'setPage()'; if (page < 1 || page > this.pager.totalPages) {             return; } if (this.allItems && this.allItems.length > 0) { // get pager object from service this.pager = Utils.getPager(this.allItems.length, page, this.cardsPerPage); // get current page of items this.pagedItems = this.allItems.slice(this.pager.startIndex, this.pager.endIndex + 1); // grouping 3 products per row this.sortedFeatures = Utils.groupProducts(this.pagedItems, this.groupByCount); } else { this.sortedFeatures = null; } } /** * This function is used to get the status of button which is enabled/disabled * based on feature availability status * @param {IFeature} featureProduct - Object contains the feature information. * @return {string} */ buttonState(featureProduct: IFeature): string { const METHOD_NAME: string = 'buttonState()'; const subGroupName: string = featureProduct.subGroupName; const featureSOC: string = featureProduct.featureSOC; let state: string = Constants.BTN_ADD; this.disableUpdateFeature = false; if (this.cart && this.package && (this.package.features || (this.accountLevelFeatureIds && this.accountLevelFeatureIds.length > 0))) { let products: IFeature[]; let flag: boolean = false; let alreadyAdded: boolean = false; const conflicts: Number[] = featureProduct.conflicts; if (this.package.features) { let groupName: string; if (this.groupName === Constants.GROUP_NAME_ACC) { groupName = Constants.FEATURE_GRP_NAME_ACC; } else if (this.groupName === Constants.GROUP_NAME_SUB) { groupName = Constants.FEATURE_GRP_NAME_SUB; } else if (this.groupName === Constants.GROUP_NAME_PROD) { groupName = Constants.FEATURE_GRP_NAME_PROD; } products = this.features.filter((product) => { return (product.groupName === groupName && product.subGroupName === subGroupName); }); for (const ordItem of this.package.features) { if (ordItem.featureSOC === featureProduct.featureSOC) { state = Constants.BTN_REMOVE; flag = true; alreadyAdded = true; } } if (conflicts && conflicts.length > 0 && !alreadyAdded ) { for (const ordItem of this.package.features) { for (const featureConflict of conflicts) { if (featureConflict === ordItem.productId) { for(const feature of this.features){ if(feature.productId===featureConflict){ if(feature.subGroupName != subGroupName) { this.disableUpdateFeature =true; } break; } } state = Constants.BTN_UPDATE; flag = true; break; } } } if (!flag) { state = Constants.BTN_ADD; flag = true; } } } // Added to disable feature soc if one of it's conflicts already exists in customer account. // let conflicts:Number[] = featureProduct.conflicts; if (this.groupName === Constants.GROUP_NAME_ACC || this.groupName === Constants.GROUP_NAME_PROD) { if (conflicts && conflicts.length > 0 && this.accountLevelFeatureIds && this.accountLevelFeatureIds.length > 0) { for (const accLevelfeature of this.accountLevelFeatureIds) { for (const featureConflict of conflicts) { if (accLevelfeature === featureConflict) { state = Constants.BTN_DISABLE; flag = true; alreadyAdded = false; break; } } if (state === Constants.BTN_DISABLE) { break; } } } } if (!flag && products && products.length > 0) { const selectedItems: any = products.filter((item) => { for (const ordItem of this.package.features) { // console.log('found item>>>'+ ordItem.featureSOC === item.featureSOC); return ordItem.featureSOC === item.featureSOC; } }); if (selectedItems && selectedItems.length > 0) { state = Constants.BTN_UPDATE; const list: any = this.package.features.filter((item) => { return item.featureSOC === featureSOC; }); if (list && list.length > 0) { // console.log('Temp Count >>>: ' + list.length); const tempList: any = products.filter((product) => { return product.featureSOC === featureSOC; }); state = (tempList && tempList.length > 0) ? Constants.BTN_REMOVE : Constants.BTN_UPDATE; } } } } return state; } /** * This function is used to group the products based on group name * @param {IFeature} feature - contains feature information * @returns any */ getGroupProducts(feature: IFeature): any { const METHOD_NAME: string = 'getGroupProducts()'; let groupName: string; if (this.groupName === Constants.GROUP_NAME_ACC) { groupName = Constants.FEATURE_GRP_NAME_ACC; } else if (this.groupName === Constants.GROUP_NAME_SUB) { groupName = Constants.FEATURE_GRP_NAME_SUB; } else if (this.groupName === Constants.GROUP_NAME_PROD) { groupName = Constants.FEATURE_GRP_NAME_PROD; } const products: IFeature[] = this.features.filter((product) => { return (product.groupName === groupName && product.subGroupName === feature.subGroupName); }); if (products && products.length > 0) { return products; } } /** * This function is used to get the products based on featureSoc * @param {IFeature[]} products - contains feature information * @param {any} orderItems - list of order items that has retrieved from products. */ getSelectedProduct(products: IFeature[], orderItems: any) { const METHOD_NAME: string = 'getSelectedProduct()'; console.log(orderItems); const ordItems: any = orderItems.filter((item) => { const sortedList: any = products.filter((product) => { return product.featureSOC === item.featureSOC }); return sortedList && sortedList.length > 0; }); if (ordItems && ordItems.length > 0) { return ordItems[0]; } } /** * This function is used to get the products based on featureSoc * @param {IFeature[]} products - contains feature information * @param {any} orderItems - list of order items that has retrieved from products. */ getSelectedProducts(products: IFeature[], orderItems: any) { const METHOD_NAME: string = 'getSelectedProduct()'; console.log(orderItems); const ordItems: any = orderItems.filter((item) => { const sortedList: any = products.filter((product) => { return product.featureSOC === item.featureSOC }); return sortedList && sortedList.length > 0; }); if (ordItems && ordItems.length > 0) { return ordItems; } } /** * This function is used to sort rateplans based on devices. * @param {string} rateplanSOC - SOC of the Rate Plan. * @param {string} deviceSKU - SKU of the device selected. * @param {string} zipCode - Current zipCode . * @param {string} financeType - finance type that user chooses. * @returns void */ sortByRateplandevice(rateplanSOC: string, deviceSKU: string, zipCode: string, financeType: string): void { const METHOD_NAME: string = 'sortByRateplandevice()'; this.sharedService.showSpinner(true); // spinner this.catalogService.getFeaturesByRateplanDevice( this.storeId, rateplanSOC, deviceSKU, zipCode, financeType ).subscribe(result => { this.KarmaTestResult = result; this.sharedService.showSpinner(false); // spinner if (result && result.length > 0) { this.features = this.catalogService.getFeatures(); this.features = this.features.filter((item) => { return (result.includes(item.productId)) }); this.resetFeatureFilters(); this.applyCustomSorting(); } }, error => { this.features = null; this.sharedService.showSpinner(false); // spinner this.sharedService.showErrorMessage(error, true); }); } /** This function is used to reset the features filters * @returns void */ resetFeatureFilters(): void { const METHOD_NAME: string = 'resetFeatureFilters()'; if (this.filters) { this.filters.forEach((element) => { if (element.type === Constants.FEATURE_GRP_NAME_ACC) { this.accFeatureFilters = element.items; } if (element.type === Constants.FEATURE_GRP_NAME_SUB) { this.subFeatureFilters = element.items; } if (element.type === Constants.FEATURE_GRP_NAME_PROD) { this.prodFeatureFilters = element.items; } }); if (this.features) { this.filters = new Array(); this.accFeatureFilters = Utils.matchFiltersProducts(this.accFeatureFilters, this.features); if (this.accFeatureFilters) { this.filters.push( {type: Constants.FEATURE_GRP_NAME_ACC, items: this.accFeatureFilters}); } this.subFeatureFilters = Utils.matchFiltersProducts(this.subFeatureFilters, this.features); if (this.subFeatureFilters) { this.filters.push( {type: Constants.FEATURE_GRP_NAME_SUB, items: this.subFeatureFilters}); } this.prodFeatureFilters = Utils.matchFiltersProducts(this.prodFeatureFilters, this.features); if (this.prodFeatureFilters) { this.filters.push( {type: Constants.FEATURE_GRP_NAME_PROD, items: this.prodFeatureFilters}); } } } } /** * This function determines whether any of the features are selected or not. * @returns boolean */ atleastOneChecked(): boolean { const METHOD_NAME: string = 'atleastOneChecked()'; if (this.filters && this.filters.length > 0) { for (const filter of this.filters) { if (filter && filter.items) { for (const item of filter.items) { if (item.isChecked) { return true; } } } } } return false; } /** * This function is used to clear all the filters. * @returns void */ clearAllFilters(): void { const METHOD_NAME: string = 'clearAllFilters()'; for (const filter of this.filters) { for (const item of filter.items) { item.isChecked = false; } } if (this.sortByOptions) { this.sortByKey = this.sortByOptions[0].key; } this.searchText = ''; this.groupName = Constants.GROUP_NAME_SUB; this.applyCustomSorting(); // Clear ALL to show all items/features } /** * This function is used to display the details of particular accessory. * @param {number} productId - valid productId of an features. * @returns void */ expandDetails(productId: number): void { const METHOD_NAME: string = 'expandDetails()'; if (this.expandedProductId && this.expandedProductId === productId) { this.expandedProductId = null; } else { this.expandedProductId = productId; } } }