import { publicProcedure } from './router'; import { z } from 'zod'; import { eq, sql } from 'drizzle-orm'; import { waitlistSignups, waitlistEvents } from '../../src/db/schema'; function generateReferralCode(length = 8): string { const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; let code = ''; for (let i = 0; i < length; i++) { code += chars.charAt(Math.floor(Math.random() * chars.length)); } return code; } export const waitlistRouter = { signup: publicProcedure .input(z.object({ email: z.string().email(), name: z.string().min(1).max(200).optional(), source: z.string().max(100).optional().default('organic'), referralCode: z.string().max(20).optional(), })) .mutation(async ({ input, ctx }) => { const existingRows = await ctx.db!.select() .from(waitlistSignups) .where(eq(waitlistSignups.email, input.email.toLowerCase())); const existing = existingRows[0]; if (existing) { const metaStr = (existing as Record).metadata as string | null; const existingMeta = metaStr ? JSON.parse(metaStr) : {}; return { success: true, alreadyJoined: true, id: existing.id, referralCode: existingMeta.referralCode || null }; } const metadata: Record = {}; if (input.referralCode) { metadata.referredBy = input.referralCode; } metadata.referralCode = generateReferralCode(); const result = await ctx.db!.insert(waitlistSignups) .values({ email: input.email.toLowerCase(), name: input.name ?? null, source: input.source ?? 'organic', metadata: JSON.stringify(metadata), }) .returning(); const signup = result[0]; await ctx.db!.insert(waitlistEvents) .values({ signupId: signup!.id, eventType: 'signup', eventData: JSON.stringify({ source: input.source, referralCode: input.referralCode }), }); const referralCode = metadata.referralCode as string; return { success: true, alreadyJoined: false, id: signup!.id, referralCode }; }), getCount: publicProcedure .query(async ({ ctx }) => { const result = await ctx.db!.select({ count: sql`count(*)` }) .from(waitlistSignups) .where(eq(waitlistSignups.status, 'waitlist')); return { count: Number(result[0]!.count) }; }), getReferralCount: publicProcedure .input(z.object({ referralCode: z.string().min(1).max(20) })) .query(async ({ input, ctx }) => { const rows = await ctx.db!.select({ id: waitlistSignups.id }) .from(waitlistSignups) .where(eq(waitlistSignups.status, 'waitlist')); let count = 0; for (const row of rows) { const metaStr = (row as Record).metadata as string | null; const meta = metaStr ? JSON.parse(metaStr) : {}; if (meta.referredBy === input.referralCode) { count++; } } return { count }; }), };