
if ( typeof Vue !== 'undefined' ) {

    /**
     * search component mixin
     * this is a template for all search components
     */
    const searchComponentMixin = {
        props: {
            id: {
                default: null
            },
            // provided
            title: {
                default: ''
            },
            // provided
            code: {
                default: ''
            },
            entityTwoIdFieldName: {
                default: ''
            },
            entityThreeIdFieldName: {
                default: ''
            },
            entityFourIdFieldName: {
                default: ''
            },
            labelText: {
                default: 'Search'
            },
            maxResults: {
                default: 100
            },
            // provided
            required: {
                default: false
            },
            disabled: {
                default: false
            },
            readOnly: {
                default: false
            },
            showLabel: {
                default: true
            },
            classes: '',
            // provided
            showInputErrorOnZeroId: {
                default: false
            },
            clearTextOnSelect: {
                default: false
            },
            inputMode:{
                default: 'text'
            }
        },
        data: function() {
            return {
                cachedEntity: null,
                entityId: this.id,
                entityTwoId: null,
                entityThreeId: null,
                entityFourId: null,
                entityCode: this.code,
                list: {
                    term: this.title,
                    items: [],
                    loading: false,
                    selected: {},
                    opened: false,
                    position: {
                        top: 0,
                        left: 0
                    }
                },
                // object for holding request data
                request: {
                    xhr: null
                }
            }
        },
        watch: {
            id: function( val ) {
                this.entityId = val;
            },
            code: function( val ) {
                this.entityCode = val;
            },
            title: function( val ) {
                this.list.term = val;
            }
        },
        methods: {
            getEmittedEventName: function() {
                return 'entity-select';
            },
            getSearchUrl: function() {

            },
            getItemKey: function( item ) {
                return JSON.stringify( item );
            },
            getDisplayTitle: function( item ) {
                return this.getTitle( item );
            },
            getTitle: function( item ) {
                if ( typeof item.code !== 'undefined' ) {
                    return `${item.title} (${item.code})`;
                }

                return item.title;
            },
            getTitleHtml: function( item ) {
                let term = this.list.term;
                let reg = new RegExp( term, 'gi' );
                return this.getDisplayTitle( item ).replace( reg, '<span class="bg-warning">$&</span>' );
            },
            onKeyup: async function( $event ) {
                // if escape key, close the list
                if ( $event.keyCode === 27 ) {
                    this.closeList();
                } else {
                    // else get and show suggestions
                    await this.showSuggestions();
                }
            },
            getSearchResults: function() {
                let self = this;
                // abort previous request
                if ( null !== this.request.xhr ) {
                    this.request.xhr.abort();
                }
                // send new request
                this.request.xhr = $.get( this.getSearchUrl(), function( data ) {
                    self.list.items.push( ...data.slice( 0, self.maxResults ) );
                    self.loading = false;
                });
            },
            showSuggestions: async function() {
                if ( this.list.term !== '' ) {
                    this.loading = true;
                    this.list.items = [];
                    this.openList();
                    this.getSearchResults();

                } else {
                    this.entityId = null;
                    this.entityCode = null;
                    this.closeList();
                    this.$emit( this.getEmittedEventName() + '-cleared' );
                }
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.id;
                this.entityCode = item.code;
                this.cachedEntity = item;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
                // if clear
                if ( this.clearTextOnSelect ) {
                    this.list.term = '';
                }
            },
            positionList: function() {
                this.list.position.top = $( this.$el ).height() + 'px';
            },
            openList: function() {
                this.list.opened = true;
            },
            closeList: function() {
                this.list.opened = false;
                this.list.items = [];
            },
            handleNoResults: function() {
                this.entityId = null;
                this.closeList();
            },
            handleClearSearchData: function() {
                this.list.term = '';
                this.entityId = null;
                this.entityCode = null;
                this.cachedEntity = null;
            },
            getSortedItems: function() {
                const sortedList = [...this.list.items];
                return sortedList.sort( ( a, b ) => {
                    const $this = this;
                    const aScore = window.ctp.utils.getSimilarityScore( $this.getDisplayTitle( a ), $this.list.term );
                    const bScore = window.ctp.utils.getSimilarityScore( $this.getDisplayTitle( b ), $this.list.term );
                    return bScore - aScore;
                });
            },
            getInputProgressionEventName: function (){
                return 'input-in-progress'
            }
        },
        template: `
            <div v-bind:class="['uind-autocomplete-container flex-grow-1', classes]">
                <input type="hidden" v-bind:name="idFieldName" v-model="entityId">
                <input type="hidden" v-bind:name="entityTwoIdFieldName" v-model="entityTwoId" v-if="entityTwoIdFieldName != ''">
                <input type="hidden" v-bind:name="entityThreeIdFieldName" v-model="entityThreeId" v-if="entityThreeIdFieldName != ''">
                <input type="hidden" v-bind:name="entityFourIdFieldName" v-model="entityFourId" v-if="entityFourIdFieldName != ''">
                <input type="hidden" v-bind:name="codeFieldName" v-model="entityCode">
                <label v-if="showLabel">{{ labelText }}</label>
                <input type="text" class="form-control"
                        v-bind:name="titleFieldName"
                        v-model="list.term"
                        v-on:keyup="onKeyup( $event ); $emit(getInputProgressionEventName())"
                        v-bind:required="required"
                        v-bind:disabled="disabled"
                        v-bind:readonly="readOnly"
                        v-bind:inputmode="inputMode"
                        autofocus
                        v-bind:class="{ 'is-invalid': ( showInputErrorOnZeroId && ( entityId === 0 || entityId == null ) ) }"
                        autocomplete="off">
                <!-- autocomplete list -->
                <div class="uind-autocomplete-list" v-if="list.opened" v-bind:style="list.position">
                    <a href="#" v-for="(item, index) in getSortedItems()" 
                                v-if="list.items.length > 0 && ! loading" 
                                v-bind:key="getItemKey(item)" 
                                v-bind:child="item" 
                                v-bind:index="index" 
                                v-html="getTitleHtml(item)"
                                v-on:click="setEntity(item, $event); $emit(getEmittedEventName(), item.id, item);"></a>
                    <li v-if="list.items.length == 0 && ! loading" v-on:click="handleNoResults">No results found</li>
                    <li v-if="loading" class="text-center"><div class="spinner-border text-secondary spinner-border-sm"></div></li>
                </div>
            </div>
        `,
        mounted: function() {
            // set list position
            this.positionList();
            // listen for clear data
            this.$parent.$on( 'clear-search-data', this.handleClearSearchData );
        }
    };

    /*
   * warehouse supplies item search
   * */
    Vue.component( 'warehouse-supplies-item-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/uic/warehouse-supplies/search-items?search=${encodeURIComponent( this.list.term )}`
            },
            getEmittedEventName: function() {
                return 'item-select';
            },
            getTitle: function( item ) {
                return item.sku;
            }
        },
        props: {
            labelText: {
                default: 'Search Item'
            },
            titleFieldName: {
                default: 'sku'
            },
            codeFieldName:{
                default: 'sku'
            },
            idFieldName:{
                default: 'sku'
            }

        }
    });


    /*
   * vehicle search
   * */
    Vue.component( 'vehicle-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                let url = `/uind/rest/uic/vehicle-request/vehicle-search?term=${encodeURIComponent( this.list.term )}`
                if(this.formType===null && this.fleetType===null){
                    return url
                } else if(this.formType!==null && this.fleetType===null){
                    url+= `&formType=${this.formType}`
                    return url
                } else if(this.fleetType!==null && this.formType===null){
                    url+= `&fleetType=${this.fleetType}`
                    return url
                } else {
                    url+= `&formType=${this.formType}&fleetType=${this.fleetType}`
                    return url
                }
            },
            getEmittedEventName: function() {
                return 'vehicle-select';
            },
            getTitle: function( vehicle ) {
                return vehicle.model + ' (' + vehicle.registrationNumber + ')';
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.id;
                this.entityCode = item.registrationNumber;
                this.cachedEntity = item;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
                // if clear
                if ( this.clearTextOnSelect ) {
                    this.list.term = '';
                }
            }
        },
        props: {
            labelText: {
                default: 'Search Vehicle'
            },
            titleFieldName: {
                default: 'vehicleRegistrationNumber'
            },
            idFieldName: {
                default: 'vehicleId'
            },
            formType: {
              default: null
            },
            fleetType: {
              default: null
            },
            codeFieldName: {
                default: 'vehicleCode'
            },
        }
    });

    /*
   * vehicle search
   * */
    Vue.component( 'physical-compensation-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/hrms/physical-compensations/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'vehicle-select';
            },
            getTitle: function( vehicle ) {
                return vehicle.model + ' (' + vehicle.registrationNumber + ')';
            },
            setEntity: function ( vehicle, event ) {
                event.preventDefault();
                this.entityCode = vehicle.registrationNumber;
                this.list.term = this.getTitle( vehicle );
                this.closeList();
            }
        },
        props: {
            labelText: {
                default: 'Search Vehicle'
            },
            titleFieldName: {
                default: 'vehicleModel'
            },
            codeFieldName: {
                default: 'vehicleRegistrationNumber'
            },
        }
    });

    /**
     * supplier search component
     */

    Vue.component( 'employee-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                let url = `/uind/rest/hrms/employees/search?term=${encodeURIComponent( this.list.term )}`;
                if ( this.departmentIds != null && this.departmentIds.length > 0 ) {
                    if( Array.isArray(this.departmentIds) ) {
                        url += `&department-ids=${this.departmentIds.join( ',' )}`;
                    } else if( typeof this.departmentIds === 'string' && !this.departmentIds.includes(',') ){
                        url += `&department-ids=${this.departmentIds.substring(1,this.departmentIds.length-1)}`;
                    }
                }
                if ( this.functionIds != null && this.functionIds.length > 0 ) {
                    url += `&function-ids=${this.functionIds.join( ',' )}`;
                }
                if ( this.ids != null && this.ids.length > 0 ) {
                    url += `&employee-ids=${this.ids.join( ',' )}`;
                }
                if ( this.isActive != null ) {
                    url += `&is-active=${this.isActive}`;
                }
                return url;
            },
            getEmittedEventName: function() {
                return 'employee-select';
            },
            getTitle: function( item ) {
                if ( !! item.serialNumber ) {
                    let title = `${item.fullName} (${item.serialNumber})`;
                    if( this.isPositionVisible && !! item.positionTitle ){
                        title += ` (${item.positionTitle}) `
                    }
                    if ( !! item.officialEmail ) {
                        title += ` / ${item.officialEmail}`
                    }
                    return title;
                }
                return item.fullName;
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.id;
                this.entityCode = item.username;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
                // if clear
                if ( this.clearTextOnSelect ) {
                    this.list.term = '';
                }
            },
        },
        props: {
            // provided
            labelText: {
                default: 'Search Employee'
            },
            // provided
            titleFieldName: {
                default: 'employeeTitle'
            },
            idFieldName: {
                default: 'employeeId'
            },
            // provided
            codeFieldName: {
                default: 'employeeCode'
            },
            departmentIds: {
                default: null
            },
            functionIds: {
                default: null
            },
            ids: {
                default: null
            },
            isActive: {
                default: null
            },
            isPositionVisible : {
                default : false
            },
        },
    });


    /**
     * financing purchase order search component
     */
    Vue.component( 'financing-po-search-component', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/accounts-finance/banking/financing/purchase-orders/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'financing-po-select';
            },
            getTitle: function( po ) {
                return po.code;
            }
        },
        props: {
            labelText: {
                default: 'Search Financing PO'
            },
            titleFieldName: {
                default: 'financingPoTitle'
            },
            idFieldName: {
                default: 'financingPoId'
            },
            codeFieldName: {
                default: 'financingPoCode'
            }
        }
    } )


    /**
     * purchase order search component
     */
    Vue.component( 'purchase-order-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/ctp/rest/purchase-orders/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'purchase-order-select';
            },
            getTitle: function( po ) {
                return po.code;
            }
        },
        props: {
            labelText: {
                default: 'Search Purchase Order'
            },
            titleFieldName: {
                default: 'purchaseOrderTitle'
            },
            idFieldName: {
                default: 'purchaseOrderId'
            },
            codeFieldName: {
                default: 'purchaseOrderCode'
            }
        }
    });

    /**
     * approved purchase order search component
     */
    Vue.component( 'approved-purchase-order-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/uic/purchase-orders/search-approved?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'purchase-order-select';
            },
            getTitle: function( po ) {
                return po.code;
            }
        },
        props: {
            labelText: {
                default: 'Search Approved Purchase Order'
            },
            titleFieldName: {
                default: 'purchaseOrderTitle'
            },
            idFieldName: {
                default: 'purchaseOrderId'
            },
            codeFieldName: {
                default: 'purchaseOrderCode'
            }
        }
    });


    Vue.component( 'import-clearing-bill-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function () {
                return `/uind/accounts-finance/support-queries/import-clearing-bill/search?term=${encodeURIComponent(this.list.term)}`;
            },
            getEmittedEventName: function (){
                return 'import-bill-select';
            },
            getTitle: function (bill){
                return bill.code;
            }
        },
        props: {
            labelText: {
                default: 'Search Bill code'
            },
            titleFieldName: {
                default: 'billTitle'
            },
            idFieldName: {
                default: 'billId'
            },
            codeFieldName: {
                default: 'billCode'
            }
        }
    })

    Vue.component( 'export-clearing-bill-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function () {
                return `/uind/accounts-finance/support-queries/export-clearing-bill/search?term=${encodeURIComponent(this.list.term)}`;
            },
            getEmittedEventName: function (){
                return 'export-bill-select';
            },
            getTitle: function (bill){
                return bill.code;
            }
        },
        props: {
            labelText: {
                default: 'Search Bill code'
            },
            titleFieldName: {
                default: 'billTitle'
            },
            idFieldName: {
                default: 'billId'
            },
            codeFieldName: {
                default: 'billCode'
            }
        }
    })

    Vue.component('grn-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function () {
                return `/uind/accounts-finance/support-queries/grn/search?term=${encodeURIComponent(this.list.term)}`;
            },
            getEmittedEventName: function () {
                return 'grn-select';
            },
            getTitle: function (grn) {
                return grn.code;
            }
        },
        props: {
            labelText: {
                default: 'Search Grn code'
            },
            titleFieldName: {
                default: 'grnTitle'
            },
            idFieldName: {
                default: 'grnId'
            },
            codeFieldName: {
                default: 'grnCode'
            }
        }
    })

    Vue.component( 'bill-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/accounts-finance/support-queries/bill/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'bill-select';
            },
            getTitle: function( bill ) {
                return bill.code;
            }
        },
        props: {
            labelText: {
                default: 'Search Bill code'
            },
            titleFieldName: {
                default: 'billTitle'
            },
            idFieldName: {
                default: 'billId'
            },
            codeFieldName: {
                default: 'billCode'
            }
        }
    });

    Vue.component( 'voucher-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/accounts-finance/support-queries/voucher/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'voucher-select';
            },
            getTitle: function( voucher ) {
                return voucher.voucherCode;
            }
        },
        props: {
            labelText: {
                default: 'Search Voucher code'
            },
            titleFieldName: {
                default: 'voucherTitle'
            },
            idFieldName: {
                default: 'voucherId'
            },
            codeFieldName: {
                default: 'voucherCode'
            }
        }
    });

    /**
     * bill of lading search component
     */
    Vue.component( 'bill-of-lading-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/uic/bol-customs/search?term=${encodeURIComponent( this.list.term )}&supplier-id=${encodeURIComponent( this.supplierId )}&invoice-date=${encodeURIComponent( this.invoiceDate )}`;
            },
            getEmittedEventName: function() {
                return 'bill-of-lading-select';
            },
            getTitle: function( bol ) {
                return bol.billOfLadding;
            }
        },
        props: {
            labelText: {
                default: 'Search BOL'
            },
            titleFieldName: {
                default: 'billOfLadingTitle'
            },
            idFieldName: {
                default: 'billOfLadingId'
            },
            codeFieldName: {
                default: ''
            },
            supplierId: {
                default: 0
            },
            invoiceDate: {
                default: ''
            }
        }
    });

    /**
     * supplier search component
     */
    Vue.component( 'supplier-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                let url = `/uind/rest/uic/suppliers/search?term=${encodeURIComponent( this.list.term )}`;
                if ( !! this.categoryId ) {
                    url += `&category-id=${this.categoryId}`;
                }
                if( !! this.purchaseOrderType ){
                    url += `&purchase-order-type=${this.purchaseOrderType}`;
                }
                return url;
            },
            getEmittedEventName: function() {
                return 'supplier-select';
            },
            getTitle: function (supplier) {
                return supplier.title;
            }
        },
        props: {
            labelText: {
                default: 'Search Supplier'
            },
            titleFieldName: {
                default: 'supplierTitle'
            },
            idFieldName: {
                default: 'supplierId'
            },
            codeFieldName: {
                default: 'supplierCode'
            },
            categoryId: {
                default: null
            },
            purchaseOrderType : {
                default : null
            }
        }
    });

    /**
     * supplier title category search component
     */
    Vue.component( 'supplier-title-category-search', {
        mixins: [searchComponentMixin],
        props: {
            labelText: {
                default: 'Search Supplier'
            },
            titleFieldName: {
                default: 'supplierTitle'
            },
            idFieldName: {
                default: 'supplierId'
            },
            codeFieldName: {
                default: 'supplierCode'
            },
            categoryId: {
                default: ''
            }
        },
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/uic/suppliers/search?term=${encodeURIComponent( this.list.term )}&category-id=${this.categoryId}`;
            },
            getEmittedEventName: function() {
                return 'supplier-select';
            },
            getTitle: function( supplier ) {
                // item title only
                return supplier.title;
            }
        }
    });

    /**
     * broker search component
     */
    Vue.component( 'broker-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/uic/brokers/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'broker-select';
            },
            getTitle: function (broker){
                return broker.title;
            }
        },
        props: {
            labelText: {
                default: 'Search Broker'
            },
            titleFieldName: {
                default: 'brokerTitle'
            },
            idFieldName: {
                default: 'brokerId'
            },
            codeFieldName: {
                default: 'brokerCode'
            }
        }
    });


    /**
     * sale-quote search component
     */
    Vue.component( 'sale-quote-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/uic/local-sale/sale-quote/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'sale-quote-select';
            }
        },
        props: {
            labelText: {
                default: 'Search Sale Quote'
            },
            titleFieldName: {
                default: 'saleQuoteTitle'
            },
            idFieldName: {
                default: 'saleQuoteId'
            },
            codeFieldName: {
                default: ''
            }
        }
    });



    /**
     * sale-order search component
     */
    Vue.component( 'sale-order-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/uic/sale-order/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'sale-order-select';
            }
        },
        props: {
            labelText: {
                default: 'Search Sale Order'
            },
            titleFieldName: {
                default: 'saleOrderTitle'
            },
            idFieldName: {
                default: 'saleOrderId'
            },
            codeFieldName: {
                default: ''
            }
        }
    });

    /**
     * customer search component
     */
    Vue.component( 'customer-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/uic/customers/search?term=${encodeURIComponent( this.list.term )}&categoryId=${encodeURIComponent(this.categoryId)}&ids=${encodeURIComponent(this.ids)}`;
            },
            getEmittedEventName: function() {
                return 'customer-select';
            }
        },
        props: {
            labelText: {
                default: 'Search Customer'
            },
            titleFieldName: {
                default: 'customerTitle'
            },
            idFieldName: {
                default: 'customerId'
            },
            codeFieldName: {
                default: 'customerCode'
            },
            categoryId: {
              default: ''
            },
            ids: {
                default: ''
            }
        }
    });

    /**
     * location unit search component
     */
    Vue.component( 'location-unit-search', {
        mixins: [ searchComponentMixin ],
        methods: {
            getSearchUrl: function() {
                let url = `/uind/rest/uic/locations/units/search?term=${encodeURIComponent( this.list.term )}`
                if ( !! this.siteId ) {
                    url += `&siteId=${this.siteId}`;
                }
                return url;
            },
            getEmittedEventName: function() {
                return 'location-unit-select';
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityTwoId = item.siteId;
                this.entityId = item.id;
                this.cachedEntity = item;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            },
        },
        props: {
            labelText: {
                default: 'Search Unit'
            },
            titleFieldName: {
                default: 'unitTitle'
            },
            idFieldName: {
                default: 'unitId'
            },
            entityTwoIdFieldName :{
                default: null
            },
            codeFieldName: {
                default: ''
            },
            siteId: {
                default: null
            },
        }
    });

    /**
     * sub meter search component
     */
    Vue.component( 'sub-meter-search', {
        mixins: [ searchComponentMixin ],
        methods: {
            getSearchUrl: function() {
                let url = `/uind/rest/uic/utilities/sub-meters/search?term=${encodeURIComponent( this.list.term )}`
                return url;
            },
            getEmittedEventName: function() {
                return 'sub-meter-select';
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityTwoId = item.siteId;
                this.entityId = item.id;
                this.cachedEntity = item;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            },
            getTitle: function(item){
                return `${item.location} ( ${item.meterNumber} )`;
            }
        },
        props: {
            labelText: {
                default: 'Search Sub Meter'
            },
            titleFieldName: {
                default: 'Sub Meter Title'
            },
            idFieldName: {
                default: 'subMeterId'
            },
            entityTwoIdFieldName :{
                default: null
            },
            codeFieldName: {
                default: ''
            },
            siteId: {
                default: null
            },
        }
    });

 /**
     * location site search component
     */
    Vue.component( 'search-job-card-dashBoard', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/ctp/rest/locations/sites/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'location-site-select';
            }
        },
        props: {
            labelText: {
                default: 'Search Site'
            },
            titleFieldName: {
                default: 'siteTitle'
            },
            idFieldName: {
                default: 'siteId'
            },
            codeFieldName: {
                default: ''
            }
        }
    });


    /**
     * location site search component
     */
    Vue.component( 'location-site-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/ctp/rest/locations/sites/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'location-site-select';
            }
        },
        props: {
            labelText: {
                default: 'Search Site'
            },
            titleFieldName: {
                default: 'siteTitle'
            },
            idFieldName: {
                default: 'siteId'
            },
            codeFieldName: {
                default: ''
            }
        }
    });

    /**
     * Work Order Type search component
     */
    Vue.component('wo-type-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function () {
                return `/uind/rest/uic/work-order/type/search?term=${encodeURIComponent(this.list.term)}`;
            },
            getEmittedEventName: function () {
                return 'wo-type-select';
            }
        },
        props: {
            labelText: {
                default: 'Search type'
            },
            titleFieldName: {
                default: 'typeTitle'
            },
            idFieldName: {
                default: 'typeId'
            },
            codeFieldName: {
                default: 'typeCode'
            }
        }
    });

    /**
     * item search component
     */
    Vue.component( 'item-search', {
        mixins: [searchComponentMixin],
        props: {
            labelText: {
                default: 'Search Item'
            },
            titleFieldName: {
                default: 'itemTitle'
            },
            idFieldName: {
                default: 'itemId'
            },
            codeFieldName: {
                default: 'itemCode'
            },
            poItemsOnly:{
                default:false
            },
            typeIds: {
                default: null
            },
            showSkuOnly: {
                default: false
            },
        },
        methods: {
            getSearchUrl: function() {
                return `/ctp/rest/items/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'item-select';
            },
            getTitle: function( item ) {
                // if show sku only
                if ( this.showSkuOnly ) {
                    return item.sku;
                }
                // else format item title with code
                if ( typeof item.code !== 'undefined' ) {
                    return `${item.title} (${item.sku}) (${item.code})`;
                }
                // item title only
                return item.title;
            },
        }
    });

    /**
     * item search component For Service Items only
     */
    Vue.component('item-search-indent', {
        mixins: [searchComponentMixin],
        props: {
            labelText: {
                default: 'Search Item'
            },
            titleFieldName: {
                default: 'itemTitle'
            },
            idFieldName: {
                default: 'itemId'
            },
            codeFieldName: {
                default: 'itemCode'
            },
            woItemsOnly: {
                default: false
            },
            typeIds: {
                default: null
            },
            showSkuOnly: {
                default: false
            },
            indentType: {
                default: 'PURCHASE_ORDER'
            }

        },
        methods: {
            getSearchUrl: function () {
                return `/uind/rest/uic/items/search-service-item?indent-type=${this.indentType}&term=${encodeURIComponent(this.list.term)}&po-items-only=${this.woItemsOnly}&type-ids=${!!this.typeIds ? this.typeIds.join(',') : ''}`;
            },
            getEmittedEventName: function () {
                return 'item-select';
            },
            getTitle: function (item) {
                // if show sku only
                if (this.showSkuOnly) {
                    return item.sku;
                }
                // else format item title with code
                if (typeof item.code !== 'undefined') {
                    return `${item.title} (${item.code})`;
                }
                // item title only
                return item.title;
            },
        }
    });

    /**
     * item configuration search component
     */
    Vue.component( 'item-configuration-search', {
        mixins: [searchComponentMixin],
        props: {
            labelText: {
                default: 'Search Item Config'
            },
            titleFieldName: {
                default: 'configTitle'
            },
            idFieldName: {
                default: 'itemConfigId'
            },
            codeFieldName: {
                default: ''
            },
            itemId: {
                default: ''
            },
            itemLookupCode: {
                default: ''
            },
        },
        methods: {
            getSearchUrl: function() {
                let url = `/uind/rest/uic/items/configurations/search?term=${encodeURIComponent( this.list.term )}&`;
                if ( !! this.itemId ) {
                    url += `item-id=${this.itemId}&`;
                }
                if ( !! this.itemLookupCode ) {
                    url += `item-lookup-code=${this.itemLookupCode}&`;
                }
                return url;
            },
            getEmittedEventName: function() {
                return 'item-configuration-select';
            },
            getTitle: function( item ) {
                return `${item.title} - ${item.itemLookupCode} (${item.configurationUom} of ${item.configurationUnits} ${item.childUom})`;
            },
            mounted: async function() {
                console(this.itemId);
            },
        }
    });

    /**
    * item type search
    */
    Vue.component( 'item-type-search' ,{
        mixins : [ searchComponentMixin ],
        methods : {
            getSearchUrl: function() {
                return `/uind/rest/uic/items/types/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'item-type-select';
            }
        },
        props: {
            labelText: {
                default: 'Item Type Search'
            },
            titleFieldName: {
                default: 'itemTypeTitle'
            },
            idFieldName: {
                default: 'itemTypeId'
            },
            codeFieldName: {
                default: 'itemTypeCode'
            }
        }
    });

    /**
     * brand search component
     */
    Vue.component( 'brand-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/admin/item-brands/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'brand-select';
            }
        },
        props: {
            labelText: {
                default: 'Search Brand'
            },
            titleFieldName: {
                default: 'brandTitle'
            },
            idFieldName: {
                default: 'brandId'
            },
            codeFieldName: {
                default: 'brandCode'
            }
        }
    });

    /**
     * gin search component (un-tagged by dc number)
     */
    Vue.component( 'gin-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/uic/gins/un-tagged/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'gin-select';
            },
            getTitle: function( item ) {
                return item.deliveryChallanNumber + ' (' + item.code + ') ' + ' (SUP-' + item.supplierId + ')';
            },
        },
        props: {
            labelText: {
                default: 'Search GIN'
            },
            titleFieldName: {
                default: 'ginTitle'
            },
            idFieldName: {
                default: 'ginId'
            },
            codeFieldName: {
                default: 'ginCode'
            }
        }
    });

    /**
     * item unit search component
     */
    Vue.component( 'item-unit-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/uic/items/units/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'item-unit-select';
            },
            getTitle: function( item ) {
                return item.title;
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.id;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            }
        },
        props: {
            labelText: {
                default: 'Search UOM'
            },
            titleFieldName: {
                default: 'unitTitle'
            },
            idFieldName: {
                default: 'unitId'
            },
            codeFieldName: {
                default: 'unitCode'
            }
        },
    });

    /**
     * cosmos sku expression search component
     */
    Vue.component( 'cosmos-sku-expression-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                let url = `/uind/rest/uic/cosmos-product-sku-expression/search?term=${encodeURIComponent( this.list.term )}`;
                if ( !! this.marketplace ) {
                    url += `&marketplace=${encodeURIComponent( this.marketplace )}`;
                }
                return url;
            },
            getEmittedEventName: function() {
                return 'cosmos-sku-expression-select';
            },
            getTitle: function( item ) {
                let title = item.skuExpression;
                if ( !! item.description || item.size || item.pack ) {
                    if ( !! item.description ) {
                        title += ` / ${item.description}`
                    }
                    if ( !! item.size ) {
                        title += ` / ${item.size}`
                    }
                    if ( !! item.pack ) {
                        title += ` / ${item.pack}`
                    }
                }
                return title;
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.id;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            },
        },
        props: {
            labelText: {
                default: 'Search Expression'
            },
            idFieldName: {
                default: 'expression'
            },
            titleFieldName: {
                default: ''
            },
            codeFieldName: {
                default: ''
            },
            marketplace: {
                default: ''
            }
        },
    });

    /**
     * account search
     */
    Vue.component( 'account-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {

                if(this.isAllAccountSearch) {
                    return `/uind/rest/accounts-finance/accounts/search?term=${encodeURIComponent( this.list.term )}`;
                }

                // if cash and bank account only
                if ( this.cashAndBankAccountsOnly ) {
                    return `/uind/rest/accounts-finance/accounts/cash-and-bank-accounts/search?term=${encodeURIComponent( this.list.term )}${this.getActiveParam()}`;
                }
                // if fund accounts only (bank accounts)
                if ( this.fundAccountsOnly ) {
                    return `/uind/rest/accounts-finance/accounts/fund-accounts/search?term=${encodeURIComponent( this.list.term )}${this.getActiveParam()}`;
                }
                // build url
                let url = `/uind/rest/accounts-finance/accounts/search?term=${encodeURIComponent( this.list.term )}${this.getActiveParam()}`;
                if ( this.accountLevelFourIds.length > 0 ) {
                    url += `&level-four-ids=${this.accountLevelFourIds.join( ',' )}`;
                }
                if ( this.accountLevelThreeIds.length > 0 ) {
                    url += `&level-three-ids=${this.accountLevelThreeIds.join( ',' )}`;
                }
                if ( this.accountLevelTwoIds.length > 0 ) {
                    url += `&level-two-ids=${this.accountLevelTwoIds.join( ',' )}`;
                }
                if ( !! this.parentEntityType ) {
                    url += `&parent-entity-type=${this.parentEntityType}`;
                }
                if ( !! this.parentEntityId ) {
                    url += `&parent-entity-id=${this.parentEntityId}`;
                }
                return url;
            },
            getActiveParam: function() {
                if ( this.activeStatus != null ) {
                    if ( this.activeStatus === 'ACTIVE' ) {
                        return '&is-active=true';
                    }
                    if ( this.activeStatus === 'INACTIVE' ) {
                        return '&is-active=false';
                    }
                }
                return '';
            },
            getEmittedEventName: function() {
                return 'account-select';
            },
            getDisplayTitle: function( item ) {
                return this.isOnlyCode ? item.code :`${item.hierarchyString}`;
            },
            getTitle: function( item ) {
                return  this.isOnlyCode ? item.code : item.title;
            }
        },
        props: {
            labelText: {
                default: 'Search Account'
            },
            titleFieldName: {
                default: 'accountTitle'
            },
            idFieldName: {
                default: 'accountId'
            },
            codeFieldName: {
                default: 'accountCode'
            },
            parentEntityType: {
                default: null
            },
            parentEntityId: {
                default: null
            },
            isAllAccountSearch: {
               default: false
            },
            accountLevelTwoIds: {
                default() {
                    return []
                }
            },
            accountLevelThreeIds: {
                default() {
                    return []
                }
            },
            accountLevelFourIds: {
                default() {
                    return []
                }
            },
            fundAccountsOnly: {
                default: false
            },
            cashAndBankAccountsOnly: {
                default: false
            },
            activeStatus: {
                default: null
            },
            isOnlyCode: {
                default: false
            }


        },
        mounted: function (){
            console.log(this.isOnlyCode)
        }
    });

    /**
     * account transaction search
     */
    Vue.component( 'account-transaction-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                let paramPart = `term=${encodeURIComponent( this.list.term )}`;
                if ( !! this.accountId ) {
                    paramPart += `&account-id=${this.accountId}`;
                }
                if ( !! this.instrumentId ) {
                    paramPart += `&instrument-id=${this.instrumentId}`;
                }
                if ( !! this.instrumentNumber ) {
                    paramPart += `&instrument-number=${this.instrumentNumber}`;
                }
                if ( this.bankStatementUntaggedOnly != null ) {
                    paramPart += `&bank-statement-untagged-only=${this.bankStatementUntaggedOnly}`;
                }
                return `/uind/rest/accounts-finance/accounts/transactions/search?${paramPart}`;
            },
            getEmittedEventName: function() {
                return 'account-transaction-select';
            },
            getTitle: function( item ) {
                return `${item.code} (${window.ctp.utils.formatCurrencyPKR( item.debitTotal )})`;
            },
        },
        props: {
            labelText: {
                default: 'Search Voucher'
            },
            titleFieldName: {
                default: 'transactionTitle'
            },
            idFieldName: {
                default: 'transactionId'
            },
            codeFieldName: {
                default: 'transactionCode'
            },
            accountId: {
                default: null
            },
            instrumentId: {
                default: null
            },
            instrumentNumber: {
                default: null
            },
            instrumentNumber: {
                default: null
            },
            bankStatementUntaggedOnly: {
                default: null
            }
        }
    });

    /**
     * bank statement search
     */
    Vue.component( 'bank-statement-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                let url = `/uind/rest/accounts-finance/banking/bank-statements/search?term=${encodeURIComponent( this.list.term )}`;
                if ( this.date != null ) {
                    url += `&date=${this.date}`
                }
                return url;
            },
            getEmittedEventName: function() {
                return 'bank-statement-select';
            },
            getTitle: function( statement ) {
                let title = `${statement.referenceNumber} / ${statement.fullBankAccountNumber}`;
                if ( statement.debitAmount > 0 ) {
                    title += ` / DEBIT: ${window.ctp.utils.formatCurrencyPKR( statement.debitAmount )}`;
                }
                if ( statement.creditAmount > 0 ) {
                    title += ` / CREDIT: ${window.ctp.utils.formatCurrencyPKR( statement.creditAmount )}`;
                }
                title += ` / ${window.ctp.utils.getFormattedDateStringFromDateString(statement.transactionDate)}`;
                return title;
            }
        },
        props: {
            labelText: {
                default: 'Search Payment'
            },
            titleFieldName: {
                default: 'payToTitle'
            },
            idFieldName: {
                default: 'id'
            },
            entityTwoIdFieldName: {
                default: ''
            },
            codeFieldName: {
                default: ''
            },
            date: {
                default: null
            }
        }
    });

    /**
     * banking institution search
     */
    Vue.component( 'banking-institution-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/admin/banking-institutions/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'banking-institution-select';
            },
            getTitle: function( item ) {
                return item.title;
            },
        },
        props: {
            labelText: {
                default: 'Search Bank'
            },
            titleFieldName: {
                default: 'bankingInstitutionTitle'
            },
            idFieldName: {
                default: 'bankingInstitutionId'
            },
            codeFieldName: {
                default: 'bankingInstitutionCode'
            }
        }
    });

    /**
     * payment-request-type-search
     */
    Vue.component( 'payment-request-type-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                    return `/uind/rest/accounts-finance/payment-request-types/search?term=${encodeURIComponent(this.list.term)}`;

            },
            getEmittedEventName: function() {
                return 'payment-type-select';
            },
            getTitle: function( item ) {
                return item.code;
            }
        },
        props: {
            labelText: {
                default: 'Search Payment Request Type'
            },
            titleFieldName: {
                default: 'paymentRequestTypeCode'
            }
        }
    });


    /**
     * financing liability search
     */
    Vue.component( 'financing-liability-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/accounts-finance/accounts/search/financing-liability-accounts?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'financing-liability-select';
            },
            getTitle: function( item ) {
                return item.title;
            },
        },
        props: {
            labelText: {
                default: 'Search Financing Liability'
            },
            titleFieldName: {
                default: 'accountTitle'
            },
            idFieldName: {
                default: 'accountId'
            },
            codeFieldName: {
                default: 'accountCode'
            }
        }
    });

    /**
     * expense search
     */
    Vue.component( 'expense-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                // return `/uind/rest/accounts-finance/accounts/search/expense-accounts?term=${encodeURIComponent( this.list.term )}`;
                return `/uind/rest/accounts-finance/accounts/search?term=${encodeURIComponent( this.list.term )}`;

            },
            getEmittedEventName: function() {
                return 'expense-select';
            },
            getTitle: function( item ) {
                return item.title;
            },
        },
        props: {
            labelText: {
                default: 'Search Expense'
            },
            titleFieldName: {
                default: 'accountTitle'
            },
            idFieldName: {
                default: 'accountId'
            },
            codeFieldName: {
                default: 'accountCode'
            }
        }
    });

    /**
     * security deposit search
     */
    Vue.component( 'security-deposit-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/accounts-finance/accounts/search/security-deposit-accounts?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'security-deposit-select';
            },
            getTitle: function( item ) {
                return item.title;
            },
        },
        props: {
            labelText: {
                default: 'Search Security Deposit'
            },
            titleFieldName: {
                default: 'accountTitle'
            },
            idFieldName: {
                default: 'accountId'
            },
            codeFieldName: {
                default: 'accountCode'
            }
        }
    });

    /**
     * financing facility search
     */
    Vue.component( 'financing-facility-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/accounts-finance/banking/financing-facilities/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'financing-facility-select';
            },
            getTitle: function( item ) {
                return item.title;
            },
        },
        props: {
            labelText: {
                default: 'Search Financing Facility'
            },
            titleFieldName: {
                default: 'financingFacilityTitle'
            },
            idFieldName: {
                default: 'financingFacilityId'
            },
            codeFieldName: {
                default: ''
            }
        }
    });

    /**
     * account level four search
     */
    Vue.component( 'account-level-four-search', {
        mixins: [searchComponentMixin],
        props: {
            oneId: {
                default: null
            },
            twoId: {
                default: null
            },
            threeId: {
                default: null
            },
            fourId: {
                default: null
            },
            companyId: {
                default: null
            },
            labelText: {
                default: 'Search Group of Accounts'
            },
            titleFieldName: {
                default: 'hierarchyString'
            },
            oneIdFieldName: {
                default: 'accountLevelOneId'
            },
            twoIdFieldName: {
                default: 'accountLevelTwoId'
            },
            threeIdFieldName: {
                default: 'accountLevelThreeId'
            },
            fourIdFieldName: {
                default: 'accountLevelFourId'
            }
        },
        methods: {
            getSearchUrl: function() {
                if( this.companyId ) {
                    return `/uind/rest/accounts-finance/accounts/level-fours/search?term=${encodeURIComponent( this.list.term )}&company=${encodeURIComponent( this.companyId )}`;
                } else {
                    return `/uind/rest/accounts-finance/accounts/level-fours/search?term=${encodeURIComponent( this.list.term )}`;
                }
            },
            getEmittedEventName: function() {
                return 'account-level-four-select';
            },
            getTitle: function( item ) {
                return item.hierarchyString;
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.oneId = item.accountLevelOneId;
                this.twoId = item.accountLevelTwoId;
                this.threeId = item.accountLevelThreeId;
                this.fourId = item.id;
                this.cachedEntity = item;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            }
        },
        template: `
            <div class="uind-autocomplete-container">
                <input type="hidden" v-bind:name="oneIdFieldName" v-model="oneId">
                <input type="hidden" v-bind:name="twoIdFieldName" v-model="twoId">
                <input type="hidden" v-bind:name="threeIdFieldName" v-model="threeId">
                <input type="hidden" v-bind:name="fourIdFieldName" v-model="fourId">
                <label v-if="showLabel">{{ labelText }}</label>
                <input type="text" class="form-control"
                        v-bind:name="titleFieldName"
                        v-model="list.term"
                        v-on:keyup="onKeyup( $event )" 
                        v-bind:required="required"
                        v-bind:disabled="disabled"
                        autocomplete="off">
                <!-- autocomplete list -->
                <div class="uind-autocomplete-list" v-if="list.opened" v-bind:style="list.position">
                    <a href="#" v-if="list.items.length > 0 && ! loading" v-for="(item, index) in list.items" 
                                v-bind:key="getItemKey(item)" 
                                v-bind:child="item" 
                                v-bind:index="index" 
                                v-html="getTitleHtml(item)"
                                v-on:click="setEntity(item, $event); $emit(getEmittedEventName(), item.id, item);"></a>
                    <li v-if="list.items.length == 0 && ! loading" v-on:click="handleNoResults">No results found</li>
                    <li v-if="loading" class="text-center"><div class="spinner-border text-secondary spinner-border-sm"></div></li>
                </div>
            </div>
        `
    });

    /**
     * invoice search
     */
    Vue.component( 'invoice-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/accounts-finance/invoices/search?number=${encodeURIComponent( this.list.term )}&supplierId=${encodeURIComponent( this.supplierId )}`;
            },
            getEmittedEventName: function() {
                return 'invoice-select';
            },
            getTitle: function( item ) {
                return `${item.number} (SUP-${item.supplierId})`;
            }
        },
        props: {
            labelText: {
                default: 'Search Invoice'
            },
            titleFieldName: {
                default: 'invoiceNumber'
            },
            idFieldName: {
                default: 'invoiceId'
            },
            supplierId: {
                default: 0
            },
            codeFieldName: {
                default: 'invoiceCode'
            }
        }
    });

    /**
     * cosmos supplier invoice search
     */
    Vue.component( 'cosmos-supplier-invoice-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/cosmos/inventory/supplier-invoices/search-by-hbl?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'cosmos-supplier-invoice-select';
            },
            getTitle: function( item ) {
                return item.hblNumber;
            },
        },
        props: {
            labelText: {
                default: 'Search HBL#'
            },
            titleFieldName: {
                default: 'houseBillOfLading'
            },
            idFieldName: {
                default: ''
            },
            codeFieldName: {
                default: ''
            }
        }
    });



    /**
     * employee and contractor search component
     */
    Vue.component( 'employee-worker-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/hrms/employees/search/serial-number?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'employee-select';
            },
            getTitle: function( item ) {
                if ( !! item.serialNumber ) {
                    return `${item.fullName} - ( ${item.serialNumber} ) - ( ${item.workerType} )`;
                }
                return item.fullName;
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.id;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            },
        },
        props: {
            labelText: {
                default: 'Search Employee'
            },
            titleFieldName: {
                default: 'employeeTitle'
            },
            idFieldName: {
                default: 'employeeId'
            },
            codeFieldName: {
                default: 'employeeCode'
            }
        },
    });

    /**
     * employee search component
     */
    Vue.component( 'worker-employee-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/hrms/employees/search/worker-employee/serial-number?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'employee-select';
            },
            getTitle: function( item ) {
                if ( !! item.serialNumber ) {
                    return `${item.fullName} - ( ${item.serialNumber} ) - ( ${item.workerType} )`;
                }
                return item.fullName;
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.id;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            },
        },
        props: {
            labelText: {
                default: 'Search Employee'
            },
            titleFieldName: {
                default: 'employeeGrantPermissionTitle'
            },
            idFieldName: {
                default: 'permissionGrantedBy'
            },
            codeFieldName: {
                default: 'employeeCode'
            }
        },
    });

    /**
     * employee and contractor search component
     */
    Vue.component( 'room-search', {
        mixins: [searchComponentMixin],
        props : ['floors', 'sites', 'colonies'],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/hrms/workers-society/room/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'room-select';
            },
            getTitle: function( item ) {
                const site = this.sites.filter((e) => e.id == item.siteId);
                const colony = this.colonies.filter((e) => e.id == item.colonyId);
                const floor = this.floors.filter((e) => e.id == item.floorId);
                if ( !! item.roomCode ) {
                     return `${site[0].title} > ${colony[0].title} > ${item.roomCode} - ( ${item.roomTitle} ) `;
                }
                    return item.roomTitle;
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.id;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            },
        },
        props: {
            labelText: {
                default: 'Search Room'
            },
            titleFieldName: {
                default: 'RoomTitle'
            },
            idFieldName: {
                default: 'roomId'
            },
            codeFieldName: {
                default: 'roomCode'
            },
            sites :{
                default :[]
            },
            floors :{
                default : []
            },
            colonies :{
                default :[]
            }
        },
    });

    /**
     * city area search component
     */
    Vue.component( 'city-area-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/admin/city-areas/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'city-area-select';
            },
            getTitle: function( item ) {
                return item.title;
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.id;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            },
        },
        props: {
            labelText: {
                default: 'Search City Area'
            },
            titleFieldName: {
                default: 'cityAreaTitle'
            },
            idFieldName: {
                default: 'cityAreaId'
            },
            codeFieldName: {
                default: 'cityAreaCode'
            }
        },
    });

    /**
     * city area search component
     */
    Vue.component( 'item-category-hs-code-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/admin/fbr-item-category-hs-codes/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'item-category-hs-code-select';
            },
            getTitle: function( item ) {
                return `${ item.title } (${ item.hsCode })`;
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.id;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            },
        },
        props: {
            labelText: {
                default: 'Search Category'
            },
            titleFieldName: {
                default: 'categoryHsCodeTitle'
            },
            idFieldName: {
                default: 'categoryHsCodeId'
            },
            codeFieldName: {
                default: 'categoryHsCode'
            }
        },
    });

    /**
     * visitor search component (by CNIC)
     */
    Vue.component( 'visitor-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/vms/visitors/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'visitor-select';
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.cnic;
                this.entityCode = '';
                this.cachedEntity = item;
                this.list.selected = item;
                this.list.term = item.cnic;
                this.closeList();
            },
            getTitle: function( item ) {
                if ( typeof item.cnic !== 'undefined' ) {
                    return `${item.cnic}`;
                }
                return item.title;
            },
            onKeyup: async function( $event ) {
                this.$emit('cnic-updated', $event.target.value);
                // if escape key, close the list
                if ( $event.keyCode === 27 ) {
                    this.closeList();
                } else {
                    // else get and show suggestions
                    await this.showSuggestions();
                }
            },
        },
        props: {
            labelText: {
                default: 'Visitor CNIC'
            },
            titleFieldName: {
                default: 'visitorCNIC'
            },
            idFieldName: {
                default: 'visitorId'
            },
            codeFieldName: {
                default: 'visitorCode'
            }
        }
    });

    /**
     * contractor search
     */
    Vue.component( 'contractor-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/hrms/contractors/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'contractor-select';
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.id;
                this.entityCode = '';
                this.cachedEntity = item;
                this.list.selected = item;
                this.list.term = item.fullName;
                this.closeList();
            },
            getTitle: function( item ) {
                return item.fullName;
            }
        },
        props: {
            labelText: {
                default: 'Search Contractor'
            },
            titleFieldName: {
                default: 'contractorTitle'
            },
            idFieldName: {
                default: 'contractorId'
            },
            codeFieldName: {
                default: 'contractorCode'
            }
        }
    });

    /**
     * company hierarchy search
     */
    Vue.component( 'department-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/hrms/departments/search?term=${encodeURIComponent( this.list.term )}&functionId=${this.functionId}`;
            },
            getEmittedEventName: function() {
                return 'department-select';
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.id;
                this.entityTwoId = item.functionId;
                this.entityThreeId = item.companyId;
                this.entityCode = '';
                this.cachedEntity = item;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            },
            getTitle: function( item ) {
                return item.title;
            }
        },
        props: {
            labelText: {
                default: 'Search Department'
            },
            titleFieldName: {
                default: 'departmentTitle'
            },
            idFieldName: {
                default: 'departmentId'
            },
            entityTwoIdFieldName: {
                default: 'functionId'
            },
            entityThreeIdFieldName: {
                default: 'companyId'
            },
            codeFieldName: {
                default: 'departmentCode'
            },
            functionId: {
                default: ''
            }
        }
    });

    /**
     * cost center search
     */
    Vue.component( 'cost-center-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/uic/cost-centers/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'cost-center-select';
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.costCenterOneId;
                this.entityTwoId = item.costCenterTwoId;
                this.entityThreeId = item.costCenterThreeId;
                this.entityFourId = item.costCenterFourId;
                this.entityCode = '';
                this.cachedEntity = item;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            },
            getTitle: function( item ) {
                return `${item.hierarchyString} - (${item.code})`;
            }
        },
        props: {
            labelText: {
                default: 'Search Cost Center'
            },
            titleFieldName: {
                default: 'costCenterTitle'
            },
            idFieldName: {
                default: 'costCenterOneId'
            },
            entityTwoIdFieldName: {
                default: 'costCenterTwoId'
            },
            entityThreeIdFieldName: {
                default: 'costCenterThreeId'
            },
            entityFourIdFieldName: {
                default: 'costCenterFourId'
            },
            codeFieldName: {
                default: ''
            }
        }
    });

    /**
     * cost center search
     */
    Vue.component( 'cost-center-one-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/accounts-finance/cost-centers/search/one?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'cost-center-one-select';
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                   this.entityId = item.id;
                   this.entityCode = '';
                   this.cachedEntity = item;
                   this.list.selected = item;
                   this.list.term = this.getTitle( item );
                   this.closeList();
            },
            getTitle: function( item ) {
                return `${item.title} ( ${item.id} )`  ;
            }
        },
        props: {
            labelText: {
                default: 'Search Cost Center'
            },
            titleFieldName: {
                default: 'costCenterTitle'
            },
            idFieldName: {
                default: 'id'
            },
            codeFieldName: {
                default: ''
            }
        }
    });

    /**
     * cost center search
     */
    Vue.component( 'cost-center-four-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/accounts-finance/cost-centers/search/four?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'cost-center-one-select';
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                   this.entityId = item.id;
                   this.entityCode = '';
                   this.cachedEntity = item;
                   this.list.selected = item;
                   this.list.term = this.getTitle( item );
                   this.closeList();
            },
            getTitle: function( item ) {
                return `${item.title} ( ${item.id} )`  ;
            }
        },
        props: {
            labelText: {
                default: 'Search Cost Center'
            },
            titleFieldName: {
                default: 'costCenterTitle'
            },
            idFieldName: {
                default: 'id'
            },
            codeFieldName: {
                default: ''
            }
        }
    });

    /**
     * cost center search
     */
    Vue.component( 'cost-center-hierarchy-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/accounts-finance/cost-centers/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'cost-center-hierarchy-select';
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                   this.entityFourId = item.fourId;
                   this.entityTwoId = item.twoId;
                   this.entityThreeId = item.threeId;
                   this.entityId = item.oneId;
                   this.entityCode = '';
                   this.cachedEntity = item;
                   this.list.selected = item;
                   this.list.term = this.getTitle( item );
                   this.closeList();
            },
            getTitle: function( item ) {
                return `${item.hierarchyString} - (${item.code})`;
            }
        },
        props: {
            labelText: {
                default: 'Search Cost Center'
            },
            titleFieldName: {
                default: 'costCenterTitle'
            },
            idFieldName: {
                default: 'oneId'
            },
            entityTwoIdFieldName: {
                default: 'twoId'
            },
            entityThreeIdFieldName: {
                default: 'threeId'
            },
            entityFourIdFieldName: {
                default: 'fourId'
            },
            codeFieldName: {
                default: ''
            }
        }
    });


    /**
     * function search
     */
    Vue.component( 'function-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/hrms/functions/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'function-select';
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.id;
                this.entityTwoId = item.companyId;
                this.entityCode = '';
                this.cachedEntity = item;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
                if ( this.clearTextOnSelect ) {
                    this.list.term = '';
                }
            },
            getTitle: function( item ) {
                return item.title;
            }
        },
        props: {
            labelText: {
                default: 'Search Function'
            },
            titleFieldName: {
                default: 'functionTitle'
            },
            idFieldName: {
                default: 'functionId'
            },
            entityTwoIdFieldName: {
                default: 'companyId'
            },
            codeFieldName: {
                default: 'functionCode'
            }
        }
    });

    /**
     * payment request search
     */
    Vue.component( 'payment-request-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/accounts-finance/payment-requests/find-by-ids?ids=${encodeURIComponent( this.list.term )}&type=${encodeURIComponent( this.type )}`;
            },
            getEmittedEventName: function() {
                return 'payment-request-select';
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.id;
                this.entityTwoId = 0;
                this.entityCode = '';
                this.cachedEntity = item;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            },
            getTitle: function( item ) {
                return "PAY-REQ-"+item.id;
            }
        },
        props: {
            labelText: {
                default: 'Search Payment Request'
            },
            titleFieldName: {
                default: 'payToTitle'
            },
            idFieldName: {
                default: 'id'
            },
            entityTwoIdFieldName: {
                default: ''
            },
            codeFieldName: {
                default: ''
            },
            type: {
                default: 'all'
            }
        }
    });

    /**
     * payment search
     */
    Vue.component( 'payment-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/accounts-finance/payments/find-by-ids?ids=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'pay-request-select';
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.id;
                this.entityTwoId = 0;
                this.entityCode = '';
                this.cachedEntity = item;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            },
            getTitle: function( item ) {
                return item.code;
            }
        },
        props: {
            labelText: {
                default: 'Search Payment'
            },
            titleFieldName: {
                default: 'payToTitle'
            },
            idFieldName: {
                default: 'id'
            },
            entityTwoIdFieldName: {
                default: ''
            },
            codeFieldName: {
                default: ''
            }
        }
    });

    /**
     * online payment collection search
     */
    Vue.component( 'payment-collection-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/accounts-finance/online-payment-collections/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'payment-collection-select';
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.id;
                this.entityTwoId = 0;
                this.entityCode = '';
                this.cachedEntity = item;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            },
            getTitle: function( item ) {
                return `${item.code}`;
            }
        },
        props: {
            labelText: {
                default: 'Search Payment Collection'
            },
            titleFieldName: {
                default: 'collectionTitle'
            },
            idFieldName: {
                default: 'id'
            },
            entityTwoIdFieldName: {
                default: ''
            },
            codeFieldName: {
                default: ''
            },
            type: {
                default: ''
            }
        }
    });

    /**
     * loader component
     */
    Vue.component( 'spinner', {
        props: {
            sizeClass: {
                default: ''
            },
            paddingClass: {
                default: 'p-4'
            },
            colorClass: {
                default: 'text-secondary'
            }
        },
        template: `
            <div class="d-flex justify-content-center" v-bind:class="paddingClass">
                <div class="spinner-border" v-bind:class="{[sizeClass]: true, [paddingClass]: true, [colorClass]: true}"></div>
            </div>
        `
    });

    /**
     * feature update feed
     */
    Vue.component( 'feature-update-feed', {
        props: ['type'],
        data: function() {
            return {
                updates: [],
                loaded: false
            }
        },
        methods: {
            getFeedUrl: function() {
                return `/uind/rest/admin/feature-updates/recent?type=${encodeURIComponent( this.type )}`;
            },
            getFeedData: async function() {
                this.updates = await $.get( this.getFeedUrl() );
                this.loaded = true;
            },
            getUpdateViewLink: function( update ) {
                return `/uind/admin/feature-updates/view/${update.id}`;
            },
            getUpdateDateFormatted: function( update ) {
                return window.ctp.utils.getFormattedDateStringFromDateString( update.dateTimeCreated );
            },
            wasPublishedToday: function( update ) {
                let today = new Date();
                let updateDate = new Date( Date.parse( update.dateTimeCreated ) );
                return ( today.getDate() == updateDate.getDate()
                    && today.getMonth() == updateDate.getMonth()
                    && today.getFullYear() == updateDate.getFullYear() );
            }
        },
        template: `
            <div class="card">
                <div class="card-header">Updates</div>
                <ul class="list-group list-group-flush">
                    <li class="list-group-item" v-if="loaded && updates.length > 0" v-for="(update, index) in updates">
                        <a class="text-reset" v-bind:href="getUpdateViewLink(update)">
                            <span>{{ update.title }}</span>
                            <small class="text-secondary font-italic">on {{ getUpdateDateFormatted(update) }}</small>
                        </a>
                        <span class="badge badge-danger badge-pill" v-if="wasPublishedToday(update)">New</span>
                    </li>
                    <li class="list-group-item text-center" v-if="!loaded">
                        <span class="spinner-border text-secondary spinner-border-sm"></span>
                    </li>
                    <li class="list-group-item" v-if="loaded && updates.length == 0">
                        No recent updates.
                    </li>
                </ul>
            </div>
        `,
        mounted: function() {
            // get feed data
            this.getFeedData();
        }
    });

    /**
     * container search component
     */
    Vue.component( 'container-search', {
        mixins: [searchComponentMixin],
        props: ['billId','supplierId','invoiceDate','isOnlyContainer'],
        methods: {
            getSearchUrl: function() {
                let url = `/uind/rest/uic/commercial-export/search?term=${encodeURIComponent( this.list.term )}&isOnlyContainer=${encodeURIComponent( this.isOnlyContainer )}&billId=${encodeURIComponent( this.billId )}&supplierId=${encodeURIComponent( this.supplierId )}&invoiceDate=${encodeURIComponent( this.invoiceDate )}`;
                return url;
            },
            getEmittedEventName: function() {
                return 'container-select';
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.id;
                this.entityTwoId = 0;
                this.entityCode = '';
                this.cachedEntity = item;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            },
            getTitle: function( item ) {
                return item.appointmentId +" ( "+item.invoice.invoiceNumber+" ) ";
            }
        },
        props: {
            labelText: {
                default: 'Search Container'
            },
            titleFieldName: {
                default: 'appointmentId'
            },
            idFieldName: {
                default: 'appointmentId'
            },
            codeFieldName: {
                default: ''
            },
            billId: {
                default: 0
            },
            supplierId: {
                default: 0
            },
            invoiceDate: {
                default: null
            },
            isOnlyContainer: {
                default: false
            }
        }
    });

    /**
     * cosmos invoice search component
     */
    Vue.component( 'cosmos-invoice-search', {
        mixins: [searchComponentMixin],
        props: ['exportId','invoiceNumber','currencySymbol','isAdvanceReceipt'],
        methods: {
            getSearchUrl: function() {
                let url = `/uind/rest/uic/commercial-export/cosmos-supplier-invoice/search?term=${encodeURIComponent( this.list.term )}&currency=${encodeURIComponent( this.currencySymbol )}&exportId=${encodeURIComponent( this.exportId )}&isAdvanceReceipt=${encodeURIComponent( this.isAdvanceReceipt )}`;
                return url;
            },
            getEmittedEventName: function() {
                return 'invoice-select';
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.id;
                this.entityTwoId = 0;
                this.entityCode = '';
                this.cachedEntity = item;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            },
            getTitle: function( item ) {
                return item.invoiceNumber +" ( "+item.containerNo+" ) ";
            }
        },
        props: {
            labelText: {
                default: 'Search Cosmos Supplier Invoice'
            },
            titleFieldName: {
                default: 'invoiceNumber'
            },
            idFieldName: {
                default: 'invoiceNumber'
            },
            codeFieldName: {
                default: ''
            },
            exportId: {
                default: 0
            },
            isAdvanceReceipt: {
                default: false
            },
            currencySymbol: {
                default: ""
            }
        }
    });

    /**
     * cosmos machine search component
     */
    Vue.component( 'cosmos-machine-search', {
        mixins: [searchComponentMixin],
        props: ['serialNumber'],
        methods: {
            getSearchUrl: function() {
                let url = `/uind/rest/uic/cosmos-machines/search?term=${encodeURIComponent( this.list.term )}`;
                return url;
            },
            getEmittedEventName: function() {
                return 'machine-select';
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.serialNumber;
                this.entityTwoId = 0;
                this.entityCode = '';
                this.cachedEntity = item;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            },
            getTitle: function( item ) {
                return item.serialNumber +" ( "+item.model+" ) ";
            }
        },
        props: {
            labelText: {
                default: 'Search Cosmos Machines'
            },
            titleFieldName: {
                default: 'machineTitle'
            },
            idFieldName: {
                default: 'machineSerialNumber'
            },
            codeFieldName: {
                default: ''
            },
            serialNumber: {
                default: ""
            }
        }
    });

    /**
     * cosmos machine search component
     */
    Vue.component( 'item-artifact-cosmos-machine-search', {
        mixins: [searchComponentMixin],
        props: ['serialNumber'],
        methods: {
            getSearchUrl: function() {
                let url = `/uind/rest/uic/cosmos-machines/search?term=${encodeURIComponent( this.list.term )}`;
                return url;
            },
            getEmittedEventName: function() {
                return 'machine-select';
            },
            getTitle: function( item ) {
                return item.serialNumber +" ( "+item.model+" ) ";
            }
        },
        props: {
            labelText: {
                default: 'Search Cosmos Machines'
            },
            titleFieldName: {
                default: 'machineTitle'
            },
            idFieldName: {
                default: 'machineSerialNumber'
            },
            codeFieldName: {
                default: ''
            },
            serialNumber: {
                default: ""
            }
        }
    });

    /**
     * advance receipt search component
     */
    Vue.component( 'advance-receipt-search', {
        mixins: [searchComponentMixin],
        props: ['code','id'],
        methods: {
            getSearchUrl: function() {
                let url = `/uind/rest/accounts-finance/advance-receipt/search-by-code?term=${encodeURIComponent( this.list.term )}`;
                return url;
            },
            getEmittedEventName: function() {
                return 'advance-receipt-select';
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.id;
                this.entityTwoId = 0;
                this.entityCode = item.code;
                this.cachedEntity = item;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            },
            getTitle: function( item ) {
                return item.code +" ( "+item.refNumber+" ) ";
            }
        },
        props: {
            labelText: {
                default: 'Search Advance Receipt'
            },
            titleFieldName: {
                default: 'code'
            },
            idFieldName: {
                default: 'id'
            },
            codeFieldName: {
                default: ''
            },
            code: {
                default: ""
            },
            id: {
                default: 0
            }
        }
    });

    /**
     * Treasury Desk Rate Negotiation search component
     */
    Vue.component( 'treasury-desk-rate-negotiation-search', {
        mixins: [searchComponentMixin],
        props: ['code','id'],
        methods: {
            getSearchUrl: function() {
                let url = `/uind/rest/accounts-finance/treasury-desk-rate-negotiation/search-by-code?term=${encodeURIComponent( this.list.term )}`;
                return url;
            },
            getEmittedEventName: function() {
                return 'treasury-desk-rate-negotiation-select';
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.id;
                this.entityTwoId = 0;
                this.entityCode = item.code;
                this.cachedEntity = item;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            },
            getTitle: function( item ) {
                return `${item.code} -> ${item.customerTitle} `;
            }
        },
        props: {
            labelText: {
                default: 'Search Treasury Rate Negotiation'
            },
            titleFieldName: {
                default: 'rateNegotiationCode'
            },
            idFieldName: {
                default: 'id'
            },
            codeFieldName: {
                default: ''
            },
            code: {
                default: ""
            },
            id: {
                default: 0
            }
        }
    });

    /**
     * Treasury Desk Rate search component
     */
    Vue.component( 'treasury-desk-rate-search', {
        mixins: [searchComponentMixin],
        props: ['code','id'],
        methods: {
            getSearchUrl: function() {
                let url = `/uind/rest/accounts-finance/treasury-desk-rate/search-by-code?term=${encodeURIComponent( this.list.term )}`;
                return url;
            },
            getEmittedEventName: function() {
                return 'treasury-desk-rate-select';
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.id;
                this.entityTwoId = 0;
                this.entityCode = item.rateNegotiation.code;
                this.cachedEntity = item;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            },
            getTitle: function( item ) {
                return `${item.rateNegotiation.code} -> ${item.currencySymbol} @ PKR ${item.exchangeRatePkr}`;
            }
        },
        props: {
            labelText: {
                default: 'Search Treasury Rate Negotiation'
            },
            titleFieldName: {
                default: 'rateNegotiationCode'
            },
            idFieldName: {
                default: 'id'
            },
            codeFieldName: {
                default: ''
            },
            code: {
                default: ""
            },
            id: {
                default: 0
            }
        }
    });

    /**
     * accounts asset search component
     */
    Vue.component( 'asset-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                let url = `/uind/rest/accounts-finance/assets/search?term=${encodeURIComponent( this.list.term )}`;
                return url;
            },
            getEmittedEventName: function() {
                return 'asset-select';
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                item.description = item.description +" ( "+item.location+" ) ";
                this.entityId = item.id;
                this.entityTwoId = 0;
                this.entityCode = '';
                this.cachedEntity = item;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            },
            getTitle: function( item ) {
                return item.description +" ( "+item.location+" ) ";
            }
        },
        props: {
            labelText: {
                default: 'Search Asset'
            },
            titleFieldName: {
                default: 'title'
            },
            idFieldName: {
                default: 'id'
            },
            codeFieldName: {
                default: 'description'
            }
        }
    });

    /**
     * accounts tanker  reg search component
     */
    Vue.component( 'tanker-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                let url = `/uind/rest/accounts-finance/water-consumption?term=${encodeURIComponent( this.list.term )}`;
                return url;
            },
            getEmittedEventName: function() {
                return 'tanker-select';
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                item.description = item.registrationNumber;
                this.entityId = item.id;
                this.entityTwoId = 0;
                this.entityCode = '';
                this.cachedEntity = item;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            },
            getTitle: function( item ) {
                return item.registrationNumber;
            }
        },
        props: {
            labelText: {
                default: 'Search Tanker'
            },
            titleFieldName: {
                default: 'title'
            },
            idFieldName: {
                default: 'id'
            },
            codeFieldName: {
                default: 'description'
            }
        }
    });

    /**
     * search tags
     */
    Vue.component( 'search-doc-tags', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                let url = `/uind/rest/admin/uploaded-documents/documents/tags?term=${encodeURIComponent( this.list.term )}`;
                return url;
            },
            getEmittedEventName: function() {
                return 'tag-select';
            },
            setEntity: function( item, event ) {
                event.preventDefault();
                this.entityId = item.id;
                this.entityTwoId = 0;
                this.entityCode = '';
                this.cachedEntity = item;
                this.list.selected = item;
                this.list.term = this.getTitle( item );
                this.closeList();
            },
            getTitle: function( item ) {
                return item.tag;
            }
        },
        props: {
            labelText: {
                default: 'Search Cosmos Machines'
            },
            titleFieldName: {
                default: 'machineTitle'
            },
            idFieldName: {
                default: 'machineSerialNumber'
            },
            codeFieldName: {
                default: ''
            },
            serialNumber: {
                default: ""
            }
        }
    });


    /**
     * local invoice search
     */
    Vue.component( 'local-invoice-search', {
          mixins: [searchComponentMixin],
          props: ['customerId'],
          methods: {
              getSearchUrl: function() {
                  return `/uind/rest/accounts-finance/local/sales-receipt/search-active-invoice/?term=${encodeURIComponent( this.list.term )}&customerId=${encodeURIComponent( this.customerId )}`;
              },
              getEmittedEventName: function() {
                return 'invoice-select';
              },
              getTitle: function( invoice ) {
                return invoice.invoiceNumber + ' (' + invoice.id + ') ' + ' (CUSTOMER-' + invoice.customerId + ')';
              }
          },
          props: {
              labelText: {
                  default: 'Search Invoice'
              },
              titleFieldName: {
                  default: 'searchInvoice'
              },
              idFieldName: {
                  default: 'invoiceId'
              },
              codeFieldName: {
                  default: 'invoiceCode'
              },
              customerId: {
                default: 0
              },

          }
    });



    /*
    * bundle search
    * */
    Vue.component('bundle-search-by-barcode',{
        mixins: [searchComponentMixin],
        methods : {
            getSearchUrl : function () {
                let url = `/ctp/rest/bundles/find-bundle-by-barcode?term=${encodeURIComponent( this.list.term )}`
                return url;
            },
            getEmittedEventName: function() {
                return 'job-card-select';
            },
            getTitle: function( card ) {
                return `(${card.barcode})`;
            }
        },
        props: {
            labelText: {
                default: 'Search By Bundle'
            },
            titleFieldName: {
                default: 'cardTitle'
            },
            idFieldName: {
                default: 'jobCardId'
            },
            codeFieldName : {
                default : 'jobCardCode'
            },
            filter : {
                default : true
            },
            inputMode: {
                default : 'none'
            }
        }
    })


