changes
This commit is contained in:
155
fusion_clock/static/src/xml/fusion_clock_dashboard.xml
Normal file
155
fusion_clock/static/src/xml/fusion_clock_dashboard.xml
Normal file
@@ -0,0 +1,155 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<t t-name="fusion_clock.Dashboard">
|
||||
<div class="o_action">
|
||||
<div class="container-fluid py-3">
|
||||
|
||||
<!-- Header -->
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h2 class="mb-0">Fusion Clock Dashboard</h2>
|
||||
<button class="btn btn-outline-primary" t-on-click="onRefresh">
|
||||
<i class="fa fa-refresh"/> Refresh
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<t t-if="state.loading">
|
||||
<div class="text-center py-5">
|
||||
<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="alert alert-danger">
|
||||
<t t-esc="state.error"/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-if="!state.loading and !state.error">
|
||||
<!-- Summary Cards -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="fclk-dash-card fclk-dash-card--total">
|
||||
<div class="fclk-dash-card-icon">
|
||||
<i class="fa fa-users"/>
|
||||
</div>
|
||||
<div class="fclk-dash-card-value"><t t-esc="state.total_employees"/></div>
|
||||
<div class="fclk-dash-card-label">Total Employees</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="fclk-dash-card fclk-dash-card--present">
|
||||
<div class="fclk-dash-card-icon">
|
||||
<i class="fa fa-check-circle"/>
|
||||
</div>
|
||||
<div class="fclk-dash-card-value"><t t-esc="state.present_count"/></div>
|
||||
<div class="fclk-dash-card-label">Present Today</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="fclk-dash-card fclk-dash-card--absent">
|
||||
<div class="fclk-dash-card-icon">
|
||||
<i class="fa fa-times-circle"/>
|
||||
</div>
|
||||
<div class="fclk-dash-card-value"><t t-esc="state.absent_count"/></div>
|
||||
<div class="fclk-dash-card-label">Absent Today</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 mb-3">
|
||||
<div class="fclk-dash-card fclk-dash-card--late">
|
||||
<div class="fclk-dash-card-icon">
|
||||
<i class="fa fa-clock-o"/>
|
||||
</div>
|
||||
<div class="fclk-dash-card-value"><t t-esc="state.late_count"/></div>
|
||||
<div class="fclk-dash-card-label">Late Today</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- Currently Clocked In -->
|
||||
<div class="col-md-8 mb-4">
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-0">Currently Clocked In</h5>
|
||||
<span class="badge bg-success"><t t-esc="state.clocked_in.length"/> active</span>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<t t-if="state.clocked_in.length === 0">
|
||||
<div class="text-center py-4 text-muted">
|
||||
No employees currently clocked in
|
||||
</div>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<table class="table table-sm mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Employee</th>
|
||||
<th>Clock-In</th>
|
||||
<th>Location</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<t t-foreach="state.clocked_in" t-as="emp" t-key="emp_index">
|
||||
<tr>
|
||||
<td><t t-esc="emp.employee"/></td>
|
||||
<td><t t-esc="emp.check_in"/></td>
|
||||
<td><t t-esc="emp.location"/></td>
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Alerts Panel -->
|
||||
<div class="col-md-4 mb-4">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">Alerts</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3 cursor-pointer"
|
||||
t-on-click="onViewActivityLogs">
|
||||
<span><i class="fa fa-exclamation-circle text-warning me-2"/>Pending Reasons</span>
|
||||
<span class="badge bg-warning"><t t-esc="state.pending_reasons"/></span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between align-items-center mb-3 cursor-pointer"
|
||||
t-on-click="onViewCorrections">
|
||||
<span><i class="fa fa-edit text-info me-2"/>Pending Corrections</span>
|
||||
<span class="badge bg-info"><t t-esc="state.pending_corrections"/></span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between align-items-center cursor-pointer"
|
||||
t-on-click="onViewPenalties">
|
||||
<span><i class="fa fa-clock-o text-danger me-2"/>Late Today</span>
|
||||
<span class="badge bg-danger"><t t-esc="state.late_count"/></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick Actions -->
|
||||
<div class="card mt-3">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">Quick Actions</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<button class="btn btn-outline-primary w-100 mb-2" t-on-click="onViewAttendances">
|
||||
<i class="fa fa-list me-1"/> View All Attendances
|
||||
</button>
|
||||
<button class="btn btn-outline-secondary w-100" t-on-click="onViewActivityLogs">
|
||||
<i class="fa fa-history me-1"/> Activity Logs
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
40
fusion_clock/static/src/xml/fusion_clock_location.xml
Normal file
40
fusion_clock/static/src/xml/fusion_clock_location.xml
Normal file
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<templates xml:space="preserve">
|
||||
|
||||
<!-- Interactive Map Widget -->
|
||||
<t t-name="fusion_clock.LocationMap">
|
||||
<div class="fclk-map-widget">
|
||||
<div t-if="state.loading" class="fclk-map-loading">
|
||||
<i class="fa fa-circle-o-notch fa-spin"/> Loading map...
|
||||
</div>
|
||||
<div t-if="state.error" class="fclk-map-error">
|
||||
<i class="fa fa-exclamation-triangle"/> <t t-esc="state.error"/>
|
||||
</div>
|
||||
<!-- ALWAYS in the DOM so the ref is available at mount time.
|
||||
Hidden via inline display:none until the map is ready. -->
|
||||
<div t-ref="mapContainer"
|
||||
class="fclk-map-container"
|
||||
t-att-style="state.mapVisible ? 'width:100%;height:400px;border-radius:8px;' : 'display:none;'"/>
|
||||
<div t-if="state.mapVisible and !props.readonly" class="fclk-map-hint">
|
||||
<i class="fa fa-hand-pointer-o"/> Click the map or drag the marker to fine-tune the location
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!-- Places Autocomplete Widget -->
|
||||
<t t-name="fusion_clock.PlacesAutocomplete">
|
||||
<t t-if="isReadonly">
|
||||
<span t-esc="props.record.data[props.name] || ''"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
<input t-ref="addressInput"
|
||||
type="text"
|
||||
class="o_input fclk-places-input"
|
||||
t-att-value="state.value"
|
||||
t-on-input="onInput"
|
||||
t-on-change="onChange"
|
||||
placeholder="Start typing an address..."/>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
@@ -68,20 +68,91 @@
|
||||
<!-- Floating Action Button -->
|
||||
<button t-attf-class="fclk-fab-btn {{ state.isCheckedIn ? 'fclk-fab-btn--active' : '' }} {{ state.expanded ? 'fclk-fab-btn--open' : '' }}"
|
||||
t-on-click="togglePanel">
|
||||
<!-- Ripple rings (always animate) -->
|
||||
<span t-if="state.isCheckedIn" class="fclk-fab-ripple-ring fclk-fab-ripple-ring--1"/>
|
||||
<span t-if="state.isCheckedIn" class="fclk-fab-ripple-ring fclk-fab-ripple-ring--2"/>
|
||||
<span t-if="state.isCheckedIn" class="fclk-fab-ripple-ring fclk-fab-ripple-ring--3"/>
|
||||
<!-- Icon -->
|
||||
<span class="fclk-fab-icon">
|
||||
<i t-if="!state.expanded" class="fa fa-clock-o"/>
|
||||
<i t-else="" class="fa fa-times"/>
|
||||
</span>
|
||||
<!-- Mini timer badge -->
|
||||
<span t-if="state.isCheckedIn and !state.expanded" class="fclk-fab-badge">
|
||||
<t t-esc="state.timerDisplay"/>
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<!-- Missed Clock-Out Reason Dialog -->
|
||||
<div t-if="state.showReasonDialog" class="fclk-fab-dialog-overlay">
|
||||
<div class="fclk-fab-dialog-backdrop" t-on-click="cancelReason"/>
|
||||
<div class="fclk-fab-dialog">
|
||||
<div class="fclk-fab-dialog-header fclk-fab-dialog-header--warning">
|
||||
<div class="fclk-fab-dialog-icon">
|
||||
<i class="fa fa-exclamation-triangle"/>
|
||||
</div>
|
||||
<h4 class="fclk-fab-dialog-title">Missed Clock-Out</h4>
|
||||
<p class="fclk-fab-dialog-subtitle">You didn't clock out on your last shift. Please provide details before continuing.</p>
|
||||
</div>
|
||||
<div class="fclk-fab-dialog-body">
|
||||
<div class="fclk-fab-dialog-field">
|
||||
<label class="fclk-fab-dialog-label">
|
||||
<i class="fa fa-comment-o"/> Reason <span class="fclk-fab-dialog-required">*</span>
|
||||
</label>
|
||||
<textarea class="fclk-fab-dialog-input" rows="3"
|
||||
placeholder="Please explain why you didn't clock out..."
|
||||
t-on-input="onReasonTextInput"
|
||||
t-att-value="state.reasonText"/>
|
||||
</div>
|
||||
<div class="fclk-fab-dialog-field">
|
||||
<label class="fclk-fab-dialog-label">
|
||||
<i class="fa fa-clock-o"/> Departure Time
|
||||
</label>
|
||||
<input type="datetime-local" class="fclk-fab-dialog-input"
|
||||
t-on-input="onReasonTimeInput"
|
||||
t-att-value="state.reasonTime"/>
|
||||
<span class="fclk-fab-dialog-hint">When did you actually leave? (optional)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fclk-fab-dialog-footer">
|
||||
<button class="fclk-fab-dialog-btn fclk-fab-dialog-btn--cancel" t-on-click="cancelReason">Cancel</button>
|
||||
<button class="fclk-fab-dialog-btn fclk-fab-dialog-btn--submit" t-on-click="submitReason"
|
||||
t-att-disabled="state.reasonSubmitting">
|
||||
<t t-if="state.reasonSubmitting"><i class="fa fa-circle-o-notch fa-spin"/> Submitting...</t>
|
||||
<t t-else=""><i class="fa fa-check"/> Submit Reason</t>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Clock-Out Confirmation Dialog -->
|
||||
<div t-if="state.showClockoutConfirm" class="fclk-fab-dialog-overlay">
|
||||
<div class="fclk-fab-dialog-backdrop" t-on-click="cancelClockOut"/>
|
||||
<div class="fclk-fab-dialog fclk-fab-dialog--compact">
|
||||
<div class="fclk-fab-dialog-header fclk-fab-dialog-header--danger">
|
||||
<div class="fclk-fab-dialog-icon">
|
||||
<i class="fa fa-stop-circle"/>
|
||||
</div>
|
||||
<h4 class="fclk-fab-dialog-title">Clock Out?</h4>
|
||||
<p class="fclk-fab-dialog-subtitle">Are you sure you want to end your current shift?</p>
|
||||
</div>
|
||||
<div class="fclk-fab-dialog-body">
|
||||
<div class="fclk-fab-dialog-summary">
|
||||
<div class="fclk-fab-dialog-summary-row">
|
||||
<span class="fclk-fab-dialog-summary-label">Clocked in at</span>
|
||||
<span class="fclk-fab-dialog-summary-value" t-esc="confirmCheckinDisplay"/>
|
||||
</div>
|
||||
<div class="fclk-fab-dialog-summary-row">
|
||||
<span class="fclk-fab-dialog-summary-label">Duration</span>
|
||||
<span class="fclk-fab-dialog-summary-value" t-esc="confirmDurationDisplay"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fclk-fab-dialog-footer">
|
||||
<button class="fclk-fab-dialog-btn fclk-fab-dialog-btn--cancel" t-on-click="cancelClockOut">Cancel</button>
|
||||
<button class="fclk-fab-dialog-btn fclk-fab-dialog-btn--danger" t-on-click="confirmClockOut">
|
||||
<i class="fa fa-stop-circle-o"/> Confirm Clock Out
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user