From 1a39082514e0ce3929ad14b9d37d1e6e81decae8 Mon Sep 17 00:00:00 2001 From: Deeman Date: Sat, 21 Feb 2026 01:15:25 +0100 Subject: [PATCH] Add sidenav layout for authenticated dashboard - Create dashboard_base.html: standalone app shell with 56px sticky header (logo + user email + sign out), 220px left sidebar with Overview/Countries/Settings nav items (SVG icons, active state via request.path), and fixed mobile bottom tab bar (md:hidden) - Add CSS component classes: .app-shell, .app-header, .app-sidebar, .sidebar-item, .app-content, .mobile-bottom-nav, .mobile-nav-item - Extract feedback widget into _feedback_widget.html partial; include from both base.html and dashboard_base.html - Switch index.html, countries.html, settings.html to extend dashboard_base.html; remove
wrappers - Remove "Back to Dashboard" button from countries.html (sidebar provides persistent navigation) Co-Authored-By: Claude Sonnet 4.6 --- .../dashboard/templates/countries.html | 5 +- .../dashboard/templates/dashboard_base.html | 130 ++++++++++++++++++ .../beanflows/dashboard/templates/index.html | 4 +- .../dashboard/templates/settings.html | 4 +- web/src/beanflows/static/css/input.css | 130 ++++++++++++++++++ .../beanflows/templates/_feedback_widget.html | 86 ++++++++++++ web/src/beanflows/templates/base.html | 87 +----------- 7 files changed, 350 insertions(+), 96 deletions(-) create mode 100644 web/src/beanflows/dashboard/templates/dashboard_base.html create mode 100644 web/src/beanflows/templates/_feedback_widget.html diff --git a/web/src/beanflows/dashboard/templates/countries.html b/web/src/beanflows/dashboard/templates/countries.html index 0e3f9ca..97dc023 100644 --- a/web/src/beanflows/dashboard/templates/countries.html +++ b/web/src/beanflows/dashboard/templates/countries.html @@ -1,4 +1,4 @@ -{% extends "base.html" %} +{% extends "dashboard_base.html" %} {% block title %}Country Comparison — {{ config.APP_NAME }}{% endblock %} @@ -7,7 +7,6 @@ {% endblock %} {% block content %} -
{% endif %} - Back to Dashboard -
{% endblock %} {% block scripts %} diff --git a/web/src/beanflows/dashboard/templates/dashboard_base.html b/web/src/beanflows/dashboard/templates/dashboard_base.html new file mode 100644 index 0000000..bf9f252 --- /dev/null +++ b/web/src/beanflows/dashboard/templates/dashboard_base.html @@ -0,0 +1,130 @@ + + + + + + {% block title %}{{ config.APP_NAME }}{% endblock %} + + + + + + + + + + + {% block head %}{% endblock %} + + + + +
+ + +
+ +
+ {% if session.get('is_admin') %} + + {% endif %} + {{ user.email }} + +
+
+ + +
+ + + + + +
+ {% with messages = get_flashed_messages(with_categories=true) %} + {% if messages %} + {% for category, message in messages %} +
+ {{ message }} +
+ {% endfor %} + {% endif %} + {% endwith %} + + {% block content %}{% endblock %} +
+
+
+ + + + + + + + {% include "_feedback_widget.html" %} + + {% block scripts %}{% endblock %} + + diff --git a/web/src/beanflows/dashboard/templates/index.html b/web/src/beanflows/dashboard/templates/index.html index d180348..eec2836 100644 --- a/web/src/beanflows/dashboard/templates/index.html +++ b/web/src/beanflows/dashboard/templates/index.html @@ -1,4 +1,4 @@ -{% extends "base.html" %} +{% extends "dashboard_base.html" %} {% block title %}Dashboard — {{ config.APP_NAME }}{% endblock %} @@ -7,7 +7,6 @@ {% endblock %} {% block content %} -
-
{% endblock %} {% block scripts %} diff --git a/web/src/beanflows/dashboard/templates/settings.html b/web/src/beanflows/dashboard/templates/settings.html index d2c0e32..57d5f6f 100644 --- a/web/src/beanflows/dashboard/templates/settings.html +++ b/web/src/beanflows/dashboard/templates/settings.html @@ -1,9 +1,8 @@ -{% extends "base.html" %} +{% extends "dashboard_base.html" %} {% block title %}Settings — {{ config.APP_NAME }}{% endblock %} {% block content %} -
-
{% endblock %} diff --git a/web/src/beanflows/static/css/input.css b/web/src/beanflows/static/css/input.css index 9658f47..31951b0 100644 --- a/web/src/beanflows/static/css/input.css +++ b/web/src/beanflows/static/css/input.css @@ -153,6 +153,136 @@ @apply max-w-6xl mx-auto px-4 sm:px-6 lg:px-8; } + /* ── App Shell (authenticated dashboard layout) ── */ + .app-shell { + display: flex; + flex-direction: column; + min-height: 100vh; + } + .app-header { + position: sticky; + top: 0; + z-index: 50; + height: 56px; + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 1.5rem; + background: rgba(255, 251, 245, 0.92); + backdrop-filter: blur(14px); + -webkit-backdrop-filter: blur(14px); + border-bottom: 1px solid rgba(232, 223, 213, 0.7); + flex-shrink: 0; + } + .app-header-right { + display: flex; + align-items: center; + gap: 1rem; + } + .app-header-email { + font-size: 0.8125rem; + color: var(--color-stone); + display: none; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 200px; + } + @media (min-width: 640px) { + .app-header-email { display: block; } + } + .app-body { + display: flex; + flex: 1; + min-height: 0; + } + .app-sidebar { + width: 220px; + flex-shrink: 0; + padding: 1.25rem 0.75rem; + border-right: 1px solid var(--color-parchment); + position: sticky; + top: 56px; + height: calc(100vh - 56px); + overflow-y: auto; + display: none; + } + @media (min-width: 768px) { + .app-sidebar { display: block; } + } + .sidebar-item { + display: flex; + align-items: center; + gap: 0.625rem; + padding: 0.5rem 0.75rem; + border-radius: 0.625rem; + font-size: 0.875rem; + font-weight: 500; + color: var(--color-stone-dark); + text-decoration: none; + transition: background 0.12s, color 0.12s; + margin-bottom: 2px; + } + .sidebar-item:hover { + background: var(--color-latte); + color: var(--color-espresso); + } + .sidebar-item.active { + background: rgba(180, 83, 9, 0.08); + color: var(--color-copper); + font-weight: 600; + } + .sidebar-item.active svg { + stroke: var(--color-copper); + } + .app-content { + flex: 1; + min-width: 0; + padding: 2rem 2rem 5rem; + } + @media (min-width: 768px) { + .app-content { padding: 2rem 2.5rem 2rem; } + } + + /* ── Mobile bottom navigation ── */ + .mobile-bottom-nav { + position: fixed; + bottom: 0; + left: 0; + right: 0; + height: 56px; + display: flex; + align-items: stretch; + background: rgba(255, 251, 245, 0.97); + backdrop-filter: blur(14px); + -webkit-backdrop-filter: blur(14px); + border-top: 1px solid rgba(232, 223, 213, 0.7); + z-index: 50; + } + @media (min-width: 768px) { + .mobile-bottom-nav { display: none; } + } + .mobile-nav-item { + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 3px; + font-size: 0.6875rem; + font-weight: 500; + color: var(--color-stone); + text-decoration: none; + transition: color 0.12s; + } + .mobile-nav-item:hover, + .mobile-nav-item.active { + color: var(--color-copper); + } + .mobile-nav-item.active svg { + stroke: var(--color-copper); + } + /* ── Display headings (Fraunces serif) ── */ .heading-display { font-family: var(--font-display); diff --git a/web/src/beanflows/templates/_feedback_widget.html b/web/src/beanflows/templates/_feedback_widget.html new file mode 100644 index 0000000..807221b --- /dev/null +++ b/web/src/beanflows/templates/_feedback_widget.html @@ -0,0 +1,86 @@ + +
+ + +
+

Share feedback

+

What's on your mind?

+
+ + + +
+
+ +
+
+
+
+ + + + diff --git a/web/src/beanflows/templates/base.html b/web/src/beanflows/templates/base.html index 4fa2fb5..2fb9e5e 100644 --- a/web/src/beanflows/templates/base.html +++ b/web/src/beanflows/templates/base.html @@ -96,92 +96,7 @@ - -
- - -
-

Share feedback

-

What's on your mind?

-
- - - -
-
- -
-
-
-
- - - - + {% include "_feedback_widget.html" %} {% block scripts %}{% endblock %}