Files
Odoo-Modules/fusion_clock/views/portal_timesheet_templates.xml
gsinghpal 3376a32143 feat(fusion_clock): Publish & Notify range + portal Schedule fold-in [A6-A7]
Generalise post_week into fclk_publish_range/fclk_email_posted_range +
planner Publish… panel + publish_range endpoint. Fold the /my/clock/schedule
controller+template+css from fusion_planning into fusion_clock (native
schedule only, role colour); inline Schedule nav across all portal pages.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 20:54:59 -04:00

170 lines
9.9 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">&#8594;</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">&#183;</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/schedule" class="fclk-nav-item">
<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"/>
<line x1="8" y1="14" x2="10" y2="14"/>
<line x1="14" y1="14" x2="16" y2="14"/>
<line x1="8" y1="18" x2="10" y2="18"/>
<line x1="14" y1="18" x2="16" y2="18"/>
</svg>
<span>Schedule</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>