Skip to main content

Prospects List

# Prospects List (ProspectsCRM)

Component File: src/features/fundraising/components/ProspectsCRM.tsx Route / navigation: /fundraising, fundraisingTool = prospects. See 00-FUNDRAISING-HUB.md. Access Level: Parent Org and Fund Users with Fundraising access (position-based)

Recent Updates (March 6, 2026)

Robust Prospect List Search (P1)

  • Issue: Prospect list search was mostly limited to a narrow name/email/source match, so phone, address, notes, status, and date-based lookups were easy to miss.
  • Fix: fetchProspectsPaginated() now uses shared search helpers from src/lib/searchUtils.ts plus a prospect-specific matcher in src/lib/db/prospects.ts.
  • Search now matches: prospect name, email, phone, address fields, source, status, notes, and added date.
  • Architecture: This follows the same shared-core plus surface-specific adapter pattern used for donor and donation search, instead of re-implementing search rules inline.
  • Files Changed: src/lib/db/prospects.ts, src/lib/searchUtils.ts

Prospect Write Access + Edit Persistence (April 14, 2026)

  • Issue: Prospect profile showed edit/delete actions to read-only users, and address edits in the profile dialog did not persist.
  • Fix: Profile edit/delete controls are now shown only when canWrite is true, and handlers defensively reject unauthorized write attempts.
  • Data Integrity: Edit saves now persist address_line1, city, state, and zip_code in addition to name/email/phone/source.
  • RLS Hardening: Prospect write policy now requires parent-org admin or org membership with access_level = 'read_write'.
  • Files Changed: src/features/fundraising/components/ProspectsCRM.tsx, supabase/migrations/20260414101500_harden_prospects_write_access.sql

Overview

The Prospects CRM manages potential donors and leads for fundraising campaigns. It provides tools for adding prospects manually, importing from CSV files, exporting prospect data, sending bulk emails, and tracking prospect sources. This is a critical tool for donor cultivation and lead management before prospects become active donors.

✨ Server-Side Search & Pagination (Updated)

Performance Optimizations

  • Server-side search - Search queries execute on Supabase, not client-side
  • Debounced input - 300ms debounce prevents excessive API calls
  • Pagination - Data loaded in pages (default 25 per page)
  • Efficient queries - Only fetches data needed for current view

Search Implementation

// Server-side search with pagination
const { data, total } = await searchProspectsServerSide(
  entityId,
  searchTerm,
  { page, pageSize }
);

UI Features

Main Features

  • Header Actions:
  • Back to Marketing Hub button
  • Search prospects by name, email, phone, address, source, status, notes, or added date (server-side)
  • Add Prospect button
  • Upload CSV button
  • Export CSV button
  • Send Email (bulk) button
  • Prospects Table:
  • Checkbox for selection
  • Name
  • Email
  • Phone
  • Source (how they were added)
  • Added Date
  • Notes
  • Actions (Delete)
  • Add Prospect Dialog:
  • Name input
  • Email input
  • Phone input
  • Source input
  • Notes textarea
  • Add button
  • CSV Upload Dialog:
  • File upload input
  • Format instructions
  • Upload button
  • Bulk Actions:
  • Select all checkbox
  • Delete selected
  • Send email to selected

Prospects Table Layout

Prospects List
Track and manage potential donors

[Search...]  [+ Add Prospect]  [📤 Upload CSV]  [📥 Export]  [✉️ Send Email]

☐ | Name           | Email                    | Phone          | Source      | Added      | Notes
--|----------------|--------------------------|----------------|-------------|------------|-------
☐ | John Smith     | john@example.com         | (555) 123-4567 | Website     | 2025-10-15 | Met at event
☐ | Jane Doe       | jane@example.com         | (555) 234-5678 | Referral    | 2025-10-16 | Friend of donor
☐ | Bob Johnson    | bob@example.com          | (555) 345-6789 | CSV Import  | 2025-10-17 | -

Add Prospect Dialog

┌─────────────────────────────────────────┐
│ Add New Prospect                        │
├─────────────────────────────────────────┤
│                                         │
│ Name *                                  │
│ [                                    ]  │
│                                         │
│ Email *                                 │
│ [                                    ]  │
│                                         │
│ Phone                                   │
│ [                                    ]  │
│                                         │
│ Source                                  │
│ [Manual                              ]  │
│                                         │
│ Notes                                   │
│ [                                    ]  │
│ [                                    ]  │
│                                         │
│ [Cancel]                    [Add Prospect] │
└─────────────────────────────────────────┘

