diff --git a/app/Http/Controllers/Admin/PetShop/InvoiceCrudController.php b/app/Http/Controllers/Admin/PetShop/InvoiceCrudController.php index 664c4b47..1390a27f 100644 --- a/app/Http/Controllers/Admin/PetShop/InvoiceCrudController.php +++ b/app/Http/Controllers/Admin/PetShop/InvoiceCrudController.php @@ -5,6 +5,7 @@ use App\Http\Requests\InvoiceRequest; use Backpack\CRUD\app\Http\Controllers\CrudController; use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD; +use Backpack\CRUD\app\Library\Widget; /** * Class InvoiceCrudController. @@ -53,15 +54,10 @@ public function setupLast5YearsView() protected function setupListOperation() { CRUD::addColumn([ - 'name' => 'owner', - 'label' => 'Owner', - 'linkTo' => [ - 'route' => 'owner.show', - 'target' => '_blank', - ], + 'name' => 'info', + 'type' => 'view', + 'view' => 'crud::chips.invoice', ]); - CRUD::column('series'); - CRUD::column('number'); CRUD::column('issuance_date'); CRUD::column('due_date'); CRUD::column('total'); @@ -148,6 +144,17 @@ protected function setupShowOperation() $this->autoSetupShowOperation(); CRUD::column('total'); + + // get the owner with important relationships + $owner = CRUD::getCurrentEntry()->owner()->with('avatar', 'invoices')->first(); + + // add a chip widget for the owner + Widget::add() + ->to('after_content') + ->type('chip') + ->view('crud::chips.owner') + ->title('Owner') + ->entry($owner); } public function fetchOwner() diff --git a/composer.lock b/composer.lock index b70b999c..09645cec 100644 --- a/composer.lock +++ b/composer.lock @@ -62,16 +62,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.347.0", + "version": "3.347.1", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "c66a35e650f077caddd7db8d3a1f58b2c2b8c78b" + "reference": "ca91caa1d93223f03905e245a268759258ca41a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/c66a35e650f077caddd7db8d3a1f58b2c2b8c78b", - "reference": "c66a35e650f077caddd7db8d3a1f58b2c2b8c78b", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/ca91caa1d93223f03905e245a268759258ca41a6", + "reference": "ca91caa1d93223f03905e245a268759258ca41a6", "shasum": "" }, "require": { @@ -153,9 +153,9 @@ "support": { "forum": "https://github.com/aws/aws-sdk-php/discussions", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.347.0" + "source": "https://github.com/aws/aws-sdk-php/tree/3.347.1" }, - "time": "2025-06-23T18:12:15+00:00" + "time": "2025-06-24T18:14:42+00:00" }, { "name": "backpack/activity-log", @@ -483,16 +483,16 @@ }, { "name": "backpack/crud", - "version": "7.0.0-alpha.8", + "version": "7.0.0-alpha.9", "source": { "type": "git", "url": "https://github.com/Laravel-Backpack/CRUD.git", - "reference": "c4bfb8fd4bb2f8ff0169bcab3d4ec8167dd7076c" + "reference": "53c4ef9eaa4cbdf45d525d79284d155a3ba9bbe0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Laravel-Backpack/CRUD/zipball/c4bfb8fd4bb2f8ff0169bcab3d4ec8167dd7076c", - "reference": "c4bfb8fd4bb2f8ff0169bcab3d4ec8167dd7076c", + "url": "https://api.github.com/repos/Laravel-Backpack/CRUD/zipball/53c4ef9eaa4cbdf45d525d79284d155a3ba9bbe0", + "reference": "53c4ef9eaa4cbdf45d525d79284d155a3ba9bbe0", "shasum": "" }, "require": { @@ -571,9 +571,9 @@ ], "support": { "issues": "https://github.com/Laravel-Backpack/CRUD/issues", - "source": "https://github.com/Laravel-Backpack/CRUD/tree/7.0.0-alpha.8" + "source": "https://github.com/Laravel-Backpack/CRUD/tree/7.0.0-alpha.9" }, - "time": "2025-06-24T09:00:20+00:00" + "time": "2025-06-25T11:01:47+00:00" }, { "name": "backpack/editable-columns", @@ -10503,12 +10503,12 @@ "source": { "type": "git", "url": "https://github.com/Laravel-Backpack/Generators.git", - "reference": "fa29b49290899cb42f11411b5cf021b17b603ebd" + "reference": "6f7cf04d01a87f08639b116d43adbb26fdde1d37" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Laravel-Backpack/Generators/zipball/fa29b49290899cb42f11411b5cf021b17b603ebd", - "reference": "fa29b49290899cb42f11411b5cf021b17b603ebd", + "url": "https://api.github.com/repos/Laravel-Backpack/Generators/zipball/6f7cf04d01a87f08639b116d43adbb26fdde1d37", + "reference": "6f7cf04d01a87f08639b116d43adbb26fdde1d37", "shasum": "" }, "require": { @@ -10561,7 +10561,7 @@ "issues": "https://github.com/Laravel-Backpack/Generators/issues", "source": "https://github.com/Laravel-Backpack/Generators/tree/next" }, - "time": "2025-03-05T16:05:27+00:00" + "time": "2025-06-25T10:57:55+00:00" }, { "name": "barryvdh/laravel-debugbar", diff --git a/resources/views/admin/new-in-v7.blade.php b/resources/views/admin/new-in-v7.blade.php index ec6b6d76..22495a82 100644 --- a/resources/views/admin/new-in-v7.blade.php +++ b/resources/views/admin/new-in-v7.blade.php @@ -33,6 +33,25 @@ @section('content') + +
+
+
Views
+

Chips

+

Include more information about an Eloquent model, in a small space. Hover over the headings + to understand more about the examples.

+
+
+
+ + See docs + +
+
+
+ +@include('admin.partials.chip-examples') +
@@ -103,6 +122,7 @@
+ @include('admin.partials.dataform-examples') @endsection diff --git a/resources/views/admin/partials/chip-examples.blade.php b/resources/views/admin/partials/chip-examples.blade.php new file mode 100644 index 00000000..4d2e1601 --- /dev/null +++ b/resources/views/admin/partials/chip-examples.blade.php @@ -0,0 +1,250 @@ +@php + $user = \App\User::inRandomOrder()->first(); + $invoices = \App\Models\PetShop\Invoice::inRandomOrder()->take(3)->get(); + $products = \App\Models\Product::inRandomOrder()->take(3)->get(); + $owners = \App\Models\PetShop\Owner::inRandomOrder()->take(3)->get(); +@endphp + +
+ +
+ +
+
+ + {{-- Example of General chip for a person, with hardcoded complete data --}} + @include('crud::chips.general', [ + 'heading' => [ + 'content' => 'John Doe', + 'href' => 'https://google.com', + 'target' => '_blank', + 'title' => 'Example of a chip without URL', + ], + 'image' => [ + 'content' => asset('uploads/person1.jpg'), + 'element' => 'a', + 'href' => 'https://chatgpt.com', + 'target' => '_blank', + 'title' => 'Image can have its own URL, but why?! Falls back to the one in the heading', + ], + 'details' => [ + [ + 'icon' => 'la la-hashtag', + 'content' => '8AH13A7', + 'url' => 'mailto:john.doe@example.com', + 'title' => 'Click to email', + ], + [ + 'icon' => 'la la-envelope', + 'content' => 'john.doe@example.com', + 'url' => 'mailto:john.doe@example.com', + 'title' => 'Click to email', + ], + [ + 'icon' => 'la la-phone', + 'content' => '+1 (555) 123-4567', + 'url' => 'tel:+15551234567', + 'title' => 'Click to call', + ] + ] + ]) + +
+
+ +
+ +
+ +
+
+ + {{-- Example of General chip for a person, with hardcoded data, missing URL and image --}} + @include('crud::chips.general', [ + 'heading' => [ + 'content' => 'Adam Mancinello', + 'title' => 'Example of a chip without URL or image', + 'element' => 'span', // can be a span, a div, or an anchor + ], + 'details' => [ + [ + 'icon' => 'la la-hashtag', + 'content' => '8AH13A7', + 'url' => 'mailto:adam.mancinello@example.com', + 'title' => 'Click to email', + ], + [ + 'icon' => 'la la-envelope', + 'content' => 'adam.mancinello@example.com', + 'url' => 'mailto:adam.mancinello@example.com', + 'title' => 'Click to email', + ], + [ + 'icon' => 'la la-phone', + 'content' => '+1 (555) 123-4567', + 'url' => 'tel:+15551234567', + 'title' => 'Click to call', + ] + ] + ]) + +
+
+ +
+ + +
+ +
+
+ + {{-- Example of General chip for a person, with data from Eloquent model --}} + @include('crud::chips.general', [ + 'heading' => [ + 'content' => $user->name, + 'href' => backpack_url('user/'.$user->id.'/show'), + 'title' => 'Click to preview', + ], + 'image' => [ + 'content' => backpack_avatar_url($user), // doesn't work well with dummy data + 'element' => 'a', + 'href' => backpack_url('user/'.$user->id.'/show'), + 'title' => 'Because of dummy data, this image is not available, but it would show a profile image', + ], + 'details' => [ + [ + 'icon' => 'la la-hashtag', + 'content' => $user->id, + 'url' => backpack_url('user/'.$user->id.'/show'), + 'title' => 'Click to preview', + ], + [ + 'icon' => 'la la-envelope', + 'content' => $user->email, + 'url' => 'mailto:'.$user->email, + 'title' => 'Click to email', + ], + [ + 'icon' => 'la la-calendar', + 'content' => $user->created_at->format('F j, Y'), + 'title' => 'Created at '.$user->created_at, + ] + ] + ]) + +
+
+ +
+ +
+ +
+
+

Works well for people - in this demo, the most obvious example is pet owners:

+
+
+ +
+ + @foreach ($owners as $owner) + +
+ +
+
+ + {{-- Example of General chip for a person, with data from Eloquent model --}} + @include('crud::chips.owner', ['entry' => $owner]) + +
+
+ +
+ + @endforeach +
+ +
+
+

But it's particularly useful for entities where the name alone can't identify an entity, eg. Invoice:

+
+
+ + +
+ + @foreach ($invoices as $invoice) + +
+ +
+
+ + {{-- Example of General chip for a person, with data from Eloquent model --}} + @include('crud::chips.invoice', ['entry' => $invoice]) + +
+
+ +
+ + @endforeach +
+ + +
+
+

Or entities that can sometimes have duplicated names, like Products:

+
+
+ +
+ + @foreach ($products as $product) + +
+ +
+
+ + {{-- Example of General chip for a person, with data from Eloquent model --}} + @include('crud::chips.general', [ + 'heading' => [ + 'content' => $product->name, + 'href' => backpack_url('product/'.$product->id.'/show'), + 'title' => 'Click to preview', + ], + 'details' => [ + [ + 'icon' => 'la la-dollar', + 'content' => $product->price, + 'title' => 'Priced at $'.$product->price, + ], + [ + 'icon' => 'la la-tag', + 'content' => $product->category->name, + 'url' => backpack_url('category/'.$product->category->id.'/show'), + 'title' => 'Product category: '.$product->category->name, + ], + [ + 'icon' => 'la la-tag', + 'content' => $product->status, + 'title' => 'Product status: '.$product->status->value, + ], + [ + 'icon' => 'la la-traffic-light', + 'content' => $product->condition, + 'title' => 'Production condition: '.$product->condition, + ] + ] + ]) + +
+
+ +
+ + @endforeach +
diff --git a/resources/views/vendor/backpack/crud/chips/invoice.blade.php b/resources/views/vendor/backpack/crud/chips/invoice.blade.php new file mode 100644 index 00000000..da334537 --- /dev/null +++ b/resources/views/vendor/backpack/crud/chips/invoice.blade.php @@ -0,0 +1,22 @@ +@include('crud::chips.general', [ + 'heading' => [ + 'content' => 'Invoice '.$entry->series.' '.$entry->number.' - '.$entry->owner->name, + 'href' => backpack_url('pet-shop/invoice/'.$entry->id.'/show'), + ], + 'details' => [ + [ + 'icon' => 'la la-dollar', + 'content' => $entry->total, + 'title' => 'Total invoice amount $'.$entry->total, + ], + [ + 'icon' => 'la la-tags', + 'content' => $entry->items->count().' items', + ], + [ + 'icon' => 'la la-calendar', + 'content' => $entry->issuance_date->format('F j, Y'), + 'title' => 'Issuance date: '.$entry->issuance_date, + ] + ] +]) diff --git a/resources/views/vendor/backpack/crud/chips/owner.blade.php b/resources/views/vendor/backpack/crud/chips/owner.blade.php new file mode 100644 index 00000000..eca85bc9 --- /dev/null +++ b/resources/views/vendor/backpack/crud/chips/owner.blade.php @@ -0,0 +1,30 @@ +@php + $last_purchase = $entry->invoices()->orderBy('issuance_date', 'DESC')->first()->issuance_date; +@endphp + +@include('crud::chips.general', [ + 'heading' => [ + 'content' => $entry->name, + 'href' => backpack_url('pet-shop/owner/'.$entry->id.'/show'), + ], + 'image' => [ + 'content' => asset($entry->avatar->url), + ], + 'details' => [ + [ + 'icon' => 'la la-dog', + 'content' => $entry->pets->count().' pets', + 'title' => 'Number of pets: '.$entry->pets->count(), + ], + [ + 'icon' => 'la la-shopping-cart', + 'content' => $entry->invoices->count(). ' purchases', + 'title' => 'Number of purchases: '.$entry->invoices->count(), + ], + [ + 'icon' => 'la la-calendar', + 'content' => $last_purchase->format('F j, Y'), + 'title' => 'Last purchase: '.$last_purchase, + ] + ] +])