169 lines
5.5 KiB
HTML
169 lines
5.5 KiB
HTML
{% extends "layout.html" %}
|
|
{% block content %}
|
|
<div class="sheet">
|
|
<div class="header">
|
|
<div class="brand">Time Period Overview</div>
|
|
<div class="row">
|
|
<div class="period"><strong>Period:</strong> {{ period_name }}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<table class="grid">
|
|
<thead>
|
|
<tr>
|
|
<th>Employee</th>
|
|
<th>Regular</th>
|
|
<th>Overtime</th>
|
|
<th>PTO</th>
|
|
<th>Holiday</th>
|
|
<th>Other</th>
|
|
<th>Paid Total</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for b in bundles %}
|
|
<tr>
|
|
<td>{{ b.employee.name }}</td>
|
|
<td class="num mono">{{ b.grouped.totals.regular|fmt2 }}</td>
|
|
<td class="num mono">{{ b.grouped.totals.overtime|fmt2 }}</td>
|
|
<td class="num mono">{{ b.grouped.totals.pto|fmt2 }}</td>
|
|
<td class="num mono">{{ b.grouped.totals.holiday|fmt2 }}</td>
|
|
<td class="num mono">{{ b.grouped.totals.bereavement|fmt2 }}</td>
|
|
<td class="num mono">{{ b.grouped.totals.paid_total|fmt2 }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
<tfoot>
|
|
<tr>
|
|
<td colspan="7" class="no-pad">
|
|
<div class="totals-footer">
|
|
<span><strong>Regular:</strong> {{ totals.regular|fmt2 }}</span>
|
|
<span><strong>Overtime:</strong> {{ totals.overtime|fmt2 }}</span>
|
|
<span><strong>PTO:</strong> {{ totals.pto|fmt2 }}</span>
|
|
<span><strong>Holiday:</strong> {{ totals.holiday|fmt2 }}</span>
|
|
<span><strong>Other:</strong> {{ totals.bereavement|fmt2 }}</span>
|
|
<span><strong>Paid Total:</strong> {{ totals.paid_total|fmt2 }}</span>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
|
|
<style>
|
|
header, nav, .navbar, .topbar, .site-header, .app-nav { display:none !important; }
|
|
@media print {
|
|
body { margin: 0 !important; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
|
|
.tk-container { display:block !important; margin:0 !important; padding:0 !important; }
|
|
}
|
|
|
|
:root { --ink:#222; --grid:#cdd3da; --head:#f4f6f9; }
|
|
@page { size: Letter landscape; margin: 0.30in; }
|
|
|
|
.sheet {
|
|
width: 10.4in;
|
|
margin: 0;
|
|
color: var(--ink);
|
|
font-family: Inter, system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
|
|
}
|
|
.header { margin-bottom: 0.08in; }
|
|
.brand { font-size: 20pt; font-weight: 800; line-height: 1.1; margin-bottom: 0.03in; }
|
|
.row { display: grid; grid-template-columns: auto 1fr; align-items: end; column-gap: 0.16in; }
|
|
.period { font-size: 10.6pt; }
|
|
|
|
table.grid { width:100%; border-collapse:collapse; }
|
|
thead { display: table-header-group; }
|
|
tfoot { display: table-footer-group; }
|
|
.no-pad { padding: 0; }
|
|
|
|
/* Main body scaled down slightly to fit more employees */
|
|
table.grid th, table.grid td {
|
|
border: 1pt solid var(--grid);
|
|
padding: 0.052in 0.072in;
|
|
font-size: 10.4pt;
|
|
background: #fff;
|
|
}
|
|
table.grid thead th {
|
|
background: var(--head);
|
|
text-transform: uppercase;
|
|
font-size: 9.6pt;
|
|
letter-spacing: .02em;
|
|
color: #3a4856;
|
|
}
|
|
.num { text-align: right; }
|
|
.mono { font-family: Menlo, Monaco, Consolas, "Courier New", monospace; }
|
|
|
|
/* Footer totals: slightly larger and bold, fixed to footer area on each page */
|
|
.totals-footer {
|
|
display: flex; flex-wrap: wrap; gap: 0.12in;
|
|
border-top: 1.5pt solid #333; margin-top: 0.06in; padding-top: 0.08in;
|
|
font-size: 11.6pt; /* a little bigger than body */
|
|
}
|
|
|
|
/* Keep rows intact; natural pagination */
|
|
table.grid tr { page-break-inside: avoid; }
|
|
|
|
/* Prevent extra whitespace creating another page */
|
|
.sheet, .grid { margin-bottom: 0; padding-bottom: 0; }
|
|
|
|
/* Nudge trims vertical spacing slightly when needed */
|
|
.nudge table.grid th, .nudge table.grid td { padding: 0.049in 0.069in; font-size: 10.2pt; }
|
|
.nudge .brand { font-size: 19pt; }
|
|
.nudge .totals-footer { gap: 0.11in; font-size: 11.2pt; padding-top: 0.07in; }
|
|
|
|
/* Clip: apply when remaining overflow is tiny (prevents page 2) */
|
|
.clip { overflow: hidden; max-block-size: calc(8.5in - 0.60in); }
|
|
</style>
|
|
|
|
<script>
|
|
(function(){
|
|
// Ensure it fits on one page by tightening spacing when needed.
|
|
const DPI = 96;
|
|
const pageHeightInches = 8.5;
|
|
const marginInches = 0.30; // sync with @page
|
|
const availablePx = (pageHeightInches - (marginInches * 2)) * DPI;
|
|
|
|
function fitToOnePage() {
|
|
const sheet = document.querySelector('.sheet');
|
|
if (!sheet) return;
|
|
|
|
sheet.classList.remove('nudge', 'clip');
|
|
const h = sheet.scrollHeight;
|
|
const nearThreshold = 28; // px
|
|
const tinyOverflow = 14; // px
|
|
|
|
if (h > availablePx) {
|
|
sheet.classList.add('nudge');
|
|
const h2 = sheet.scrollHeight;
|
|
if (h2 > availablePx && (h2 - availablePx) <= tinyOverflow) {
|
|
sheet.classList.add('clip');
|
|
}
|
|
}
|
|
}
|
|
|
|
// After print/cancel, return to Overview page (not Review)
|
|
const backUrl = "/overview?timesheet_id={{ timesheet_id }}";
|
|
function finish() {
|
|
if (window.parent && window.parent !== window) {
|
|
try { window.parent.postMessage({ type: 'close-print' }, '*'); } catch(e){}
|
|
} else {
|
|
window.location.href = backUrl;
|
|
}
|
|
}
|
|
|
|
window.addEventListener('load', function(){
|
|
fitToOnePage();
|
|
setTimeout(function(){ window.focus(); window.print(); }, 80);
|
|
});
|
|
|
|
if (typeof window.onbeforeprint !== 'undefined') {
|
|
window.addEventListener('beforeprint', fitToOnePage);
|
|
}
|
|
if (window.matchMedia) {
|
|
window.matchMedia('print').addEventListener('change', e => { if (e.matches) fitToOnePage(); });
|
|
}
|
|
|
|
window.addEventListener('afterprint', finish);
|
|
})();
|
|
</script>
|
|
{% endblock %} |