diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/point_of_sale/static/src/js/Misc/SearchBar.js | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/point_of_sale/static/src/js/Misc/SearchBar.js')
| -rw-r--r-- | addons/point_of_sale/static/src/js/Misc/SearchBar.js | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/addons/point_of_sale/static/src/js/Misc/SearchBar.js b/addons/point_of_sale/static/src/js/Misc/SearchBar.js new file mode 100644 index 00000000..e9f56fea --- /dev/null +++ b/addons/point_of_sale/static/src/js/Misc/SearchBar.js @@ -0,0 +1,115 @@ +odoo.define('point_of_sale.SearchBar', function (require) { + 'use strict'; + + const { useState, useExternalListener } = owl.hooks; + const PosComponent = require('point_of_sale.PosComponent'); + const Registries = require('point_of_sale.Registries'); + + /** + * This is a simple configurable search bar component. It has search fields + * and selection filter. Search fields allow the users to specify the type + * of their searches. The filter is a dropdown menu for selection. Depending on + * user's action, this component emits corresponding event with the action + * information (payload). + * + * TODO: This component can be made more generic and be able to replace + * all the search bars across pos ui. + * + * @prop {{ + * config: { + * searchFields: string[], + * filter: { show: boolean, options: string[] } + * }, + * placeholder: string, + * }} + * @emits search @payload { fieldValue: string, searchTerm: '' } + * @emits filter-selected @payload { filter: string } + * + * NOTE: The payload of the emitted event is accessible via the `detail` + * field of the event. + */ + class SearchBar extends PosComponent { + constructor() { + super(...arguments); + this.config = this.props.config; + this.state = useState({ + searchInput: '', + selectedFieldId: this.config.searchFields.length ? 0 : null, + showSearchFields: false, + showFilterOptions: false, + selectedFilter: this.config.filter.options[0] || this.env._t('Select'), + }); + useExternalListener(window, 'click', this._hideOptions); + } + selectFilter(option) { + this.state.selectedFilter = option; + this.trigger('filter-selected', { filter: this.state.selectedFilter }); + } + get placeholder() { + return this.props.placeholder; + } + /** + * When vertical arrow keys are pressed, select fields for searching. + * When enter key is pressed, trigger search event if there is searchInput. + */ + onKeydown(event) { + if (['ArrowUp', 'ArrowDown'].includes(event.key)) { + event.preventDefault(); + this.state.selectedFieldId = this._fieldIdToSelect(event.key); + } else if (event.key === 'Enter') { + this.trigger('search', { + fieldValue: this.config.searchFields[this.state.selectedFieldId], + searchTerm: this.state.searchInput, + }); + this.state.showSearchFields = false; + } else { + if (this.state.selectedFieldId === null && this.config.searchFields.length) { + this.state.selectedFieldId = 0; + } + this.state.showSearchFields = true; + } + } + /** + * Called when a search field is clicked. + */ + onClickSearchField(id) { + this.state.showSearchFields = false; + this.trigger('search', { + fieldValue: this.config.searchFields[id], + searchTerm: this.state.searchInput, + }); + } + /** + * Given an arrow key, return the next selectedFieldId. + * E.g. If the selectedFieldId is 1 and ArrowDown is pressed, return 2. + * + * @param {string} key vertical arrow key + */ + _fieldIdToSelect(key) { + const length = this.config.searchFields.length; + if (!length) return null; + if (this.state.selectedFieldId === null) return 0; + const current = this.state.selectedFieldId || length; + return (current + (key === 'ArrowDown' ? 1 : -1)) % length; + } + _hideOptions() { + this.state.showFilterOptions = false; + this.state.showSearchFields = false; + } + } + SearchBar.template = 'point_of_sale.SearchBar'; + SearchBar.defaultProps = { + config: { + searchFields: [], + filter: { + show: false, + options: [], + }, + }, + placeholder: 'Search ...', + }; + + Registries.Component.add(SearchBar); + + return SearchBar; +}); |
