Quick Actions Card
Quick Actions Card
Component File: src/features/dashboard/components/QuickActionsCard.tsx Access Level: All authenticated users Last Updated: January 29, 2026 Status: ✅ Implemented
---
Overview
The Quick Actions Card is an addable dashboard component that surfaces actionable insights requiring director attention. It displays up to 5 items sorted by urgency (days overdue), with clickable jumpoffs to resolve each issue.
UI Features
Main Display
- Title: "Quick Actions" with count badge
- Action Items: Up to 5 items, sorted by days overdue (most urgent first)
- Each Item Shows:
- Status indicator (🔴 red for urgent, 🟡 yellow for attention needed)
- Description (e.g., "John Smith hasn't made his monthly donation")
- Context (e.g., "Expected Jan 15 • 5 days late")
- Clickable jumpoff link
- View All Link: If more than 5 items, show "View all X items" link
Empty State
When no action items exist:
✅ All caught up! No action items right now.Action Types (v1)
1. Late Recurring Donor
Detection Logic:
// Donor has donation_type = 'recurring' or 'both'
// AND last_donation_date + recurring_frequency + 3 days < today
// AND last_donation_date is within the last 90 days (excludes churned donors)
function getExpectedDonationDate(lastDonation: Date, frequency: string): Date {
const expected = new Date(lastDonation);
switch (frequency) {
case 'weekly': expected.setDate(expected.getDate() + 7); break;
case 'monthly': expected.setMonth(expected.getMonth() + 1); break;
case 'quarterly': expected.setMonth(expected.getMonth() + 3); break;
case 'annually': expected.setFullYear(expected.getFullYear() + 1); break;
}
return expected;
}
function isDonationLate(expectedDate: Date, graceDays = 3): boolean {
const today = new Date();
const graceDate = new Date(expectedDate);
graceDate.setDate(graceDate.getDate() + graceDays);
return today > graceDate;
}
// 90-day lookback filter: excludes donors who haven't donated in 3+ months
// These are considered "churned" and not actionable quick actions
const maxLookbackDate = new Date();
maxLookbackDate.setDate(maxLookbackDate.getDate() - 90);Display:
- Icon: 🔴 (if > 7 days late) or 🟡 (3-7 days late)
- Text: "{First Name} {Last Name} hasn't made their {frequency} donation"
- Context: "Expected {date} • {X} days late"
- Jumpoff: Navigate to donor profile in Donors CRM
Jumpoff Action:
setCurrentPage('donors');
setDonorTool('donors');
// Open donor detail view with donorId2. Overdue Pledge
Detection Logic:
SELECT * FROM pledges
WHERE expected_date < CURRENT_DATE
AND amount_received < amount
AND status != 'cancelled'
ORDER BY expected_date ASCDisplay:
- Icon: 🟡
- Text: "{Donor Name}'s pledge is overdue"
- Context: "${amount} expected {date}"
- Jumpoff: Navigate to Pledges in Accounting Hub
Jumpoff Action:
setCurrentPage('fund-accounting');
setAccountingTool('pledges');3. Overdue Grant
Detection Logic:
SELECT * FROM grants_receivable
WHERE expected_date < CURRENT_DATE
AND amount_received < amount
AND status != 'cancelled'
ORDER BY expected_date ASCDisplay:
- Icon: 🟡
- Text: "{Grant Name} payment pending"
- Context: "${amount} expected {date}"
- Jumpoff: Navigate to Grants Receivable in Accounting Hub
Jumpoff Action:
setCurrentPage('fund-accounting');
setAccountingTool('grants-receivable');Future Action Types (v2+)
| Action Type | Detection | Jumpoff |
|-------------|-----------|---------|
| Overdue Todos | `todos.due_date < today AND completed = false` | Todo List |
| Unacknowledged Donations | Donations without thank-you email | Donor profile |
| Failed Recurring Payments | Stripe webhook data | Donor Payment Management |
| Budget Variance | Expenses > 110% of budget | Budget Report |
| Reconciliation Reminder | Bank account not reconciled in 30+ days | Reconciliation |
Data Requirements
QuickActionItem Interface
interface QuickActionItem {
id: string;
type: 'late-recurring-donor' | 'overdue-pledge' | 'overdue-grant';
priority: 'urgent' | 'attention'; // urgent = red, attention = yellow
title: string; // Main description
context: string; // Secondary info (date, amount)
daysOverdue: number; // For sorting
jumpoff: {
page: PageView;
tool?: string;
params?: Record<string, string>; // e.g., { donorId: 'xxx' }
};
}
interface QuickActionsData {
items: QuickActionItem[];
totalCount: number; // Total items (may be > 5)
}Sorting & Limiting
1. Sort by: daysOverdue descending (most urgent first) 2. Limit: Show top 5 items 3. View All: If totalCount > 5, show link to expanded view
Grace Period & Lookback
- Recurring Donors: 3 days after expected date before showing alert
- 90-Day Lookback: Only donors with
last_donation_datewithin the last 90 days are shown. Donors who haven't donated in 3+ months are considered "churned" and excluded from quick actions. - Pledges/Grants: Show immediately when past expected date
Dashboard Registration
Store Types (src/store/types.ts)
// Add to DashboardComponent type
export type DashboardComponent =
| 'donations-chart'
| 'recent-donations'
| 'to-do-list'
| 'top-donors'
| 'fund-summary'
| 'quick-actions'; // NEW
// Add to ADDABLE_DASHBOARD_COMPONENTS
export const ADDABLE_DASHBOARD_COMPONENTS: DashboardComponent[] = [
'top-donors',
'fund-summary',
'quick-actions', // NEW
];
// Add to DASHBOARD_COMPONENT_INFO
export const DASHBOARD_COMPONENT_INFO: Record<DashboardComponent, { label: string; description: string }> = {
// ... existing entries
'quick-actions': {
label: 'Quick Actions',
description: 'Actionable alerts for late donations, overdue pledges, and more'
},
};App.tsx Render Switch
case 'quick-actions':
return <QuickActionsCard />;Implementation Files
| File | Purpose |
|------|---------|
| `src/features/dashboard/components/QuickActionsCard.tsx` | UI component |
| `src/lib/db.ts` | Add `fetchQuickActionsData()` function |
| `src/hooks/useDashboardMetrics.ts` | Add `useQuickActions()` hook |
| `src/store/types.ts` | Register component type |
| `src/App.tsx` | Add render case |
UI Mockup
With Items
┌─────────────────────────────────────────────────────┐
│ ⚡ Quick Actions (3) │
├─────────────────────────────────────────────────────┤
│ 🔴 John Smith hasn't made his monthly donation │
│ Expected Jan 15 • 5 days late │
│ View Donor → │
├─────────────────────────────────────────────────────┤
│ 🟡 Sarah Johnson's pledge is overdue │
│ $500 expected Jan 20 │
│ View Pledge → │
├─────────────────────────────────────────────────────┤
│ 🟡 Community Foundation grant payment pending │
│ $10,000 expected Jan 10 │
│ View Grant → │
├─────────────────────────────────────────────────────┤
│ View all 7 items → │
└─────────────────────────────────────────────────────┘Empty State
┌─────────────────────────────────────────────────────┐
│ ⚡ Quick Actions │
│ │
│ ✅ All caught up! No action items right now. │
│ │
└─────────────────────────────────────────────────────┘Styling
Following existing dashboard component patterns:
// Priority colors
const priorityStyles = {
urgent: 'text-red-600 dark:text-red-400',
attention: 'text-amber-600 dark:text-amber-400',
};
// Card styling
<Card className="hover:shadow-md transition-shadow">
<CardHeader className="pb-2">
<div className="flex items-center justify-between">
<CardTitle className="flex items-center gap-2">
<Zap className="h-5 w-5" />
Quick Actions
</CardTitle>
{totalCount > 0 && (
<Badge variant="secondary">{totalCount}</Badge>
)}
</div>
</CardHeader>
<CardContent>
{/* Action items */}
</CardContent>
</Card>Related Documentation
Synced from IFMmvp-Frontend documentation: pages/dashboard/QUICK-ACTIONS-CARD.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