project-standalo-todo-super/app/api/referrals/claim/route.ts

138 lines
3.6 KiB
TypeScript

/**
* POST /api/referrals/claim - Claim referral bonus
*/
import { NextRequest, NextResponse } from 'next/server';
import { requireAuth } from '@/app/lib/auth';
import { createReferral, findUser, getUserReferrals } from '@/app/lib/db/store';
import { awardReferralBonus } from '@/app/lib/points';
import { checkAndAwardBadges } from '@/app/lib/badges';
import { ApiResponse } from '@/app/lib/types';
interface ClaimReferralRequest {
referralCode: string;
}
const REFERRAL_BONUS = 50; // Points awarded for referrals
export async function POST(request: NextRequest) {
try {
// Authenticate user
const user = requireAuth(request);
// Parse request body
const body: ClaimReferralRequest = await request.json();
const { referralCode } = body;
if (!referralCode) {
return NextResponse.json<ApiResponse>(
{
success: false,
error: 'Referral code is required'
},
{ status: 400 }
);
}
// Decode referral code to get referrer user ID
let referrerId: string;
try {
referrerId = Buffer.from(referralCode, 'base64').toString('utf-8');
} catch (error) {
return NextResponse.json<ApiResponse>(
{
success: false,
error: 'Invalid referral code'
},
{ status: 400 }
);
}
// Check if referrer exists
const referrer = findUser(referrerId);
if (!referrer) {
return NextResponse.json<ApiResponse>(
{
success: false,
error: 'Referrer not found'
},
{ status: 404 }
);
}
// Prevent self-referral
if (referrerId === user.id) {
return NextResponse.json<ApiResponse>(
{
success: false,
error: 'You cannot refer yourself'
},
{ status: 400 }
);
}
// Check if user was already referred
const allReferrals = getUserReferrals(referrerId);
const alreadyReferred = allReferrals.some(ref => ref.referredId === user.id);
if (alreadyReferred) {
return NextResponse.json<ApiResponse>(
{
success: false,
error: 'Referral bonus already claimed'
},
{ status: 409 }
);
}
// Create referral record
const referral = createReferral(referrerId, user.id, REFERRAL_BONUS);
// Award points to referrer
awardReferralBonus(referrerId, referral.id, REFERRAL_BONUS);
// Award smaller bonus to referred user
const referredBonus = Math.floor(REFERRAL_BONUS / 2); // 25 points
awardReferralBonus(user.id, referral.id, referredBonus);
// Check and award badges for both users
const referrerBadges = checkAndAwardBadges(referrerId);
const referredBadges = checkAndAwardBadges(user.id);
return NextResponse.json<ApiResponse>(
{
success: true,
data: {
referral,
referrerBonus: REFERRAL_BONUS,
referredBonus,
referrerName: referrer.name
},
message: `Referral claimed! You earned ${referredBonus} points, and ${referrer.name} earned ${REFERRAL_BONUS} points${
referredBadges.length > 0 ? `. You also earned ${referredBadges.length} new badge(s)!` : ''
}`
},
{ status: 201 }
);
} catch (error) {
if (error instanceof Error && error.message === 'Unauthorized') {
return NextResponse.json<ApiResponse>(
{
success: false,
error: 'Unauthorized'
},
{ status: 401 }
);
}
console.error('Claim referral error:', error);
return NextResponse.json<ApiResponse>(
{
success: false,
error: 'Internal server error'
},
{ status: 500 }
);
}
}