feat: script per criptare frasi motivazionali/demotivazionali e spostate all'interno del sqllite. Mantenuti file txt per compatibilità. Aggiunta soglia di attivazione nel env

This commit is contained in:
2026-07-08 03:09:44 +02:00
parent e6c3a6a43f
commit d39c9895b4
7 changed files with 208 additions and 13 deletions
+26
View File
@@ -2395,4 +2395,30 @@ body {
opacity: 1;
transform: translateY(-50%) translateX(0);
pointer-events: auto;
}
/* ---- Overperformance Glow ---- */
@keyframes overperformance-glow {
0% {
box-shadow: 0 0 15px rgba(239, 68, 68, 0.4), inset 0 0 15px rgba(239, 68, 68, 0.2);
border-color: rgba(239, 68, 68, 0.6);
}
50% {
box-shadow: 0 0 30px rgba(239, 68, 68, 0.8), inset 0 0 30px rgba(239, 68, 68, 0.4);
border-color: rgba(239, 68, 68, 1);
}
100% {
box-shadow: 0 0 15px rgba(239, 68, 68, 0.4), inset 0 0 15px rgba(239, 68, 68, 0.2);
border-color: rgba(239, 68, 68, 0.6);
}
}
.sidebar-brand.glow {
animation: overperformance-glow 2s infinite;
background: rgba(239, 68, 68, 0.1) !important;
border: 1px solid rgba(239, 68, 68, 0.6) !important;
border-radius: var(--radius-md);
margin: var(--space-sm);
padding: 12px !important;
transition: all 0.5s ease;
}
+26 -11
View File
@@ -387,26 +387,24 @@ const App = {
}
},
/** Load demotivational phrases from txt file */
/** Load demotivational phrases from SQLite cache */
async loadDemotivationalPhrases() {
try {
const res = await fetch('/demotivational.txt');
const res = await fetch('/api/dashboard/phrases?tipo=demotivational');
if (res.ok) {
const text = await res.text();
this.demotivationalPhrases = text.split('\n').map(line => line.trim()).filter(line => line.length > 0);
this.demotivationalPhrases = await res.json();
}
} catch (e) {
console.warn('Failed to load demotivational phrases:', e);
}
},
/** Load motivational phrases from txt file */
/** Load motivational phrases from SQLite cache */
async loadMotivationalPhrases() {
try {
const res = await fetch('/motivational.txt');
const res = await fetch('/api/dashboard/phrases?tipo=motivational');
if (res.ok) {
const text = await res.text();
this.motivationalPhrases = text.split('\n').map(line => line.trim()).filter(line => line.length > 0);
this.motivationalPhrases = await res.json();
}
} catch (e) {
console.warn('Failed to load motivational phrases:', e);
@@ -425,10 +423,22 @@ const App = {
const data = await this.api('/api/users/time-today');
const todayTime = typeof data.totalToday === 'number' ? data.totalToday : 0;
const remaining = Math.max(0, targetTime - todayTime);
const percentage = Math.min(100, Math.round((todayTime / targetTime) * 100));
const mathematicalPercentage = Math.round((todayTime / targetTime) * 100);
const hasOverperformance = mathematicalPercentage > 100;
const percentage = Math.min(100, mathematicalPercentage);
const brandEl = document.querySelector('.sidebar-brand');
if (brandEl) {
if (hasOverperformance) {
brandEl.classList.add('glow');
} else {
brandEl.classList.remove('glow');
}
}
let phrase = "";
const isDemotivational = percentage >= 70;
const phraseThreshold = this.lookups.config?.phraseThreshold || 70;
const isDemotivational = percentage >= phraseThreshold;
if (isDemotivational) {
if (this.demotivationalPhrases.length > 0) {
@@ -458,11 +468,16 @@ const App = {
<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;">
<span>Progresso Giornaliero</span>
<strong>${percentage}%</strong>
<strong>${mathematicalPercentage}%</strong>
</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="width:${percentage}%; background:linear-gradient(90deg, var(--accent-primary), var(--accent-secondary)); height:100%; border-radius:inherit; transition: width 0.3s ease;"></div>
</div>
${hasOverperformance ? `
<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
</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;">
"${phrase}"
</div>