From 2e097e95f28c9fcb3df182a325e877e75a9bd21f Mon Sep 17 00:00:00 2001 From: Nguyen Ngo Date: Wed, 19 Nov 2025 07:52:00 -0500 Subject: [PATCH] Enhanced dashboard, show maximum 12 qr codes, add View All button, and View All project's code page (new) --- app.py | 39 +++ templates/dashboard.html | 35 +- templates/project_qr_codes.html | 572 ++++++++++++++++++++++++++++++++ 3 files changed, 645 insertions(+), 1 deletion(-) create mode 100644 templates/project_qr_codes.html diff --git a/app.py b/app.py index 5d1308e..4c019ef 100644 --- a/app.py +++ b/app.py @@ -1703,6 +1703,45 @@ def dashboard(): flash('Error loading dashboard. Please try again.', 'error') return redirect(url_for('login')) +@app.route('/project//qr-codes') +@login_required +def project_qr_codes(project_id): + """ + Paginated view of all QR codes for a specific project + Shows 20 QR codes per page with pagination controls + """ + try: + # Get the project + project = Project.query.get_or_404(project_id) + + # Get page number from query parameter (default to 1) + page = request.args.get('page', 1, type=int) + per_page = 20 # QR codes per page + + # Query QR codes for this project with pagination + pagination = QRCode.query.filter_by(project_id=project_id)\ + .order_by(QRCode.created_date.desc())\ + .paginate(page=page, per_page=per_page, error_out=False) + + qr_codes = pagination.items + + # Log access + logger_handler.logger.info( + f"User {session['username']} viewed project '{project.name}' QR codes page {page}: " + f"{len(qr_codes)} QR codes displayed (total: {pagination.total})" + ) + + return render_template('project_qr_codes.html', + project=project, + qr_codes=qr_codes, + pagination=pagination) + + except Exception as e: + logger_handler.log_database_error('project_qr_codes_view', e) + print(f"Error loading project QR codes: {e}") + flash('Error loading project QR codes. Please try again.', 'error') + return redirect(url_for('dashboard')) + @app.route('/api/dashboard/stats') @login_required def dashboard_stats_api(): diff --git a/templates/dashboard.html b/templates/dashboard.html index 9ac605e..83584e2 100644 --- a/templates/dashboard.html +++ b/templates/dashboard.html @@ -160,6 +160,26 @@ Management{% endblock %} {% block extra_head %} transform: rotate(180deg); } + .view-all-qr-btn { + display: inline-flex; + align-items: center; + gap: 0.375rem; + padding: 0.375rem 0.75rem; + font-size: 0.75rem; + font-weight: 500; + white-space: nowrap; + height: 20px; + } + + .view-all-qr-btn i { + font-size: 0.7rem; + } + + .view-all-qr-btn:hover { + transform: translateY(-1px); + box-shadow: 0 2px 8px rgba(37, 99, 235, 0.2); + } + .project-qr-codes { max-height: 0; overflow: hidden; @@ -1076,6 +1096,19 @@ Management{% endblock %} {% block extra_head %} {{ 'Active' if project.active_status else 'Inactive' }} + + + {% if project_qr_codes|length > 12 %} + + + View All + + {% endif %} + @@ -1086,7 +1119,7 @@ Management{% endblock %} {% block extra_head %}
{% if project_qr_codes %}
- {% for qr in project_qr_codes %} + {% for qr in project_qr_codes[:12] %}
+ +{% endblock %} {% block content %} +
+ +
+
+
+ +
+
+

{{ project.name }}

+ {% if project.description %} +

{{ project.description }}

+ {% endif %} +
+ + + Back to Dashboard + +
+ +
+
+ + {{ pagination.total }} Total QR Codes +
+
+ + {{ qr_codes|selectattr('active_status', 'equalto', + True)|list|length }} + Active +
+
+ + {{ qr_codes|selectattr('active_status', 'equalto', + False)|list|length }} + Inactive +
+
+ + Page {{ pagination.page }} of + {{ pagination.pages }} +
+
+
+ + + {% if qr_codes %} +
+ {% for qr in qr_codes %} +
+
+
+ QR Code for {{ qr.name }} +
+ +
+

{{ qr.name }}

+
+ + {{ qr.location }} +
+ + {% if qr.location_address %} +
+ + {{ qr.location_address }} +
+ {% endif %} + +
+ + {{ get_qr_code_checkin_count(qr.id) }} check-ins +
+ + {% if qr.qr_url %} +
+ + {{ qr.qr_url[:50] }}{% if qr.qr_url|length > 50 %}...{% endif + %} +
+ {% endif %} + + + + {{ 'Active' if qr.active_status else 'Inactive' }} + +
+
+ + + {% if session.role == 'admin' %} +
+ + Edit + + +
+ {% endif %} +
+ {% endfor %} +
+ + + {% if pagination.pages > 1 %} +
+
+ Showing {{ (pagination.page - 1) * pagination.per_page + 1 }} to {{ + [pagination.page * pagination.per_page, pagination.total]|min }} of {{ + pagination.total }} QR codes +
+ +
    + +
  • + {% if pagination.page == 1 %} + + {% else %} + + + + {% endif %} +
  • + + +
  • + {% if pagination.has_prev %} + + + + {% else %} + + {% endif %} +
  • + + + {% for page_num in pagination.iter_pages(left_edge=1, right_edge=1, + left_current=2, right_current=2) %} {% if page_num %} {% if page_num == + pagination.page %} +
  • + {{ page_num }} +
  • + {% else %} +
  • + + {{ page_num }} + +
  • + {% endif %} {% else %} +
  • + ... +
  • + {% endif %} {% endfor %} + + +
  • + {% if pagination.has_next %} + + + + {% else %} + + {% endif %} +
  • + + +
  • + {% if pagination.page == pagination.pages %} + + {% else %} + + + + {% endif %} +
  • +
+
+ {% endif %} {% else %} + +
+ +

No QR Codes Found

+

This project doesn't have any QR codes yet.

+ {% if session.role == 'admin' %} + + Create QR Code + + {% endif %} +
+ {% endif %} +
+ + +{% include 'partials/_qr_modal.html' ignore missing %} {% endblock %} {% block +extra_scripts %} + +{% endblock %}