components([ Section::make('Basic Information') ->schema([ Grid::make(2) ->schema([ Select::make('user_id') ->label('User') ->relationship('user', 'name') ->searchable() ->preload() ->required() ->createOptionForm([ TextInput::make('name') ->required(), TextInput::make('email') ->email() ->required(), ]), Select::make('plan_id') ->label('Plan') ->relationship('plan', 'name') ->searchable() ->preload() ->required(), ]), Grid::make(2) ->schema([ Select::make('type') ->label('Subscription Type') ->options([ 'default' => 'Default', 'premium' => 'Premium', 'enterprise' => 'Enterprise', 'trial' => 'Trial', ]) ->required() ->default('default') ->helperText('Type of subscription'), Select::make('status') ->label('Status') ->options([ 'active' => 'Active', 'trialing' => 'Trial', 'cancelled' => 'Cancelled', 'paused' => 'Paused', 'incomplete' => 'Incomplete', ]) ->required() ->default('active'), ]), Grid::make(2) ->schema([ Select::make('provider') ->label('Provider') ->options(function () { $providers = PaymentProvider::orderBy('priority', 'desc') ->orderBy('name') ->get(); if ($providers->isEmpty()) { return [ 'no_providers' => '⚠️ No payment providers configured - Please add providers first', ]; } return $providers->mapWithKeys(function ($provider) { $status = $provider->is_active ? 'Active' : 'Inactive'; return [ $provider->name => "{$provider->display_name} ({$status})", ]; })->toArray(); }) ->required() ->default(function () { $providers = PaymentProvider::orderBy('priority', 'desc') ->orderBy('name') ->get(); if ($providers->isEmpty()) { return 'no_providers'; } return PaymentProvider::where('name', 'stripe')->exists() ? 'stripe' : PaymentProvider::active()->first()?->name; }) ->helperText(function () { $providers = PaymentProvider::orderBy('priority', 'desc') ->orderBy('name') ->get(); if ($providers->isEmpty()) { return '⚠️ No payment providers available. Please configure payment providers in the Payment Providers section first.'; } return 'Select a payment provider for this subscription'; }), TextInput::make('provider_subscription_id') ->label('Provider Subscription ID'), ]), ]), Section::make('Trial Management') ->schema([ Grid::make(2) ->schema([ DateTimePicker::make('trial_ends_at') ->label('Trial Ends At'), TextInput::make('quantity') ->label('Quantity') ->numeric() ->default(1), ]), ]) ->collapsible(), Section::make('Billing Dates') ->schema([ Grid::make(2) ->schema([ DateTimePicker::make('starts_at') ->label('Starts At'), DateTimePicker::make('ends_at') ->label('Ends At'), ]), Grid::make(2) ->schema([ DateTimePicker::make('cancelled_at') ->label('Cancelled At'), DateTimePicker::make('paused_at') ->label('Paused At'), ]), Grid::make(2) ->schema([ DateTimePicker::make('resumed_at') ->label('Resumed At'), DateTimePicker::make('last_provider_sync') ->label('Last Provider Sync'), ]), ]) ->collapsible(), Section::make('Cancellation Details') ->schema([ Textarea::make('cancellation_reason') ->label('Reason'), ]) ->collapsible() ->visible(fn ($get) => $get('status') === 'cancelled'), Section::make('Migration Information') ->schema([ TextInput::make('migration_batch_id') ->label('Migration Batch ID'), Toggle::make('is_migrated') ->label('Is Migrated'), Textarea::make('legacy_data') ->label('Legacy Data') ->rows(3), ]) ->collapsible(), Tabs::make('Provider Data') ->tabs([ Tab::make('Overview') ->schema([ Section::make('Activation Key') ->schema([ TextEntry::make('provider_data.activation_key') ->label('Activation Key') ->copyable(), TextEntry::make('provider_data.key_id') ->label('Key ID'), TextEntry::make('provider_data.redeemed_at') ->label('Redeemed At'), ]) ->columns(1) ->hidden(fn ($record) => ! data_get($record, 'provider_data.activation_key')), Section::make('Plan Details') ->schema([ TextEntry::make('provider_data.plan_details.name') ->label('Plan Name'), TextEntry::make('provider_data.plan_details.price') ->label('Price') ->prefix('$'), TextEntry::make('provider_data.plan_details.billing_cycle_display') ->label('Billing Cycle'), TextEntry::make('provider_data.plan_details.plan_tier') ->badge() ->label('Tier'), TextEntry::make('provider_data.plan_details.billing_cycle_days') ->label('Duration') ->suffix(' days'), ]) ->columns(2) ->hidden(fn ($record) => ! data_get($record, 'provider_data.plan_details')), Section::make('Provider Info') ->schema([ TextEntry::make('provider_data.provider_info.name') ->label('Provider Name'), TextEntry::make('provider_data.provider_info.version') ->label('Version'), TextEntry::make('provider_data.provider_info.processed_at') ->label('Processed At'), ]) ->columns(2) ->hidden(fn ($record) => ! data_get($record, 'provider_data.provider_info')), ]), Tab::make('Features') ->schema([ RepeatableEntry::make('provider_data.plan_details.features') ->schema([ Section::make() ->schema([ TextEntry::make('feature.display_name') ->label('Feature Name') ->weight('bold'), TextEntry::make('feature.description') ->label('Description') ->columnSpanFull(), TextEntry::make('feature.category') ->label('Category') ->badge(), TextEntry::make('feature.type') ->label('Type'), Section::make('Limit Details') ->schema([ TextEntry::make('limit.limit_value') ->label('Limit Value'), TextEntry::make('limit.trial_limit_value') ->label('Trial Limit'), TextEntry::make('limit.limit_type') ->badge() ->label('Limit Type'), TextEntry::make('limit.is_enabled') ->label('Status') ->badge() ->formatStateUsing(fn ($state) => $state ? 'Enabled' : 'Disabled') ->color(fn ($state) => $state ? 'success' : 'gray'), ]) ->columns(2) ->collapsed(), ]) ->columns(2), ]) ->columnSpanFull(), ]) ->hidden(fn ($record) => ! data_get($record, 'provider_data.plan_details.features')), Tab::make('Raw JSON') ->schema([ TextEntry::make('provider_data') ->formatStateUsing(function ($state) { if (is_string($state)) { $data = json_decode($state, true); } else { $data = (array) $state; } return json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); }) ->state(fn ($record) => $record?->provider_data ?? '{}') ->copyable() ->columnSpanFull(), ]), ])->columnSpanFull(), ]); } }