feat: Credits-System mit Verbrauchsanzeige im User-Dropdown

- DB-Migration: credits_total/credits_used/cost_per_credit auf licenses, token_usage_monthly Tabelle
- Orchestrator: Monatliche Token-Aggregation + Credits-Abzug nach Refresh
- Auth: Credits-Daten im /me Endpoint + Bugfix fehlende Klammer in get()
- Frontend: Credits-Balken im User-Dropdown mit Farbwechsel

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
Claude Dev
2026-03-17 23:53:19 +01:00
Ursprung 4d6d022bee
Commit 7bfa1d29cf
7 geänderte Dateien mit 186 neuen und 1 gelöschten Zeilen

Datei anzeigen

@@ -5335,3 +5335,61 @@ body.tutorial-active .tutorial-cursor {
color: var(--text-primary);
box-shadow: 0 0 0 2px rgba(150, 121, 26, 0.25);
}
/* ===== Credits-Anzeige im User-Dropdown ===== */
.credits-section {
padding: 8px 16px 12px;
}
.credits-divider {
height: 1px;
background: var(--border);
margin-bottom: 10px;
}
.credits-label {
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
color: var(--text-secondary);
margin-bottom: 6px;
}
.credits-bar-container {
width: 100%;
height: 6px;
background: var(--bg-tertiary);
border-radius: 3px;
overflow: hidden;
margin-bottom: 4px;
}
.credits-bar {
height: 100%;
border-radius: 3px;
background: var(--accent);
transition: width 0.6s ease, background-color 0.3s ease;
min-width: 2px;
}
.credits-bar.warning {
background: #e67e22;
}
.credits-bar.critical {
background: #e74c3c;
}
.credits-info {
font-size: 12px;
color: var(--text-secondary);
display: flex;
justify-content: center;
gap: 4px;
}
.credits-info span {
font-weight: 600;
color: var(--text-primary);
}

Datei anzeigen

@@ -50,6 +50,16 @@
<span class="header-dropdown-label">Lizenz</span>
<span class="header-dropdown-value" id="header-license-info">-</span>
</div>
<div id="credits-section" class="credits-section" style="display: none;">
<div class="credits-divider"></div>
<div class="credits-label">Credits</div>
<div class="credits-bar-container">
<div id="credits-bar" class="credits-bar"></div>
</div>
<div class="credits-info">
<span id="credits-remaining">0</span> von <span id="credits-total">0</span>
</div>
</div>
</div>
</div>
<div class="header-license-warning" id="header-license-warning"></div>

Datei anzeigen

@@ -466,6 +466,32 @@ const App = {
licInfoEl.textContent = label;
}
// Credits-Anzeige im Dropdown
const creditsSection = document.getElementById('credits-section');
if (creditsSection && user.credits_total) {
creditsSection.style.display = 'block';
const bar = document.getElementById('credits-bar');
const remainingEl = document.getElementById('credits-remaining');
const totalEl = document.getElementById('credits-total');
const remaining = user.credits_remaining || 0;
const total = user.credits_total || 1;
const percentUsed = user.credits_percent_used || 0;
const percentRemaining = Math.max(0, 100 - percentUsed);
remainingEl.textContent = remaining.toLocaleString('de-DE');
totalEl.textContent = total.toLocaleString('de-DE');
bar.style.width = percentRemaining + '%';
// Farbwechsel je nach Verbrauch
bar.classList.remove('warning', 'critical');
if (percentUsed > 80) {
bar.classList.add('critical');
} else if (percentUsed > 50) {
bar.classList.add('warning');
}
}
// Dropdown Toggle
const userBtn = document.getElementById('header-user-btn');
const userDropdown = document.getElementById('header-user-dropdown');