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:
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
'name': 'Fusion Clock',
|
'name': 'Fusion Clock',
|
||||||
'version': '19.0.3.12.1',
|
'version': '19.0.3.12.2',
|
||||||
'category': 'Human Resources/Attendances',
|
'category': 'Human Resources/Attendances',
|
||||||
'summary': 'Complete Employee T&A with Geofencing, Shifts, Penalties, Overtime, Kiosk, Dashboard & Payroll Export',
|
'summary': 'Complete Employee T&A with Geofencing, Shifts, Penalties, Overtime, Kiosk, Dashboard & Payroll Export',
|
||||||
'description': """
|
'description': """
|
||||||
|
|||||||
@@ -83,6 +83,27 @@ body:has(.fclk-app) .o_footer {
|
|||||||
display: none !important;
|
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 {
|
.fclk-container {
|
||||||
max-width: 480px;
|
max-width: 480px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
@@ -1201,6 +1222,83 @@ html.o_dark .fclk-wizard-overlay {
|
|||||||
border-radius: 4px;
|
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 ---- */
|
/* ---- Reports Page ---- */
|
||||||
.fclk-reports-container {
|
.fclk-reports-container {
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
|
|||||||
@@ -51,31 +51,25 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Attendance Table -->
|
<!-- Attendance Entries (responsive cards) -->
|
||||||
<t t-if="attendances">
|
<t t-if="attendances">
|
||||||
<table class="fclk-ts-table">
|
<div class="fclk-ts-list">
|
||||||
<thead>
|
<t t-foreach="attendances" t-as="entry">
|
||||||
<tr>
|
<div class="fclk-ts-card">
|
||||||
<th>Date</th>
|
<div class="fclk-ts-card-top">
|
||||||
<th>In</th>
|
<div class="fclk-ts-card-date">
|
||||||
<th>Out</th>
|
<t t-esc="entry['day_name']"/>
|
||||||
<th>Break</th>
|
<span><t t-esc="entry['day_date']"/></span>
|
||||||
<th>Net</th>
|
</div>
|
||||||
<th>Location</th>
|
<div class="fclk-ts-card-net">
|
||||||
<th></th>
|
<t t-esc="'%.1f' % (entry['att'].x_fclk_net_hours or 0)"/>h
|
||||||
</tr>
|
</div>
|
||||||
</thead>
|
</div>
|
||||||
<tbody>
|
<div class="fclk-ts-card-times">
|
||||||
<t t-foreach="attendances" t-as="entry">
|
<span><span class="fclk-ts-k">In</span><t t-esc="entry['time_in']"/></span>
|
||||||
<tr>
|
<span class="fclk-ts-arrow">→</span>
|
||||||
<td>
|
<span>
|
||||||
<strong><t t-esc="entry['day_name']"/></strong>
|
<span class="fclk-ts-k">Out</span>
|
||||||
<span style="color:#9ca3af; margin-left:4px;">
|
|
||||||
<t t-esc="entry['day_date']"/>
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td><t t-esc="entry['time_in']"/></td>
|
|
||||||
<td>
|
|
||||||
<t t-if="entry['att'].check_out">
|
<t t-if="entry['att'].check_out">
|
||||||
<t t-esc="entry['time_out']"/>
|
<t t-esc="entry['time_out']"/>
|
||||||
<t t-if="entry['att'].x_fclk_auto_clocked_out">
|
<t t-if="entry['att'].x_fclk_auto_clocked_out">
|
||||||
@@ -85,27 +79,24 @@
|
|||||||
<t t-else="">
|
<t t-else="">
|
||||||
<span style="color:#f59e0b;">Active</span>
|
<span style="color:#f59e0b;">Active</span>
|
||||||
</t>
|
</t>
|
||||||
</td>
|
</span>
|
||||||
<td><t t-esc="int(entry['att'].x_fclk_break_minutes or 0)"/>m</td>
|
</div>
|
||||||
<td style="font-weight:600; color:#10B981;">
|
<div class="fclk-ts-card-meta">
|
||||||
<t t-esc="'%.1f' % (entry['att'].x_fclk_net_hours or 0)"/>h
|
<span><t t-esc="int(entry['att'].x_fclk_break_minutes or 0)"/>m break</span>
|
||||||
</td>
|
<t t-if="entry['att'].x_fclk_location_id">
|
||||||
<td style="color:#9ca3af; font-size:12px;">
|
<span class="fclk-ts-dot">·</span>
|
||||||
<t t-esc="entry['att'].x_fclk_location_id.name or ''"/>
|
<span><t t-esc="entry['att'].x_fclk_location_id.name or ''"/></span>
|
||||||
</td>
|
</t>
|
||||||
<td>
|
<a href="#" class="fclk-correction-link fclk-ts-correct"
|
||||||
<a href="#" class="fclk-correction-link"
|
t-att-data-att-id="entry['att'].id"
|
||||||
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-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 ''">
|
||||||
t-att-data-check-out="entry['att'].check_out.strftime('%Y-%m-%d %H:%M:%S') if entry['att'].check_out else ''"
|
Correct
|
||||||
style="font-size:11px; color:#6b7280;">
|
</a>
|
||||||
Correct
|
</div>
|
||||||
</a>
|
</div>
|
||||||
</td>
|
</t>
|
||||||
</tr>
|
</div>
|
||||||
</t>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</t>
|
</t>
|
||||||
<t t-else="">
|
<t t-else="">
|
||||||
<div class="fclk-empty-state">
|
<div class="fclk-empty-state">
|
||||||
|
|||||||
Reference in New Issue
Block a user