Landing page philosophy across ALL dashboard pages

Home:
- Empty state: 2-column with 'How it works' 5-step guide
- Has data: 7/5 grid — pledges left, education right
- Right column: status breakdown, sources, 'What to do next' contextual links, 'What the statuses mean' guide

Money:
- 8/4 two-column layout: table left, education right
- Right column: 'How matching works' 4-step guide, status explainer, collection tips, quick action buttons
- No more wasted right margin

Reports:
- 7/5 two-column layout: downloads left, education right
- Right column: 'For your treasurer' 3-step guide, Gift Aid FAQ, 'Understanding your numbers' explainer
- Activity log moved to right column

Settings:
- Removed max-w-2xl constraint, now uses full width
- 7/5 two-column: checklist left, education right
- Right column: 'What you're setting up' (5 items with Required badges), Privacy & data assurance, Common questions FAQ, 'Need help?' CTA
- Every setting explained in human language
This commit is contained in:
2026-03-05 03:35:08 +08:00
parent 8366054bd7
commit e852250ce0
9 changed files with 1402 additions and 278 deletions

184
temp_files/sg/nav_update.py Normal file
View File

@@ -0,0 +1,184 @@
#!/usr/bin/env python3
"""
Navigation overhaul:
- Daily: Donors, Donations (with recurring tab)
- Seasonal Campaigns: Campaign Dashboard, Subscribers, Giving Campaigns config
- Fundraising: Review Queue, All Fundraisers
- Setup: unchanged
"""
import os
BASE = '/home/forge/app.charityright.org.uk'
# ── 1. ScheduledGivingDonationResource → Seasonal Campaigns group ──
path = os.path.join(BASE, 'app/Filament/Resources/ScheduledGivingDonationResource.php')
with open(path, 'r') as f:
c = f.read()
# Change nav group
c = c.replace(
"protected static ?string $navigationGroup = 'Daily';",
"protected static ?string $navigationGroup = 'Seasonal Campaigns';"
)
# Change label
c = c.replace(
"protected static ?string $navigationLabel = 'Regular Giving';",
"protected static ?string $navigationLabel = 'Subscribers';"
)
# Change sort
c = c.replace(
"protected static ?int $navigationSort = 3;",
"protected static ?int $navigationSort = 1;"
)
# Change model label
c = c.replace(
"protected static ?string $modelLabel = 'Regular Giving';",
"protected static ?string $modelLabel = 'Scheduled Giving';"
)
c = c.replace(
"protected static ?string $pluralModelLabel = 'Regular Giving';",
"protected static ?string $pluralModelLabel = 'Scheduled Giving';"
)
# Change icon to calendar
c = c.replace(
"protected static ?string $navigationIcon = 'heroicon-o-arrow-path';",
"protected static ?string $navigationIcon = 'heroicon-o-user-group';"
)
with open(path, 'w') as f:
f.write(c)
print('Updated ScheduledGivingDonationResource nav')
# ── 2. ScheduledGivingCampaignResource → Seasonal Campaigns group ──
path = os.path.join(BASE, 'app/Filament/Resources/ScheduledGivingCampaignResource.php')
with open(path, 'r') as f:
c = f.read()
c = c.replace(
"protected static ?string $navigationGroup = 'Fundraising';",
"protected static ?string $navigationGroup = 'Seasonal Campaigns';"
)
c = c.replace(
"protected static ?string $navigationLabel = 'Giving Campaigns';",
"protected static ?string $navigationLabel = 'Campaign Config';"
)
# Add sort if missing
if 'navigationSort' not in c:
c = c.replace(
"protected static ?string $navigationLabel = 'Campaign Config';",
"protected static ?string $navigationLabel = 'Campaign Config';\n\n protected static ?int $navigationSort = 2;"
)
with open(path, 'w') as f:
f.write(c)
print('Updated ScheduledGivingCampaignResource nav')
# ── 3. AdminPanelProvider → Add Seasonal Campaigns group ──
path = os.path.join(BASE, 'app/Providers/Filament/AdminPanelProvider.php')
with open(path, 'r') as f:
c = f.read()
old_groups = """ ->navigationGroups([
// ── Daily Work (always visible, top of sidebar) ──
NavigationGroup::make('Daily')
->collapsible(false),
// ── Fundraising (campaigns, 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(),
])"""
new_groups = """ ->navigationGroups([
// ── Daily Work (always visible, top of sidebar) ──
NavigationGroup::make('Daily')
->collapsible(false),
// ── Seasonal Campaigns (30 Nights, 10 Days, Night of Power) ──
NavigationGroup::make('Seasonal Campaigns')
->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(),
])"""
c = c.replace(old_groups, new_groups)
with open(path, 'w') as f:
f.write(c)
print('Updated AdminPanelProvider nav groups')
# ── 4. Update ListScheduledGivingDonations labels ──
path = os.path.join(BASE, 'app/Filament/Resources/ScheduledGivingDonationResource/Pages/ListScheduledGivingDonations.php')
with open(path, 'r') as f:
c = f.read()
c = c.replace(
"return 'Regular Giving';",
"return 'Scheduled Giving Subscribers';"
)
c = c.replace(
'return "{$active} people giving every month.";',
'return "{$active} active subscribers across all campaigns.";'
)
with open(path, 'w') as f:
f.write(c)
print('Updated ListScheduledGivingDonations labels')
# ── 5. Add "Recurring" tab to Donations list ──
# Monthly/weekly donors should be visible under Donations
path = os.path.join(BASE, 'app/Filament/Resources/DonationResource/Pages/ListDonations.php')
with open(path, 'r') as f:
c = f.read()
# Check if 'recurring' tab already exists
if "'recurring'" not in c:
# Find the 'everything' tab and add 'recurring' before it
old_everything = """ 'everything' => Tab::make('Everything')"""
new_recurring = """ 'recurring' => Tab::make('Recurring')
->icon('heroicon-o-arrow-path')
->badge($recurring > 0 ? $recurring : null)
->badgeColor('info')
->modifyQueryUsing(fn (Builder $q) => $q->where('reoccurrence', '!=', -1)
->whereHas('donationConfirmation', fn ($sub) => $sub->whereNotNull('confirmed_at'))),
'everything' => Tab::make('Everything')"""
c = c.replace(old_everything, new_recurring)
# Add $recurring count variable
if '$recurring' not in c:
c = c.replace(
"return [",
"$recurring = Donation::where('reoccurrence', '!=', -1)\n ->whereHas('donationConfirmation', fn ($q) => $q->whereNotNull('confirmed_at'))\n ->count();\n\n return [",
1 # only first occurrence in getTabs
)
with open(path, 'w') as f:
f.write(c)
print('Added Recurring tab to ListDonations')
else:
print('ListDonations already has recurring tab')
print('Navigation update complete!')