records(fn (?string $search, ?string $sortColumn, ?string $sortDirection, int|string $page, int|string $recordsPerPage) => $service->paginate( search: $search, sortColumn: $sortColumn, sortDirection: $sortDirection, page: (int) $page, perPage: (int) $recordsPerPage, )) ->columns([ TextColumn::make('code')->label('Kode')->sortable(), TextColumn::make('name')->label('Nama')->searchable()->sortable(), TextColumn::make('unit')->label('Satuan'), TextColumn::make('weight')->label('Berat'), TextColumn::make('stock_minimum')->label('Stok Minimum')->numeric()->sortable(), TextColumn::make('cost_price')->label('Harga Beli')->numeric()->prefix('Rp ')->sortable(), IconColumn::make('is_active')->label('Aktif')->boolean(), ]) ->headerActions([ CreateAction::make() ->schema(fn (Schema $schema): Schema => $schema->components(self::productFormSchema())) ->using(function (array $data): void { $data['is_active'] = true; app(ProductService::class)->create($data); }), ]) ->recordActions([ EditAction::make() ->schema(fn (Schema $schema): Schema => $schema->components(self::productFormSchema(withStatus: true))) ->fillForm(fn (array $record): array => $record) ->action(function (array $data, array $record): void { app(ProductService::class)->update($record['id'], $data); }), Action::make('hapus') ->label('Hapus') ->color('danger') ->icon('heroicon-o-trash') ->requiresConfirmation() ->modalDescription('Yakin menghapus produk ini?') ->action(function (array $record): void { app(ProductService::class)->delete($record['id']); }), ]) ->paginated([10, 25, 50]); } /** * @return list */ private static function productFormSchema(bool $withStatus = false): array { return [ TextInput::make('code')->label('Kode')->default(fn () => app(ProductService::class)->nextCode())->required()->maxLength(50), TextInput::make('name')->label('Nama Produk')->required()->maxLength(150), Select::make('unit')->label('Satuan')->options(['kg' => 'Kilogram', 'sak' => 'Sak', 'ton' => 'Ton'])->default('kg')->required(), TextInput::make('weight')->label('Berat')->numeric()->default(0), TextInput::make('stock_minimum')->label('Stok Minimum')->numeric()->default(0), TextInput::make('cost_price')->label('Harga Beli')->numeric()->default(0), ...($withStatus ? [Select::make('is_active')->label('Status')->options([1 => 'Aktif', 0 => 'Nonaktif'])->default(1)->required()] : []), ]; } public function content(Schema $schema): Schema { return $schema ->components([ EmbeddedTable::make(), ]); } }