From 1b8f651fcf377fb68a9589b9daadfee941febe02 Mon Sep 17 00:00:00 2001 From: luanfreitasdev Date: Sat, 18 May 2024 20:16:16 -0300 Subject: [PATCH] Add summary support in the collections table --- src/ProcessDataSource.php | 2 + .../DishesCalculationsCollectionTable.php | 154 ++++++++++++++++++ tests/Feature/CalculationsCollectionTest.php | 50 ++++++ 3 files changed, 206 insertions(+) create mode 100644 tests/Concerns/Components/DishesCalculationsCollectionTable.php create mode 100644 tests/Feature/CalculationsCollectionTest.php diff --git a/src/ProcessDataSource.php b/src/ProcessDataSource.php index 9871dffd0..1e513353b 100644 --- a/src/ProcessDataSource.php +++ b/src/ProcessDataSource.php @@ -89,6 +89,8 @@ private function processCollection(mixed $datasource, bool $isExport = false): \ $results = $this->component->applySorting($filters); + $this->applySummaries($results); + $this->component->total = $results->count(); if ($results->count()) { diff --git a/tests/Concerns/Components/DishesCalculationsCollectionTable.php b/tests/Concerns/Components/DishesCalculationsCollectionTable.php new file mode 100644 index 000000000..e656e7d9c --- /dev/null +++ b/tests/Concerns/Components/DishesCalculationsCollectionTable.php @@ -0,0 +1,154 @@ +showCheckBox(); + + return [ + Header::make() + ->showToggleColumns() + ->showSearchInput(), + + Footer::make() + ->showPerPage() + ->showRecordCount(), + ]; + } + + public function datasource(): Collection + { + return collect([ + [ + 'id' => 29, + 'name' => 'Luan', + 'balance' => 241.86, + 'is_online' => true, + 'created_at' => '2023-01-01 00:00:00', + ], + [ + 'id' => 57, + 'name' => 'Daniel', + 'balance' => 166.51, + 'is_online' => true, + 'created_at' => '2023-02-02 00:00:00', + ], + [ + 'id' => 93, + 'name' => 'Claudio', + 'balance' => 219.01, + 'is_online' => false, + 'created_at' => '2023-03-03 00:00:00', + ], + [ + 'id' => 104, + 'name' => 'Vitor', + 'balance' => 44.28, + 'is_online' => true, + 'created_at' => '2023-04-04 00:00:00', + ], + ]); + } + + public function query(): Builder + { + return Dish::with('category'); + } + + public function join(): Builder + { + return Dish::query() + ->join('categories', function ($categories) { + $categories->on('dishes.category_id', '=', 'categories.id'); + }) + ->select('dishes.*', 'categories.name as category_name'); + } + + public function fields(): PowerGridFields + { + return PowerGrid::fields() + ->add('id') + ->add('name') + ->add('balance', fn ($item) => Number::currency($item->balance, in: 'BRL', locale: 'pt-BR')) + ->add('is_online', fn ($item) => $item->is_online ? '✅' : '❌') + ->add('created_at', fn ($item) => Carbon::parse($item->created_at)) + ->add('created_at_formatted', fn ($item) => Carbon::parse($item->created_at)->format('d/m/Y')); + } + + public function columns(): array + { + return [ + Column::make('Index', 'id')->index(), + + Column::make('ID', 'id') + ->withCount('Count ID', true, false), + + Column::add() + ->title('Name') + ->field('name') + ->searchable() + ->sortable(), + + Column::add() + ->title('Balance') + ->field('balance') + ->withSum('Sum Balance', true, false) + ->withAvg('Avg Balance', true, false) + ->withCount('Count Balance', true, false) + ->withMin('Min Balance', true, false) + ->withMax('Max Balance', true, false) + ->sortable(), + + Column::add() + ->title('Online') + ->field('is_online'), + + Column::add() + ->title('Created At') + ->field('created_at_formatted'), + ]; + } + + public function summarizeFormat(): array + { + $fmt = (new \NumberFormatter('pt-PT', \NumberFormatter::DEFAULT_STYLE)); + + return [ + 'id.{count}' => fn ($value) => $fmt->format($value) . ' item(s)', + + 'balance.{sum,avg,min,max}' => function ($value) { + return (new \NumberFormatter('en_US', \NumberFormatter::CURRENCY)) + ->formatCurrency($value, 'USD'); + }, + ]; + } + + public function bootstrap(): void + { + config(['livewire-powergrid.theme' => 'bootstrap']); + } + + public function tailwind(): void + { + config(['livewire-powergrid.theme' => 'tailwind']); + } +} diff --git a/tests/Feature/CalculationsCollectionTest.php b/tests/Feature/CalculationsCollectionTest.php new file mode 100644 index 000000000..a6db05c44 --- /dev/null +++ b/tests/Feature/CalculationsCollectionTest.php @@ -0,0 +1,50 @@ +call($params->theme) + ->assertSeeHtml('Count ID: 4 item(s)') + ->set('search', 'Luan') + ->assertSeeHtml('Count ID: 1 item(s)'); +})->with('calculations collection'); + +it('calculates "sum" on price balance', function (string $component, object $params) { + livewire($component) + ->call($params->theme) + ->assertSeeHtml('Sum Balance: $671.66') + ->set('search', 'Luan') + ->assertSeeHtml('Sum Balance: $241.86'); +})->with('calculations collection'); + +it('calculates and formats "avg" on balance field and calorie fields', function (string $component, object $params) { + livewire($component) + ->call($params->theme) + ->assertSeeHtml('Avg Balance: $167.92') + ->set('search', 'Luan') + ->assertSeeHtml('Avg Balance: $241.86'); +})->with('calculations collection'); + +it('calculates "min" on balance field', function (string $component, object $params) { + livewire($component) + ->call($params->theme) + ->assertSeeHtml('Min Balance: $44.28') + ->set('search', 'Luan') + ->assertSeeHtml('Min Balance: $241.86'); +})->with('calculations collection'); + +it('calculates "max" on balance field', function (string $component, object $params) { + livewire($component) + ->call($params->theme) + ->assertSeeHtml('Max Balance: $241.86') + ->set('search', 'Luan') + ->assertSeeHtml('Max Balance: $241.86'); +})->with('calculations collection'); + +dataset('calculations collection', [ + 'tailwind' => [DishesCalculationsCollectionTable::class, (object) ['theme' => 'tailwind']], + 'bootstrap' => [DishesCalculationsCollectionTable::class, (object) ['theme' => 'bootstrap']], +]);