Referral page, bug fixes, seed data, persona tiers

- New /refer page with share/copy/stats
- Fixed modal z-index conflicts (z-50 → z-[60]) across forum, groups, souq, halal-monitor
- Seed route: forum categories, marketplace listings, private groups
- Mufti/Daie personas now available in Premium tier
- Fixed referral share link: falahos.my/mobile/auth?ref=CODE
- Fixed client-side persona access check for premium
This commit is contained in:
root
2026-06-18 09:38:05 +02:00
parent b39bce91e4
commit ed34b186f9
29 changed files with 996 additions and 188 deletions
+4 -51
View File
@@ -1,17 +1,6 @@
import { NextRequest, NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
// Decode a base62 referral code back to a userId prefix for lookup
function decodeBase62Lookup(code: string): number {
const chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
let hash = 0;
for (const ch of code) {
const idx = chars.indexOf(ch);
if (idx === -1) return -1;
hash = hash * 62 + idx;
}
return hash >>> 0;
}
import { findReferrerByCode } from "@/lib/referral";
export async function POST(req: NextRequest) {
try {
@@ -25,42 +14,12 @@ export async function POST(req: NextRequest) {
);
}
// In a real system, you'd look up the referrer by their stored referral code.
// For simplicity, we encode the userId in the code. We need to find the user
// whose userId produces this code. Since encodeBase62 uses a hash, we
// can't reverse it perfectly. Instead, we iterate active users.
// A production approach: store referral codes in a dedicated table or column.
// For now, we'll iterate through users and find a match.
// Look up the referrer by matching the referral code against all users
const users = await prisma.user.findMany({
select: { id: true },
});
// Recreate the encode logic to find the matching user
function encodeForMatch(id: string): string {
const chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
let hash = 0;
for (let i = 0; i < Math.min(id.length, 10); i++) {
hash = (hash * 31 + id.charCodeAt(i)) >>> 0;
}
let result = "";
let h = hash;
while (result.length < 6) {
result = chars[h % 62] + result;
h = Math.floor(h / 62);
if (h === 0 && result.length < 6) {
h = Math.floor(Math.random() * 62 ** (6 - result.length));
}
}
return result;
}
let referrerId: string | null = null;
for (const u of users) {
if (encodeForMatch(u.id) === code) {
referrerId = u.id;
break;
}
}
const referrerId = await findReferrerByCode(users, code);
if (!referrerId) {
return NextResponse.json(
@@ -76,12 +35,6 @@ export async function POST(req: NextRequest) {
// Since we don't have a "referredId" yet, we store a temporary token.
const tempToken = `pending_${referrerId}_${Date.now()}`;
// Check if this referrer already has a pending referral with this temp token
const existing = await prisma.referral.findFirst({
where: { referrerId, status: "pending" },
orderBy: { createdAt: "desc" },
});
// Store in a lightweight way — we'll use the Referral model with a placeholder referredId
// The referredId will be updated when registration completes.
// For production, a ReferralClaimToken model would be better.
@@ -96,7 +49,7 @@ export async function POST(req: NextRequest) {
return NextResponse.json({
success: true,
message: "Referral code applied! You'll get 1000 FLH when you sign up.",
message: "Referral code applied! You'll get 1,000 FLH extra when you sign up, and your referrer earns 200 FLH.",
referralId: referral.id,
tempToken,
});