Your commit message
This commit is contained in:
95
backend/src/routes/waitlist.ts
Normal file
95
backend/src/routes/waitlist.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import { Router } from 'express';
|
||||
import { pool } from '../db';
|
||||
import { z } from 'zod';
|
||||
|
||||
const router = Router();
|
||||
|
||||
// Validation schema
|
||||
const waitlistSchema = z.object({
|
||||
email: z.string().email('Invalid email address'),
|
||||
source: z.string().optional().default('landing_page'),
|
||||
referrer: z.string().optional(),
|
||||
});
|
||||
|
||||
// POST /api/waitlist - Add email to waitlist
|
||||
router.post('/', async (req, res) => {
|
||||
try {
|
||||
const data = waitlistSchema.parse(req.body);
|
||||
|
||||
// Check if email already exists
|
||||
const existing = await pool.query(
|
||||
'SELECT id FROM waitlist_leads WHERE email = $1',
|
||||
[data.email.toLowerCase()]
|
||||
);
|
||||
|
||||
if (existing.rows.length > 0) {
|
||||
// Already on waitlist - return success anyway (don't reveal they're already signed up)
|
||||
const countResult = await pool.query('SELECT COUNT(*) FROM waitlist_leads');
|
||||
const position = parseInt(countResult.rows[0].count, 10);
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
message: 'You\'re on the list!',
|
||||
position,
|
||||
alreadySignedUp: true,
|
||||
});
|
||||
}
|
||||
|
||||
// Insert new lead
|
||||
await pool.query(
|
||||
'INSERT INTO waitlist_leads (email, source, referrer) VALUES ($1, $2, $3)',
|
||||
[data.email.toLowerCase(), data.source, data.referrer || null]
|
||||
);
|
||||
|
||||
// Get current position (total count)
|
||||
const countResult = await pool.query('SELECT COUNT(*) FROM waitlist_leads');
|
||||
const position = parseInt(countResult.rows[0].count, 10);
|
||||
|
||||
console.log(`✅ Waitlist signup: ${data.email} (Position #${position})`);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'You\'re on the list!',
|
||||
position,
|
||||
});
|
||||
} catch (error) {
|
||||
if (error instanceof z.ZodError) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
error: 'validation_error',
|
||||
message: error.errors[0].message,
|
||||
});
|
||||
}
|
||||
|
||||
console.error('Waitlist signup error:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: 'server_error',
|
||||
message: 'Failed to join waitlist. Please try again.',
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/waitlist/count - Get current waitlist count (public)
|
||||
router.get('/count', async (_req, res) => {
|
||||
try {
|
||||
const result = await pool.query('SELECT COUNT(*) FROM waitlist_leads');
|
||||
const count = parseInt(result.rows[0].count, 10);
|
||||
|
||||
// Add a base number to make it look more impressive at launch
|
||||
const displayCount = count + 430; // Starting with "430+ waiting"
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
count: displayCount,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Waitlist count error:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
count: 430, // Fallback to base number
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
||||
Reference in New Issue
Block a user