Replaces the disabled "Coming soon" buttons on the pricing page with a waitlist band so visitors can be notified when alerts launch — separate from registered users. - waitlist_subscribers table (name, email unique, source, referrer) - WaitlistService::subscribe — normalises email, idempotent - Public POST /api/waitlist (throttle:10,1), thin controller + form request - Read-only Filament resource with streamed CSV export - Vue: useWaitlist composable + WaitlistForm, rendered below the grid while any tier is still "coming soon"; sends source + document.referrer Announcement send mechanism deferred to a later task. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
43 lines
1.5 KiB
PHP
43 lines
1.5 KiB
PHP
<?php
|
|
|
|
namespace App\Filament\Resources\WaitlistSubscriberResource\Pages;
|
|
|
|
use App\Filament\Resources\WaitlistSubscriberResource;
|
|
use App\Models\WaitlistSubscriber;
|
|
use Filament\Actions\Action;
|
|
use Filament\Resources\Pages\ListRecords;
|
|
use Symfony\Component\HttpFoundation\StreamedResponse;
|
|
|
|
class ListWaitlistSubscribers extends ListRecords
|
|
{
|
|
protected static string $resource = WaitlistSubscriberResource::class;
|
|
|
|
protected function getHeaderActions(): array
|
|
{
|
|
return [
|
|
Action::make('export')
|
|
->label('Export CSV')
|
|
->icon('heroicon-o-arrow-down-tray')
|
|
->action(fn (): StreamedResponse => response()->streamDownload(function (): void {
|
|
$handle = fopen('php://output', 'wb');
|
|
|
|
fputcsv($handle, ['name', 'email', 'source', 'referrer', 'joined_at']);
|
|
|
|
WaitlistSubscriber::query()
|
|
->orderBy('created_at')
|
|
->each(function (WaitlistSubscriber $subscriber) use ($handle): void {
|
|
fputcsv($handle, [
|
|
$subscriber->name,
|
|
$subscriber->email,
|
|
$subscriber->source,
|
|
$subscriber->referrer,
|
|
$subscriber->created_at?->toDateTimeString(),
|
|
]);
|
|
});
|
|
|
|
fclose($handle);
|
|
}, 'waitlist.csv', ['Content-Type' => 'text/csv'])),
|
|
];
|
|
}
|
|
}
|