diff --git a/application/recipes/__pycache__/database_recipes.cpython-313.pyc b/application/recipes/__pycache__/database_recipes.cpython-313.pyc index 72db4bb..a2753f9 100644 Binary files a/application/recipes/__pycache__/database_recipes.cpython-313.pyc and b/application/recipes/__pycache__/database_recipes.cpython-313.pyc differ diff --git a/application/recipes/__pycache__/recipes_api.cpython-313.pyc b/application/recipes/__pycache__/recipes_api.cpython-313.pyc index caa1dd5..cf7a6fc 100644 Binary files a/application/recipes/__pycache__/recipes_api.cpython-313.pyc and b/application/recipes/__pycache__/recipes_api.cpython-313.pyc differ diff --git a/application/recipes/database_recipes.py b/application/recipes/database_recipes.py index 56e374d..39bfe18 100644 --- a/application/recipes/database_recipes.py +++ b/application/recipes/database_recipes.py @@ -125,6 +125,33 @@ def getPicturePath(site:str, payload:tuple): cur.execute(f"SELECT picture_path FROM {site}_recipes WHERE id=%s;", payload) rows = cur.fetchone()[0] return rows + +def getFuzzyMatch(site: str, payload, convert=True, conn=None): + matches = [] + self_conn = False + sql = f"SELECT id, item_name FROM {site}_items WHERE LOWER(item_name) ILIKE '%%' || LOWER(TRIM(%s)) || '%%';" + try: + if not conn: + database_config = config.config() + conn = psycopg2.connect(**database_config) + conn.autocommit = True + self_conn = True + print(payload) + with conn.cursor() as cur: + cur.execute(sql, (payload,)) + rows = cur.fetchall() + print(rows) + if rows and convert: + matches = [postsqldb.tupleDictionaryFactory(cur.description, row) for row in rows] + elif rows and not convert: + matches = rows + + if self_conn: + conn.close() + + return matches + except Exception as error: + return error def selectSiteTuple(payload, convert=True): """ payload (tuple): (site_name,) """ diff --git a/application/recipes/recipes_api.py b/application/recipes/recipes_api.py index bb08bc8..2ea447c 100644 --- a/application/recipes/recipes_api.py +++ b/application/recipes/recipes_api.py @@ -228,7 +228,6 @@ def saveRecipeItem(): return jsonify({'recipe': recipe, 'error': False, 'message': f'Recipe Item {updated_line['item_name']} was updated successful!'}) return jsonify({'recipe': recipe, 'error': True, 'message': f'method {request.method} not allowed!'}) - @recipes_api.route('/api/receiptRecipe', methods=["POST"]) @access_api.login_required def receiptRecipe(): @@ -239,4 +238,14 @@ def receiptRecipe(): if not status: return jsonify(status=400, message=message) return jsonify(status=201, message="Recipe Transacted Successfully!") - return jsonify(status=405, message=f"{request.method} is not an allowed method on this endpoint!") \ No newline at end of file + return jsonify(status=405, message=f"{request.method} is not an allowed method on this endpoint!") + +@recipes_api.route('/api/fuzzy-match') +@access_api.login_required +def fuzzyMatchItems(): + query = request.args.get('q', '').strip().lower() + site_name = session['selected_site'] + print(query) + matches = database_recipes.getFuzzyMatch(site_name, query, convert=False) + return jsonify(status=201, message="matches fetched Successfully!", matches=matches) + \ No newline at end of file diff --git a/application/recipes/static/js/recipeEditHandler.js b/application/recipes/static/js/recipeEditHandler.js index f02b709..03d500c 100644 --- a/application/recipes/static/js/recipeEditHandler.js +++ b/application/recipes/static/js/recipeEditHandler.js @@ -379,6 +379,62 @@ async function openNewSKUModal() { UIkit.modal(itemsModal).show(); } + + +// Suggestions for new sku Model +var fullsuggestions = ''; +var shortsuggestions = ''; +async function showMoreSuggestions(){ + document.getElementById('similar-items-list').innerHTML = fullsuggestions; +} + +async function showLessSuggestions(){ + document.getElementById('similar-items-list').innerHTML = shortsuggestions; +} + +document.getElementById('newSKUName').addEventListener('input', async function(e) { + let query = e.target.value.trim(); + if(query.length === 0) { + document.getElementById('suggestions').innerHTML = ''; + return; + } + let resp = await fetch(`/recipes/api/fuzzy-match?q=${encodeURIComponent(query)}`); + let data = await resp.json(); + let matches = data.matches + let total_matches = 3 + let html = ` Similar item(s) found: ` + let fullhtml = ' Similar item(s) found: ' + + if(matches.length){ + document.getElementById('item-warning').hidden = false + if (matches.length < total_matches){ + total_matches = matches.length + } + + for (let i = 0; i < total_matches; i++){ + html = html + `${matches[i][1]}, ` + fullhtml = fullhtml + `${matches[i][1]}, ` + shortsuggestions = html + fullsuggestions = fullhtml + } + + for (let i = total_matches + 1; i < matches.length; i++){ + fullhtml = fullhtml + `${matches[i][1]}, ` + fullsuggestions = fullhtml + `Show less` + } + + if(matches.length > 3 ){ + html = html + `${matches.length - (total_matches+1)} more matches...` + } + shortsuggestions = html + document.getElementById('similar-items-list').innerHTML = html; + } else { + document.getElementById('item-warning').hidden = true + document.getElementById('similar-items-list').innerHTML = ''; + } +}); + + let pagination_current = 1; let pagination_end = 10; let search_string = ""; diff --git a/application/recipes/templates/recipe_edit.html b/application/recipes/templates/recipe_edit.html index 36dacd5..42a7342 100644 --- a/application/recipes/templates/recipe_edit.html +++ b/application/recipes/templates/recipe_edit.html @@ -341,8 +341,13 @@
Similar item(s) found:
+