import { Router, Request, Response, NextFunction } from 'express'; import { validate } from '../../middleware/validate'; import { paymentCheckoutRateLimit } from '../../middleware/rate-limit'; import { requirePaymentsEnabled } from './payment-settings.service'; import { donationPagesService } from './donation-pages.service'; import { donationsService } from './donations.service'; import { donationPageCheckoutSchema } from './donation-pages.schemas'; const router = Router(); // GET /api/donation-pages — list active pages (with stats) router.get('/', async (_req: Request, res: Response, next: NextFunction) => { try { const pages = await donationPagesService.findActivePages(); res.json(pages); } catch (err) { next(err); } }); // GET /api/donation-pages/:slug — get active page by slug router.get('/:slug', async (req: Request, res: Response, next: NextFunction) => { try { const page = await donationPagesService.findBySlugPublic(req.params.slug as string); res.json(page); } catch (err) { next(err); } }); // POST /api/donation-pages/:slug/donate — create Stripe checkout for this page router.post( '/:slug/donate', requirePaymentsEnabled, paymentCheckoutRateLimit, validate(donationPageCheckoutSchema), async (req: Request, res: Response, next: NextFunction) => { try { const page = await donationPagesService.findBySlugPublic(req.params.slug as string); const { amountCents, email, name, message, isAnonymous } = req.body; // Validate against page-specific minimum if (amountCents < page.minimumAmount) { res.status(400).json({ error: { message: `Minimum donation is $${(page.minimumAmount / 100).toFixed(2)}`, code: 'MINIMUM_NOT_MET', }, }); return; } const result = await donationsService.createDonationCheckout( amountCents, email, name, message, isAnonymous, page.id, page.slug, page.title, ); res.json(result); } catch (err) { next(err); } }, ); export { router as donationPagesPublicRouter };