Telepathic Collect: link-first, flattened hierarchy, embedded leaderboard
Core insight: The primary object is the LINK, not the appeal.
Aaisha doesn't think 'manage appeals' — she thinks 'share my link'.
## Collect page (/dashboard/collect) — complete rewrite
- Flattened hierarchy: single-appeal orgs see links directly (no card to click)
- Multi-appeal orgs: quiet appeal switcher at top, links below
- Inline link creation: just type a name + press Enter (no dialog)
- Quick preset buttons: 'Table 1', 'WhatsApp Group', 'Instagram', etc.
- Share buttons are THE primary CTA on every link card (Copy, WhatsApp, Email, Share)
- Each link shows: clicks, pledges, amount raised, conversion rate
- Embedded mini-leaderboard when 3+ links have pledges
- Contextual tips when pledges < 5 ('give each volunteer their own link')
- New appeal creation is inline, auto-creates 'Main link'
## Appeal detail page (/dashboard/events/[id]) — brand redesign
- Sharp edges, gap-px grids, typography-as-hero
- Same link card component with share-first design
- Embedded leaderboard section
- Inline link creation (same as Collect)
- Clone appeal button
- Appeal details in collapsed <details> (context, not hero)
- Download all QR codes link
- Public progress page link
## Leaderboard page — brand redesign
- Total raised as hero number (dark section)
- Progress bars relative to leader
- Medal badges for top 3
- Conversion rate badges
- Auto-refresh every 10 seconds (live event mode)
## Route cleanup
- /dashboard/events re-exports /dashboard/collect (backward compat)
- Old events/page.tsx removed (was duplicate)
5 files changed, 3 pages redesigned
This commit is contained in:
86
temp_files/RecentDonationsWidget.php
Normal file
86
temp_files/RecentDonationsWidget.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Widgets;
|
||||
|
||||
use App\Filament\Resources\CustomerResource;
|
||||
use App\Models\Donation;
|
||||
use Filament\Tables\Actions\Action;
|
||||
use Filament\Tables\Columns\IconColumn;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Table;
|
||||
use Filament\Widgets\TableWidget as BaseWidget;
|
||||
|
||||
class RecentDonationsWidget extends BaseWidget
|
||||
{
|
||||
protected static ?int $sort = 4;
|
||||
|
||||
protected int | string | array $columnSpan = 'full';
|
||||
|
||||
protected static ?string $heading = 'Latest Donations';
|
||||
|
||||
protected int $defaultPaginationPageOption = 5;
|
||||
|
||||
public function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->query(
|
||||
Donation::query()
|
||||
->with(['customer', 'donationType', 'donationConfirmation', 'appeal'])
|
||||
->latest('created_at')
|
||||
)
|
||||
->columns([
|
||||
IconColumn::make('is_confirmed')
|
||||
->label('')
|
||||
->boolean()
|
||||
->getStateUsing(fn (Donation $r) => $r->isConfirmed())
|
||||
->trueIcon('heroicon-o-check-circle')
|
||||
->falseIcon('heroicon-o-x-circle')
|
||||
->trueColor('success')
|
||||
->falseColor('danger'),
|
||||
|
||||
TextColumn::make('customer.name')
|
||||
->label('Donor')
|
||||
->description(fn (Donation $d) => $d->customer?->email)
|
||||
->searchable(query: function (\Illuminate\Database\Eloquent\Builder $query, string $search) {
|
||||
$query->whereHas('customer', fn ($q) => $q
|
||||
->where('first_name', 'like', "%{$search}%")
|
||||
->orWhere('last_name', 'like', "%{$search}%")
|
||||
->orWhere('email', 'like', "%{$search}%")
|
||||
);
|
||||
}),
|
||||
|
||||
TextColumn::make('amount')
|
||||
->label('Amount')
|
||||
->money('gbp', divideBy: 100)
|
||||
->sortable()
|
||||
->weight('bold'),
|
||||
|
||||
TextColumn::make('donationType.display_name')
|
||||
->label('Cause')
|
||||
->badge()
|
||||
->color('success')
|
||||
->limit(20),
|
||||
|
||||
TextColumn::make('appeal.name')
|
||||
->label('Fundraiser')
|
||||
->limit(20)
|
||||
->placeholder('Direct donation'),
|
||||
|
||||
TextColumn::make('created_at')
|
||||
->label('When')
|
||||
->since()
|
||||
->sortable(),
|
||||
])
|
||||
->actions([
|
||||
Action::make('view_donor')
|
||||
->label('View Donor')
|
||||
->icon('heroicon-o-user')
|
||||
->url(fn (Donation $d) => $d->customer_id
|
||||
? CustomerResource::getUrl('edit', ['record' => $d->customer_id])
|
||||
: null)
|
||||
->visible(fn (Donation $d) => (bool) $d->customer_id),
|
||||
])
|
||||
->paginated([5, 10])
|
||||
->defaultSort('created_at', 'desc');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user