/*
    * job card search for reporting
    * */
    Vue.component('job-card-for-reporting',{
        mixins: [searchComponentMixin],
        methods : {
            getSearchUrl : function () {
                let url = `/ctp/rest/job-cards/search?term=${encodeURIComponent(this.list.term)}&filter=false`;
                if( ! this.filter ){
                    url += '&filter=false'
                }
                return url;
            },
            getEmittedEventName: function() {
                return 'job-card-select';
            },
            getTitle: function( card ) {
                return `(${card.code}) - ${card.createdBy}`;
            }
        },
        props: {
            labelText: {
                default: 'Search Job Card'
            },
            titleFieldName: {
                default: 'cardTitle'
            },
            idFieldName: {
                default: 'jobCardId'
            },
            codeFieldName : {
                default : 'jobCardCode'
            },
            filter : {
                default : true
            }
        }
    })


    /*
    * job card search
    * */
    Vue.component('job-card-search',{
        mixins: [searchComponentMixin],
        methods : {
            getSearchUrl : function () {
                let url = `/ctp/rest/job-cards/search?term=${encodeURIComponent( this.list.term )}`
                if( ! this.filter ){
                    url += '&filter=false'
                }
                return url;
            },
            getEmittedEventName: function() {
                return 'job-card-select';
            },
            getTitle: function( card ) {
                return `(${card.code}) - ${card.createdBy}`;
            }
        },
        props: {
            labelText: {
                default: 'Search Job Card'
            },
            titleFieldName: {
                default: 'cardTitle'
            },
            idFieldName: {
                default: 'jobCardId'
            },
            codeFieldName : {
                default : 'jobCardCode'
            },
            filter : {
                default : true
            }
        }
    })


    /*
    * master bundle search
    * */
    Vue.component('master-bundle-search',{
        mixins: [searchComponentMixin],
        methods : {
            getSearchUrl : function () {
               return `/ctp/rest/bundles/master/search?term=${encodeURIComponent( this.list.term )}&received=${this.received}`
            },
            getEmittedEventName: function() {
                return 'master-bundle-select';
            },
            getTitle: function( card ) {
                return `(${card.id}) - ${card.barcode}`;
            }
        },
        props: {
            labelText: {
                default: 'Search Master Bundle'
            },
            titleFieldName: {
                default: 'bundleTitle'
            },
            idFieldName: {
                default: 'masterBundleId'
            },
            codeFieldName : {
                default : 'masterBundleCode'
            },
            received : {
                default : false
            },
            inputMode: {
                default : 'none'
            }
        }
    })

    /*
    *  stitched offline item
    * */
    Vue.component( 'stitching-offline-item',{
        mixins: [searchComponentMixin],
        methods : {
            getSearchUrl : function () {
                return `/ctp/rest/stitching-offline-items/search?term=${encodeURIComponent( this.list.term )}`
            },
            getEmittedEventName: function() {
                return 'stitching-offline-item-select';
            },
            getTitle: function( item ) {
                return `${item.id}  - ( ${item.barcode} )`;
            }
        },
        props: {
            labelText: {
                default: 'Search Stitching Item'
            },
            titleFieldName: {
                default: 'title'
            },
            idFieldName: {
                default: 'id'
            },
            codeFieldName : {
                default : 'code'
            },
            inputMode: {
                default : 'none'
            }
        }

    });

    /*
     * search po
     * */
    Vue.component('search-ctp-po',{
        mixins: [searchComponentMixin],
        data: {
            purchaseOrderCode: '',
        },
        methods : {
            getSearchUrl : function () {
                return `/ctp/rest/purchase-orders/ctp-po-search?term=${encodeURIComponent( this.list.term )}`
            },
            getEmittedEventName: function() {
                return 'select-po';
            },
            getTitle: function( po ) {
                this.purchaseOrderCode = po.purchaseOrderCode;
                return this.purchaseOrderCode;
            }
        },
        props: {
            labelText: {
                default: 'Search PO '
            },
            titleFieldName: {
                default: 'poCode'
            },
            idFieldName: {
                default: 'poId'
            },
            codeFieldName : {
                default : 'poCode'
            },
            received : {
                default : false
            },
            inputMode: {
                default : 'none'
            },
        }
    })


    Vue.component('search-item', {
    props: {
        label: {
            type: String,
            default: 'Search Finished Item'
        },
        url: {
            type: String,
            default: ''
        },
        isSegregated: {
            type: Boolean,
            default: false
        },
        debounceTime: {
            type: Number,
            default: 500
        }
    },
    data() {
        return {
            searchTerm: '',
            timeout: null
        };
    },
    methods: {
        handleInput() {
            clearTimeout(this.timeout);
            this.timeout = setTimeout(() => {
                this.fetchData();
            }, this.debounceTime);
        },
        async fetchData() {
            if (this.searchTerm.trim() === '') return;
            try {
                const response = await fetch(`${this.url}?term=${encodeURIComponent(this.searchTerm)}&is-segregated=${this.isSegregated}`);
                const data = await response.json();

                if (data.length > 0) {
                    const selectedItem = data[0];
                    this.$emit('finished-item-select', selectedItem.id, selectedItem);
                    this.searchTerm = `${selectedItem.id} - (${selectedItem.barcode})`;
                    setTimeout(() => {
                        this.searchTerm = '';
                    }, 500);
                } else {
                setTimeout(() => {
                    this.searchTerm = '';
                }, 500);
                }
            } catch (error) {
                console.error('Error fetching search results:', error);
            }
        }
    },

    template: `
        <div class="search-container">
            <label>{{ label }}</label>
            <input type="text" class="form-control"
                v-model="searchTerm"
                @input="handleInput"
                placeholder="Scan QR"
                autocomplete="off"
                inputmode="none"
                autofocus>
        </div>
    `
});

    /*
    * bundle search component
    * */
    Vue.component( 'bundle-search',{
        mixins: [searchComponentMixin],
        methods : {
            getSearchUrl : function () {
                return `/ctp/rest/bundles/search?term=${encodeURIComponent( this.list.term )}`
            },
            getEmittedEventName: function() {
                return 'bundle-select';
            },
            getTitle: function( bundle ) {
                return ` ${bundle.barcode} - ${bundle.type} -  ( JC:${bundle.jobCardId} )`;
            }
        },
        props: {
            labelText: {
                default: 'Search Bundle'
            },
            titleFieldName: {
                default: 'bundleTitle'
            },
            idFieldName: {
                default: 'bundleId'
            },
            codeFieldName : {
                default : 'bundleCode'
            },
            inputMode: {
                default : 'none'
            }
        }
    })

    /*
    * tms task search search
    * */
    Vue.component( 'tms-task-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                let url = `/uind/rest/tms/tasks/search?term=${encodeURIComponent( this.list.term )}`;
                if ( !! this.projectId ) {
                    url += `&project-id=${this.projectId}`;
                }
                if ( !! this.currentTaskId ) {
                    url += `&current-task-id=${this.currentTaskId}`;
                }
                return url;
            },
            getEmittedEventName: function() {
                return 'tms-task-select';
            },
            getTitle: function( task ) {
                return `(${task.code}) - ${task.title}`;
            }
        },
        props: {
            labelText: {
                default: 'Search Task'
            },
            titleFieldName: {
                default: 'taskTitle'
            },
            idFieldName: {
                default: 'taskId'
            },
            codeFieldName: {
                default: 'taskCode'
            },
            projectId: {
                default: null
            },
            currentTaskId: {
                default: null
            }
        }
    });

    /**
     * document component
     */
    Vue.component( 'document', {
        props: ['index', 'name'],
        template: `
            <div class="form-row">
                <div class="col-sm-3 form-group">
                    <input type="file" class="form-control-file" v-bind:name="name">
                </div>
            </div>
        `
    });

    /**
     * file input
     */
    Vue.component( 'file-input',
        {
        props: {
            index: {
                default: 0
            },
            nameFieldTitle: {
                default: 'files'
            },
            accepts: {
                default: 'image/png, image/gif, image/jpeg'
            },
            columns: {
                default: 2
            },
            required: {
                type: Boolean,
                default: false
            }
        },
        methods: {
            handleFileRemove: function( index, e ) {
                e.preventDefault();
                this.$emit( 'file-removed', index );
            },

            handleFileChange(e) {
                const file = e.target.files[0];
                this.$emit('file-selected', { file, index: this.index });
            }
        },
        template: `
            <div class="form-row">
                <div class="form-group" v-bind:class="'col-sm-' + columns">
                    <input type="file" 
                           class="form-control-file" 
                           v-bind:accept="accepts" 
                           v-bind:name="nameFieldTitle + '[' + index + ']'"
                           @change="handleFileChange">
                </div>
                <div class="col-sm-1 form-group">
                    <a href="#" class="text-danger font-sm" v-on:click="handleFileRemove( index, $event )">Remove</a>
                </div>
            </div>
        `
    });

    /**
     * file input without indexing
     */
    Vue.component( 'non-idx-file-input',
        {
            props: {
                index: {
                    default: 0
                },
                nameFieldTitle: {
                    default: 'files'
                },
                accepts: {
                    default: 'image/png, image/gif, image/jpeg'
                },
                columns: {
                    default: 2
                }
            },
            methods: {
                handleFileRemove: function( index, e ) {
                    e.preventDefault();
                    this.$emit( 'file-removed', index );
                }
            },
            template: `
            <div class="form-row">
                <div class="form-group" v-bind:class="'col-sm-' + columns">
                    <input type="file" class="form-control-file" v-bind:accept="accepts" v-bind:name="nameFieldTitle">
                </div>
                <div class="col-sm-1 form-group">
                    <a href="#" class="text-danger font-sm" v-on:click="handleFileRemove( index, $event )">Remove</a>
                </div>
            </div>
        `
        });

    /**
     * local sale notification
     */
    Vue.component( 'local-sale-notification', {
            data: function() {
                return {
                    openAlert: false
                }
            },
            props: {
                visible: {
                    default: true
                },
            },
            methods: {
                getNumberOfPendingRequests: function( ) {
                    return window.ctp.pendingApprovalSaleRequests;
                },
                closePendingRequestAlert: function() {
                debugger;
                    openAlert = false;
                },
            },
            template: `
                <div style="position:absolute;bottom:0;right:20px;" class="alert alert-primary d-flex align-items-center" role="alert">

                  <div>
                    you have {{ getNumberOfPendingRequests() }} pending approval sale request
                  </div>
                  <button type="button" class="close" v-on:click="$emit('close-pending-request-alert')"><span>×</span></button>
                </div>
            `,
            mounted: function() {}
        });

    /**
     * dispatch requisition search component
     */
    Vue.component( 'dispatch-requisition-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/uic/dispatch-requisitions/search?term=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'dispatch-requisition-select';
            },
            getTitle: function( po ) {
                return po.code;
            }
        },
        props: {
            labelText: {
                default: 'Search Dispatch Requisition'
            },
            titleFieldName: {
                default: 'dispatchRequisitionTitle'
            },
            idFieldName: {
                default: 'dispatchRequisitionId'
            },
            codeFieldName: {
                default: 'dispatchRequisitionCode'
            }
        }
    });

    /**
     * fps customer search component
     */
    Vue.component( 'fps-customer-search', {
        mixins: [searchComponentMixin],
        methods: {
            getSearchUrl: function() {
                return `/uind/rest/fair-price-shop/customers?title=${encodeURIComponent( this.list.term )}`;
            },
            getEmittedEventName: function() {
                return 'fps-customer-select';
            },
            getTitle: function( customer ) {
                return customer.title;
            }
        },
        props: {
            labelText: {
                default: 'Search Customer'
            },
            titleFieldName: {
                default: 'dispatchRequisitionTitle'
            },
            idFieldName: {
                default: 'customerId'
            },
            codeFieldName: {
                default: 'dispatchRequisitionCode'
            }
        }
    });

}


