38686-vm/core/templates/base.html
Konrad du Plessis 82c1906607 Redesign UI with premium orange theme, sidebar nav, and bottom tab bar
Replace the green accent with a warm orange/amber palette and switch to a
dark-first design. Add a fixed sidebar for desktop navigation and a bottom
tab bar for mobile, replacing the top navbar. Cards now use glass-morphism
with left accent bars, buttons use orange gradients, and decorative glow
effects add depth. All 8 page templates updated, both light and dark modes
tested across desktop and mobile viewports.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-20 18:40:00 +02:00

245 lines
11 KiB
HTML

{% load static %}
<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}FoxFitt{% endblock %}</title>
<!-- === THEME: Apply saved preference BEFORE first paint (prevents flash) === -->
<script>
(function() {
var saved = localStorage.getItem('foxfitt-theme');
if (saved === 'light') {
document.documentElement.setAttribute('data-theme', 'light');
}
})();
</script>
<!-- Bootstrap 5.3 CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Poppins:wght@500;600;700&display=swap" rel="stylesheet">
<!-- Font Awesome 6 -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<!-- Custom CSS (cache-busted with deployment timestamp) -->
<link rel="stylesheet" href="{% static 'css/custom.css' %}?v={{ request.timestamp|default:'1.0' }}">
{% block extra_css %}{% endblock %}
</head>
<body>
{% if user.is_authenticated %}
<!-- ===================================================================
APP LAYOUT — sidebar (desktop) + top bar (mobile) + content
=================================================================== -->
<div class="app-layout">
<!-- === SIDEBAR (desktop only, hidden on mobile via CSS) === -->
<aside class="app-sidebar d-print-none">
<!-- Brand / Logo -->
<div class="sidebar-brand">
<div class="sidebar-brand__icon">
<i class="fas fa-bolt"></i>
</div>
<a href="{% url 'home' %}" class="sidebar-brand__text">
<span>Fox</span>Fitt
</a>
</div>
<!-- Navigation Links -->
<nav class="sidebar-nav">
<a href="{% url 'home' %}" class="sidebar-nav__link {% if request.resolver_match.url_name == 'home' %}active{% endif %}">
<i class="fas fa-th-large"></i>
<span>Dashboard</span>
</a>
<a href="{% url 'attendance_log' %}" class="sidebar-nav__link {% if request.resolver_match.url_name == 'attendance_log' %}active{% endif %}">
<i class="fas fa-clipboard-list"></i>
<span>Log Work</span>
</a>
<a href="{% url 'work_history' %}" class="sidebar-nav__link {% if request.resolver_match.url_name == 'work_history' %}active{% endif %}">
<i class="fas fa-clock"></i>
<span>History</span>
</a>
{% if user.is_staff %}
<a href="{% url 'payroll_dashboard' %}" class="sidebar-nav__link {% if request.resolver_match.url_name == 'payroll_dashboard' %}active{% endif %}">
<i class="fas fa-wallet"></i>
<span>Payroll</span>
</a>
{% endif %}
<a href="{% url 'create_receipt' %}" class="sidebar-nav__link {% if request.resolver_match.url_name == 'create_receipt' %}active{% endif %}">
<i class="fas fa-receipt"></i>
<span>Receipts</span>
</a>
{% if user.is_staff %}
<a href="{% url 'admin:index' %}" class="sidebar-nav__link">
<i class="fas fa-cog"></i>
<span>Admin</span>
</a>
{% endif %}
</nav>
<!-- Sidebar Footer: theme toggle + user -->
<div class="sidebar-footer">
<div class="d-flex align-items-center justify-content-between mb-3">
<button type="button" class="theme-toggle" id="themeToggle" title="Toggle dark/light mode">
<i class="fas fa-moon" id="themeIcon"></i>
</button>
<form method="post" action="{% url 'logout' %}">
{% csrf_token %}
<button type="submit" class="theme-toggle" title="Sign out" style="color: var(--color-danger);">
<i class="fas fa-sign-out-alt"></i>
</button>
</form>
</div>
<div class="sidebar-user">
<div class="sidebar-user__avatar">
{{ user.username|make_list|first|upper }}
</div>
<div>
<div class="sidebar-user__name">{{ user.first_name|default:user.username }}</div>
<div class="sidebar-user__role">{% if user.is_staff %}Administrator{% else %}Supervisor{% endif %}</div>
</div>
</div>
</div>
</aside>
<!-- === MAIN CONTENT AREA === -->
<div class="app-main">
<!-- === TOP BAR (mobile only, hidden on desktop via CSS) === -->
<div class="app-topbar d-print-none">
<a href="{% url 'home' %}" style="text-decoration: none; font-family: 'Poppins', sans-serif; font-weight: 700; font-size: 1.2rem;">
<span style="color: var(--accent);">Fox</span><span style="color: var(--text-on-nav);">Fitt</span>
</a>
<div class="d-flex align-items-center gap-2">
<button type="button" class="theme-toggle" id="themeToggleMobile" title="Toggle dark/light mode">
<i class="fas fa-moon" id="themeIconMobile"></i>
</button>
<form method="post" action="{% url 'logout' %}" class="d-inline">
{% csrf_token %}
<button type="submit" class="theme-toggle" title="Sign out" style="color: var(--color-danger);">
<i class="fas fa-sign-out-alt"></i>
</button>
</form>
</div>
</div>
<!-- === Flash messages (Django messages framework) === -->
{% if messages %}
<div class="container-fluid px-3 px-lg-4 mt-3">
{% for message in messages %}
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
{% if message.tags == 'success' %}<i class="fas fa-check-circle me-2"></i>
{% elif message.tags == 'error' or message.tags == 'danger' %}<i class="fas fa-exclamation-circle me-2"></i>
{% elif message.tags == 'warning' %}<i class="fas fa-exclamation-triangle me-2"></i>
{% elif message.tags == 'info' %}<i class="fas fa-info-circle me-2"></i>
{% endif %}
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{% endfor %}
</div>
{% endif %}
<!-- === Page Content === -->
<div class="app-content">
{% endif %}
{% block content %}
{% endblock %}
{% if user.is_authenticated %}
</div>
<!-- === Footer (inside main area) === -->
<footer class="app-footer d-print-none">
<div class="container">
<div class="d-flex flex-column flex-sm-row justify-content-between align-items-center">
<p class="mb-1 mb-sm-0">
<span style="color: var(--accent); font-weight: 600;">Fox</span><span style="font-weight: 600;">Fitt</span>
<span class="ms-1">Construction</span>
</p>
<p class="mb-0">&copy; {% now "Y" %} All rights reserved.</p>
</div>
</div>
</footer>
<!-- === BOTTOM TAB BAR (mobile only, hidden on desktop via CSS) === -->
<nav class="app-bottom-nav d-print-none">
<div class="bottom-nav-inner">
<a href="{% url 'home' %}" class="bottom-nav__link {% if request.resolver_match.url_name == 'home' %}active{% endif %}">
<i class="fas fa-th-large"></i>
<span>Dashboard</span>
</a>
<a href="{% url 'attendance_log' %}" class="bottom-nav__link {% if request.resolver_match.url_name == 'attendance_log' %}active{% endif %}">
<i class="fas fa-clipboard-list"></i>
<span>Log Work</span>
</a>
{% if user.is_staff %}
<a href="{% url 'payroll_dashboard' %}" class="bottom-nav__link {% if request.resolver_match.url_name == 'payroll_dashboard' %}active{% endif %}">
<i class="fas fa-wallet"></i>
<span>Payroll</span>
</a>
{% endif %}
<a href="{% url 'work_history' %}" class="bottom-nav__link {% if request.resolver_match.url_name == 'work_history' %}active{% endif %}">
<i class="fas fa-clock"></i>
<span>History</span>
</a>
<a href="{% url 'create_receipt' %}" class="bottom-nav__link {% if request.resolver_match.url_name == 'create_receipt' %}active{% endif %}">
<i class="fas fa-receipt"></i>
<span>Receipts</span>
</a>
</div>
</nav>
</div>
</div>
{% endif %}
<!-- Bootstrap 5.3 JS Bundle (includes Popper) -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
<!-- === THEME TOGGLE — switches dark/light and persists to localStorage === -->
<script>
(function() {
// Both desktop sidebar and mobile top bar toggle buttons
var toggles = [
{ btn: document.getElementById('themeToggle'), icon: document.getElementById('themeIcon') },
{ btn: document.getElementById('themeToggleMobile'), icon: document.getElementById('themeIconMobile') }
];
function updateIcons() {
var isDark = document.documentElement.getAttribute('data-theme') !== 'light';
toggles.forEach(function(t) {
if (t.icon) {
t.icon.className = isDark ? 'fas fa-sun' : 'fas fa-moon';
}
if (t.btn) {
t.btn.title = isDark ? 'Switch to light mode' : 'Switch to dark mode';
}
});
}
updateIcons();
toggles.forEach(function(t) {
if (t.btn) {
t.btn.addEventListener('click', function() {
var current = document.documentElement.getAttribute('data-theme');
var next = (current === 'light') ? 'dark' : 'light';
document.documentElement.setAttribute('data-theme', next);
localStorage.setItem('foxfitt-theme', next);
updateIcons();
});
}
});
})();
</script>
{% block extra_js %}{% endblock %}
</body>
</html>