components([ Grid::make() ->schema([ Section::make() ->schema([ TextInput::make('name') ->label(__('users.fields.name')) ->required() ->maxLength(255), TextInput::make('username') ->label(__('users.fields.username')) ->required() ->maxLength(255) ->unique(table: User::class, column: 'username', ignoreRecord: true), TextInput::make('password') ->label(__('users.fields.password')) ->password() ->required(fn (string $operation): bool => $operation === 'create') ->dehydrateStateUsing(fn (string $state): string => Hash::make($state)) ->dehydrated(fn (?string $state): bool => filled($state)) ->maxLength(255), Select::make('roles') ->label(__('users.fields.roles')) ->relationship('roles', 'name') ->multiple() ->preload(), ]) ->columns(2) ->columnSpanFull() ->footerActions([ fn (string $operation) => Action::make('create') ->label(__('filament-panels::resources/pages/create-record.form.actions.create.label')) ->submit('create') ->keyBindings(['mod+s']) ->visible($operation === 'create'), fn (string $operation) => Action::make('createAnother') ->label(__('filament-panels::resources/pages/create-record.form.actions.create_another.label')) ->action('createAnother') ->keyBindings(['mod+shift+s']) ->color('gray') ->visible($operation === 'create'), fn (string $operation) => Action::make('cancelCreate') ->label(__('filament-panels::resources/pages/create-record.form.actions.cancel.label')) ->url(static::getUrl('index')) ->color('gray') ->visible($operation === 'create'), fn (string $operation) => Action::make('save') ->label(__('filament-panels::resources/pages/edit-record.form.actions.save.label')) ->submit('save') ->keyBindings(['mod+s']) ->visible($operation === 'edit'), fn (string $operation) => Action::make('cancelEdit') ->label(__('filament-panels::resources/pages/edit-record.form.actions.cancel.label')) ->url(static::getUrl('index')) ->color('gray') ->visible($operation === 'edit'), ]), ]) ->columnSpanFull(), ]); } public static function table(Table $table): Table { return $table ->columns([ TextColumn::make('name') ->label(__('users.fields.name')) ->searchable() ->sortable(), TextColumn::make('username') ->label(__('users.fields.username')) ->searchable() ->sortable(), TextColumn::make('roles.name') ->label(__('users.fields.roles')) ->badge() ->separator(','), TextColumn::make('created_at') ->label(__('users.fields.created_at')) ->sortable(), ]) ->recordActions([ EditAction::make(), DeleteAction::make(), ]) ->toolbarActions([ BulkActionGroup::make([ DeleteBulkAction::make(), BulkAction::make('export_excel_selected') ->label(__('table.export_excel_selected')) ->icon('heroicon-o-table-cells') ->color('success') ->action(function (Collection $records) { $tempPath = tempnam(sys_get_temp_dir(), 'export_') . '.xlsx'; $writer = new Writer(); $writer->openToFile($tempPath); $writer->addRow(Row::fromValues([ 'ID', __('users.fields.name'), __('users.fields.username'), __('users.fields.roles'), __('users.fields.created_at'), ])); foreach ($records as $record) { $writer->addRow(Row::fromValues([ $record->id, $record->name, $record->username, $record->roles->pluck('name')->join(', '), $record->created_at, ])); } $writer->close(); return response()->streamDownload(function () use ($tempPath) { readfile($tempPath); @unlink($tempPath); }, 'users-' . now()->format('Y-m-d') . '.xlsx', [ 'Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', ]); }), ]), ActionGroup::make([ Action::make('export_excel') ->label(__('table.export_excel')) ->color('success') ->icon('heroicon-o-table-cells') ->action(function () { $records = User::with('roles')->get(); $tempPath = tempnam(sys_get_temp_dir(), 'export_') . '.xlsx'; $writer = new Writer(); $writer->openToFile($tempPath); $writer->addRow(Row::fromValues([ 'ID', __('users.fields.name'), __('users.fields.username'), __('users.fields.roles'), __('users.fields.created_at'), ])); foreach ($records as $record) { $writer->addRow(Row::fromValues([ $record->id, $record->name, $record->username, $record->roles->pluck('name')->join(', '), $record->created_at, ])); } $writer->close(); return response()->streamDownload(function () use ($tempPath) { readfile($tempPath); @unlink($tempPath); }, 'users-' . now()->format('Y-m-d') . '.xlsx', [ 'Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', ]); }), Action::make('export_pdf') ->label(__('table.export_pdf')) ->color('danger') ->icon('heroicon-o-document-arrow-down') ->action(function () { $records = User::with('roles')->get(); return PdfService::download( 'exports.users-pdf', ['records' => $records], 'users-' . now()->format('Y-m-d') . '.pdf', ); }), ]) ->label(__('table.export')) ->color('orange') ->button(), ]); } public static function getPages(): array { return [ 'index' => Pages\ListUsers::route('/'), 'create' => Pages\CreateUser::route('/create'), 'edit' => Pages\EditUser::route('/{record}/edit'), ]; } public static function getNavigationLabel(): string { return __('navigation.users.title'); } public static function getModelLabel(): string { return __('navigation.users.singular'); } public static function getPluralModelLabel(): string { return __('navigation.users.title'); } }