Auto-mint referral codes + action-based points for volunteer dashboard
Referral: if the user has no active invite code when the dashboard loads, one is auto-created via referralService.createInviteCode. Every volunteer now sees a ready-to-share referral link on first visit without needing to manually create one. Points: replaced the media-engagement placeholder (videos watched + upvotes + comments) with a weighted tally of actual volunteer actions: shift signups (10pts), influence campaign emails (5pts), verified petition signatures (5pts), event tickets (10pts), action step completions (5pts), and achievements (15pts). This reflects organizing work rather than gallery browsing. Bunker Admin
This commit is contained in:
parent
df65b1b72e
commit
82db26fcef
@ -1,4 +1,4 @@
|
||||
import { Prisma, TicketedEventStatus, ShiftKind, ShiftStatus, TicketStatus } from '@prisma/client';
|
||||
import { Prisma, TicketedEventStatus, ShiftKind, ShiftStatus, SignupStatus, TicketStatus } from '@prisma/client';
|
||||
import { prisma } from '../../config/database';
|
||||
import { env } from '../../config/env';
|
||||
import { actionCampaignsService, type ActiveCampaignForUser } from '../action-campaigns/action-campaigns.service';
|
||||
@ -97,13 +97,17 @@ async function getProfile(userId: string): Promise<DashboardProfile | null> {
|
||||
|
||||
async function getReferral(userId: string): Promise<DashboardReferral> {
|
||||
const stats = await referralService.getReferralStats(userId);
|
||||
const firstCode = await prisma.inviteCode.findFirst({
|
||||
let firstCode = await prisma.inviteCode.findFirst({
|
||||
where: { createdByUserId: userId, isActive: true },
|
||||
orderBy: { createdAt: 'desc' },
|
||||
select: { code: true },
|
||||
});
|
||||
const code = firstCode?.code ?? null;
|
||||
const link = code ? `${env.ADMIN_URL}/register?ref=${code}` : null;
|
||||
if (!firstCode) {
|
||||
const created = await referralService.createInviteCode(userId, {});
|
||||
firstCode = { code: created.code };
|
||||
}
|
||||
const code = firstCode.code;
|
||||
const link = `${env.ADMIN_URL}/register?ref=${code}`;
|
||||
return { code, link, totalReferrals: stats.totalReferrals };
|
||||
}
|
||||
|
||||
@ -196,19 +200,26 @@ async function getMyEvents(userId: string): Promise<DashboardMyEvent[]> {
|
||||
}
|
||||
|
||||
async function getPoints(userId: string): Promise<DashboardPoints> {
|
||||
const [stats, achievementCount] = await Promise.all([
|
||||
prisma.userStats.findUnique({
|
||||
where: { userId },
|
||||
select: { totalVideosWatched: true, totalUpvotesGiven: true, totalCommentsMade: true, totalFinishes: true },
|
||||
}),
|
||||
prisma.userAchievement.count({ where: { userId } }),
|
||||
]);
|
||||
const user = await prisma.user.findUnique({ where: { id: userId }, select: { email: true } });
|
||||
const email = user?.email ?? '';
|
||||
|
||||
const [shiftSignups, campaignEmails, petitionSignatures, eventTickets, stepCompletions, achievementCount] =
|
||||
await Promise.all([
|
||||
prisma.shiftSignup.count({ where: { userId, status: SignupStatus.CONFIRMED } }),
|
||||
prisma.campaignEmail.count({ where: { userId } }),
|
||||
prisma.petitionSignature.count({ where: { signerEmail: email, verifiedAt: { not: null } } }),
|
||||
prisma.ticket.count({ where: { userId, status: TicketStatus.VALID } }),
|
||||
prisma.actionStepCompletion.count({ where: { userId } }),
|
||||
prisma.userAchievement.count({ where: { userId } }),
|
||||
]);
|
||||
|
||||
const total =
|
||||
(stats?.totalVideosWatched ?? 0) +
|
||||
(stats?.totalUpvotesGiven ?? 0) +
|
||||
(stats?.totalCommentsMade ?? 0) +
|
||||
(stats?.totalFinishes ?? 0);
|
||||
shiftSignups * 10 +
|
||||
campaignEmails * 5 +
|
||||
petitionSignatures * 5 +
|
||||
eventTickets * 10 +
|
||||
stepCompletions * 5 +
|
||||
achievementCount * 15;
|
||||
|
||||
return { total, achievementCount };
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user