diff --git a/src/Providers/Macros.php b/src/Providers/Macros.php index d456051a..096490b0 100644 --- a/src/Providers/Macros.php +++ b/src/Providers/Macros.php @@ -55,12 +55,26 @@ public static function columns(): void return $this; }); - Column::macro('searchableRaw', function (string $sql = '') { + Column::macro('searchableRaw', function (string $sql = ''): Column { + /** @var Column $this */ + $field = $this->dataField ?: $this->field; + $this->rawQueries[] = [ 'method' => 'orWhereRaw', 'sql' => $sql, - 'bindings' => ['%{search}%'], - 'enabled' => function (PowerGridComponent $component) { + 'bindings' => [function (PowerGridComponent $component) use ($field): string { + $search = $component->search; + $fieldMethod = 'beforeSearch' . str($field)->camel()->ucfirst(); + + if (method_exists($component, $fieldMethod)) { + $search = $component->{$fieldMethod}($field, $search); + } elseif (method_exists($component, 'beforeSearch')) { + $search = $component->beforeSearch($field, $search); + } + + return "%$search%"; + }], + 'enabled' => function (PowerGridComponent $component) { return filled($component->search); }, ]; diff --git a/tests/Concerns/Components/DishesSearchableRawTable.php b/tests/Concerns/Components/DishesSearchableRawTable.php index 7d00b4af..40d511f8 100644 --- a/tests/Concerns/Components/DishesSearchableRawTable.php +++ b/tests/Concerns/Components/DishesSearchableRawTable.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Facades\DB; +use NumberFormatter; use PowerComponents\LivewirePowerGrid\Tests\Concerns\Models\Dish; use PowerComponents\LivewirePowerGrid\{Column, Facades\PowerGrid, PowerGridComponent, PowerGridFields}; @@ -48,6 +49,11 @@ public function fields(): PowerGridFields return PowerGrid::fields() ->add('id') ->add('name') + ->add('price_formatted', function (Dish $row): string { + $formatter = new NumberFormatter('pt_BR', NumberFormatter::CURRENCY); + + return $formatter->formatCurrency($row->price, 'BRL'); + }) ->add('produced_at_formatted'); } @@ -62,7 +68,11 @@ public function columns(): array return [ Column::make('ID', 'id') - ->searchable() + ->searchableRaw($this->database === 'pgsql' ? 'dishes.id::text ilike ?' : 'dishes.id like ?') + ->sortable(), + + Column::make('Preço', 'price_formatted', 'price') + ->searchableRaw($this->database === 'pgsql' ? 'price::text ilike ?' : 'price like ?') ->sortable(), Column::make('Prato', 'name') @@ -78,6 +88,22 @@ public function columns(): array ]; } + public function beforeSearch(string $field): string + { + return $field === 'id' + ? preg_replace('/[^0-9]/', '', $this->search) + : $this->search; + } + + public function beforeSearchPrice(): float + { + return (float) str_replace( + ',', + '.', + preg_replace('/[^0-9,]/', '', $this->search) + ); + } + public function setTestThemeClass(string $themeClass): void { config(['livewire-powergrid.theme' => $themeClass]); diff --git a/tests/Feature/SearchableRawTest.php b/tests/Feature/SearchableRawTest.php index 86cc2b8c..1cc379de 100644 --- a/tests/Feature/SearchableRawTest.php +++ b/tests/Feature/SearchableRawTest.php @@ -11,13 +11,26 @@ ->assertSee('Polpetone Filé Mignon') ->assertDontSee('Barco-Sushi Simples') ->assertDontSee('No records found') + # Id: 2 + ->set('search', '#2') + ->assertSee('Peixada da chef Nábia') + ->assertDontSee('Polpetone Filé Mignon') + ->assertDontSee('No records found') # 09/09/2046 ->set('search', '09/09/2046') //No dishes in this date ->assertSee('No records found') # 06/2026 ->set('search', '06/2026') ->assertSee('Francesinha') - ->assertDontSee('Polpetone Filé Mignon'); + ->assertDontSee('Polpetone Filé Mignon') + # $60.50 + ->set('search', 'R$ 60,50') + ->assertSee('Francesinha') + ->assertDontSee('Polpetone Filé Mignon') + # 1,500.40 + ->set('search', '1.500,40') + ->assertSee('Barco-Sushi Simples') + ->assertDontSee('Francesinha'); })->with('searchable_raw_themes')->requiresSQLite(); it('searches data using whereRaw on mysql', function (string $component, object $params) { @@ -28,13 +41,26 @@ ->assertSee('Polpetone Filé Mignon') ->assertDontSee('Barco-Sushi Simples') ->assertDontSee('No records found') + # Id: 2 + ->set('search', '#2') + ->assertSee('Peixada da chef Nábia') + ->assertDontSee('Polpetone Filé Mignon') + ->assertDontSee('No records found') # 09/09/2046 ->set('search', '09/09/2046') //No dishes in this date ->assertSee('No records found') # 06/2026 ->set('search', '06/2026') ->assertSee('Francesinha') - ->assertDontSee('Polpetone Filé Mignon'); + ->assertDontSee('Polpetone Filé Mignon') + # $60.50 + ->set('search', 'R$ 60,50') + ->assertSee('Francesinha') + ->assertDontSee('Polpetone Filé Mignon') + # 1,500.40 + ->set('search', '1.500,40') + ->assertSee('Barco-Sushi Simples') + ->assertDontSee('Francesinha'); })->with('searchable_raw_themes')->requiresMySQL(); it('searches data using whereRaw on pgsql', function (string $component, object $params) { @@ -44,13 +70,26 @@ ->assertSee('Polpetone Filé Mignon') ->assertDontSee('Barco-Sushi Simples') ->assertDontSee('No records found') + # Id: 2 + ->set('search', '#2') + ->assertSee('Peixada da chef Nábia') + ->assertDontSee('Polpetone Filé Mignon') + ->assertDontSee('No records found') # 09/09/2046 ->set('search', '09/09/2046') //No dishes in this date ->assertSee('No records found') # 06/2026 ->set('search', '06/2026') ->assertSee('Francesinha') - ->assertDontSee('Polpetone Filé Mignon'); + ->assertDontSee('Polpetone Filé Mignon') + # $60.50 + ->set('search', 'R$ 60,50') + ->assertSee('Francesinha') + ->assertDontSee('Polpetone Filé Mignon') + # 1,500.40 + ->set('search', '1.500,40') + ->assertSee('Barco-Sushi Simples') + ->assertDontSee('Francesinha'); })->with('searchable_raw_themes')->requiresPostgreSQL(); dataset('searchable_raw_themes', [