fundraiser mode: external platforms, role-aware onboarding, show-don't-gate

SCHEMA:
- Organization.orgType: 'charity' | 'fundraiser'
- Organization.whatsappConnected: boolean
- Event.paymentMode: 'self' (bank transfer) | 'external' (redirect to URL)
- Event.externalUrl: fundraising page URL
- Event.externalPlatform: launchgood, enthuse, justgiving, gofundme, other

ONBOARDING (role-aware):
- Dashboard shows getting-started banner AT TOP, not full-page blocker
- First-time users see role picker: 'Charity/Mosque' vs 'Personal Fundraiser'
- POST /api/onboarding sets orgType
- Charity checklist: bank details → WhatsApp → create fundraiser → share link
- Fundraiser checklist: add fundraising page → WhatsApp → share pledge link → first pledge
- WhatsApp is now a core onboarding step for both types
- Banner is dismissable via X button
- Dashboard always shows stats (with zeros), progress bar, empty-state card

SHOW DON'T GATE:
- Stats cards show immediately (with zeros, slightly faded)
- Collection progress bar always visible
- Empty-state card says 'Your pledge data will appear here'
- Getting started is a guidance banner, not a lock screen

EXTERNAL PAYMENT FLOW:
- Events can be paymentMode='external' with externalUrl
- Pledge flow: amount → identity → 'Donate on LaunchGood' redirect (skips schedule + payment method)
- ExternalRedirectStep: branded per platform (LaunchGood green, Enthuse purple, etc.)
- Marks pledge as 'initiated' when donor clicks through
- WhatsApp sends donation link instead of bank details
- Share button shares the external URL

EVENT CREATION:
- Payment mode toggle: 'Bank transfer' vs 'External page'
- External shows URL input + platform dropdown
- Fundraiser orgs default to external mode
- Platform badge on event cards

PLATFORMS SUPPORTED:
🌙 LaunchGood, 💜 Enthuse, 💛 JustGiving, 💚 GoFundMe, 🔗 Other/Custom
This commit is contained in:
2026-03-03 06:42:11 +08:00
parent 05acda0adb
commit 0e8df76f89
11 changed files with 767 additions and 269 deletions

View File

@@ -0,0 +1,10 @@
-- Organization type: charity processes payments, fundraiser redirects to external platform
ALTER TABLE "Organization" ADD COLUMN "orgType" TEXT NOT NULL DEFAULT 'charity';
-- Per-event: can this event process payments itself, or redirect to an external page?
ALTER TABLE "Event" ADD COLUMN "paymentMode" TEXT NOT NULL DEFAULT 'self';
ALTER TABLE "Event" ADD COLUMN "externalUrl" TEXT;
ALTER TABLE "Event" ADD COLUMN "externalPlatform" TEXT;
-- WhatsApp connected flag (set when QR scanned + session active)
ALTER TABLE "Organization" ADD COLUMN "whatsappConnected" BOOLEAN NOT NULL DEFAULT false;

View File

@@ -11,6 +11,7 @@ model Organization {
id String @id @default(cuid())
name String
slug String @unique
orgType String @default("charity") // charity | fundraiser
country String @default("UK")
timezone String @default("Europe/London")
bankName String?
@@ -22,6 +23,7 @@ model Organization {
primaryColor String @default("#1e40af")
gcAccessToken String?
gcEnvironment String @default("sandbox")
whatsappConnected Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@ -48,17 +50,20 @@ model User {
}
model Event {
id String @id @default(cuid())
name String
slug String
description String?
eventDate DateTime?
location String?
goalAmount Int? // in pence
currency String @default("GBP")
status String @default("active") // draft, active, closed, archived
organizationId String
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
id String @id @default(cuid())
name String
slug String
description String?
eventDate DateTime?
location String?
goalAmount Int? // in pence
currency String @default("GBP")
status String @default("active") // draft, active, closed, archived
paymentMode String @default("self") // self = we show bank details, external = redirect to URL
externalUrl String? // e.g. https://launchgood.com/my-campaign
externalPlatform String? // launchgood, enthuse, justgiving, gofundme, other
organizationId String
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt