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>
245 lines
11 KiB
HTML
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">© {% 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>
|