fix(fusion_clock): portal white-border + responsive timesheet entries

- 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>
This commit is contained in:
gsinghpal
2026-05-30 22:20:56 -04:00
parent 11108dfea3
commit a479052b72
3 changed files with 135 additions and 46 deletions

View File

@@ -5,7 +5,7 @@
{
'name': 'Fusion Clock',
'version': '19.0.3.12.1',
'version': '19.0.3.12.2',
'category': 'Human Resources/Attendances',
'summary': 'Complete Employee T&A with Geofencing, Shifts, Penalties, Overtime, Kiosk, Dashboard & Payroll Export',
'description': """

View File

@@ -83,6 +83,27 @@ body:has(.fclk-app) .o_footer {
display: none !important;
}
/* Full-bleed: never let the portal layout's white chrome show as a border
around the dark app. Match the PAGE background to the app's background in
both themes (so the wrapper's container padding reads as an invisible
gutter) and clip horizontal overflow from the .fclk-app full-bleed margins. */
html:has(.fclk-app),
body:has(.fclk-app) {
background: #f3f4f6;
overflow-x: hidden;
}
@media (prefers-color-scheme: dark) {
html:has(.fclk-app),
body:has(.fclk-app) {
background: #0f1117;
}
}
html.o_dark:has(.fclk-app),
html.o_dark body:has(.fclk-app),
body:has(.fclk-app.fclk-dark) {
background: #0f1117;
}
.fclk-container {
max-width: 480px;
margin: 0 auto;
@@ -1201,6 +1222,83 @@ html.o_dark .fclk-wizard-overlay {
border-radius: 4px;
}
/* Responsive timesheet entries — stacked cards instead of a cramped table.
Reads cleanly at any phone/tablet width; no horizontal overflow. */
.fclk-ts-list {
display: flex;
flex-direction: column;
gap: 10px;
}
.fclk-ts-card {
background: var(--fclk-card);
border: 1px solid var(--fclk-card-border);
border-radius: 12px;
padding: 14px 16px;
}
.fclk-ts-card-top {
display: flex;
justify-content: space-between;
align-items: baseline;
gap: 8px;
}
.fclk-ts-card-date {
color: var(--fclk-text);
font-size: 14px;
font-weight: 700;
}
.fclk-ts-card-date span {
color: var(--fclk-text-dim);
font-weight: 400;
margin-left: 6px;
}
.fclk-ts-card-net {
color: var(--fclk-green);
font-weight: 700;
font-size: 15px;
white-space: nowrap;
}
.fclk-ts-card-times {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 8px;
margin-top: 8px;
color: var(--fclk-text);
font-size: 14px;
}
.fclk-ts-arrow {
color: var(--fclk-text-dim);
}
.fclk-ts-k {
color: var(--fclk-text-dim);
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.4px;
margin-right: 4px;
}
.fclk-ts-card-meta {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 6px;
margin-top: 8px;
color: var(--fclk-text-muted);
font-size: 12px;
}
.fclk-ts-dot {
color: var(--fclk-text-dim);
}
.fclk-ts-correct {
margin-left: auto;
color: var(--fclk-text-muted);
font-size: 12px;
text-decoration: none;
}
.fclk-ts-correct:hover {
color: var(--fclk-green);
text-decoration: underline;
}
/* ---- Reports Page ---- */
.fclk-reports-container {
max-width: 600px;

View File

@@ -51,31 +51,25 @@
</div>
</div>
<!-- Attendance Table -->
<!-- Attendance Entries (responsive cards) -->
<t t-if="attendances">
<table class="fclk-ts-table">
<thead>
<tr>
<th>Date</th>
<th>In</th>
<th>Out</th>
<th>Break</th>
<th>Net</th>
<th>Location</th>
<th></th>
</tr>
</thead>
<tbody>
<t t-foreach="attendances" t-as="entry">
<tr>
<td>
<strong><t t-esc="entry['day_name']"/></strong>
<span style="color:#9ca3af; margin-left:4px;">
<t t-esc="entry['day_date']"/>
</span>
</td>
<td><t t-esc="entry['time_in']"/></td>
<td>
<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">
@@ -85,27 +79,24 @@
<t t-else="">
<span style="color:#f59e0b;">Active</span>
</t>
</td>
<td><t t-esc="int(entry['att'].x_fclk_break_minutes or 0)"/>m</td>
<td style="font-weight:600; color:#10B981;">
<t t-esc="'%.1f' % (entry['att'].x_fclk_net_hours or 0)"/>h
</td>
<td style="color:#9ca3af; font-size:12px;">
<t t-esc="entry['att'].x_fclk_location_id.name or ''"/>
</td>
<td>
<a href="#" class="fclk-correction-link"
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 ''"
style="font-size:11px; color:#6b7280;">
Correct
</a>
</td>
</tr>
</t>
</tbody>
</table>
</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">