"use client"; import { useCallback } from "react"; import { useTranslation } from "react-i18next"; import { AdminPageCard } from "@/components/admin/admin-page-card"; import { useConfirmAction } from "@/hooks/use-confirm-action"; import { SettingsSectionActions } from "@/modules/settings/components/settings-section-actions"; import { useSettingsSection } from "@/modules/settings/hooks/use-settings-section"; import { DRAW_KEYS } from "@/modules/settings/settings-keys"; 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; drawIntervalMinutes: string; drawBettingWindowSeconds: string; drawCloseBeforeDrawSeconds: string; drawBufferDrawsAhead: string; requireManualReview: boolean; cooldownMinutes: string; } const INITIAL: DrawDraft = { defaultCurrency: "NPR", drawIntervalMinutes: "5", drawBettingWindowSeconds: "270", drawCloseBeforeDrawSeconds: "30", drawBufferDrawsAhead: "8", requireManualReview: false, cooldownMinutes: "15", }; function fromKv(kv: Record): DrawDraft { return { defaultCurrency: String(kv[DRAW_KEYS.DEFAULT_CURRENCY] ?? "NPR"), drawIntervalMinutes: String(kv[DRAW_KEYS.DRAW_INTERVAL_MINUTES] ?? 5), drawBettingWindowSeconds: String(kv[DRAW_KEYS.DRAW_BETTING_WINDOW_SECONDS] ?? 270), drawCloseBeforeDrawSeconds: String(kv[DRAW_KEYS.DRAW_CLOSE_BEFORE_DRAW_SECONDS] ?? 30), drawBufferDrawsAhead: String(kv[DRAW_KEYS.DRAW_BUFFER_DRAWS_AHEAD] ?? 8), requireManualReview: Boolean(kv[DRAW_KEYS.REQUIRE_MANUAL_REVIEW] ?? false), cooldownMinutes: String(kv[DRAW_KEYS.COOLDOWN_MINUTES] ?? 15), }; } function buildDirtyItems(draft: DrawDraft, saved: DrawDraft): AdminSettingBatchItem[] { const items: AdminSettingBatchItem[] = []; const push = (key: string, value: unknown, changed: boolean) => { if (changed) { items.push({ key, value }); } }; push( DRAW_KEYS.DEFAULT_CURRENCY, draft.defaultCurrency.trim().toUpperCase() || "NPR", draft.defaultCurrency !== saved.defaultCurrency, ); push( DRAW_KEYS.DRAW_INTERVAL_MINUTES, Math.max(1, Number.parseInt(draft.drawIntervalMinutes || "5", 10) || 5), draft.drawIntervalMinutes !== saved.drawIntervalMinutes, ); push( DRAW_KEYS.DRAW_BETTING_WINDOW_SECONDS, Math.max(10, Number.parseInt(draft.drawBettingWindowSeconds || "270", 10) || 270), draft.drawBettingWindowSeconds !== saved.drawBettingWindowSeconds, ); push( DRAW_KEYS.DRAW_CLOSE_BEFORE_DRAW_SECONDS, Math.max(5, Number.parseInt(draft.drawCloseBeforeDrawSeconds || "30", 10) || 30), draft.drawCloseBeforeDrawSeconds !== saved.drawCloseBeforeDrawSeconds, ); push( DRAW_KEYS.DRAW_BUFFER_DRAWS_AHEAD, Math.max(1, Number.parseInt(draft.drawBufferDrawsAhead || "8", 10) || 8), draft.drawBufferDrawsAhead !== saved.drawBufferDrawsAhead, ); push(DRAW_KEYS.REQUIRE_MANUAL_REVIEW, draft.requireManualReview, draft.requireManualReview !== saved.requireManualReview); push( DRAW_KEYS.COOLDOWN_MINUTES, Math.max(0, Number.parseInt(draft.cooldownMinutes || "0", 10) || 0), draft.cooldownMinutes !== saved.cooldownMinutes, ); return items; } 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({ initialDraft: INITIAL, fromKv, buildDirtyItems: buildItems, saveSuccessKey: "system.saveDrawSuccess", saveFailedKey: "system.saveFailed", }); const { draft, loading, saving, dirty, updateField, discard, save } = section; return ( <>
updateField("requireManualReview", value)} />
updateField("defaultCurrency", e.target.value.toUpperCase())} disabled={!canManage || loading || saving} maxLength={16} className="h-10 bg-background/50 transition-colors focus:bg-background" />
updateField("drawIntervalMinutes", e.target.value)} disabled={!canManage || loading || saving} className="h-10 bg-background/50 transition-colors focus:bg-background" />
updateField("drawBettingWindowSeconds", e.target.value)} disabled={!canManage || loading || saving} className="h-10 bg-background/50 transition-colors focus:bg-background" />
updateField("drawCloseBeforeDrawSeconds", e.target.value)} disabled={!canManage || loading || saving} className="h-10 bg-background/50 transition-colors focus:bg-background" />
updateField("drawBufferDrawsAhead", e.target.value)} disabled={!canManage || loading || saving} className="h-10 bg-background/50 transition-colors focus:bg-background" />
updateField("cooldownMinutes", e.target.value)} disabled={!canManage || loading || saving} className="h-10 bg-background/50 transition-colors focus:bg-background" />
requestConfirm({ title: t("system.confirmSaveDrawTitle", { ns: "config" }), description: t("system.confirmSaveDrawDescription", { ns: "config" }), confirmLabel: t("confirm.confirmSave", { ns: "common" }), onConfirm: () => { void save(); }, }) } onDiscard={discard} saveLabel={t("actions.save", { ns: "adminUsers" })} savingLabel={t("saving", { ns: "adminUsers" })} discardLabel={t("system.discard", { ns: "config" })} />
); }