diff --git a/app/app.py b/app/app.py index 71af7af..4eb5038 100644 --- a/app/app.py +++ b/app/app.py @@ -42,7 +42,7 @@ app.register_blueprint(canvas_bp) @app.route('/') def home(): """Redirect to login if not authenticated, otherwise show home""" - if 'user_id' not in session: + if 'username' not in session: return redirect(url_for('auth.login_page')) # If user hasn't selected a location yet, redirect to selection diff --git a/app/blueprints/products.py b/app/blueprints/products.py index d2716dc..162d8ef 100644 --- a/app/blueprints/products.py +++ b/app/blueprints/products.py @@ -30,6 +30,15 @@ def advanced_search(): """Serve the advanced search page""" return render_template('advanced_search.html') +@products_bp.route('/list') +@login_required +def product_list(): + """Serve the product listing page with search and pagination""" + # Check if user has permission to manage products + if not can_user('manage_products'): + return redirect(url_for('products.product_finder')) + return render_template('product_list.html') + @products_bp.route('/manage') @login_required def product_manager(): @@ -67,6 +76,58 @@ def get_products(): 'products': products }) +@products_bp.route('/api/products/search', methods=['GET']) +@login_required +def search_products(): + """Search products with pagination and filtering""" + # Get query parameters + search_query = request.args.get('q', '').strip().lower() + page = int(request.args.get('page', 1)) + per_page = int(request.args.get('per_page', 20)) + location = request.args.get('location') + status_filter = request.args.get('status', 'all') # 'all', 'active', 'discontinued' + + # Get all products + all_products = da.get_all_products(location=location) + + # Filter by search query (description and product code) + if search_query: + filtered_products = [ + p for p in all_products + if search_query in p.get('description', '').lower() + or search_query in p.get('productCode', '').lower() + ] + else: + filtered_products = all_products + + # Filter by status + if status_filter == 'active': + filtered_products = [p for p in filtered_products if not p.get('discontinued', False)] + elif status_filter == 'discontinued': + filtered_products = [p for p in filtered_products if p.get('discontinued', False)] + + # Calculate pagination + total_products = len(filtered_products) + total_pages = (total_products + per_page - 1) // per_page if per_page > 0 else 1 + start_idx = (page - 1) * per_page + end_idx = start_idx + per_page + + # Get page slice + products_page = filtered_products[start_idx:end_idx] + + return jsonify({ + 'status': 'success', + 'products': products_page, + 'pagination': { + 'page': page, + 'per_page': per_page, + 'total_products': total_products, + 'total_pages': total_pages, + 'has_prev': page > 1, + 'has_next': page < total_pages + } + }) + @products_bp.route('/api/products/', methods=['GET']) @login_required def get_product(product_code): diff --git a/app/templates/product_finder.html b/app/templates/product_finder.html index 5f2d20f..4784fc3 100644 --- a/app/templates/product_finder.html +++ b/app/templates/product_finder.html @@ -79,10 +79,10 @@ let manageProductsLink = ''; if (data.permissions && data.permissions.manage_products) { - manageProductsLink = ` | Manage Products`; + title="Product Manager">Product Manager`; } document.getElementById('userLocationInfo').innerHTML = diff --git a/app/templates/product_list.html b/app/templates/product_list.html new file mode 100644 index 0000000..999dde1 --- /dev/null +++ b/app/templates/product_list.html @@ -0,0 +1,630 @@ + + + + + + Product List - Product Finder + + + + +
+
+
+

📦 Product List

+ +
+ +
+ + +
+ + +
+ +
+ + +
+
+ +
+ Loading products... +
+
+ +
+
⏳ Loading products...
+
+ +
+
+ + + + diff --git a/app/templates/product_manager.html b/app/templates/product_manager.html index 1a8f8ef..effb09d 100644 --- a/app/templates/product_manager.html +++ b/app/templates/product_manager.html @@ -259,8 +259,9 @@

Product Manager

@@ -756,7 +757,47 @@ } // Initialize on page load - document.addEventListener('DOMContentLoaded', loadProductAttributes); + document.addEventListener('DOMContentLoaded', async () => { + await loadProductAttributes(); + + // Check if a product code was passed via URL parameter + const urlParams = new URLSearchParams(window.location.search); + const productCode = urlParams.get('product'); + if (productCode) { + await loadProductByCode(productCode); + } + }); + + // Load a product by its code + async function loadProductByCode(productCode) { + try { + const response = await fetch(`/quiz/api/products/${encodeURIComponent(productCode)}`); + const data = await response.json(); + + if (data.status === 'success' && data.product) { + // Populate the form with the product data + const product = data.product; + + // Fill in basic fields + document.getElementById('location').value = product.location || ''; + document.getElementById('description').value = product.description || ''; + document.getElementById('productCode').value = product.productCode || ''; + document.getElementById('category').value = product.category || ''; + + // Set discontinued status + document.getElementById('discontinued').checked = product.discontinued || false; + + // Note: You may need to add more field mappings based on your form structure + // This is a basic implementation to get started + + console.log('Loaded product:', product); + } else { + console.error('Product not found:', productCode); + } + } catch (error) { + console.error('Error loading product:', error); + } + }