import { useCallback, useEffect, useMemo, useState } from 'react'; import { api, formatCredits } from '../api'; function dropPercents(items) { const total = items.reduce((s, ci) => s + Number(ci.dropRate || 0), 0); if (!(total > 0)) return items.map(() => 0); return items.map((ci) => (Number(ci.dropRate) / total) * 100); } export default function AdminDrops() { const [cases, setCases] = useState([]); const [items, setItems] = useState([]); const [error, setError] = useState(''); const [selectedCaseId, setSelectedCaseId] = useState(''); const [dropForm, setDropForm] = useState({ itemId: '', dropRate: 1 }); const load = useCallback(async () => { const [c, i] = await Promise.all([api.adminCases(), api.adminItems()]); setCases(c.cases); setItems(i.items); setSelectedCaseId((prev) => { if (prev && c.cases.some((x) => String(x.id) === String(prev))) return prev; return c.cases[0] ? String(c.cases[0].id) : ''; }); setDropForm((f) => ({ ...f, itemId: f.itemId || (i.items[0] ? String(i.items[0].id) : ''), })); }, []); useEffect(() => { load().catch((err) => setError(err.message)); }, [load]); const selected = useMemo( () => cases.find((c) => String(c.id) === String(selectedCaseId)) || null, [cases, selectedCaseId] ); const poolItems = useMemo(() => { if (!selected) return []; return [...selected.items].sort((a, b) => Number(a.dropRate) - Number(b.dropRate)); }, [selected]); const percents = useMemo(() => dropPercents(poolItems), [poolItems]); return (

Drop rates

Weights per case · % shown from relative weights

{error &&
{error}
} {!selected ? (
Create a case first.
) : ( <>

Add drop · {selected.name}{' '} ({formatCredits(selected.price)} cr)

{ e.preventDefault(); setError(''); try { await api.addCaseItem(Number(selectedCaseId), { itemId: Number(dropForm.itemId), dropRate: Number(dropForm.dropRate), }); await load(); } catch (err) { setError(err.message); } }} > setDropForm({ ...dropForm, dropRate: e.target.value })} placeholder="Weight" required />

Pool ({poolItems.length})

{poolItems.length === 0 ? (
No drops yet.
) : (
{poolItems.map((ci, idx) => (
{ci.item.imageUrl ? ( ) : null} {ci.item.name}{' '} ({ci.item.rarity}) { const dropRate = Number(e.target.value); if (!(dropRate > 0) || dropRate === ci.dropRate) return; try { await api.updateCaseItem(ci.id, { dropRate }); await load(); } catch (err) { setError(err.message); } }} /> {percents[idx].toFixed(2)}%
))}
)}
)}
); }