style: aggiunti effetti per le overperformance.
No files matched your search
@@ -41,6 +41,9 @@ CRYPTO_KEY=f30b91e92d77a06c59b20b2272e2cfbc
|
|||||||
# Soglia in percentuale del target tempo giornaliero per l'attivazione delle frasi demotivazionali (es. 70 per il 70%)
|
# Soglia in percentuale del target tempo giornaliero per l'attivazione delle frasi demotivazionali (es. 70 per il 70%)
|
||||||
PHRASE_THRESHOLD=70
|
PHRASE_THRESHOLD=70
|
||||||
|
|
||||||
|
# Immagine ironica mostrata in caso di overperformance (default over9000.jpg nella cartella public/img)
|
||||||
|
OVERPERFORMANCE_IMAGE=over9000.jpg
|
||||||
|
|
||||||
# Configurazioni per la consuntivazione automatica fine giornata
|
# Configurazioni per la consuntivazione automatica fine giornata
|
||||||
AUTO_TIME_MIN_HOUR=18:00
|
AUTO_TIME_MIN_HOUR=18:00
|
||||||
AUTO_TIME_QUEUE=Assistenza
|
AUTO_TIME_QUEUE=Assistenza
|
||||||
|
|||||||
|
After Width: | Height: | Size: 31 KiB |
@@ -2403,8 +2403,8 @@ body {
|
|||||||
.timer-tooltip {
|
.timer-tooltip {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 105%;
|
left: 105%;
|
||||||
top: 50%;
|
top: -5px;
|
||||||
transform: translateY(-50%) translateX(-8px);
|
transform: translateX(-8px);
|
||||||
width: 290px;
|
width: 290px;
|
||||||
background: var(--bg-secondary);
|
background: var(--bg-secondary);
|
||||||
border: 1px solid var(--border-light);
|
border: 1px solid var(--border-light);
|
||||||
@@ -2423,7 +2423,7 @@ body {
|
|||||||
.timer-tooltip::after {
|
.timer-tooltip::after {
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 18px;
|
||||||
right: 100%;
|
right: 100%;
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
border-width: 6px;
|
border-width: 6px;
|
||||||
@@ -2433,7 +2433,7 @@ body {
|
|||||||
|
|
||||||
.timer-tooltip-border {
|
.timer-tooltip-border {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 50%;
|
top: 18px;
|
||||||
right: 100%;
|
right: 100%;
|
||||||
transform: translateY(-50%);
|
transform: translateY(-50%);
|
||||||
border-width: 7px;
|
border-width: 7px;
|
||||||
@@ -2444,7 +2444,7 @@ body {
|
|||||||
|
|
||||||
.sidebar-timer:hover .timer-tooltip {
|
.sidebar-timer:hover .timer-tooltip {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: translateY(-50%) translateX(0);
|
transform: translateX(0);
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 970 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
@@ -756,6 +756,32 @@ const App = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const overDelta = Math.max(0, mathematicalPercentage - 100);
|
||||||
|
const visualBarWidth = hasOverperformance ? (100 + (overDelta * 3.5)) : percentage;
|
||||||
|
|
||||||
|
let overImgName = 'over9000.jpg';
|
||||||
|
let overPhraseText = '';
|
||||||
|
|
||||||
|
if (mathematicalPercentage > 150) {
|
||||||
|
overImgName = this.lookups?.config?.overperformanceImage || 'over9000.jpg';
|
||||||
|
overPhraseText = "IT'S OVER 9000! Il livello di consuntivazione ha superato ogni limite!";
|
||||||
|
} else if (mathematicalPercentage > 140) {
|
||||||
|
overImgName = 'over_150.jpg';
|
||||||
|
overPhraseText = 'Questo livello di consuntivazione è impossibile.';
|
||||||
|
} else if (mathematicalPercentage > 130) {
|
||||||
|
overImgName = 'over_140.jpg';
|
||||||
|
overPhraseText = 'Io sono il principe dei Saiyan, non glielo permetterò';
|
||||||
|
} else if (mathematicalPercentage > 120) {
|
||||||
|
overImgName = 'over_130.jpg';
|
||||||
|
overPhraseText = 'Sono un Saiyan, non può consuntivare più di me.';
|
||||||
|
} else if (mathematicalPercentage > 110) {
|
||||||
|
overImgName = 'over_120.jpg';
|
||||||
|
overPhraseText = 'Non è possibile! La sua consuntivazione continua ad aumentare.';
|
||||||
|
} else {
|
||||||
|
overImgName = 'over_110.jpg';
|
||||||
|
overPhraseText = "C'è qualcosa di sicuro nella vita. Il più forte è al di sopra di tutti e può consuntivare tutto!";
|
||||||
|
}
|
||||||
|
|
||||||
timerEl.innerHTML = `
|
timerEl.innerHTML = `
|
||||||
<div class="timer-display" style="display:flex; justify-content:space-between; align-items:center; width:100%; font-size:0.75rem; font-weight:500;">
|
<div class="timer-display" style="display:flex; justify-content:space-between; align-items:center; width:100%; font-size:0.75rem; font-weight:500;">
|
||||||
<span>⏱ ${todayTime} / ${targetTime} m</span>
|
<span>⏱ ${todayTime} / ${targetTime} m</span>
|
||||||
@@ -764,21 +790,36 @@ const App = {
|
|||||||
</div>
|
</div>
|
||||||
<div class="timer-tooltip">
|
<div class="timer-tooltip">
|
||||||
<div class="timer-tooltip-border"></div>
|
<div class="timer-tooltip-border"></div>
|
||||||
<div style="font-size:0.75rem; font-weight:600; color:var(--text-primary); margin-bottom:4px; display:flex; justify-content:space-between;">
|
<div style="font-size:0.75rem; font-weight:600; color:var(--text-primary); margin-bottom:4px; display:flex; justify-content:space-between; align-items:center;">
|
||||||
<span>Progresso Giornaliero</span>
|
<span>Progresso Giornaliero</span>
|
||||||
<strong>${mathematicalPercentage}%</strong>
|
<strong>${mathematicalPercentage}% ${hasOverperformance ? '<span style="animation: pulse 1.5s infinite; display:inline-block; margin-left:4px;">⚠️</span>' : ''}</strong>
|
||||||
</div>
|
</div>
|
||||||
<div style="background:var(--border-light); border-radius:var(--radius-full); height:10px; width:100%; overflow:hidden; border:1px solid var(--border-subtle);">
|
<div style="background:var(--border-light); border-radius:var(--radius-full); height:10px; width:100%; position:relative; overflow:visible; border:1px solid var(--border-subtle);">
|
||||||
<div style="width:${percentage}%; background:linear-gradient(90deg, var(--accent-primary), var(--accent-secondary)); height:100%; border-radius:inherit; transition: width 0.3s ease;"></div>
|
<div style="width:${visualBarWidth}%; background:${hasOverperformance ? 'linear-gradient(90deg, var(--accent-primary), #ef4444, #f59e0b, #ec4899)' : 'linear-gradient(90deg, var(--accent-primary), var(--accent-secondary))'}; height:100%; border-radius:var(--radius-full); transition: width 0.3s ease; ${hasOverperformance ? 'box-shadow: 0 0 10px rgba(239, 68, 68, 0.8);' : ''}"></div>
|
||||||
</div>
|
</div>
|
||||||
${hasOverperformance ? `
|
${hasOverperformance ? (() => {
|
||||||
|
const overImgSrc = (overImgName.startsWith('http://') || overImgName.startsWith('https://') || overImgName.startsWith('/')) ? overImgName : `img/${overImgName}`;
|
||||||
|
const imgWidth = Math.min(500, 180 + Math.round(overDelta * 10));
|
||||||
|
return `
|
||||||
<div style="font-size:0.72rem; color:var(--error); font-weight:700; line-height:1.3; text-transform:uppercase; margin-top:8px; border-top:1px solid var(--border-subtle); padding-top:8px; text-align:center; animation: pulse 1.5s infinite;">
|
<div style="font-size:0.72rem; color:var(--error); font-weight:700; line-height:1.3; text-transform:uppercase; margin-top:8px; border-top:1px solid var(--border-subtle); padding-top:8px; text-align:center; animation: pulse 1.5s infinite;">
|
||||||
⚠️ Rilevata una overperformance allontanarsi dalla postazione immediatamente
|
Rilevata una overperformance allontanarsi <span style="font-size:1.4rem; display:block; font-weight:900; margin-top:2px;">IMMEDIATAMENTE</span>
|
||||||
|
</div>
|
||||||
|
<div style="margin-top:6px; text-align:center; position:relative; overflow:visible;">
|
||||||
|
<a href="${App.escapeHtml(overImgSrc)}" target="_blank" title="Apri immagine originale in una nuova scheda" style="display:inline-block; text-decoration:none;">
|
||||||
|
<img src="${App.escapeHtml(overImgSrc)}" alt="Overperformance Meme" style="width:${imgWidth}px; max-width:none; border-radius:var(--radius-md); box-shadow:var(--shadow-md); display:block; margin:0 auto; transition: width 0.3s ease; cursor:pointer;" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
${overPhraseText ? `
|
||||||
|
<div style="font-size:0.75rem; color:var(--text-primary); font-weight:600; line-height:1.35; font-style:italic; margin-top:8px; border-top:1px dashed var(--border-subtle); padding-top:6px; text-align:center;">
|
||||||
|
"${App.escapeHtml(overPhraseText)}"
|
||||||
</div>
|
</div>
|
||||||
` : ''}
|
` : ''}
|
||||||
|
`;
|
||||||
|
})() : `
|
||||||
<div style="font-size:0.72rem; color:var(--text-secondary); line-height:1.35; font-style:italic; margin-top:6px; border-top:1px solid var(--border-subtle); padding-top:6px; text-align:center;">
|
<div style="font-size:0.72rem; color:var(--text-secondary); line-height:1.35; font-style:italic; margin-top:6px; border-top:1px solid var(--border-subtle); padding-top:6px; text-align:center;">
|
||||||
"${phrase}"
|
"${phrase}"
|
||||||
</div>
|
</div>
|
||||||
|
`}
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
// Update sidebar counts as well
|
// Update sidebar counts as well
|
||||||
|
|||||||
@@ -151,7 +151,8 @@ router.get('/config', async (req, res) => {
|
|||||||
phraseThreshold: parseInt(process.env.PHRASE_THRESHOLD, 10) || 70,
|
phraseThreshold: parseInt(process.env.PHRASE_THRESHOLD, 10) || 70,
|
||||||
autoTimeMinHour: process.env.AUTO_TIME_MIN_HOUR || '18:00',
|
autoTimeMinHour: process.env.AUTO_TIME_MIN_HOUR || '18:00',
|
||||||
helpdeskEmail: process.env.OTRS_MAIL_BCC || '',
|
helpdeskEmail: process.env.OTRS_MAIL_BCC || '',
|
||||||
agentEmail: agentEmail
|
agentEmail: agentEmail,
|
||||||
|
overperformanceImage: process.env.OVERPERFORMANCE_IMAGE || 'over9000.jpg'
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||