components([ Schemas\Components\Section::make(__('Regulă')) ->columns(2) ->schema([ Forms\Components\Select::make('type') ->label(__('Tip')) ->options(\App\Support\I18n::opts(MarkupRule::TYPES)) ->default('category') ->required() ->live(), Forms\Components\Select::make('key') ->label(fn (Get $get) => $get('type') === 'brand' ? __('Brand') : __('Categorie')) ->options(fn (Get $get) => $get('type') === 'brand' ? Part::distinct()->pluck('brand', 'brand')->filter()->toArray() : \App\Support\I18n::opts(array_combine(Part::CATEGORIES, Part::CATEGORIES))) ->visible(fn (Get $get) => in_array($get('type'), ['category', 'brand'], true)) ->searchable() ->required(fn (Get $get) => in_array($get('type'), ['category', 'brand'], true)), Forms\Components\TextInput::make('range_from') ->label(__('De la (preț achiziție)')) ->numeric() ->visible(fn (Get $get) => $get('type') === 'range'), Forms\Components\TextInput::make('range_to') ->label(__('Până la (gol = ∞)')) ->numeric() ->visible(fn (Get $get) => $get('type') === 'range'), Forms\Components\TextInput::make('markup_pct') ->label(__('Markup %')) ->numeric() ->required() ->suffix('%') ->helperText(__('Ex 30 → preț vânzare = preț achiziție × 1.30')), Forms\Components\TextInput::make('priority') ->label(__('Prioritate')) ->numeric() ->default(100) ->helperText(__('Mai mic = aplicat primul.')), Forms\Components\Toggle::make('is_active')->label(__('Activă'))->default(true), ]), ]); } public static function table(Table $table): Table { return $table ->columns([ Tables\Columns\TextColumn::make('priority')->label('#')->sortable(), Tables\Columns\TextColumn::make('type') ->formatStateUsing(fn ($s) => __(MarkupRule::TYPES[$s] ?? $s)) ->badge(), Tables\Columns\TextColumn::make('key')->label(__('Cheie'))->placeholder('—'), Tables\Columns\TextColumn::make('range_from')->label(__('De la'))->placeholder('—'), Tables\Columns\TextColumn::make('range_to')->label(__('Până la'))->placeholder('∞'), Tables\Columns\TextColumn::make('markup_pct') ->label(__('Markup')) ->formatStateUsing(fn ($s) => '+' . $s . '%') ->color('success') ->weight('bold'), Tables\Columns\IconColumn::make('is_active')->boolean(), ]) ->filters([ Tables\Filters\SelectFilter::make('type')->options(\App\Support\I18n::opts(MarkupRule::TYPES)), ]) ->headerActions([ Actions\Action::make('apply_all') ->label(__('Aplică toate regulile la stoc')) ->icon('heroicon-m-bolt') ->color('warning') ->requiresConfirmation() ->modalDescription(__('Va recalcula sell_price pentru TOATE piesele active. Continui?')) ->action(function () { $count = 0; Part::where('is_active', true)->where('buy_price', '>', 0)->chunk(100, function ($parts) use (&$count) { foreach ($parts as $part) { MarkupRule::applyToPart($part); $count++; } }); Notification::make()->title(__('Recalculat preț pentru :n piese', ['n' => $count]))->success()->send(); }), ]) ->actions([ Actions\EditAction::make(), Actions\DeleteAction::make(), ]) ->defaultSort('priority'); } public static function getPages(): array { return [ 'index' => Pages\ListMarkupRules::route('/'), 'create' => Pages\CreateMarkupRule::route('/create'), 'edit' => Pages\EditMarkupRule::route('/{record}/edit'), ]; } }