summaryrefslogtreecommitdiff
path: root/addons/point_of_sale/static/src/js/Misc/SearchBar.js
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/point_of_sale/static/src/js/Misc/SearchBar.js
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (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.js115
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;
+});