*/ public static $model = FlashSaleModel::class; /** * The single value that should be used to represent the resource when being displayed. * * @var string */ public static $title = 'id'; /** * The columns that should be searched. * * @var array */ public static $search = [ 'title', ]; /** * The relationships that should be eager loaded on index queries. * * @var array */ public static $with = ['products']; /** * Get the displayable label of the resource. */ public static function label(): string { return __('Flash sales'); } /** * Get the displayable singular label of the resource. */ public static function singularLabel(): string { return __('Flash sale'); } /** * Get the fields displayed by the resource. */ public function fields(NovaRequest $request): array { return [ new Panel(__('Basic information'), [ ID::make()->sortable(), Text::make(__('Title'), 'title') ->rules('required') ->translatable(), DateTime::make(__('Starts at'), 'starts_at') ->rules('required', 'date') ->default(now()), DateTime::make(__('Ends at'), 'ends_at') ->rules('required', 'date', 'after:starts_at') ->default(now()->addDay()), Text::make(__('Products count'), fn () => $this->products->count()) ->exceptOnForms(), Text::make(__('Products'), fn () => $this->products->pluck('name')->implode(', ')) ->onlyOnDetail(), Multiselect::make(__('Products'), 'products') ->asyncResource(Product::class) ->placeholder(__('Search by id, name, sku, barcode...')) ->rules('required') ->resolveUsing(fn () => $this->products->pluck('id')->toArray()) ->fillUsing(NovaForm::fillEmpty()) ->onlyOnForms(), NovaSwitcher::make(__('Visible'), 'is_visible') ->default(true) ->sortable(), ]), ]; } /** * Register a callback to be called after the resource is created. */ public static function afterCreate(NovaRequest $request, Model $model): void { static::syncProducts($request, $model); } /** * Register a callback to be called after the resource is updated. */ public static function afterUpdate(NovaRequest $request, Model $model): void { static::syncProducts($request, $model); } /** * Sync selected products. */ protected static function syncProducts(NovaRequest $request, Model $model): void { $products = $request->input('products', []); if (is_string($products)) { $products = str_contains($products, ',') ? explode(',', $products) : [$products]; } $products = collect($products) ->filter() ->map(fn ($product) => intval($product)) ->values() ->toArray(); $model->products()->sync($products); } /** * Get the cards available for the request. */ public function cards(NovaRequest $request): array { return []; } /** * Get the filters available for the resource. */ public function filters(NovaRequest $request): array { return []; } /** * Get the lenses available for the resource. */ public function lenses(NovaRequest $request): array { return []; } /** * Get the actions available for the resource. */ public function actions(NovaRequest $request): array { return []; } }