CSV Upload Dialog

┌─────────────────────────────────────────┐
│ Upload Prospects from CSV               │
├─────────────────────────────────────────┤
│                                         │
│ CSV Format Requirements:                │
│ • Must include "name" and "email" columns│
│ • Optional: phone, source, notes        │
│ • First row should be headers           │
│                                         │
│ Example:                                │
│ name,email,phone,source,notes           │
│ John Doe,john@...,555-1234,Web,Note     │
│                                         │
│ [Choose File]                           │
│                                         │
│ [Cancel]                       [Upload] │
└─────────────────────────────────────────┘

Data Requirements

Prospect

  • id (uuid) - Unique identifier
  • organization_id (uuid) - Organization
  • name (string) - Prospect name
  • email (string) - Email address
  • phone (string, nullable) - Phone number
  • source (string) - How added (Manual, CSV Import, Website, Referral, Event, etc.)
  • added_date (date) - When added
  • notes (string, nullable) - Additional notes
  • status (enum, nullable) - 'new', 'contacted', 'interested', 'converted', 'not_interested'
  • converted_to_donor_id (uuid, nullable) - If converted to donor
  • last_contact_date (date, nullable) - Last contact
  • created_by (uuid) - User who added

Request/Response Schemas

interface Prospect {
  id: string;
  organization_id: string;
  name: string;
  email: string;
  phone?: string;
  source: string;
  added_date: string;
  notes?: string;
  status?: 'new' | 'contacted' | 'interested' | 'converted' | 'not_interested';
  converted_to_donor_id?: string;
  last_contact_date?: string;
  created_by: string;
}

interface ProspectFormData {
  name: string;
  email: string;
  phone?: string;
  source?: string;
  notes?: string;
}

Authentication & Authorization

Required Permissions

  • prospects:read - View prospects
  • prospects:create - Add prospects
  • prospects:update - Edit prospects
  • prospects:delete - Delete prospects
  • prospects:email - Send emails to prospects
  • Read-only memberships (`access_level = read_only`) can view prospects but cannot create, update, merge, import, or delete.

Role-Based Access

  • Parent Org (`parent_org`): View prospects across all nonprofits (subject to position/access level)
  • Fund User (`fund_user`): View and manage prospects for assigned nonprofits (subject to position/access level)
  • Positions: Directors and assistants typically have Marketing access; custom positions must enable Marketing permissions
  • Donor/Volunteer: No access
  • Backend enforcement: Prospect writes are enforced by RLS (can_manage_prospects_for_org) requiring parent-org admin or read-write org membership.

Business Logic & Validations

Frontend Validations

  • Name required
  • Email required and valid format
  • Phone format validation (optional)
  • Email uniqueness check
  • CSV format validation
  • File size limit (5MB)
  • Defensive permission checks block edit/delete handlers when user is read-only

Backend Validations (Rails)

  • Valid organization access
  • Email format validation
  • Duplicate email check (within organization)
  • CSV parsing validation
  • Bulk operation limits (max 1000 at once)
  • Email sending rate limits

Business Rules

  • Prospects are organization-specific
  • Email must be unique within organization
  • CSV import skips duplicates
  • Deleted prospects cannot be recovered
  • Converting to donor creates donor record
  • Email templates support merge fields ([Name], [Email])
  • Source tracked for analytics
  • Bulk operations have confirmation
  • Profile address edits persist to prospect record fields (address_line1, city, state, zip_code)

State Management

Local State

  • selectedProspects - Array of selected IDs
  • searchQuery - Search filter text
  • showAddDialog - Add dialog visibility
  • showUploadDialog - Upload dialog visibility
  • newProspect - Form data for new prospect

Global State (AppContext)

  • prospects - Array of prospects
  • addProspect - Function to add prospect
  • deleteProspect - Function to delete prospect

Dependencies

Internal Dependencies

  • AppContext - Global state and prospects management
  • UI components (Card, Button, Table, Dialog, Input, etc.)

External Libraries

  • lucide-react - Icons
  • sonner - Toast notifications

Error Handling

Error Scenarios

1. Network Error: Show toast "Unable to load prospects" 2. Invalid Email: Show error "Invalid email format" 3. Duplicate Email: Show toast "Prospect with this email already exists" 4. CSV Error: Show toast "Invalid CSV format" 5. Upload Failed: Show toast "Failed to import prospects" 6. Email Failed: Show toast "Failed to send emails" 7. Permission Error: Show toast "You don't have permission"

