components([ TextInput::make('name') ->required() ->maxLength(255), TextInput::make('email') ->email() ->required() ->maxLength(255), TextInput::make('email_verified_at') ->label('Email Verification Status') ->disabled() ->formatStateUsing(fn ($record): string => $record->email_verified_at ?? '' ? 'Verified at '.$record->email_verified_at->toDateTimeString() : 'Not Verified') ->helperText('Shows whether the user has verified their email address.'), TextInput::make('stripe_id') ->label('Stripe ID') ->disabled() ->helperText('Automatically managed by Stripe'), TextInput::make('pm_type') ->label('Payment Method Type') ->disabled(), TextInput::make('pm_last_four') ->label('Card Last 4 Digits') ->disabled(), DatePicker::make('trial_ends_at') ->label('Trial Ends At') ->disabled() ->displayFormat('Y-m-d H:i:s'), Select::make('level') ->label('User Level') ->options(UserLevel::class) ->enum(UserLevel::class) ->required() ->helperText('Select the appropriate user level. Super Admin has full system access.'), ]); } public static function table(Table $table): Table { return $table ->columns([ TextColumn::make('name')->sortable()->searchable(), TextColumn::make('email')->sortable()->searchable(), IconColumn::make('email_verified_at') ->label('Verified') ->boolean() ->trueIcon('heroicon-o-check-circle') ->falseIcon('heroicon-o-x-circle') ->trueColor('success') ->falseColor('danger') ->getStateUsing(fn ($record): bool => ! is_null($record->email_verified_at)) ->sortable(), TextColumn::make('level') ->label('User Level') ->badge() ->getStateUsing(fn ($record): string => $record->level->getLabel()) ->color(fn ($record): string => $record->level->getColor()) ->icon(fn ($record): string => $record->level->getIcon()) ->sortable(), TextColumn::make('stripe_id')->label('Stripe ID')->copyable(), TextColumn::make('pm_last_four')->label('Card Last 4'), TextColumn::make('trial_ends_at')->label('Trial Ends')->dateTime()->sortable(), ]) ->defaultSort('created_at', 'desc') ->filters([ SelectFilter::make('level') ->label('User Level') ->options(UserLevel::class), SelectFilter::make('subscription_status') ->label('Subscription Status') ->options([ 'subscribed' => 'Has Active Subscription', 'not_subscribed' => 'No Active Subscription', ]) ->query(function ($query, array $data): void { if ($data['value'] === 'subscribed') { $query->whereHas('subscriptions', function ($query): void { $query->where('stripe_status', 'active') ->orWhere('stripe_status', 'trialing'); }); } elseif ($data['value'] === 'not_subscribed') { $query->whereDoesntHave('subscriptions', function ($query): void { $query->where('stripe_status', 'active') ->orWhere('stripe_status', 'trialing'); }); } }), SelectFilter::make('email_verified') ->label('Email Verification') ->options([ 'verified' => 'Verified', 'not_verified' => 'Not Verified', ]) ->query(function ($query, array $data): void { if ($data['value'] === 'verified') { $query->whereNotNull('email_verified_at'); } elseif ($data['value'] === 'not_verified') { $query->whereNull('email_verified_at'); } }), ]) ->recordActions([ EditAction::make(), ]) ->toolbarActions([ BulkActionGroup::make([ DeleteBulkAction::make(), BulkAction::make('updateLevel') ->label('Update User Level') ->action(function (Collection $records, array $data): void { $newLevel = (int) $data['new_level']; // Prevent bulk updating to Super Admin level for security if ($newLevel === UserLevel::SUPERADMIN->value) { $message = 'Cannot bulk assign Super Admin level for security reasons.'; Log::warning('Attempted bulk Super Admin assignment', [ 'user_ids' => $records->pluck('id')->toArray(), 'attempted_level' => $newLevel, 'ip' => request()->ip(), ]); Notification::make() ->title('Security Restriction') ->body($message) ->danger() ->send(); return; } DB::table('users') ->whereIn('id', $records->pluck('id')) ->update(['level' => $newLevel]); Log::info('Bulk user level update completed', [ 'user_ids' => $records->pluck('id')->toArray(), 'new_level' => $newLevel, 'updated_by' => auth()->id(), ]); Notification::make() ->title('User Level Updated') ->body('The selected users\' levels have been updated successfully.') ->success() ->send(); }) ->icon('heroicon-o-pencil') ->color('primary') ->modalHeading('Select User Level') ->modalDescription('Please choose the user level to apply to the selected users.') ->modalSubmitActionLabel('Update Level') ->modalCancelActionLabel('Cancel') ->form([ Select::make('new_level') ->label('Select User Level') ->options([ UserLevel::NORMALUSER->value => UserLevel::NORMALUSER->getLabel(), UserLevel::BANNEDUSER->value => UserLevel::BANNEDUSER->getLabel(), ]) ->required() ->helperText('Super Admin level cannot be assigned via bulk action for security.'), ]), ]), ]); } public static function getRelations(): array { return [ LogsRelationManager::class, UsageLogsRelationManager::class, ]; } public static function getPages(): array { return [ 'index' => ListUsers::route('/'), 'create' => CreateUser::route('/create'), 'edit' => EditUser::route('/{record}/edit'), ]; } }