Files
zemailnator/app/Filament/Pages/GenerateActivationKeys.php
2025-11-14 02:01:01 -08:00

162 lines
4.7 KiB
PHP

<?php
namespace App\Filament\Pages;
use BackedEnum;
use UnitEnum;
use Illuminate\Support\Str;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use App\Models\ActivationKey;
use App\Models\Plan;
use Filament\Actions\BulkAction;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Filament\Tables\Columns\BooleanColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Concerns\InteractsWithTable;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Filters\SelectFilter;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use Response;
class GenerateActivationKeys extends Page implements HasForms, HasTable
{
use InteractsWithForms, InteractsWithTable;
protected static string|BackedEnum|null $navigationIcon = 'heroicon-o-key';
protected string $view = 'filament.pages.generate-activation-keys';
protected static string|UnitEnum|null $navigationGroup = 'Admin';
protected static ?string $title = 'Activation Keys';
public $plan_id;
public $quantity = 1;
public function mount(): void
{
$this->form->fill();
}
protected function getFormSchema(): array
{
return [
Select::make('plan_id')
->label('Select Plan')
->options(Plan::all()->pluck('name', 'id'))
->required(),
TextInput::make('quantity')
->numeric()
->minValue(1)
->maxValue(100)
->default(1)
->required(),
];
}
public function generate(): void
{
$data = $this->form->getState();
$plan = Plan::query()->findOrFail($data['plan_id']);
for ($i = 0; $i < $data['quantity']; $i++) {
ActivationKey::query()->create([
'price_id' => $plan->pricing_id,
'activation_key' => strtoupper('Z'.Str::random(16)),
'is_activated' => false,
]);
}
Notification::make()
->title("{$data['quantity']} activation key(s) generated.")
->success()
->send();
$this->form->fill(); // Reset form
}
// === Table Setup ===
protected function getTableQuery(): Builder
{
return ActivationKey::query()->latest();
}
protected function getTableColumns(): array
{
return [
TextColumn::make('activation_key')
->label('Key')
->copyable(),
BooleanColumn::make('is_activated'),
TextColumn::make('user.email')
->label('Activated By'),
TextColumn::make('billing_interval')
->label('Interval')
->getStateUsing(function ($record): string {
$isMonthly = Plan::query()->where('pricing_id', $record->price_id)->value('monthly_billing');
return $isMonthly ? 'Monthly' : 'Yearly';
}),
TextColumn::make('created_at')
->dateTime(),
];
}
protected function getTableFilters(): array
{
return [
SelectFilter::make('is_activated')
->options([
true => 'Activated',
false => 'Not Activated',
]),
SelectFilter::make('price_id')
->label('Plan')
->options(
Plan::query()->pluck('name', 'pricing_id')
),
];
}
protected function getTableBulkActions(): array
{
return [
BulkAction::make('Download Keys')
->action(fn (Collection $records): BinaryFileResponse => $this->downloadKeys($records))
->deselectRecordsAfterCompletion()
->requiresConfirmation(),
];
}
public function downloadKeys(Collection $records): BinaryFileResponse
{
$text = $records->pluck('activation_key')->implode("\n");
$filename = 'activation_keys_'.now()->timestamp.'.txt';
// Store the file in the 'public' directory or a subdirectory within 'public'
$path = public_path("activation/{$filename}");
// Make sure the 'activation' folder exists, create it if it doesn't
if (! file_exists(public_path('activation'))) {
mkdir(public_path('activation'), 0777, true);
}
// Write the contents to the file
file_put_contents($path, $text);
// Return the response that allows users to download the file directly
return response()->download($path)->deleteFileAfterSend(true);
}
}