import { Component , OnInit , OnDestroy , Input , Output , EventEmitter , AfterViewInit , ChangeDetectorRef , ChangeDetectionStrategy } from '@angular/core' ; import { EmployeesService } from './../../../../../@core/services/employees.service' ; import { filter , debounceTime , tap , switchMap } from 'rxjs/operators' ; import { EmployeeStore , Store } from './../../../../../@core/services' ; import { CrudActionEnum , DEFAULT_TYPE , IEmployee , IOrganization , ISelectedEmployee } from '@gauzy/contracts' ; import { ActivatedRoute } from '@angular/router' ; import { UntilDestroy , untilDestroyed } from '@ngneat/until-destroy' ; import { combineLatest , Subject } from 'rxjs' ; import { ALL_EMPLOYEES_SELECTED } from './default-employee' ; import { isNotEmpty } from '@gauzy/common-angular' ; @ UntilDestroy ( { checkProperties : true } ) @ Component ( { selector : 'ga-employee-selector' , templateUrl : './employee.component.html' , styleUrls : [ './employee.component.scss' ] , changeDetection : ChangeDetectionStrategy . OnPush } ) export class EmployeeSelectorComponent implements OnInit , OnDestroy , AfterViewInit { private _skipGlobalChange : boolean = false ; get skipGlobalChange ( ) : boolean { return this . _skipGlobalChange ; } @ Input ( ) set skipGlobalChange ( value ) { this . _skipGlobalChange = value ; } private _disabled : boolean = false ; get disabled ( ) : boolean { return this . _disabled ; } @ Input ( ) set disabled ( value ) { this . _disabled = value ; } private _placeholder : string ; get placeholder ( ) : string { return this . _placeholder ; } @ Input ( ) set placeholder ( value ) { this . _placeholder = value ; } private _defaultSelected : boolean = true ; get defaultSelected ( ) : boolean { return this . _defaultSelected ; } @ Input ( ) set defaultSelected ( value ) { this . _defaultSelected = value ; } private _showAllEmployeesOption : boolean = true ; get showAllEmployeesOption ( ) : boolean { return this . _showAllEmployeesOption ; } @ Input ( ) set showAllEmployeesOption ( value ) { this . _showAllEmployeesOption = value ; } private _selectedDate ? : Date ; get selectedDate ( ) : Date { return this . _selectedDate ; } @ Input ( ) set selectedDate ( value ) { this . subject$ . next ( [ this . store . selectedOrganization , value ] ) ; } @ Output ( ) selectionChanged : EventEmitter < ISelectedEmployee > = new EventEmitter ( ) ; people : ISelectedEmployee [ ] = [ ] ; selectedEmployee : ISelectedEmployee ; subject$ : Subject < any > = new Subject ( ) ; constructor ( private readonly employeesService , private readonly store , private readonly activatedRoute , private readonly cdRef , private readonly _employeeStore ) { } ngOnInit ( ) { this . _selectedEmployee ( ) ; this . subject$ . pipe ( debounceTime ( 200 ) , switchMap ( async ( [ organization , date ] ) => { await this . loadWorkingEmployeesIfRequired ( organization , date ) ; } ) , untilDestroyed ( this ) ) . subscribe ( ) ; this . store . selectedEmployee$ . pipe ( filter ( ( employee ) => ! ! employee ) , tap ( ( employee ) => { if ( this . defaultSelected ) { this . selectedEmployee = employee ; } this . cdRef . detectChanges ( ) ; } ) , untilDestroyed ( this ) ) . subscribe ( ) ; this . activatedRoute . queryParams . pipe ( debounceTime ( 500 ) , filter ( ( query ) => ! ! query . employeeId ) , tap ( ( { employeeId } ) => this . selectEmployeeById ( employeeId ) ) , untilDestroyed ( this ) ) . subscribe ( ) ; const storeOrganization$ = this . store . selectedOrganization$ ; const selectedDate$ = this . store . selectedDate$ ; combineLatest ( [ storeOrganization$ , selectedDate$ ] ) . pipe ( filter ( ( [ organization ] ) => ! ! organization ) , tap ( ( [ organization , date ] ) => { this . _selectedDate = date ; this . subject$ . next ( [ organization , date ] ) ; } ) , untilDestroyed ( this ) ) . subscribe ( ) ; } ngAfterViewInit ( ) { this . cdRef . detectChanges ( ) ; this . _employeeStore . employeeAction$ . pipe ( filter ( ( { action , employees } ) => ! ! action && ! ! employees ) , tap ( ( ) => this . _employeeStore . destroy ( ) ) , untilDestroyed ( this ) ) . subscribe ( ( { action , employees } ) => { switch ( action ) { case CrudActionEnum . CREATED : this . createEmployee ( employees ) ; break ; case CrudActionEnum . DELETED : const [ employee ] = employees ; this . deleteEmployee ( employee as IEmployee ) ; break ; default : break ; } } ) ; } createEmployee ( employees ) { const people = this . people || [ ] ; if ( Array . isArray ( people ) ) { employees . forEach ( ( employee ) => { people . push ( { id : employee . id , firstName : employee . user . firstName , lastName : employee . user . lastName , fullName : employee . user . name , imageUrl : employee . user . imageUrl } ) ; } ) ; this . people = [ ... people ] . filter ( isNotEmpty ) ; } } deleteEmployee ( employee ) { let people = this . people || [ ] ; if ( Array . isArray ( people ) && people . length ) { people = people . filter ( ( item ) => item . id !== employee . id ) ; } this . people = [ ... people ] . filter ( isNotEmpty ) ; } searchEmployee ( term , item ) { if ( item . firstName && item . lastName ) { return ( item . firstName . toLowerCase ( ) . includes ( term . toLowerCase ( ) ) || item . lastName . toLowerCase ( ) . includes ( term . toLowerCase ( ) ) ) ; } else if ( item . firstName ) { return item . firstName . toLowerCase ( ) . includes ( term . toLowerCase ( ) ) ; } else if ( item . lastName ) { return item . lastName . toLowerCase ( ) . includes ( term . toLowerCase ( ) ) ; } } selectEmployee ( employee ) { if ( ! this . skipGlobalChange ) { this . store . selectedEmployee = employee || ALL_EMPLOYEES_SELECTED ; } else { this . selectedEmployee = employee ; } this . selectionChanged . emit ( employee ) ; } selectEmployeeById ( employeeId ) { const employee = this . people . find ( ( employee ) => employeeId === employee . id ) ; if ( employee ) { this . selectEmployee ( employee ) ; } } getShortenedName ( firstName , lastName ) { if ( firstName && lastName ) { return firstName + ' ' + lastName [ 0 ] + '.' ; } else { return firstName || lastName || '[error: bad name]' ; } } getFullName ( firstName , lastName ) { return firstName && lastName ? firstName + ' ' + lastName : firstName || lastName ; } private _selectedEmployee ( ) { if ( ! this . selectedEmployee ) { this . selectEmployee ( this . people [ 0 ] ) ; } if ( ! this . defaultSelected && this . selectedEmployee === ALL_EMPLOYEES_SELECTED ) { this . selectedEmployee = null ; } } loadWorkingEmployeesIfRequired = async ( organization , selectedDate ) => { if ( ! organization ) { this . people = [ ] ; return ; } this . _selectedDate = selectedDate ; await this . getEmployees ( organization , selectedDate ) ; } ; private getEmployees = async ( organization , selectedDate ) => { if ( ! organization ) { this . people = [ ] ; return ; } const { tenantId } = this . store . user ; const { id } = organization ; const { items } = await this . employeesService . getWorking ( id , tenantId , selectedDate , true ) ; this . people = [ ... items . map ( ( e ) => { return { id : e . id , firstName : e . user . firstName , lastName : e . user . lastName , fullName : e . user . name , imageUrl : e . user . imageUrl , shortDescription : e . short_description , employeeLevel : e . employeeLevel } as ISelectedEmployee ; } ) ] ; if ( this . showAllEmployeesOption ) { this . people . unshift ( ALL_EMPLOYEES_SELECTED ) ; } if ( items . length > 0 && ! this . store . selectedEmployee ) { this . store . selectedEmployee = this . people [ 0 ] || ALL_EMPLOYEES_SELECTED ; } } ; ngOnDestroy ( ) { if ( this . people . length > 0 && ! this . store . selectedEmployee && ! this . skipGlobalChange ) { this . store . selectedEmployee = this . people [ 0 ] || ALL_EMPLOYEES_SELECTED ; } } returns isClearable ( ) { if ( this . selectedEmployee && this . selectedEmployee . hasOwnProperty ( 'defaultType' ) ) { if ( this . selectedEmployee . defaultType === DEFAULT_TYPE . ALL_EMPLOYEE ) { return false ; } } return true ; } }