feat: aggiunta consuntivazione automatica tramite variabili env. style: aggiunto bordino anche attorno al tempo nel caso di overperformance

This commit is contained in:
2026-07-08 08:26:10 +02:00
parent fd78b7e283
commit 3b06609fcb
5 changed files with 439 additions and 3 deletions
+71
View File
@@ -2421,4 +2421,75 @@ body {
margin: var(--space-sm);
padding: 12px !important;
transition: all 0.5s ease;
}
@keyframes autotime-pulse {
0% {
box-shadow: 0 0 5px rgba(16, 112, 202, 0.4);
border-color: rgba(16, 112, 202, 0.5);
}
50% {
box-shadow: 0 0 15px rgba(16, 112, 202, 0.8), inset 0 0 5px rgba(16, 112, 202, 0.3);
border-color: rgba(16, 112, 202, 0.9);
background: rgba(16, 112, 202, 0.15);
}
100% {
box-shadow: 0 0 5px rgba(16, 112, 202, 0.4);
border-color: rgba(16, 112, 202, 0.5);
}
}
.sidebar-brand.clickable-auto-time {
cursor: pointer;
animation: autotime-pulse 2.5s infinite ease-in-out;
border: 1px dashed var(--accent-primary) !important;
border-radius: var(--radius-md);
margin: var(--space-xs) var(--space-sm);
padding: 8px 12px !important;
transition: all 0.3s ease;
}
.sidebar-brand.clickable-auto-time:hover {
filter: brightness(1.2);
transform: translateY(-1px);
}
.sidebar-timer.clickable-auto-time {
cursor: pointer;
animation: autotime-pulse 2.5s infinite ease-in-out;
border: 1px dashed var(--accent-primary) !important;
border-radius: var(--radius-md);
margin: var(--space-xs) var(--space-sm);
padding: 8px 12px !important;
transition: all 0.3s ease;
}
.sidebar-timer.clickable-auto-time:hover {
filter: brightness(1.2);
transform: translateY(-1px);
}
@keyframes overperformance-alarm-pulse {
0% {
box-shadow: 0 0 5px rgba(239, 68, 68, 0.4);
border-color: rgba(239, 68, 68, 0.6);
}
50% {
box-shadow: 0 0 15px rgba(239, 68, 68, 0.8), inset 0 0 5px rgba(239, 68, 68, 0.3);
border-color: rgba(239, 68, 68, 0.9);
background: rgba(239, 68, 68, 0.15) !important;
}
100% {
box-shadow: 0 0 5px rgba(239, 68, 68, 0.4);
border-color: rgba(239, 68, 68, 0.6);
}
}
.sidebar-timer.overperformance-alarm {
animation: overperformance-alarm-pulse 1.5s infinite ease-in-out;
border: 1px solid rgba(239, 68, 68, 0.6) !important;
border-radius: var(--radius-md);
margin: var(--space-xs) var(--space-sm);
padding: 8px 12px !important;
transition: all 0.3s ease;
}
+69 -1
View File
@@ -186,10 +186,13 @@ const App = {
if (cached) {
try {
this.lookups = JSON.parse(cached);
if (!this.lookups.config || this.lookups.config.autoTimeMinHour === undefined) {
throw new Error('Outdated config cache (missing autoTimeMinHour)');
}
this.lookupsLoaded = true;
return;
} catch (e) {
console.warn('Failed to parse cached lookups, reloading...', e);
console.warn('Failed to parse cached lookups, reloading...', e.message);
}
}
}
@@ -436,6 +439,71 @@ const App = {
}
}
if (timerEl) {
if (hasOverperformance) {
timerEl.classList.add('overperformance-alarm');
} else {
timerEl.classList.remove('overperformance-alarm');
}
}
const minTimeStr = this.lookups.config?.autoTimeMinHour || '18:00';
const [minHour, minMin] = minTimeStr.split(':').map(x => parseInt(x, 10));
const now = new Date();
const currentHour = now.getHours();
const currentMin = now.getMinutes();
let isPastTime = false;
if (currentHour > minHour) {
isPastTime = true;
} else if (currentHour === minHour && currentMin >= minMin) {
isPastTime = true;
}
const triggerAction = async (e) => {
e.preventDefault();
e.stopPropagation();
const confirmed = confirm(`Sei sicuro di voler effettuare la consuntivazione automatica di ${remaining} minuti rimanenti di oggi? Verrà creato un ticket chiuso a tuo carico.`);
if (!confirmed) return;
try {
Toast.success('Consuntivazione in corso...');
const res = await this.api('/api/tickets/auto-time', { method: 'POST' });
Toast.success(res.message || 'Consuntivazione completata!');
this.updateDailyTimer();
this.route();
} catch (err) {
Toast.error('Errore consuntivazione automatica: ' + err.message);
}
};
if (isPastTime && remaining > 0) {
if (brandEl) {
brandEl.classList.add('clickable-auto-time');
brandEl.setAttribute('title', `Consuntivazione Automatica fine giornata (${remaining} m)`);
brandEl.onclick = triggerAction;
}
if (timerEl) {
timerEl.classList.add('clickable-auto-time');
timerEl.setAttribute('title', `Consuntivazione Automatica fine giornata (${remaining} m). Clicca per eseguire.`);
timerEl.onclick = triggerAction;
}
} else {
if (brandEl) {
brandEl.classList.remove('clickable-auto-time');
brandEl.removeAttribute('title');
brandEl.onclick = null;
}
if (timerEl) {
timerEl.classList.remove('clickable-auto-time');
timerEl.removeAttribute('title');
timerEl.onclick = null;
}
}
let phrase = "";
const phraseThreshold = this.lookups.config?.phraseThreshold || 70;
const isDemotivational = percentage >= phraseThreshold;