user()?->canDo(\App\Auth\Permissions::ADMIN_USERS_VIEW) ?? false; } public static function canCreate(): bool { return auth()->user()?->canDo(\App\Auth\Permissions::ADMIN_USERS_MANAGE) ?? false; } public static function canDelete($record): bool { return auth()->user()?->canDo(\App\Auth\Permissions::ADMIN_USERS_MANAGE) ?? false; } public static function form(Schema $schema): Schema { return $schema->components([ Schemas\Components\Section::make('Identitate') ->columns(2) ->schema([ Forms\Components\TextInput::make('name')->label('Nume')->required()->maxLength(120), Forms\Components\TextInput::make('email')->email()->required()->maxLength(120), Forms\Components\TextInput::make('phone')->tel()->maxLength(40), Forms\Components\Select::make('locale') ->options(['ro' => 'Română', 'ru' => 'Русский', 'en' => 'English']) ->default('ro'), ]), Schemas\Components\Section::make('Acces') ->columns(2) ->schema([ Forms\Components\Select::make('role') ->label('Rol primar') ->options(\App\Auth\Permissions::roleLabels()) ->required() ->default('mechanic') ->helperText('Rolul principal — sincronizat automat cu drepturile RBAC.'), Forms\Components\Select::make('status') ->options(['active' => 'Activ', 'inactive' => 'Inactiv', 'blocked' => 'Blocat']) ->default('active') ->required(), Forms\Components\TextInput::make('password') ->label('Parolă') ->password() ->required(fn (string $context) => $context === 'create') ->dehydrated(fn ($state) => filled($state)) ->dehydrateStateUsing(fn ($state) => Hash::make($state)) ->minLength(6) ->helperText('La editare lasă gol pentru a păstra parola actuală.'), Forms\Components\Select::make('roles_picked') ->label('Roluri suplimentare') ->multiple() ->options(\App\Auth\Permissions::roleLabels()) ->afterStateHydrated(function ($component, $record) { if ($record) $component->state($record->roles->pluck('name')->all()); }) ->dehydrated(false) ->columnSpanFull() ->helperText('Roluri suplimentare peste rolul primar — drepturile se cumulează.'), ]), Schemas\Components\Section::make('Securitate') ->columns(2) ->schema([ Forms\Components\Placeholder::make('mfa_status') ->label('Autentificare 2FA') ->content(fn ($record) => $record && $record->hasTwoFactorEnabled() ? '✓ Activat (TOTP)' : '✗ Dezactivat'), Forms\Components\Placeholder::make('last_login') ->label('Ultima autentificare') ->content(fn ($record) => $record?->last_login_at?->diffForHumans() ?? '—'), ]), ]); } public static function table(Table $table): Table { return $table ->columns([ Tables\Columns\TextColumn::make('name')->searchable()->sortable(), Tables\Columns\TextColumn::make('email')->searchable()->copyable(), Tables\Columns\TextColumn::make('phone')->placeholder('—'), Tables\Columns\TextColumn::make('role') ->formatStateUsing(fn ($state) => \App\Auth\Permissions::roleLabels()[$state] ?? $state) ->badge(), Tables\Columns\IconColumn::make('app_authentication_secret') ->label('2FA') ->boolean() ->getStateUsing(fn ($record) => $record->hasTwoFactorEnabled()) ->trueIcon('heroicon-o-shield-check') ->trueColor('success') ->falseIcon('heroicon-o-shield-exclamation') ->falseColor('warning'), Tables\Columns\TextColumn::make('status') ->badge() ->colors([ 'success' => ['active'], 'warning' => ['inactive'], 'danger' => ['blocked'], ]), Tables\Columns\TextColumn::make('last_login_at')->dateTime()->placeholder('—')->toggleable(), Tables\Columns\TextColumn::make('created_at')->date()->sortable()->toggleable(isToggledHiddenByDefault: true), ]) ->filters([ Tables\Filters\SelectFilter::make('role')->options([ 'admin' => 'Admin', 'manager' => 'Manager', 'receptionist' => 'Recepție', 'mechanic' => 'Mecanic', 'parts_manager' => 'Magazie', 'accountant' => 'Contabil', 'marketer' => 'Marketing', ]), Tables\Filters\SelectFilter::make('status')->options([ 'active' => 'Activ', 'inactive' => 'Inactiv', 'blocked' => 'Blocat', ]), ]) ->actions([ Actions\EditAction::make(), Actions\Action::make('reset_2fa') ->label('Resetează 2FA') ->icon('heroicon-o-shield-exclamation') ->color('warning') ->visible(fn ($record) => $record && $record->hasTwoFactorEnabled()) ->requiresConfirmation() ->modalDescription('Dezactivează 2FA pentru acest utilizator. Va trebui să re-configureze TOTP la următoarea autentificare.') ->action(function ($record) { $record->saveAppAuthenticationSecret(null); $record->saveAppAuthenticationRecoveryCodes(null); \Filament\Notifications\Notification::make()->title('2FA resetat')->success()->send(); }), Actions\DeleteAction::make(), ]) ->defaultSort('created_at', 'desc'); } public static function getPages(): array { return [ 'index' => Pages\ListUsers::route('/'), 'create' => Pages\CreateUser::route('/create'), 'edit' => Pages\EditUser::route('/{record}/edit'), ]; } }