P0 Critical (7): - STOP/UNSUBSCRIBE keyword → CANCEL (PECR compliance) - Rate limiting on pledge creation (10/IP/5min) - Terms of Service + Privacy Policy pages - WhatsApp onboarding gate (persistent dashboard banner) - Demo account seeding (demo@pnpl.app) - Footer legal links - Basic accessibility (aria labels on donor flow) P1 Within 2 Weeks (8): - Pledge editing by staff (PATCH amount, name, email, phone, rail) - Donor self-cancel page (/p/cancel) + API - Donor 'My Pledges' lookup page (/p/my-pledges) - Bulk QR code download (print-ready HTML) - Public event progress bar (/e/[slug]/progress) - Email-only donor handling (honest status + WhatsApp fallback) - Email verification (format + disposable domain blocking) - Organisations page rewrite (multi-campaign, not multi-org) P2 Within First Month (10): - Event cloning with QR sources - Account deletion (GDPR Article 17) - Daily digest cron via WhatsApp - AI-6 Smart reminder timing (due date anchoring, cultural sensitivity) - H1 Duplicate donor detection (email, phone, Jaro-Winkler name) - H5 Bank CSV format presets (10 UK banks) - H16 Partial payment matching (underpay, overpay, instalment) - H10 Activity logging (audit trail for staff actions) - AI nudge endpoint + AI column mapping + AI event setup wizard - AI anomaly detection wired into daily digest AI Features (11): smart reconciliation, social proof, auto column mapper, daily digest, impact storyteller, smart timing, nudge composer, event wizard, NLU concierge, anomaly detection, bank presets 22 new files, 15 modified files, 0 TypeScript errors, clean build.
12 KiB
CharityRight Admin Panel — Full Audit & Overhaul Plan
Date: 4 March 2026
Auditor: Claude (via pi)
Stack: Laravel 11 + Filament v3.3.26 + PHP 8.3 + DigitalOcean
1. Current State Inventory
Navigation Groups & Resources
| Group | Resource | Model | Records | Notes |
|---|---|---|---|---|
| Management | Customers | Customer | 21,558 | Basic CRUD, no search filters |
| Users | User | 20,189 | Hidden from Admin role, minimal form | |
| Snowdon Registrations | SnowdonRegistration | 112 | Legacy event, still in nav | |
| Campaign Registrations | CampaignRegistration | 115 | T365/Ramadan, hardcoded title | |
| Donations | General | Donation | 30,497 | Main donation view, good filters |
| Scheduled | ScheduledGivingDonation | 2,841 | Separate resource from general | |
| URL Builder | (page) | — | Utility page for donation links | |
| Campaigns | Appeals | Appeal | 8,914 | Core resource, complex |
| Approvals | ApprovalQueue | 1,934 | Queue for appeal changes | |
| Scheduled Campaigns | ScheduledGivingCampaign | 3 | Very few records | |
| Words of Hope | WOHMessage | 817 | Form submissions | |
| Allocation | Donation Items | DonationType | 30 | Hidden from Admin role |
| Countries | DonationCountry | 12 | Hidden from Admin role | |
| Fund Dimensions | EngageFundDimension | — | N3O Engage sync | |
| Attribution Dimensions | EngageAttributionDimension | — | N3O Engage sync | |
| Misc | Settings | (page) | — | Global settings, hidden from Admin |
| Event Logs | EventLog | 2,276,079 | ⚠️ 2.2M rows, no cleanup |
Roles & Permissions
| Role | Permissions | Can See |
|---|---|---|
| Superadmin | All (via Gate::before) | Everything |
| Admin | Full CRUD on customers, donations, appeals, campaigns | Most things, hidden: Users, Settings, DonationType, DonationCountry |
| Appeal Manager | view/edit/delete appeal | Appeals only |
| Finance Manager | view/edit/delete donation + donation-item | Donations only |
| User | (none) | Nothing in admin |
2. Critical Issues Found
🔴 A. No Dashboard — Zero At-a-Glance Intelligence
The admin panel has no widgets, no dashboard, no KPIs. When staff log in they see a blank page with navigation. They have no idea:
- How many donations came in today/this week/this month
- Total revenue
- Active campaigns and their progress
- Pending approvals count
- Failed/errored donations
- Scheduled giving health
🔴 B. No Supporter/Care View
There is zero support workflow. A support agent can't:
- Search for a donor by email/name/phone and see everything about them in one place
- See a donor's full history (all donations, scheduled giving, appeals, gift aid status)
- Issue refunds or resend receipts easily
- Add notes/tags to a customer record
- Merge duplicate customer records (21K customers vs 20K users = many duplicates)
- See a timeline/activity log for a customer
🔴 C. Customer ↔ User Confusion
Two separate models (User = login account, Customer = donation record) with no unified view. Staff must:
- Search Users to find the login account
- Search Customers to find donation records
- Mentally link them (via
customer.user_id) - No way to see "this person's full picture"
🔴 D. Event Logs — 2.2 Million Rows, No Cleanup
EventLog table has 2.2M rows with no pruning, no auto-archive, no summary view. This:
- Slows down the admin panel
- Makes the "Event Logs" page unusable (loads millions of rows)
- No alerting on errors
- No way to filter by severity or recent errors only
🔴 E. Hardcoded Emails for Export Access
->visible(function () {
$authedEmail = auth()->user()->email;
return $authedEmail == 'omair.saleh@charityright.org.uk' || $authedEmail == 'development@verge.digital';
})
Export functionality is locked to specific email addresses instead of using the permission system.
3. UX Issues
🟠 F. Top Navigation is Overcrowded
->topNavigation() with 5 groups × 3-5 items = 15+ items in a horizontal bar. With long names like "Scheduled Giving Campaigns", this overflows on most screens. Many items are rarely used (Snowdon Registrations, Fund Dimensions, Attribution Dimensions).
🟠 G. Deprecated Code Patterns (Partially Fixed)
->reactive()instead of->live()— fixed for Appeal resources, but DonationResource, CustomerResource, ScheduledGivingDonationResource still use->reactive()andcallable $getHtmlStringused extensively for simple formatting (should use Filament's native badge/formatting)
🟠 H. No Global Search
No ->globalSearch() configured. Staff can't type a donor email in the search bar and find them. They must navigate to Customers, then search.
🟠 I. Donation Edit Form is Read-Only Placeholders
The DonationResource edit form is entirely Placeholder components — nothing is actually editable. The form pretends to be an edit page but is really a view page. Should use ViewAction or a proper view page.
🟠 J. No Inline Links Between Resources
- Viewing a Donation doesn't link to the Customer
- Viewing a Customer doesn't link to their User account
- Viewing an Appeal doesn't link to the parent appeal in a clickable way
view_customeraction exists but has no URL attached
🟠 K. Inconsistent Form Patterns
- AppealResource defines the form schema TWICE (in
AppealResource::form()ANDEditAppeal::form()) — 100% duplicated - Some resources use
ViewAction, others useEditActionfor the same purpose - Some tables have bulk actions, others don't
- Inconsistent use of
->collapsible()->collapsed()vs not
🟠 L. Legacy/Dead Resources in Navigation
- Snowdon Registrations (112 records, likely a past event)
- Campaign Registrations with hardcoded "T365 / Ramadan Challenge" title
- Both clutter the Management group for daily users
4. Functional Gaps
🟡 M. No Refund Workflow
No ability to process or record refunds from the admin panel. Support staff need to go to Stripe dashboard.
🟡 N. No Donation Notes/Comments
No way to add internal notes to a donation (e.g., "Donor called, wants to change allocation" or "Refunded via Stripe on 2024-01-15").
🟡 O. No Customer Merge Tool
With 21K customers and 20K users, there are certainly duplicates. No tool to merge them.
🟡 P. No Scheduled Giving Management
Can't pause, cancel, or modify a scheduled giving subscription from the admin. The edit page exists but fields are placeholder-only.
🟡 Q. No Bulk Operations for Appeals
Can't bulk-approve, bulk-reject, or bulk-publish appeals. Approval queue exists but it's a basic list.
🟡 R. No Communication/Email Log
No record of emails sent to donors (receipts, confirmations). Can't tell if a receipt was sent or if it bounced.
🟡 S. No Gift Aid Reporting
Gift Aid is tracked per donation but there's no aggregated report view for HMRC claims.
🟡 T. Missing Filters on Key Resources
- Customers: No filters at all (no date range, no donation count, no total donated)
- Appeals: No status filter, no date filter, no "has donations" filter
- Users: No role filter, no activity filter
5. Overhaul Plan — Phases
Phase 1: Dashboard & Navigation (High Impact, Quick Win)
-
Build a Dashboard with widgets:
- Today's donations (count + total £)
- This week/month revenue chart
- Pending approvals badge
- Active campaigns progress bars
- Recent errors count (from EventLog)
- Scheduled giving health (active/paused/failed)
-
Fix Navigation Structure:
Dashboard (home) ├── Supporter Care (new) │ ├── Donors (unified Customer+User view) │ └── Donor Lookup (global search page) ├── Donations │ ├── All Donations │ ├── Scheduled Giving │ └── URL Builder ├── Campaigns │ ├── Appeals │ ├── Approvals (with badge count) │ ├── Scheduled Campaigns │ └── Registrations (merge Snowdon + Campaign) ├── Configuration (collapsible, for admins) │ ├── Donation Items │ ├── Countries │ ├── Fund Dimensions │ ├── Attribution Dimensions │ └── Settings ├── Logs & System │ └── Event Logs (with cleanup) -
Switch from Top Nav to Sidebar — Too many items for top nav. Sidebar with collapsible groups is standard for admin panels this size.
-
Enable Global Search across Customers, Donations, Appeals.
Phase 2: Supporter Care Hub (Highest Business Value)
-
Unified Donor Profile Page — Single page showing:
- Customer details + linked User account
- All donations (one-off + scheduled) in a timeline
- All appeals they've donated to
- Gift aid status across all donations
- Address history
- Internal notes (new feature)
- Communication log (new feature)
- Quick actions: Send receipt, Add note, View in Stripe
-
Donor Search Widget — Search by email, name, phone, donation reference, provider reference. Returns unified results.
-
Internal Notes System — Polymorphic
notestable: add notes to Customers, Donations, Appeals.
Phase 3: Operational Improvements
- Fix DonationResource — Make it a proper ViewRecord page, not a fake edit page with Placeholders
- Add missing filters to all key resources
- Replace hardcoded email checks with proper permissions (
can-exportpermission) - Add cross-resource links (Donation → Customer, Customer → User, Appeal → Parent)
- Deduplicate AppealResource form (remove from
AppealResource::form(), keep only inEditAppeal::form()) - Archive/hide legacy resources (Snowdon, or move to a "Legacy" group)
Phase 4: Reporting & Data Health
- Gift Aid Report Page — Aggregate view for HMRC claims
- Donation Summary Report — By type, country, period
- EventLog Cleanup — Auto-prune entries older than 90 days, add severity indicators
- Scheduled Giving Health Dashboard — Failed payments, retries, cancellations
6. Technical Recommendations
| Item | Current | Recommended |
|---|---|---|
| Navigation | ->topNavigation() |
->sidebarCollapsibleOnDesktop() |
| Global Search | None | Enable on Customer, Donation, Appeal |
| Dashboard | Blank | Custom widgets page |
| Form pattern | ->reactive() + callable $get |
->live() + \Filament\Forms\Get $get |
| Export access | Hardcoded emails | Permission-based (can-export) |
| EventLog | 2.2M unmanaged rows | Pruning schedule + summary widget |
| Donation form | Placeholder-only edit page | ViewRecord page |
| Customer-User | Separate resources | Unified Donor resource |
7. Priority Matrix
| Priority | Item | Effort | Impact |
|---|---|---|---|
| 🔴 P0 | Dashboard widgets | Medium | Very High |
| 🔴 P0 | Fix navigation (sidebar + groups) | Low | High |
| 🔴 P0 | Global search | Low | High |
| 🔴 P0 | Supporter Care donor profile | High | Very High |
| 🟠 P1 | Internal notes system | Medium | High |
| 🟠 P1 | Fix donation view page | Low | Medium |
| 🟠 P1 | Add missing filters | Low | Medium |
| 🟠 P1 | Cross-resource links | Low | Medium |
| 🟠 P1 | Replace hardcoded email checks | Low | Medium |
| 🟡 P2 | Gift Aid report | Medium | Medium |
| 🟡 P2 | EventLog cleanup | Medium | Medium |
| 🟡 P2 | Customer merge tool | High | Medium |
| 🟡 P2 | Communication log | Medium | Medium |
| 🟡 P2 | Archive legacy resources | Low | Low |