changes
This commit is contained in:
@@ -66,12 +66,23 @@ html.o_dark .fclk-app,
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Hide portal navigation */
|
||||
/* Hide portal navigation and footer */
|
||||
.fclk-app ~ .o_portal_navbar,
|
||||
.fclk-app .o_portal_navbar {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.fclk-app ~ footer,
|
||||
.fclk-app ~ .o_footer,
|
||||
.fclk-app ~ .o_footer_copyright {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
body:has(.fclk-app) footer,
|
||||
body:has(.fclk-app) .o_footer {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.fclk-container {
|
||||
max-width: 480px;
|
||||
margin: 0 auto;
|
||||
@@ -224,11 +235,12 @@ html.o_dark .fclk-app,
|
||||
|
||||
.fclk-timer {
|
||||
color: var(--fclk-text);
|
||||
font-size: 52px;
|
||||
font-size: clamp(32px, 10vw, 52px);
|
||||
font-weight: 300;
|
||||
letter-spacing: 4px;
|
||||
letter-spacing: 2px;
|
||||
font-variant-numeric: tabular-nums;
|
||||
font-family: 'SF Mono', 'Fira Code', 'Courier New', monospace;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* ---- Clock Button ---- */
|
||||
@@ -282,6 +294,13 @@ html.o_dark .fclk-app,
|
||||
.fclk-btn-icon {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.fclk-btn-icon svg[id="fclk-btn-icon-play"] {
|
||||
transform: translateX(3px);
|
||||
}
|
||||
|
||||
.fclk-btn-ripple {
|
||||
@@ -1000,14 +1019,15 @@ html.o_dark .fclk-wizard-overlay {
|
||||
}
|
||||
|
||||
/* ---- Responsive ---- */
|
||||
@media (max-width: 380px) {
|
||||
.fclk-timer {
|
||||
font-size: 40px;
|
||||
}
|
||||
@media (max-width: 420px) {
|
||||
.fclk-clock-btn {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
.fclk-clock-btn svg {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
.fclk-stat-value {
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,13 @@ export class FusionClockPortal extends Interaction {
|
||||
this.checkInTime = new Date(this.el.dataset.checkInTime + "Z");
|
||||
}
|
||||
|
||||
// If server didn't provide check-in data, try localStorage
|
||||
if (!this.isCheckedIn || !this.checkInTime) {
|
||||
this._restoreState();
|
||||
} else {
|
||||
this._saveState();
|
||||
}
|
||||
|
||||
// Load locations
|
||||
const locDataEl = document.getElementById("fclk-locations-data");
|
||||
this.locations = [];
|
||||
@@ -34,9 +41,6 @@ export class FusionClockPortal extends Interaction {
|
||||
this.selectedLocationId = this.locations[0].id;
|
||||
}
|
||||
|
||||
// Restore localStorage state
|
||||
this._restoreState();
|
||||
|
||||
// Start live clock
|
||||
this._updateCurrentTime();
|
||||
this.clockInterval = setInterval(() => this._updateCurrentTime(), 1000);
|
||||
@@ -44,6 +48,9 @@ export class FusionClockPortal extends Interaction {
|
||||
// Start timer if checked in
|
||||
if (this.isCheckedIn && this.checkInTime) {
|
||||
this._startTimer();
|
||||
this._updateUIForClockIn({
|
||||
location_name: this.el.dataset.locationName || "",
|
||||
});
|
||||
}
|
||||
|
||||
this._updateDateDisplay();
|
||||
@@ -51,14 +58,16 @@ export class FusionClockPortal extends Interaction {
|
||||
// Event listeners
|
||||
this._setupEventListeners();
|
||||
|
||||
// Visibility sync
|
||||
// Visibility sync -- also sync on load to verify with server
|
||||
this._onVisibilityChange = () => this._syncOnVisibilityChange();
|
||||
document.addEventListener("visibilitychange", this._onVisibilityChange);
|
||||
this._syncTimeout = setTimeout(() => this._syncOnVisibilityChange(), 3000);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this._stopTimer();
|
||||
if (this.clockInterval) clearInterval(this.clockInterval);
|
||||
if (this._syncTimeout) clearTimeout(this._syncTimeout);
|
||||
if (this._onVisibilityChange) {
|
||||
document.removeEventListener("visibilitychange", this._onVisibilityChange);
|
||||
}
|
||||
@@ -247,6 +256,7 @@ export class FusionClockPortal extends Interaction {
|
||||
if (result.action === "clock_in") {
|
||||
this.isCheckedIn = true;
|
||||
this.checkInTime = new Date(result.check_in + "Z");
|
||||
this.el.dataset.locationName = result.location_name || "";
|
||||
this._updateUIForClockIn(result);
|
||||
this._startTimer();
|
||||
this._playSound("in");
|
||||
@@ -483,6 +493,9 @@ export class FusionClockPortal extends Interaction {
|
||||
if (this.checkInTime) {
|
||||
localStorage.setItem("fclk_check_in_time", this.checkInTime.toISOString());
|
||||
}
|
||||
if (this.el.dataset.locationName) {
|
||||
localStorage.setItem("fclk_location_name", this.el.dataset.locationName);
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
@@ -490,13 +503,21 @@ export class FusionClockPortal extends Interaction {
|
||||
try {
|
||||
localStorage.removeItem("fclk_checked_in");
|
||||
localStorage.removeItem("fclk_check_in_time");
|
||||
localStorage.removeItem("fclk_location_name");
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
_restoreState() {
|
||||
try {
|
||||
if (!this.isCheckedIn && localStorage.getItem("fclk_checked_in") === "true") {
|
||||
this._clearState();
|
||||
const wasCheckedIn = localStorage.getItem("fclk_checked_in") === "true";
|
||||
const savedTime = localStorage.getItem("fclk_check_in_time");
|
||||
if (wasCheckedIn && savedTime) {
|
||||
const t = new Date(savedTime);
|
||||
if (!isNaN(t.getTime()) && (Date.now() - t.getTime()) < 24 * 60 * 60 * 1000) {
|
||||
this.isCheckedIn = true;
|
||||
this.checkInTime = t;
|
||||
this.el.dataset.locationName = localStorage.getItem("fclk_location_name") || "";
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
@@ -587,6 +608,12 @@ export class FusionClockPortal extends Interaction {
|
||||
this._updateUIForClockIn({ location_name: result.location_name });
|
||||
this._startTimer();
|
||||
this._saveState();
|
||||
} else if (result.is_checked_in && this.isCheckedIn) {
|
||||
const serverTime = new Date(result.check_in + "Z");
|
||||
if (Math.abs(serverTime - this.checkInTime) > 5000) {
|
||||
this.checkInTime = serverTime;
|
||||
this._saveState();
|
||||
}
|
||||
} else if (!result.is_checked_in && this.isCheckedIn) {
|
||||
this.isCheckedIn = false;
|
||||
this._updateUIForClockOut({});
|
||||
@@ -602,7 +629,9 @@ export class FusionClockPortal extends Interaction {
|
||||
if (weekEl && result.week_hours !== undefined) {
|
||||
weekEl.textContent = result.week_hours.toFixed(1) + "h";
|
||||
}
|
||||
} catch (e) {}
|
||||
} catch {
|
||||
// Server unavailable (restarting) -- keep timer running from localStorage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,26 +76,44 @@ export class FusionClockFAB extends Component {
|
||||
async _fetchStatus() {
|
||||
try {
|
||||
const result = await rpc("/fusion_clock/get_status", {});
|
||||
if (result.error) {
|
||||
this.state.isDisplayed = false;
|
||||
return;
|
||||
}
|
||||
if (result.error) return;
|
||||
|
||||
this.state.isDisplayed = result.enable_clock !== false;
|
||||
this.state.isCheckedIn = result.is_checked_in;
|
||||
this.state.locationName = result.location_name || "";
|
||||
this.state.todayHours = (result.today_hours || 0).toFixed(1);
|
||||
this.state.weekHours = (result.week_hours || 0).toFixed(1);
|
||||
|
||||
if (result.is_checked_in && result.check_in) {
|
||||
this.state.checkInTime = new Date(result.check_in + "Z");
|
||||
this._startTimer();
|
||||
} else {
|
||||
const serverTime = new Date(result.check_in + "Z");
|
||||
const wasRunning = this.state.isCheckedIn;
|
||||
this.state.isCheckedIn = true;
|
||||
if (!wasRunning || Math.abs(serverTime - this.state.checkInTime) > 5000) {
|
||||
this.state.checkInTime = serverTime;
|
||||
this._startTimer();
|
||||
}
|
||||
try { localStorage.setItem("fclk_fab_check_in", serverTime.toISOString()); } catch {}
|
||||
} else if (!result.is_checked_in) {
|
||||
this.state.isCheckedIn = false;
|
||||
this.state.checkInTime = null;
|
||||
this._stopTimer();
|
||||
this.state.timerDisplay = "00:00:00";
|
||||
try { localStorage.removeItem("fclk_fab_check_in"); } catch {}
|
||||
}
|
||||
} catch {
|
||||
if (!this.state.isCheckedIn) {
|
||||
try {
|
||||
const saved = localStorage.getItem("fclk_fab_check_in");
|
||||
if (saved) {
|
||||
const t = new Date(saved);
|
||||
if (!isNaN(t.getTime()) && (Date.now() - t.getTime()) < 24 * 60 * 60 * 1000) {
|
||||
this.state.isDisplayed = true;
|
||||
this.state.isCheckedIn = true;
|
||||
this.state.checkInTime = t;
|
||||
this._startTimer();
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
} catch (e) {
|
||||
this.state.isDisplayed = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user