feat: per-account quota threshold protection (#212)

feat: per-account quota threshold protection

Resolves #135

- Adds configurable quota protection with three-tier threshold resolution (per-model → per-account → global)
- New global Minimum Quota Level slider in Settings
- Per-account threshold settings via Account Settings modal
- Draggable per-account threshold markers on model quota bars
- Backend: PATCH /api/accounts/:email endpoint, globalQuotaThreshold config
- i18n: quota protection keys for all 5 languages
This commit is contained in:
jgor20
2026-02-01 11:45:46 +00:00
committed by GitHub
parent 33584d31bb
commit a43d2332ca
23 changed files with 806 additions and 31 deletions

View File

@@ -1222,6 +1222,38 @@
</div>
</div>
<!-- Quota Protection -->
<div class="space-y-4 pt-2 border-t border-space-border/10">
<div class="flex items-center gap-2 mb-2">
<span class="text-[10px] text-gray-500 font-bold uppercase tracking-widest"
x-text="$store.global.t('quotaProtection')">Quota Protection</span>
</div>
<div class="form-control">
<label class="label pt-0">
<span class="label-text text-gray-400 text-xs"
x-text="$store.global.t('minimumQuotaLevel')">Minimum Quota Level</span>
<span class="label-text-alt font-mono text-neon-green text-xs font-semibold"
x-text="Math.round((serverConfig.globalQuotaThreshold || 0) * 100) > 0 ? Math.round((serverConfig.globalQuotaThreshold || 0) * 100) + '%' : $store.global.t('quotaDisabled')"></span>
</label>
<div class="flex gap-3 items-center">
<input type="range" min="0" max="99" step="1"
class="custom-range custom-range-green flex-1"
:value="Math.round((serverConfig.globalQuotaThreshold || 0) * 100)"
:style="`background-size: ${Math.round((serverConfig.globalQuotaThreshold || 0) * 100) / 99 * 100}% 100%`"
@input="toggleGlobalQuotaThreshold($event.target.value)"
aria-label="Minimum quota level slider">
<input type="number" min="0" max="99"
class="input input-xs input-bordered w-16 bg-space-800 border-space-border text-white font-mono text-center"
:value="Math.round((serverConfig.globalQuotaThreshold || 0) * 100)"
@change="toggleGlobalQuotaThreshold($event.target.value)"
aria-label="Minimum quota level value">
</div>
<p class="text-[9px] text-gray-600 mt-1 leading-tight"
x-text="$store.global.t('minimumQuotaLevelDesc')">Switch accounts when quota drops below this level. Per-account overrides take priority.</p>
</div>
</div>
<!-- Error Handling Tuning -->
<div class="space-y-4 pt-2 border-t border-space-border/10">
<div class="flex items-center gap-2 mb-2">