"use client"; import { useState } from "react"; import { toast } from "sonner"; import { bulkAdjustCurrency, bulkBan, bulkGiveBadge, bulkUnban, } from "@/actions/bulk-users"; type PendingDialog = | { kind: "ban"; ids: number[] } | { kind: "give-currency"; ids: number[] } | { kind: "give-badge"; ids: number[] } | null; export function useUserBulkActions() { const [pending, setPending] = useState(null); const [busy, setBusy] = useState(false); const [banReason, setBanReason] = useState("Bulk ban"); const [banDuration, setBanDuration] = useState("-1"); const [currencyType, setCurrencyType] = useState< "credits" | "pixels" | "points" >("credits"); const [currencyAmount, setCurrencyAmount] = useState("100"); const [badgeCode, setBadgeCode] = useState(""); function reportResult( label: string, ok: number, total: number, failures = 0, ) { if (ok > 0) toast.success( `${label}: ${ok}/${total}${failures ? ` ยท ${failures} failed` : ""}`, ); if (failures > 0 && ok === 0) toast.error(`${label} failed for ${failures} users`); } async function handleBulkAction(action: string, ids: (number | string)[]) { if (busy) return; const numericIds = ids.map((i) => Number(i)); if (action === "unban") { setBusy(true); try { const result = await bulkUnban({ userIds: numericIds }); if (result.ok) { const data = result.data as { unbanned: number; total: number }; reportResult("Unbanned", data.unbanned, data.total); } else toast.error(result.error); } catch { toast.error( "Network error. The outcome is uncertain; check the user before retrying.", ); } finally { setBusy(false); } return; } if (action === "ban") { setPending({ kind: "ban", ids: numericIds }); return; } if (action === "give-currency") { setPending({ kind: "give-currency", ids: numericIds }); return; } if (action === "give-badge") { setPending({ kind: "give-badge", ids: numericIds }); return; } } async function confirmBan() { if (pending?.kind !== "ban") return; setBusy(true); try { const result = await bulkBan({ userIds: pending.ids, reason: banReason, duration: Number(banDuration), }); if (result.ok) { const data = result.data as { banned: number }; reportResult("Banned", data.banned, pending.ids.length); setPending(null); } else toast.error(result.error); } catch { toast.error( "Network error. The outcome is uncertain; check the user before retrying.", ); } finally { setBusy(false); } } async function confirmGiveCurrency() { if (pending?.kind !== "give-currency") return; setBusy(true); try { const result = await bulkAdjustCurrency({ userIds: pending.ids, amount: Number(currencyAmount), type: currencyType, }); if (result.ok) { const data = result.data as { adjusted: number; total: number; failedIds: { userId: number; reason: string }[]; }; reportResult( `Adjusted ${currencyAmount} ${currencyType}`, data.adjusted, data.total, data.failedIds.length, ); setPending(null); } else toast.error(result.error); } catch { toast.error( "Network error. The outcome is uncertain; check the user before retrying.", ); } finally { setBusy(false); } } async function confirmGiveBadge() { if (pending?.kind !== "give-badge") return; setBusy(true); try { const result = await bulkGiveBadge({ userIds: pending.ids, badgeCode: badgeCode.trim().toUpperCase(), }); if (result.ok) { const data = result.data as { given: number; total: number; failedIds: { userId: number; reason: string }[]; }; reportResult( `Given badge ${badgeCode}`, data.given, data.total, data.failedIds.length, ); setPending(null); } else toast.error(result.error); } catch { toast.error( "Network error. The outcome is uncertain; check the user before retrying.", ); } finally { setBusy(false); } } return { pending, setPending, busy, banReason, setBanReason, banDuration, setBanDuration, currencyType, setCurrencyType, currencyAmount, setCurrencyAmount, badgeCode, setBadgeCode, handleBulkAction, confirmBan, confirmGiveCurrency, confirmGiveBadge, }; }