import { Component , OnInit , OnDestroy } from '@angular/core' ; import { NbDialogService } from '@nebular/theme' ; import { TranslateService } from '@ngx-translate/core' ; import { debounceTime , filter , tap } from 'rxjs/operators' ; import { TranslationBaseComponent } from '../../../@shared/language-base/translation-base.component' ; import { ITag , IOrganizationExpenseCategory , ComponentLayoutStyleEnum , IOrganization } from '@gauzy/contracts' ; import { UntilDestroy , untilDestroyed } from '@ngneat/until-destroy' ; import { Subject , firstValueFrom } from 'rxjs' ; import { API_PREFIX , ComponentEnum } from '../../../@core/constants' ; import { NotesWithTagsComponent } from '../../../@shared/table-components' ; import { DeleteConfirmationComponent } from '../../../@shared/user/forms/delete-confirmation/delete-confirmation.component' ; import { ErrorHandlingService , OrganizationExpenseCategoriesService , Store , ToastrService } from '../../../@core/services' ; import { distinctUntilChange } from '@gauzy/common-angular' ; import { ServerDataSource } from '../../../@core/utils/smart-table/server.data-source' ; import { HttpClient } from '@angular/common/http' ; import { combineLatest } from 'rxjs' ; @ UntilDestroy ( { checkProperties : true } ) @ Component ( { selector : 'ga-expense-categories' , templateUrl : './expense-categories.component.html' , styles : [ ':host > nb-card { min-height: 47.50rem; }' ] } ) export class ExpenseCategoriesComponent extends TranslationBaseComponent implements OnInit , OnDestroy { smartTableSource : ServerDataSource ; organization : IOrganization ; showAddCard : boolean ; showEditDiv : boolean ; settingsSmartTable : object ; expenseCategories : IOrganizationExpenseCategory [ ] ; selectedExpenseCategory : IOrganizationExpenseCategory ; tags : ITag [ ] = [ ] ; isGridEdit : boolean ; viewComponentName : ComponentEnum = ComponentEnum . EXPENSES_CATEGORY ; dataLayoutStyle = ComponentLayoutStyleEnum . TABLE ; componentLayoutStyleEnum = ComponentLayoutStyleEnum ; subject$ : Subject < any > = new Subject ( ) ; pagination : any = { totalItems : 0 , activePage : 1 , itemsPerPage : 8 } ; loading : boolean ; constructor ( private readonly organizationExpenseCategoryService , private readonly toastrService , private readonly store , readonly translateService , private readonly errorHandlingService , private readonly dialogService , private readonly httpClient ) { super ( translateService ) ; } ngOnInit ( ) { this . _loadSettingsSmartTable ( ) ; this . subject$ . pipe ( tap ( ( ) => this . loading = true ) , debounceTime ( 300 ) , tap ( ( ) => this . cancel ( ) ) , tap ( ( ) => this . getCategories ( ) ) , untilDestroyed ( this ) ) . subscribe ( ) ; const storeOrganization$ = this . store . selectedOrganization$ ; const componentLayout$ = this . store . componentLayout$ ( this . viewComponentName ) ; combineLatest ( [ storeOrganization$ , componentLayout$ ] ) . pipe ( debounceTime ( 300 ) , filter ( ( [ organization , componentLayout ] ) => ! ! organization && ! ! componentLayout ) , distinctUntilChange ( ) , tap ( ( [ organization , componentLayout ] ) => { this . organization = organization ; this . dataLayoutStyle = componentLayout ; this . refreshPagination ( ) ; this . subject$ . next ( true ) ; } ) , untilDestroyed ( this ) ) . subscribe ( ) ; } ngOnDestroy ( ) { } showEditCard ( expenseCategory ) { this . showEditDiv = true ; this . showAddCard = false ; this . selectedExpenseCategory = expenseCategory ; this . tags = expenseCategory . tags ; } cancel ( ) { this . showEditDiv = false ; this . showAddCard = false ; this . selectedExpenseCategory = null ; this . isGridEdit = false ; this . tags = [ ] ; } async _loadSettingsSmartTable ( ) { this . settingsSmartTable = { actions : false , columns : { name : { title : this . getTranslation ( 'ORGANIZATIONS_PAGE.NAME' ) , type : 'custom' , class : 'align-row' , renderComponent : NotesWithTagsComponent } } } ; } async removeCategory ( id , name ) { try { const result = await firstValueFrom ( this . dialogService . open ( DeleteConfirmationComponent , { context : { recordType : 'EXPENSES_PAGE.EXPENSE_CATEGORY' } } ) . onClose ) ; if ( result ) { await this . organizationExpenseCategoryService . delete ( id ) ; this . subject$ . next ( true ) ; this . toastrService . success ( 'NOTES.ORGANIZATIONS.EDIT_ORGANIZATIONS_EXPENSE_CATEGORIES.REMOVE_EXPENSE_CATEGORY' , { name } ) ; } } catch ( error ) { this . errorHandlingService . handleError ( error ) ; } } save ( name ) { if ( this . isGridEdit ) { this . editCategory ( this . selectedExpenseCategory . id , name ) ; } else { this . addCategory ( name ) ; } } public async editCategory ( id , name ) { const expenseCategory = { name : name , tags : this . tags } ; await this . organizationExpenseCategoryService . update ( id , expenseCategory ) ; this . subject$ . next ( true ) ; this . toastrService . success ( 'NOTES.ORGANIZATIONS.EDIT_ORGANIZATIONS_EXPENSE_CATEGORIES.UPDATE_EXPENSE_CATEGORY' , { name } ) ; } public async addCategory ( name ) { if ( name ) { const { id : organizationId } = this . organization ; const { tenantId } = this . store . user ; await this . organizationExpenseCategoryService . create ( { name , organizationId , tenantId , tags : this . tags } ) ; this . subject$ . next ( true ) ; this . toastrService . success ( 'NOTES.ORGANIZATIONS.EDIT_ORGANIZATIONS_EXPENSE_CATEGORIES.ADD_EXPENSE_CATEGORY' , { name } ) ; } else { this . toastrService . danger ( 'NOTES.ORGANIZATIONS.EDIT_ORGANIZATIONS_EXPENSE_CATEGORIES.INVALID_EXPENSE_CATEGORY_NAME' , 'TOASTR.MESSAGE.NEW_ORGANIZATION_EXPENSE_CATEGORY_INVALID_NAME' ) ; } } setSmartTableSource ( ) { const { tenantId } = this . store . user ; const { id : organizationId } = this . organization ; this . smartTableSource = new ServerDataSource ( this . httpClient , { endPoint : `${ API_PREFIX }/expense-categories/pagination` , relations : [ 'tags' ] , where : { organizationId , tenantId } , finalize : ( ) => { this . loading = false ; } } ) ; } private async getCategories ( ) { if ( ! this . organization ) { return ; } try { this . setSmartTableSource ( ) ; const { activePage , itemsPerPage } = this . pagination ; this . smartTableSource . setPaging ( activePage , itemsPerPage , false ) ; await this . smartTableSource . getElements ( ) ; this . expenseCategories = this . smartTableSource . getData ( ) ; this . pagination [ 'totalItems' ] = this . smartTableSource . count ( ) ; this . emptyListInvoke ( ) ; } catch ( error ) { this . errorHandlingService . handleError ( error ) ; } } selectedTagsEvent ( ev ) { this . tags = ev ; } edit ( expenseCategory ) { this . showAddCard = true ; this . isGridEdit = true ; this . selectedExpenseCategory = expenseCategory ; this . tags = expenseCategory . tags ; } private emptyListInvoke ( ) { if ( this . expenseCategories . length === 0 ) { this . cancel ( ) ; } } onPageChange ( selectedPage ) { this . pagination [ 'activePage' ] = selectedPage ; this . subject$ . next ( true ) ; } refreshPagination ( ) { this . pagination [ 'activePage' ] = 1 ; } }