feat(referrals): add referral attribution and daily login rewards
- Track referral attribution at registration via ?ref code with same-IP and duplicate-pair guards - Add daily login rewards with streak tracking, claim flow and sendCurrency payout backed by RCON with DB fallback - Add admin pages for referral settings and the daily reward schedule - Add migration 0033 with tables, seed schedule, settings and ACL grants - Add admin.referrals.* and admin.dailyrewards.* permission slugs - Localize new copy in en, nl and it
This commit is contained in:
1 parent
463bc2cb47
commit
c3ff497050
30 files changed
+2028
-11
No files matched your search
@@ -57,8 +57,16 @@ export function RegisterForm({
|
||||
null,
|
||||
);
|
||||
const autoLoginStartedRef = useRef(false);
|
||||
const [referralCode, setReferralCode] = useState("");
|
||||
const strength = passwordStrength(password);
|
||||
|
||||
// The invite link is `/register?ref=<username>`; read it client-side so the
|
||||
// attribution travels with the sign-up form without server state.
|
||||
useEffect(() => {
|
||||
const ref = new URLSearchParams(window.location.search).get("ref");
|
||||
if (ref) setReferralCode(ref);
|
||||
}, []);
|
||||
|
||||
// Successful sign-up: sign in with the submitted credentials and go
|
||||
// straight to /me. If the automatic sign-in is refused (e.g. email
|
||||
// verification required), fall back to the regular login page.
|
||||
@@ -187,6 +195,23 @@ export function RegisterForm({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{referralCode && (
|
||||
<div
|
||||
className="animate-fade-in-up flex items-center gap-2 p-3 rounded-lg text-sm font-semibold"
|
||||
style={{
|
||||
backgroundColor:
|
||||
"color-mix(in srgb, var(--color-primary) 12%, transparent)",
|
||||
color: "var(--color-primary-readable, var(--color-primary))",
|
||||
border:
|
||||
"1px solid color-mix(in srgb, var(--color-primary) 22%, transparent)",
|
||||
}}
|
||||
>
|
||||
{t("invitedBy", { username: referralCode })}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<input type="hidden" name="ref" value={referralCode} />
|
||||
|
||||
{/* Username & Email */}
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2">
|
||||
|
||||
Reference in new issue
Block a user