feat(admin, settlement, dashboard): strengthen permission gating and billing workflows
This commit is contained in:
@@ -12,6 +12,9 @@ import type { AdminSettingBatchItem } from "@/api/admin-settings";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { adminHasAnyPermission } from "@/lib/admin-permissions";
|
||||
import { PRD_DRAW_RESULT_MANAGE } from "@/lib/admin-prd";
|
||||
import { useAdminProfile } from "@/stores/admin-session";
|
||||
|
||||
interface DrawDraft {
|
||||
defaultCurrency: string;
|
||||
@@ -90,6 +93,8 @@ function buildDirtyItems(draft: DrawDraft, saved: DrawDraft): AdminSettingBatchI
|
||||
|
||||
export function DrawSettingsPanel() {
|
||||
const { t } = useTranslation(["config", "adminUsers", "common"]);
|
||||
const profile = useAdminProfile();
|
||||
const canManage = adminHasAnyPermission(profile?.permissions, [PRD_DRAW_RESULT_MANAGE]);
|
||||
const { request: requestConfirm, ConfirmDialog } = useConfirmAction();
|
||||
const buildItems = useCallback(buildDirtyItems, []);
|
||||
const section = useSettingsSection({
|
||||
@@ -113,7 +118,7 @@ export function DrawSettingsPanel() {
|
||||
<Label className="text-sm font-medium">{t("system.fields.manualReview", { ns: "config" })}</Label>
|
||||
<Switch
|
||||
checked={draft.requireManualReview}
|
||||
disabled={loading || saving}
|
||||
disabled={!canManage || loading || saving}
|
||||
aria-label={t("system.fields.manualReview", { ns: "config" })}
|
||||
onCheckedChange={(value) => updateField("requireManualReview", value)}
|
||||
/>
|
||||
@@ -131,7 +136,7 @@ export function DrawSettingsPanel() {
|
||||
value={draft.defaultCurrency}
|
||||
placeholder={t("system.placeholders.defaultCurrency", { ns: "config" })}
|
||||
onChange={(e) => updateField("defaultCurrency", e.target.value.toUpperCase())}
|
||||
disabled={loading || saving}
|
||||
disabled={!canManage || loading || saving}
|
||||
maxLength={16}
|
||||
/>
|
||||
</div>
|
||||
@@ -148,7 +153,7 @@ export function DrawSettingsPanel() {
|
||||
value={draft.drawIntervalMinutes}
|
||||
placeholder={t("system.placeholders.drawIntervalMinutes", { ns: "config" })}
|
||||
onChange={(e) => updateField("drawIntervalMinutes", e.target.value)}
|
||||
disabled={loading || saving}
|
||||
disabled={!canManage || loading || saving}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
@@ -163,7 +168,7 @@ export function DrawSettingsPanel() {
|
||||
value={draft.drawBettingWindowSeconds}
|
||||
placeholder={t("system.placeholders.drawBettingWindowSeconds", { ns: "config" })}
|
||||
onChange={(e) => updateField("drawBettingWindowSeconds", e.target.value)}
|
||||
disabled={loading || saving}
|
||||
disabled={!canManage || loading || saving}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
@@ -178,7 +183,7 @@ export function DrawSettingsPanel() {
|
||||
value={draft.drawCloseBeforeDrawSeconds}
|
||||
placeholder={t("system.placeholders.drawCloseBeforeDrawSeconds", { ns: "config" })}
|
||||
onChange={(e) => updateField("drawCloseBeforeDrawSeconds", e.target.value)}
|
||||
disabled={loading || saving}
|
||||
disabled={!canManage || loading || saving}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
@@ -193,7 +198,7 @@ export function DrawSettingsPanel() {
|
||||
value={draft.drawBufferDrawsAhead}
|
||||
placeholder={t("system.placeholders.drawBufferDrawsAhead", { ns: "config" })}
|
||||
onChange={(e) => updateField("drawBufferDrawsAhead", e.target.value)}
|
||||
disabled={loading || saving}
|
||||
disabled={!canManage || loading || saving}
|
||||
/>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
@@ -208,14 +213,14 @@ export function DrawSettingsPanel() {
|
||||
value={draft.cooldownMinutes}
|
||||
placeholder={t("system.placeholders.cooldownMinutes", { ns: "config" })}
|
||||
onChange={(e) => updateField("cooldownMinutes", e.target.value)}
|
||||
disabled={loading || saving}
|
||||
disabled={!canManage || loading || saving}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<SettingsSectionActions
|
||||
dirty={dirty}
|
||||
loading={loading}
|
||||
loading={!canManage || loading}
|
||||
saving={saving}
|
||||
onSave={() =>
|
||||
requestConfirm({
|
||||
|
||||
Reference in New Issue
Block a user