components([ Schemas\Components\Section::make('Identificare') ->columns(2) ->schema([ Forms\Components\TextInput::make('slug') ->required() ->alphaDash() ->maxLength(30) ->unique( ignoreRecord: true, modifyRuleUsing: fn ($rule) => $rule->whereNull('deleted_at'), ) ->dehydrateStateUsing(fn ($state) => strtolower((string) $state)) ->extraInputAttributes(['style' => 'text-transform: lowercase']) ->helperText('Subdomeniul: .service.mir.md'), Forms\Components\TextInput::make('name')->required()->maxLength(120), Forms\Components\TextInput::make('display_name')->maxLength(120), Forms\Components\TextInput::make('city')->maxLength(60), ]), Schemas\Components\Section::make('Contact') ->columns(2) ->schema([ Forms\Components\TextInput::make('contact_name')->maxLength(120), Forms\Components\TextInput::make('phone')->tel()->maxLength(40), Forms\Components\TextInput::make('email')->email()->maxLength(120), ]), Schemas\Components\Section::make('Abonament') ->columns(2) ->schema([ Forms\Components\Select::make('status') ->options([ 'trial' => 'Trial', 'active' => 'Activ', 'expired' => 'Expirat', 'suspended' => 'Suspendat', 'archived' => 'Arhivat', ]) ->default('trial') ->required(), Forms\Components\Select::make('plan_id') ->label('Plan') ->options(fn () => Plan::pluck('name', 'id')) ->searchable(), Forms\Components\DateTimePicker::make('trial_ends_at')->label('Trial expiră la'), Forms\Components\DateTimePicker::make('active_until')->label('Abonament până la'), ]), Schemas\Components\Section::make('Admin tenant (la creare)') ->columns(2) ->visible(fn (string $operation) => $operation === 'create') ->schema([ Forms\Components\TextInput::make('admin_name') ->label('Nume admin') ->default('Administrator'), Forms\Components\TextInput::make('admin_email') ->label('Email admin') ->email() ->required(), Forms\Components\TextInput::make('admin_password') ->label('Parolă (lasă gol pentru auto-generat)') ->password() ->minLength(8) ->helperText('Dacă e gol, generăm 10 caractere random.'), ]), ]); } public static function table(Table $table): Table { return $table ->columns([ Tables\Columns\TextColumn::make('id')->sortable(), Tables\Columns\TextColumn::make('slug') ->searchable() ->copyable() ->url(fn (Company $r) => $r->url('/app')) ->openUrlInNewTab(), Tables\Columns\TextColumn::make('name')->searchable()->sortable(), Tables\Columns\TextColumn::make('status') ->badge() ->colors([ 'success' => ['active'], 'warning' => ['trial'], 'danger' => ['suspended', 'expired'], 'gray' => ['archived'], ]), Tables\Columns\TextColumn::make('plan.name')->label('Plan')->placeholder('—'), Tables\Columns\TextColumn::make('city')->toggleable(), Tables\Columns\TextColumn::make('users_count')->counts('users')->label('Useri'), Tables\Columns\TextColumn::make('created_at')->date()->sortable(), ]) ->filters([ Tables\Filters\SelectFilter::make('status')->options([ 'trial' => 'Trial', 'active' => 'Activ', 'expired' => 'Expirat', 'suspended' => 'Suspendat', 'archived' => 'Arhivat', ]), ]) ->recordUrl(fn (Company $r) => CompanyResource::getUrl('view', ['record' => $r])) ->actions([ Actions\ViewAction::make() ->url(fn (Company $r) => CompanyResource::getUrl('view', ['record' => $r])), Actions\Action::make('open_tenant') ->label('Deschide') ->icon('heroicon-m-arrow-top-right-on-square') ->color('primary') ->url(fn (Company $r) => $r->url('/app')) ->openUrlInNewTab(), Actions\Action::make('suspend') ->label('Suspendă') ->icon('heroicon-m-no-symbol') ->color('danger') ->visible(fn (Company $r) => in_array($r->status, ['active', 'trial'])) ->requiresConfirmation() ->action(fn (Company $r) => app(\App\Services\CompanyProvisioner::class)->suspend($r)), Actions\Action::make('activate') ->label('Activează') ->icon('heroicon-m-check-circle') ->color('success') ->visible(fn (Company $r) => in_array($r->status, ['suspended', 'expired'])) ->requiresConfirmation() ->action(fn (Company $r) => app(\App\Services\CompanyProvisioner::class)->reactivate($r)), Actions\EditAction::make(), Actions\DeleteAction::make(), ]) ->emptyStateHeading('Niciun tenant încă') ->emptyStateDescription('Adaugă primul client SaaS folosind butonul „Adaugă companie" — se va crea un tenant nou cu admin pe `.service.mir.md/app`.') ->emptyStateIcon('heroicon-o-building-office-2') ->defaultSort('created_at', 'desc'); } public static function getPages(): array { return [ 'index' => Pages\ListCompanies::route('/'), 'create' => Pages\CreateCompany::route('/create'), 'view' => Pages\ViewCompany::route('/{record}'), 'edit' => Pages\EditCompany::route('/{record}/edit'), ]; } }