feat(ST-qfpqpxzy): DB schema + settings-UI voor min_quota_pct worker-drempel (#118)
- User.min_quota_pct Int @default(20) + ClaudeWorker.last_quota_pct/last_quota_check_at - Migratie add_worker_quota_gate - lib/schemas/user.ts: minQuotaPctSchema (int, 1-100) - actions/settings.ts: updateMinQuotaPctAction met auth/demo/zod-guard - MinQuotaEditor component met numeric input en DemoTooltip - Settings-pagina: Worker-instellingen sectie Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
78543ee796
commit
555ed8fe89
7 changed files with 190 additions and 4 deletions
59
components/settings/min-quota-editor.tsx
Normal file
59
components/settings/min-quota-editor.tsx
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
'use client'
|
||||
|
||||
import { useState, useTransition } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { DemoTooltip } from '@/components/shared/demo-tooltip'
|
||||
import { updateMinQuotaPctAction } from '@/actions/settings'
|
||||
|
||||
interface MinQuotaEditorProps {
|
||||
currentValue: number
|
||||
isDemo: boolean
|
||||
}
|
||||
|
||||
export function MinQuotaEditor({ currentValue, isDemo }: MinQuotaEditorProps) {
|
||||
const [value, setValue] = useState(currentValue)
|
||||
const [isPending, startTransition] = useTransition()
|
||||
|
||||
function handleSave() {
|
||||
startTransition(async () => {
|
||||
const result = await updateMinQuotaPctAction(value)
|
||||
if ('error' in result) {
|
||||
toast.error(result.error as string)
|
||||
} else {
|
||||
toast.success('Instelling opgeslagen')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<label htmlFor="min-quota-pct" className="text-sm font-medium text-foreground">
|
||||
Minimaal beschikbaar Claude-quota voordat de worker een job oppakt (%)
|
||||
</label>
|
||||
<p className="text-xs text-muted-foreground mt-0.5">
|
||||
Worker slaapt tot quota gereset is wanneer onder deze drempel.
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<input
|
||||
id="min-quota-pct"
|
||||
type="number"
|
||||
min={1}
|
||||
max={100}
|
||||
value={value}
|
||||
onChange={e => setValue(Number(e.target.value))}
|
||||
disabled={isDemo || isPending}
|
||||
className="w-24 rounded border border-border bg-surface-container px-3 py-1.5 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-primary disabled:opacity-50"
|
||||
/>
|
||||
<span className="text-sm text-muted-foreground">%</span>
|
||||
<DemoTooltip show={isDemo}>
|
||||
<Button onClick={handleSave} disabled={isDemo || isPending} size="sm">
|
||||
Opslaan
|
||||
</Button>
|
||||
</DemoTooltip>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue