Files
Odoo-Modules/fusion_clock/static/src/xml/fusion_clock_dashboard.xml
gsinghpal 3f78f652e7 feat(fusion_clock): bi-weekly attendance filter — pay-period filters + picker
Reuse the existing Pay Period setting (Frequency + Anchor) as the single
source of truth via a shared pure helper (models/pay_period.py); fusion.clock.report
delegates to it. Add Current/Previous/Next Pay Period filters to the attendance
search view (search-method computed booleans on hr.attendance), a Bi-Weekly Period
picker wizard (pick start -> auto +2 weeks, editable; Apply opens the filtered list)
reachable from an Attendance menu item and a dashboard tile. Window follows the
configured frequency; TZ-correct via local-day boundaries. Bump 3.14.4 -> 3.15.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 11:20:06 -04:00

208 lines
12 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?xml version="1.0" encoding="utf-8"?>
<templates xml:space="preserve">
<t t-name="fusion_clock.Dashboard">
<div class="o_action fclk-dash">
<div class="fclk-dash-wrap">
<t t-if="state.loading">
<div class="fclk-dash-empty">
<i class="fa fa-spinner fa-spin fa-2x"/>
<p class="mt-2">Loading dashboard…</p>
</div>
</t>
<t t-if="state.error">
<div class="fclk-dash-card"><t t-esc="state.error"/></div>
</t>
<t t-if="!state.loading and !state.error">
<!-- HEADER -->
<div class="fclk-dash-header">
<div>
<div class="fclk-dash-hello"><t t-esc="greeting"/>, <t t-esc="state.personal.employee_name"/> 👋</div>
<div class="fclk-dash-date"><t t-esc="todayLabel"/></div>
</div>
<div class="fclk-dash-headctl">
<span class="fclk-dash-statusbadge" t-att-class="{'is-out': !state.personal.is_checked_in}">
<t t-if="state.personal.is_checked_in">● Clocked in</t>
<t t-else="">○ Not clocked in</t>
</span>
<button class="fclk-dash-btn-primary" t-on-click="onOpenClock">Open My Clock</button>
<button class="fclk-dash-btn-ghost" t-on-click="onRefresh"><i class="fa fa-refresh"/></button>
</div>
</div>
<!-- PERSONAL KPIs -->
<div class="fclk-kpi-row">
<div class="fclk-kpi fclk-kpi--today">
<div class="fclk-kpi-ic"></div>
<div class="fclk-kpi-val"><t t-esc="state.personal.today_hours"/>h</div>
<div class="fclk-kpi-lbl">Today</div>
</div>
<div class="fclk-kpi fclk-kpi--week">
<div class="fclk-kpi-ic">📅</div>
<div class="fclk-kpi-val"><t t-esc="state.personal.week_hours"/>h</div>
<div class="fclk-kpi-lbl">This Week</div>
</div>
<div class="fclk-kpi fclk-kpi--ot">
<div class="fclk-kpi-ic"></div>
<div class="fclk-kpi-val"><t t-esc="state.personal.overtime_week"/>h</div>
<div class="fclk-kpi-lbl">OT This Week</div>
</div>
<div class="fclk-kpi fclk-kpi--streak">
<div class="fclk-kpi-ic">🔥</div>
<div class="fclk-kpi-val"><t t-esc="state.personal.ontime_streak"/></div>
<div class="fclk-kpi-lbl">On-time Streak</div>
</div>
</div>
<!-- PERSONAL DETAIL -->
<div class="fclk-dash-2col">
<div class="fclk-dash-card">
<h4>Today's Shift</h4>
<div class="fclk-dash-line">
<span>Scheduled</span>
<span class="fclk-dash-muted">
<t t-if="state.personal.shift.label"><t t-esc="state.personal.shift.label"/> (<t t-esc="state.personal.shift.hours"/>h)</t>
<t t-else="">Not scheduled today</t>
</span>
</div>
<div class="fclk-dash-line">
<span>Status</span>
<span t-att-class="state.personal.is_checked_in ? 'fclk-pin' : 'fclk-dash-muted'"><t t-esc="state.personal.shift.status_note"/></span>
</div>
<div class="fclk-dash-line">
<span>Source</span>
<span class="fclk-dash-muted"><t t-esc="sourceLabel(state.personal.shift.source)"/></span>
</div>
</div>
<div class="fclk-dash-card">
<h4>My Recent Activity</h4>
<t t-if="state.personal.recent_activity.length === 0">
<div class="fclk-dash-empty">No recent activity</div>
</t>
<t t-foreach="state.personal.recent_activity" t-as="a" t-key="a_index">
<div class="fclk-dash-line">
<span><t t-esc="fmtDate(a.check_in)"/></span>
<span class="fclk-dash-muted">
<t t-esc="a.worked_hours"/>h<t t-if="a.overtime_hours &gt; 0"> · +<t t-esc="a.overtime_hours"/> OT</t>
</span>
</div>
</t>
</div>
</div>
<div class="fclk-dash-2col">
<div class="fclk-dash-card">
<h4>Upcoming Leave</h4>
<t t-if="state.personal.leaves.length === 0">
<div class="fclk-dash-empty">No upcoming leave</div>
</t>
<t t-foreach="state.personal.leaves" t-as="lv" t-key="lv_index">
<div class="fclk-dash-line"><span><t t-esc="lv.label"/></span><span class="fclk-dash-muted"><t t-esc="lv.state"/></span></div>
</t>
</div>
<div class="fclk-dash-card">
<h4>Recent Penalties</h4>
<t t-if="state.personal.penalties.length === 0">
<div class="fclk-dash-empty">None this month 🎉</div>
</t>
<t t-foreach="state.personal.penalties" t-as="p" t-key="p_index">
<div class="fclk-dash-line"><span><t t-esc="p.type"/> · <t t-esc="p.date"/></span><span class="fclk-pyel"><t t-esc="p.minutes"/> min</span></div>
</t>
</div>
</div>
<!-- QUICK ACTIONS (kept above the team/org cards so managers reach them without scrolling) -->
<div class="fclk-dash-card">
<h4>Quick Actions</h4>
<div class="fclk-dash-actions">
<span class="fclk-dash-act" t-on-click="onOpenClock">🕒 Open My Clock</span>
<span class="fclk-dash-act" t-on-click="onViewTimesheets">📄 My Timesheets</span>
<t t-if="state.team">
<span class="fclk-dash-act" t-on-click="onViewAttendances">📋 All Attendances</span>
<span class="fclk-dash-act" t-on-click="onViewCorrections">📨 Approvals</span>
<span class="fclk-dash-act" t-on-click="onViewPenalties">⚠ Penalties</span>
<span class="fclk-dash-act" t-on-click="onViewActivityLogs">🗒 Activity Logs</span>
<span class="fclk-dash-act" t-on-click="onViewBiweekly">🗓 Bi-Weekly Period</span>
</t>
<t t-if="state.role === 'manager'">
<span class="fclk-dash-act" t-on-click="onViewShiftPlanner">📅 Shift Planner</span>
<span class="fclk-dash-act" t-on-click="onViewReports">📊 Reports</span>
</t>
</div>
</div>
<!-- TEAM / ORG BAND -->
<t t-if="state.team">
<div class="fclk-dash-divider"><span>Team / Org</span></div>
<div class="fclk-kpi-row">
<div class="fclk-kpi fclk-kpi--present">
<div class="fclk-kpi-ic"></div>
<div class="fclk-kpi-val"><t t-esc="state.team.present_count"/></div>
<div class="fclk-kpi-lbl">Present now</div>
</div>
<div class="fclk-kpi fclk-kpi--absent">
<div class="fclk-kpi-ic">🚫</div>
<div class="fclk-kpi-val"><t t-esc="state.team.absent_count"/></div>
<div class="fclk-kpi-lbl">Absent today</div>
</div>
<div class="fclk-kpi fclk-kpi--late">
<div class="fclk-kpi-ic"></div>
<div class="fclk-kpi-val"><t t-esc="state.team.late_count"/></div>
<div class="fclk-kpi-lbl">Late today</div>
</div>
<div class="fclk-kpi fclk-kpi--pending">
<div class="fclk-kpi-ic">📨</div>
<div class="fclk-kpi-val"><t t-esc="state.team.pending_approvals"/></div>
<div class="fclk-kpi-lbl">Pending approvals</div>
</div>
</div>
<div class="fclk-dash-2col">
<div class="fclk-dash-card">
<h4>Currently Clocked In <span class="fclk-dash-muted"><t t-esc="state.team.present_count"/> of <t t-esc="state.team.total_employees"/></span></h4>
<t t-if="state.team.clocked_in.length === 0">
<div class="fclk-dash-empty">No one is clocked in right now</div>
</t>
<t t-foreach="state.team.clocked_in" t-as="emp" t-key="emp_index">
<div class="fclk-dash-line">
<span><span class="fclk-dash-av"><t t-esc="initials(emp.employee)"/></span><t t-esc="emp.employee"/>
<span t-if="emp.late" class="fclk-dash-late-badge">late</span>
</span>
<span class="fclk-dash-muted"><t t-esc="fmtTime(emp.check_in)"/> · <t t-esc="emp.location"/></span>
</div>
</t>
</div>
<div class="fclk-dash-card">
<h4>Needs Attention</h4>
<div class="fclk-dash-line" t-on-click="onViewActivityLogs" style="cursor:pointer;">
<span class="fclk-pred"><t t-esc="state.team.absent_count"/> absent (no leave)</span>
<span class="fclk-dash-muted">review →</span>
</div>
<div class="fclk-dash-line">
<span><t t-esc="state.team.on_leave_count"/> on approved leave</span>
<span class="fclk-dash-muted">today</span>
</div>
<div class="fclk-dash-line" t-on-click="onViewActivityLogs" style="cursor:pointer;">
<span class="fclk-pyel"><t t-esc="state.team.pending_reasons"/> auto clock-out — reason pending</span>
<span class="fclk-dash-muted">view →</span>
</div>
<div class="fclk-dash-line" t-on-click="onViewCorrections" style="cursor:pointer;">
<span><t t-esc="state.team.pending_approvals"/> correction requests</span>
<span class="fclk-dash-muted">open →</span>
</div>
</div>
</div>
</t>
</t>
</div>
</div>
</t>
</templates>