diff --git a/.env.example b/.env.example index 88d8aec..06401ec 100644 --- a/.env.example +++ b/.env.example @@ -159,6 +159,10 @@ RECFLARE_DOMAIN=rec.example.com # staff can give in total. # RECFLARE_MAX_TOKEN_GIFT=10000 +# The same guard for one XP gift from that staff card (`www`). Every level to the top costs +# 15,090 XP in all (level 1 to 50). +# RECFLARE_MAX_XP_GIFT=100 + # Signup on the website is configured OUTSIDE this file: it's guarded by a Cloudflare # Turnstile widget, and both of that widget's keys live in the shared Secrets Store # (RECFLARE_SECRETS_STORE above), alongside JWT_SECRET — not as vars, not as worker secrets. diff --git a/apps/www/src/client/App.tsx b/apps/www/src/client/App.tsx index 47298ad..019f0e0 100644 --- a/apps/www/src/client/App.tsx +++ b/apps/www/src/client/App.tsx @@ -1172,7 +1172,11 @@ function PlayerPage({ function StaffPlayerActions({ account, navigate }: { account: PublicAccount; navigate: Navigate }) { const [tokens, setTokens] = useState('') const [confirmingClear, setConfirmingClear] = useState(false) + const [customItemId, setCustomItemId] = useState('') + const [xp, setXp] = useState('') const gift = useAction() + const xpGift = useAction() + const customGift = useAction() const usernameChange = useAction() const clearPassword = useAction() const base = `/api/staff/players/${account.accountId}` @@ -1218,6 +1222,86 @@ function StaffPlayerActions({ account, navigate }: { account: PublicAccount; nav {gift.done &&

{gift.done}

} +
{ + e.preventDefault() + void xpGift.run(async () => { + const amount = Number(xp) + const res = await call<{ level: number; levelsGained: number }>(`${base}/gift-xp`, { + authed: true, + json: { amount }, + }) + setXp('') + const levels = + res.levelsGained > 0 + ? ` They went up ${res.levelsGained} level${res.levelsGained === 1 ? '' : 's'}, to ${res.level}.` + : ` They're level ${res.level}.` + return `Sent ${amount.toLocaleString()} XP.${levels}` + }) + }} + > + + {xpGift.error &&

{xpGift.error}

} + {xpGift.done &&

{xpGift.done}

} +
+ +
{ + e.preventDefault() + void customGift.run(async () => { + const res = await call<{ name: string }>(`${base}/gift-custom-item`, { + authed: true, + json: { customAvatarItemId: customItemId.trim() }, + }) + setCustomItemId('') + return `Sent “${res.name}” to @${account.username}.` + }) + }} + > + + {customGift.error &&

{customGift.error}

} + {customGift.done &&

{customGift.done}

} +
+