- White border on every portal page: the .fclk-app full-bleed relied on exact negative margins to cancel the portal layout's container padding; when it didn't match, the white page chrome showed through. Match the PAGE background to the app (light #f3f4f6 / dark #0f1117, via body:has(.fclk-app)) so the gutter is invisible, and clip horizontal overflow. - Timesheets not responsive: the 6-column table crammed/wrapped on phones. Replaced the table with stacked cards (date + net up top, in -> out, then break / location / Correct) that read cleanly at any width. Correction-link data attributes preserved; the xpath-inherited .fclk-nav-bar untouched. Live on entech 19.0.3.12.2 (both rules verified in the served frontend bundle). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
157 lines
9.0 KiB
XML
157 lines
9.0 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<odoo>
|
|
|
|
<!-- Timesheet Portal Page -->
|
|
<template id="portal_timesheet_page" name="Fusion Clock Timesheets">
|
|
<t t-call="portal.portal_layout">
|
|
<t t-set="breadcrumbs_searchbar" t-value="False"/>
|
|
<t t-set="no_breadcrumbs" t-value="True"/>
|
|
<t t-set="no_header" t-value="True"/>
|
|
|
|
<div class="fclk-app">
|
|
<div class="fclk-timesheet-container">
|
|
|
|
<!-- Header -->
|
|
<div class="fclk-ts-header">
|
|
<h2>Timesheets</h2>
|
|
<div class="fclk-ts-period-nav">
|
|
<a t-attf-href="/my/clock/timesheets?period=last"
|
|
t-attf-class="fclk-ts-period-btn {{ 'fclk-ts-period-btn-active' if period == 'last' else '' }}">
|
|
Previous
|
|
</a>
|
|
<a t-attf-href="/my/clock/timesheets?period=current"
|
|
t-attf-class="fclk-ts-period-btn {{ 'fclk-ts-period-btn-active' if period == 'current' else '' }}">
|
|
Current
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Period Info -->
|
|
<div style="margin-bottom:16px;">
|
|
<span class="fclk-ts-period-btn" style="cursor:default; display:inline-block;">
|
|
<t t-esc="period_start.strftime('%b %d')"/> -
|
|
<t t-esc="period_end.strftime('%b %d, %Y')"/>
|
|
(<t t-esc="dict([('weekly','Weekly'),('biweekly','Bi-Weekly'),('semi_monthly','Semi-Monthly'),('monthly','Monthly')]).get(schedule_type, schedule_type)"/>)
|
|
</span>
|
|
</div>
|
|
|
|
<!-- Summary Cards -->
|
|
<div class="fclk-ts-summary">
|
|
<div class="fclk-ts-summary-card">
|
|
<div class="fclk-ts-summary-value"><t t-esc="total_hours"/>h</div>
|
|
<div class="fclk-ts-summary-label">Total Hours</div>
|
|
</div>
|
|
<div class="fclk-ts-summary-card">
|
|
<div class="fclk-ts-summary-value" style="color:#10B981;"><t t-esc="net_hours"/>h</div>
|
|
<div class="fclk-ts-summary-label">Net Hours</div>
|
|
</div>
|
|
<div class="fclk-ts-summary-card">
|
|
<div class="fclk-ts-summary-value"><t t-esc="int(total_breaks)"/>m</div>
|
|
<div class="fclk-ts-summary-label">Total Breaks</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Attendance Entries (responsive cards) -->
|
|
<t t-if="attendances">
|
|
<div class="fclk-ts-list">
|
|
<t t-foreach="attendances" t-as="entry">
|
|
<div class="fclk-ts-card">
|
|
<div class="fclk-ts-card-top">
|
|
<div class="fclk-ts-card-date">
|
|
<t t-esc="entry['day_name']"/>
|
|
<span><t t-esc="entry['day_date']"/></span>
|
|
</div>
|
|
<div class="fclk-ts-card-net">
|
|
<t t-esc="'%.1f' % (entry['att'].x_fclk_net_hours or 0)"/>h
|
|
</div>
|
|
</div>
|
|
<div class="fclk-ts-card-times">
|
|
<span><span class="fclk-ts-k">In</span><t t-esc="entry['time_in']"/></span>
|
|
<span class="fclk-ts-arrow">→</span>
|
|
<span>
|
|
<span class="fclk-ts-k">Out</span>
|
|
<t t-if="entry['att'].check_out">
|
|
<t t-esc="entry['time_out']"/>
|
|
<t t-if="entry['att'].x_fclk_auto_clocked_out">
|
|
<span class="fclk-ts-badge-auto">AUTO</span>
|
|
</t>
|
|
</t>
|
|
<t t-else="">
|
|
<span style="color:#f59e0b;">Active</span>
|
|
</t>
|
|
</span>
|
|
</div>
|
|
<div class="fclk-ts-card-meta">
|
|
<span><t t-esc="int(entry['att'].x_fclk_break_minutes or 0)"/>m break</span>
|
|
<t t-if="entry['att'].x_fclk_location_id">
|
|
<span class="fclk-ts-dot">·</span>
|
|
<span><t t-esc="entry['att'].x_fclk_location_id.name or ''"/></span>
|
|
</t>
|
|
<a href="#" class="fclk-correction-link fclk-ts-correct"
|
|
t-att-data-att-id="entry['att'].id"
|
|
t-att-data-check-in="entry['att'].check_in.strftime('%Y-%m-%d %H:%M:%S') if entry['att'].check_in else ''"
|
|
t-att-data-check-out="entry['att'].check_out.strftime('%Y-%m-%d %H:%M:%S') if entry['att'].check_out else ''">
|
|
Correct
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</t>
|
|
</div>
|
|
</t>
|
|
<t t-else="">
|
|
<div class="fclk-empty-state">
|
|
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="#6b7280" stroke-width="1.5">
|
|
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"/>
|
|
<line x1="16" y1="2" x2="16" y2="6"/>
|
|
<line x1="8" y1="2" x2="8" y2="6"/>
|
|
<line x1="3" y1="10" x2="21" y2="10"/>
|
|
</svg>
|
|
<p>No attendance records for this period.</p>
|
|
</div>
|
|
</t>
|
|
|
|
<!-- Navigation Bar -->
|
|
<div class="fclk-nav-bar">
|
|
<a href="/my/clock" class="fclk-nav-item">
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<circle cx="12" cy="12" r="10"/>
|
|
<polyline points="12 6 12 12 16 14"/>
|
|
</svg>
|
|
<span>Clock</span>
|
|
</a>
|
|
<a href="/my/clock/timesheets" class="fclk-nav-item fclk-nav-active">
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"/>
|
|
<line x1="16" y1="2" x2="16" y2="6"/>
|
|
<line x1="8" y1="2" x2="8" y2="6"/>
|
|
<line x1="3" y1="10" x2="21" y2="10"/>
|
|
</svg>
|
|
<span>Timesheets</span>
|
|
</a>
|
|
<a href="/my/clock/reports" class="fclk-nav-item">
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
|
|
<polyline points="14 2 14 8 20 8"/>
|
|
<line x1="16" y1="13" x2="8" y2="13"/>
|
|
<line x1="16" y1="17" x2="8" y2="17"/>
|
|
</svg>
|
|
<span>Reports</span>
|
|
</a>
|
|
<t t-if="show_payslips">
|
|
<a href="/my/clock/payslips" class="fclk-nav-item">
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<rect x="2" y="5" width="20" height="14" rx="2"/>
|
|
<line x1="2" y1="10" x2="22" y2="10"/>
|
|
</svg>
|
|
<span>Payslips</span>
|
|
</a>
|
|
</t>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</t>
|
|
</template>
|
|
|
|
</odoo>
|