THE CORE PROBLEM:
Users didn't understand the appeal→link hierarchy.
Payment method was hidden inside appeal creation.
The widget was a separate, undiscoverable concept.
External platforms (JustGiving, LaunchGood) felt disconnected.
THE FIX:
1. ONE CREATION FLOW for everything:
Step 1: 'What are you raising for?' → creates the appeal
Step 2: 'How will donors pay?' → 3 big clear cards:
- Bank transfer (most popular, free)
- External platform (JustGiving, LaunchGood, etc.)
- Card payment (Stripe)
Step 3: 'Name your link' → shows summary, creates both
2. PAYMENT METHOD VISIBLE ON EVERY LINK:
Each link card shows a badge: 'Bank' or 'JustGiving' etc.
External links show 'After pledging, donors are sent to...'
No confusion about how money flows.
3. WIDGET IS A SHARING TAB, NOT A SEPARATE CONCEPT:
Every link card expands to show 3 tabs:
- Link (copy URL, WhatsApp, email, share)
- QR Code (download PNG for printing)
- Website Widget (iframe embed code with copy button)
The widget is just another way to share the same link.
4. FLAT LINK LIST (not appeal→link hierarchy):
All links shown in one flat list
Appeal name shown as subtitle when multiple appeals exist
'New link' adds to existing appeal
'New appeal' uses the full 3-step wizard
5. EDUCATIONAL RIGHT COLUMN:
'How it works' 5-step guide
'Which payment method should I choose?' comparison
'Can I mix payment methods?' FAQ
'What's an appeal?' explanation (demystifies the concept)
Leaderboard when 3+ links have pledges
94 lines
3.6 KiB
PHP
94 lines
3.6 KiB
PHP
<?php
|
|
|
|
namespace App\Providers\Filament;
|
|
|
|
use App\Helpers;
|
|
use Filament\Http\Middleware\Authenticate;
|
|
use Filament\Http\Middleware\DisableBladeIconComponents;
|
|
use Filament\Http\Middleware\DispatchServingFilamentEvent;
|
|
use Filament\Navigation\MenuItem;
|
|
use Filament\Navigation\NavigationGroup;
|
|
use Filament\Navigation\NavigationItem;
|
|
use Filament\Panel;
|
|
use Filament\PanelProvider;
|
|
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
|
|
use Illuminate\Cookie\Middleware\EncryptCookies;
|
|
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
|
|
use Illuminate\Routing\Middleware\SubstituteBindings;
|
|
use Illuminate\Session\Middleware\AuthenticateSession;
|
|
use Illuminate\Session\Middleware\StartSession;
|
|
use Illuminate\View\Middleware\ShareErrorsFromSession;
|
|
|
|
class AdminPanelProvider extends PanelProvider
|
|
{
|
|
public function panel(Panel $panel): Panel
|
|
{
|
|
return $panel
|
|
->default()
|
|
->id('admin')
|
|
->path('admin')
|
|
->login()
|
|
->colors(['primary' => config('branding.colours')])
|
|
->viteTheme('resources/css/filament/admin/theme.css')
|
|
->sidebarCollapsibleOnDesktop()
|
|
->sidebarWidth('16rem')
|
|
->globalSearch(true)
|
|
->globalSearchKeyBindings(['command+k', 'ctrl+k'])
|
|
->globalSearchDebounce('300ms')
|
|
->navigationGroups([
|
|
// ── Daily Work (always visible, top of sidebar) ──
|
|
NavigationGroup::make('Daily')
|
|
->collapsible(false),
|
|
|
|
// ── Giving (30 Nights, 10 Days, Night of Power) ──
|
|
NavigationGroup::make('Giving')
|
|
->icon('heroicon-o-calendar-days')
|
|
->collapsible(),
|
|
|
|
// ── Fundraising (appeals, review queue) ──
|
|
NavigationGroup::make('Fundraising')
|
|
->icon('heroicon-o-megaphone')
|
|
->collapsible(),
|
|
|
|
// ── Setup (rarely touched config) ──
|
|
NavigationGroup::make('Setup')
|
|
->icon('heroicon-o-cog-6-tooth')
|
|
->collapsible()
|
|
->collapsed(),
|
|
])
|
|
->brandLogo(Helpers::getCurrentLogo(true))
|
|
->discoverResources(in: app_path('Filament/Resources'), for: 'App\\Filament\\Resources')
|
|
->discoverPages(in: app_path('Filament/Pages'), for: 'App\\Filament\\Pages')
|
|
->pages([\Filament\Pages\Dashboard::class])
|
|
->userMenuItems([
|
|
'profile' => MenuItem::make()
|
|
->label('Edit profile')
|
|
->url(url('user/profile')),
|
|
|
|
'back2site' => MenuItem::make()
|
|
->label('Return to site')
|
|
->icon('heroicon-o-home')
|
|
->url(url('/')),
|
|
])
|
|
->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\\Filament\\Widgets')
|
|
->middleware([
|
|
EncryptCookies::class,
|
|
AddQueuedCookiesToResponse::class,
|
|
StartSession::class,
|
|
AuthenticateSession::class,
|
|
ShareErrorsFromSession::class,
|
|
VerifyCsrfToken::class,
|
|
SubstituteBindings::class,
|
|
DisableBladeIconComponents::class,
|
|
DispatchServingFilamentEvent::class,
|
|
])
|
|
->authMiddleware([
|
|
Authenticate::class,
|
|
])
|
|
->login(null)
|
|
->registration(null)
|
|
->darkMode(false)
|
|
->databaseNotifications();
|
|
}
|
|
}
|