components([ Section::make('Trial Extension Details') ->schema([ Grid::make(2) ->schema([ Select::make('subscription_id') ->label('Subscription') ->options(function () { return Subscription::with(['user', 'plan']) ->where('status', 'trialing') ->orWhere('status', 'active') ->get() ->mapWithKeys(function ($subscription) { $label = "{$subscription->user->name} - {$subscription->plan->name}"; if ($subscription->trial_ends_at) { $label .= " ({$subscription->trial_ends_at->format('M j, Y')})"; } return [$subscription->id => $label]; }) ->toArray(); }) ->searchable() ->preload() ->required() ->live() ->afterStateUpdated(function ($state, callable $set, callable $get) { if ($state) { $subscription = Subscription::find($state); if ($subscription) { $set('user_id', $subscription->user_id); $set('original_trial_ends_at', $subscription->trial_ends_at); // Set user display name if ($subscription->relationLoaded('user')) { $set('user_display', $subscription->user->name); } else { $subscription->load('user'); $set('user_display', $subscription->user->name); } self::calculateNewTrialEndDate($set, $get); } } }), TextInput::make('user_display') ->label('User') ->disabled() ->dehydrated(false), ]), // Hidden field for user_id to ensure it gets submitted TextInput::make('user_id') ->hidden(), Grid::make(2) ->schema([ TextInput::make('extension_days') ->label('Extension Days') ->numeric() ->required() ->default(7) ->live(onBlur: true) ->helperText('Number of days to extend the trial') ->afterStateUpdated(fn ($state, callable $set, callable $get) => self::calculateNewTrialEndDate($set, $get)), Select::make('extension_type') ->label('Extension Type') ->options([ 'manual' => 'Manual Grant', 'automatic' => 'Automatic Extension', 'compensation' => 'Compensation', ]) ->default('manual') ->required(), ]), Grid::make(2) ->schema([ DateTimePicker::make('original_trial_ends_at') ->label('Original Trial End Date') ->disabled() ->dehydrated(false), DateTimePicker::make('new_trial_ends_at') ->label('New Trial End Date') ->required() ->readOnly() ->helperText('This will be calculated automatically based on extension days'), ]), ]), Section::make('Additional Information') ->schema([ Textarea::make('reason') ->label('Reason') ->rows(3) ->helperText('Reason for granting this trial extension'), Select::make('granted_by_admin_id') ->label('Granted By') ->relationship('grantedByAdmin', 'name') ->searchable() ->preload() ->default(fn () => auth()->id()) ->helperText('Admin who granted this extension'), ]) ->collapsible(), Section::make('Timestamps') ->schema([ DateTimePicker::make('granted_at') ->label('Granted At') ->default(now()) ->required(), ]) ->collapsible(), Section::make('Metadata') ->schema([ KeyValue::make('metadata') ->label('Custom Metadata') ->addActionLabel('Add metadata') ->keyLabel('Key') ->valueLabel('Value') ->helperText('Additional key-value data for this trial extension'), ]) ->collapsible(), ]); } /** * Calculate the new trial end date based on original date and extension days */ private static function calculateNewTrialEndDate(callable $set, callable $get): void { $subscriptionId = $get('subscription_id'); $extensionDays = (int) $get('extension_days') ?: 0; if (! $subscriptionId || ! $extensionDays) { $set('new_trial_ends_at', null); return; } $subscription = Subscription::find($subscriptionId); if (! $subscription) { $set('new_trial_ends_at', null); return; } // Use the original trial end date if available, otherwise use current date $baseDate = $subscription->trial_ends_at ?: now(); // Calculate new end date by adding extension days $newEndDate = $baseDate->copy()->addDays($extensionDays); // Format for DateTimePicker (Y-m-d H:i:s format) $set('new_trial_ends_at', $newEndDate->format('Y-m-d H:i:s')); } }