timekeeper/app/templates/layout.html
2026-01-15 15:46:35 -05:00

164 lines
5.6 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>TimeKeeper</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/static/styles.css?v=20251223-03">
<script>
// Expose edit capability to client scripts (true only for admins)
window.can_edit = {{ 'true' if request.session.get('is_admin') else 'false' }};
</script>
<style>
/* Admin dropdown: inline in nav, no outline/border; ASCII-safe caret */
.tk-nav { display: flex; gap: 12px; align-items: center; }
.tk-dropdown { position: relative; display: inline-flex; align-items: center; }
.tk-dropdown-toggle.tk-nav-link {
border: 0;
outline: none;
box-shadow: none;
background: transparent;
display: inline-flex;
align-items: center;
padding: 6px 10px;
}
.tk-dropdown-toggle.tk-nav-link:focus { outline: none; box-shadow: none; }
.tk-dropdown-toggle.tk-nav-link::after {
content: "\25BE"; /* small down triangle */
margin-left: 4px;
font-size: 0.9em;
}
.tk-dropdown-menu {
position: absolute;
right: 0;
top: calc(100% + 6px);
min-width: 200px;
background: #fff;
border: 1px solid #e5e7eb;
box-shadow: 0 6px 18px rgba(0,0,0,0.08);
border-radius: 8px;
padding: 6px;
display: none;
z-index: 1001;
}
.tk-dropdown.open .tk-dropdown-menu { display: block; }
.tk-dropdown-menu a { display: block; padding: 8px 10px; border-radius: 6px; }
.tk-dropdown-menu a:hover { background: #f3f4f6; }
</style>
</head>
<body class="tk">
<header class="tk-header">
<div class="tk-header-inner">
<a href="/viewer" class="tk-brand">TimeKeeper</a>
{% if not hide_nav_links %}
<nav class="tk-nav">
<a href="/viewer" class="tk-nav-link">Timesheet Editor</a>
<a href="/review" class="tk-nav-link">Review Timesheets</a>
{% if request.session.get('is_admin') %}
<a href="/pto-tracker" class="tk-nav-link">PTO Tracker</a>
<a href="/upload" class="tk-nav-link">Import</a>
<div class="tk-dropdown" id="adminDropdown">
<button type="button" class="tk-nav-link tk-dropdown-toggle" aria-haspopup="true" aria-expanded="false">Admin</button>
<div class="tk-dropdown-menu" role="menu" aria-label="Admin menu">
<a href="/admin/users" class="tk-nav-link">User Management</a>
<a href="/admin/employees" class="tk-nav-link">Employee Management</a>
<a href="/attendance" class="tk-nav-link">Attendance</a>
</div>
</div>
{% endif %}
<a href="/logout" class="tk-nav-link danger">Logout</a>
</nav>
{% endif %}
</div>
</header>
<main class="tk-container">
{% block content %}{% endblock %}
</main>
<script>
// Admin dropdown toggle
(function () {
var dd = document.getElementById('adminDropdown');
if (!dd) return;
var btn = dd.querySelector('.tk-dropdown-toggle');
function closeAll() {
dd.classList.remove('open');
if (btn) btn.setAttribute('aria-expanded', 'false');
}
btn.addEventListener('click', function (e) {
e.stopPropagation();
var willOpen = !dd.classList.contains('open');
if (willOpen) {
dd.classList.add('open');
btn.setAttribute('aria-expanded', 'true');
} else {
closeAll();
}
});
document.addEventListener('click', function (e) {
if (!dd.contains(e.target)) closeAll();
});
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape') closeAll();
});
})();
</script>
<script>
// Preserve and restore scroll position across same-origin navigations and refreshes.
(function () {
var key = 'scrollpos:' + location.pathname + location.search;
function headerOffset() {
var hdr = document.querySelector('.tk-header');
return hdr ? hdr.getBoundingClientRect().height : 0;
}
function restore() {
// If URL has a hash, let the browser handle anchor scrolling.
if (location.hash) return;
try {
var v = sessionStorage.getItem(key);
if (v !== null) {
var y = parseInt(v, 10) || 0;
var off = headerOffset();
window.scrollTo({ top: Math.max(0, y - off), left: 0, behavior: 'auto' });
}
} catch (e) {}
}
function persist() {
try {
var y = window.scrollY || window.pageYOffset || 0;
sessionStorage.setItem(key, String(y));
} catch (e) {}
}
if (document.readyState === 'complete' || document.readyState === 'interactive') {
restore();
} else {
document.addEventListener('DOMContentLoaded', restore, { once: true });
}
window.addEventListener('beforeunload', persist);
// Persist on same-origin link clicks and form submits
document.addEventListener('click', function (ev) {
var a = ev.target && ev.target.closest ? ev.target.closest('a[href]') : null;
if (!a) return;
try {
var u = new URL(a.href, location.href);
if (u.origin === location.origin) persist();
} catch (e) {}
}, true);
document.addEventListener('submit', function () { persist(); }, true);
})();
</script>
</body>
</html>