Loading States

  • Initial load: Skeleton table
  • Search: Instant filtering (client-side)
  • Add: Button loading state
  • Upload: Progress indicator
  • Export: Download preparation
  • Email: Sending progress

Mock Data to Remove

  • AppContext.tsx - prospects array (move to API)
  • ProspectsList.tsx - Local prospect management (use API)
  • Move interfaces to src/types/prospects.ts

Migration Notes

Phase 1: Data Layer Integration

1. Create/expand Supabase helpers for prospects CRUD and conversion flows 2. Create src/types/prospects.ts 3. Implement CRUD endpoints 4. Test import/export

Phase 2: Email Integration

1. Integrate with email service (SendGrid, Mailgun) 2. Implement email templates 3. Add merge field support 4. Test bulk sending

Phase 3: Conversion Tracking

1. Implement prospect-to-donor conversion 2. Track conversion rates 3. Add conversion analytics 4. Link to Donor CRM

Phase 4: Advanced Features

1. Add status tracking workflow 2. Implement contact history 3. Add tags/categories 4. Implement automated follow-ups

Related Documentation

Additional Notes

CSV Import Format

Required columns:

  • name
  • email

Optional columns:

  • phone
  • source
  • notes

Example CSV:

name,email,phone,source,notes
John Smith,john@example.com,(555) 123-4567,Website,Met at event
Jane Doe,jane@example.com,(555) 234-5678,Referral,Friend of donor

Prospect Sources

Common sources tracked:

  • Manual (added by staff)
  • CSV Import
  • Website Form
  • Referral
  • Event
  • Social Media
  • Direct Mail
  • Phone Call
  • Other

Email Merge Fields

Supported merge fields in email templates:

  • [Name] - Prospect name
  • [Email] - Prospect email
  • [Phone] - Prospect phone
  • [Organization] - Nonprofit name
  • [Date] - Current date

Conversion Workflow

1. Prospect Added: New lead entered 2. Contact: Initial outreach 3. Interested: Positive response 4. Convert: Makes first donation 5. Donor Created: Moved to Donor CRM

Automatic Prospect-to-Donor Conversion (NEW)

When entering a donation in the Donations Manager or Regular Deposit Manager, the system now searches both donors AND prospects. If a prospect is selected:

1. Search Results Show Both: Donors display with a "Donor" badge, prospects with an amber "Prospect" badge 2. Visual Indicator: When a prospect is selected, a message appears: "⚡ Prospect will be converted to donor when donation is saved" 3. Automatic Conversion: When the donation is saved:

  • The prospect record is used to create a new donor record
  • The prospect is deleted from the prospects table
  • The donation is linked to the new donor
  • A toast notification confirms: "[Name] converted from prospect to donor!"

API Function: convertProspectToDonor(prospectId: string, options?: { targetOrganizationId?: string })

  • Fetches prospect data
  • Parses name into first_name/last_name
  • Creates donor record with all available data
  • Can override the target donor organization_id when the conversion happens in a donation workflow scoped to a specific fund
  • Deletes the prospect record
  • Returns the new donor ID

Search Function: searchDonorsAndProspects(entityId, searchTerm, limit)

  • Searches both donors and prospects tables
  • Returns results with source: 'donor' | 'prospect' field
  • Donors appear first in results, sorted by name

Integration Points

  • Donor CRM: Converted prospects become donors
  • Marketing Campaigns: Prospects can be campaign targets
  • Email System: Bulk email capabilities
  • Analytics: Track conversion rates and sources

Best Practices

  • Regular cleanup of old prospects
  • Track source for ROI analysis
  • Follow up within 48 hours
  • Personalize outreach
  • Respect opt-out requests
  • Maintain data privacy
  • Regular exports for backup

Marketing communications (profile)

Prospect profile embeds the shared CommunicationStatusCard (same as Donors CRM): per-channel email vs text marketing status, read-only.


Synced from IFMmvp-Frontend documentation: pages/fundraising/02-PROSPECTS-LIST.md

Ready to Get Started?

See how Alignmint can simplify your nonprofit's operations. Schedule a free demo with our team and we'll walk you through everything.

Questions? Email us at steven@getalignmint.org

Ready to get started?Start Plus Trial